leofontes
leofontes

Reputation: 927

Undefined reference to rand() even thought it's included and defined

I'm working on the scheduler for a custom OS we are using in class, but when I try to call the rand() function, it gives me this error:

In function `gen_rand_number':
sched.c:(.text+0x5e): undefined reference to `rand'

Here is my sched.c file

#include <stdlib.h>
#include <signal.h>

PUBLIC int gen_rand_number(int min, int max) {
    int r;
    const int range = 1 + max - min;
    const int buckets = RAND_MAX / range;
    const int limit = buckets * range;  

    do {
        r = rand();
    } while (r >= limit);

    return min + (r / buckets);
}

So after a lot of Googling, I realized maybe the stdlib wasn't implemented on this OS, however I checked and

it is defined on: include/stdlib.h

and implemented on: src/lib/libc/stdlib/rand.c as follows:

int rand(void)
{
    _next = (_next * 1103515245) + 12345;
    return ((_next >> 16) & 0x7fff);
}

I realize this is a quite specific problem, but I hope someone is able to help me out. Also, if more information is needed, please let me know.

If you want to look at the whole OS code

Since this is coming up, I'm using a makefile:

export EDUCATIONAL_KERNEL=1

# Directories.
export BINDIR   = $(CURDIR)/bin
export SBINDIR  = $(BINDIR)/sbin
export UBINDIR  = $(BINDIR)/ubin
export DOCDIR   = $(CURDIR)/doc
export INCDIR   = $(CURDIR)/include
export LIBDIR   = $(CURDIR)/lib
export DOXYDIR  = $(CURDIR)/doxygen
export SRCDIR   = $(CURDIR)/src
export TOOLSDIR = $(CURDIR)/tools

# Toolchain
export CC = $(TARGET)-gcc
export LD = $(TARGET)-ld
export AR = $(TARGET)-ar

# Random number for chaos.
export KEY = 13

# Toolchain configuration.
export CFLAGS    = -I $(INCDIR)
export CFLAGS   += -DKERNEL_HASH=$(KEY) -DEDUCATIONAL_KERNEL=$(EDUCATIONAL_KERNEL)
export CFLAGS   += -std=c99 -pedantic-errors -fextended-identifiers
export CFLAGS   += -nostdlib -nostdinc -fno-builtin -fno-stack-protector
export CFLAGS   += -Wall -Wextra -Werror
export CFLAGS   += -Wstack-usage=3192 -Wlogical-op
export CFLAGS   += -Wredundant-decls -Wvla
export ASMFLAGS  = -Wa,--divide,--warn
export ARFLAGS   = -vq
export LDFLAGS   = -Wl,-T $(LIBDIR)/link.ld

# Resolves conflicts.
.PHONY: tools

# Builds everything.
all: nanvix documentation

# Builds Nanvix.
nanvix:
    mkdir -p $(BINDIR)
    mkdir -p $(SBINDIR)
    mkdir -p $(UBINDIR)
    cd $(SRCDIR) && $(MAKE) all

# Builds system's image.
image: $(BINDIR)/kernel tools
    mkdir -p $(BINDIR)
    bash $(TOOLSDIR)/build/build-img.sh $(EDUCATIONAL_KERNEL)

# Builds documentation.
documentation:
    doxygen $(DOXYDIR)/kernel.config

# Builds tools.
tools:
    mkdir -p $(BINDIR)
    cd $(TOOLSDIR) && $(MAKE) all

# Cleans compilation files.
clean:
    @rm -f *.img
    @rm -rf $(BINDIR)
    @rm -rf $(DOCDIR)/*-kernel
    cd $(SRCDIR) && $(MAKE) clean
    cd $(TOOLSDIR) && $(MAKE) clean

Upvotes: 0

Views: 5025

Answers (2)

Bodo Thiesen
Bodo Thiesen

Reputation: 2514

You need to link in your own implementation of the c library somewhat like this:

$ gcc -LPATH -lc $object_files -o executable

where PATH is the relative path to your own libc

Or ... probably you should better listen to David Schwartz, who already pointed out, that you have to implement rand yourself. Here it means: You need to implement it in the kernel, because I guess, sched.c is a file belonging to your kernel, and so, the stdclib functions are not available to you.

Upvotes: 1

David Schwartz
David Schwartz

Reputation: 182769

Since you're building a freestanding OS, not an application, you have no access to the standard library. If you look in the makefile, you'll see that it passes -nostdlib -nostdinc to the compiler and linker. If your codebase provides a PRNG, you can use it. Otherwise, you'll need to add an implementation of one.

Upvotes: 4

Related Questions