leofontes leofontes - 1 month ago 5
C Question

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

Answer

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.