Page 1 of 1

Issue with compiling "Hello World" OS setup

Posted: Thu Nov 10, 2016 4:05 pm
by SimonHA
Hi all!

It's my first time here at the forum and I have a beginner issue with compiling my simple OS for an Raspberry Pi Zero.
Here is my MakeFile:

Code: Select all

# Target definitions.
ARCH 			= arch/arm
TARGET_BOARD	= pi-zero
TARGET_CPU		= arm1176jzf-s

# Compiler setup.
COMPILER = /home/simonha/opt/cross/bin/arm-none-eabi
AS = $(COMPILER)-as
CC = $(COMPILER)-g++
LD = $(COMPILER)-ld
CP = $(COMPILER)-objcopy
OD = $(COMPILER)-objdump

ASFLAGS	= -mcpu=$(TARGET_CPU)
CFLAGS 	= -mcpu=$(TARGET_CPU) -ffreestanding -Wall -Wextra -fpic -std=c++11 \
	-nodefaultlibs -lgcc
LDFLAGS = 

# Directory setup.
BUILD = build/
SOURCE = src/

# The name of the output file to generate.
KERNEL_TARGET = kernel.img

# The name of the assembler listing file to generate.
LIST = kernel.list

# The name of the map file to generate.
MAP = kernel.map

# The name of the linker script to use.
LINKER = $(ARCH)/$(TARGET_BOARD)/kernel.ld

# Header includes
HEADER_INCLUDES = \
	-I$(SOURCE) \
	-I$(SOURCE)/lib/libc/include \
	-I$(ARCH) \
	-I$(ARCH)/$(TARGET_BOARD)

# Assembly files.
KERNEL_AS = \
	$(wildcard $(ARCH)/kernel/*.s) \
	$(wildcard $(ARCH)/$(TARGET_BOARD)/lib/*.s)
	
# Source files.
KERNEL_SRC = \
	$(wildcard $(ARCH)/kernel/*.cpp) \
	$(wildcard $(ARCH)/$(TARGET_BOARD)/driver/*.cpp) \
	$(wildcard $(SOURCE)/kernel/*.cpp)

# Kernel C-library files.
KERNEL_C_LIB = \
	$(wildcard $(SOURCE)/lib/libc/string/*.c)

KERNEL_AS_OBJ =  $(patsubst %.s, %.o, $(KERNEL_AS))
KERNEL_SRC_OBJ = $(patsubst %.cpp, %.o, $(KERNEL_SRC))
KERNEL_C_LIB_OBJ = $(patsubst %.c, %.o, $(KERNEL_C_LIB))

# Rule to make everything.
all: build_kernel_c_lib build_kernel build_binary build_list

# Rule to make kernel C library.
build_kernel_c_lib: $(KERNEL_C_LIB_OBJ)
%.o : %.c
	mkdir -p $(dir $(BUILD)$@)
	$(CC) $(CFLAGS) $(HEADER_INCLUDES) -c $< -o $(BUILD)$@

# Rule to make the object files.
build_kernel: $(KERNEL_AS_OBJ) $(KERNEL_SRC_OBJ)
%.o : %.s
	mkdir -p $(dir $(BUILD)$@)
	$(AS) $(ASFLAGS) $< -o $(BUILD)$@ 
%.o : %.cpp
	mkdir -p $(dir $(BUILD)$@)
	$(CC) $(CFLAGS) $(HEADER_INCLUDES) -c $< -o $(BUILD)$@

# Rule to make the kernel image file.
build_binary: $(KERNEL_AS_OBJ) $(KERNEL_SRC_OBJ) $(KERNEL_C_LIB_OBJ))
	$(CC) $(CFLAGS) \
	$(addprefix $(BUILD), $(KERNEL_C_LIB_OBJ)) \
	$(addprefix $(BUILD), $(KERNEL_AS_OBJ)) \
	$(addprefix $(BUILD), $(KERNEL_SRC_OBJ)) \
	-T $(LINKER)  -o $(BUILD)MinOS.elf
	$(LD) $(LDFLAGS) -Map $(BUILD)$(MAP)
	$(CP) $(BUILD)MinOS.elf -O binary $(BUILD)$(KERNEL_TARGET)

# Rule to make the listing file.
build_list: $(BUILD)MinOS.elf
	$(OD) -D $(BUILD)MinOS.elf > $(BUILD)$(LIST)

# Rule to clean the project.
clean:
	rm -f $(addprefix $(BUILD), $(KERNEL_C_LIB_OBJ))
	rm -f $(addprefix $(BUILD), $(KERNEL_AS_OBJ))
	rm -f $(addprefix $(BUILD), $(KERNEL_SRC_OBJ))
	rm -f $(BUILD)MinOS.elf
	rm -f $(BUILD)$(MAP)
	rm -f $(BUILD)$(KERNEL_TARGET)
	rm -f $(BUILD)$(LIST)
	find $(BUILD) -type d -empty -delete
Which unfortunately gives me an annoying error I cannot seem to understand why it is there:

Code: Select all

mkdir -p build/src//lib/libc/string/
/home/simonha/opt/cross/bin/arm-none-eabi-g++ -mcpu=arm1176jzf-s -ffreestanding -Wall -Wextra -fpic -std=c++11 -nodefaultlibs -lgcc -Isrc/ -Isrc//lib/libc/include -Iarch/arm -Iarch/arm/pi-zero -c src//lib/libc/string/strlen.c -o build/src//lib/libc/string/strlen.o
mkdir -p build/arch/arm/kernel/
/home/simonha/opt/cross/bin/arm-none-eabi-as -mcpu=arm1176jzf-s arch/arm/kernel/boot.s -o build/arch/arm/kernel/boot.o 
mkdir -p build/arch/arm/pi-zero/lib/
/home/simonha/opt/cross/bin/arm-none-eabi-as -mcpu=arm1176jzf-s arch/arm/pi-zero/lib/ok_led.s -o build/arch/arm/pi-zero/lib/ok_led.o 
mkdir -p build/arch/arm/pi-zero/driver/
/home/simonha/opt/cross/bin/arm-none-eabi-g++ -mcpu=arm1176jzf-s -ffreestanding -Wall -Wextra -fpic -std=c++11 -nodefaultlibs -lgcc -Isrc/ -Isrc//lib/libc/include -Iarch/arm -Iarch/arm/pi-zero -c arch/arm/pi-zero/driver/uart.cpp -o build/arch/arm/pi-zero/driver/uart.o
mkdir -p build/src//kernel/
/home/simonha/opt/cross/bin/arm-none-eabi-g++ -mcpu=arm1176jzf-s -ffreestanding -Wall -Wextra -fpic -std=c++11 -nodefaultlibs -lgcc -Isrc/ -Isrc//lib/libc/include -Iarch/arm -Iarch/arm/pi-zero -c src//kernel/kernel.cpp -o build/src//kernel/kernel.o
make: *** No rule to make target 'src//lib/libc/string/strlen.o)', needed by 'build_binary'.  Stop.
[Finished in 0.5s with exit code 2]
[shell_cmd: make]
[dir: /media/sf_MinOS]
[path: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games]
Any ideas about the issue? Furthermore, should I compile my kernel C-library externally and link it with the kernel makefile afterwards? I appreciate your help.

Best regards,
Simon

Re: Issue with compiling "Hello World" OS setup

Posted: Thu Nov 10, 2016 4:38 pm
by iansjack
There appears to be a rogue ")" at the end of the line:

build_binary: $(KERNEL_AS_OBJ) $(KERNEL_SRC_OBJ) $(KERNEL_C_LIB_OBJ))

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 3:01 am
by SimonHA
Okay, that is a bit embarrassing :shock:
It does not complain about this anymore. However, how do I deal with this new error?

Code: Select all

/home/simonha/opt/cross/lib/gcc/arm-none-eabi/6.2.0/../../../../arm-none-eabi/bin/ld: cannot find crt0.o: No such file or directory
I know that crt0 is the startup routine, which I already have in my boot.s file, where I clean up the BSS etc. before
jumping to my kernel main entry. The boot.s contain a global _start routine so the linker should find this, yet it still complains?

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 3:15 am
by iansjack
I would move your startup routines into your own version of crt0.o. There are other solutions, but this is probably the easiest.

Bear in mind that any userspace programs that you want to compile for your system will also need some sort of startup routine. Normally, at the very least, it creates argv[] and argc, and calls main().

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 3:50 am
by SimonHA
Okay, thank you for your help. How do I tell my cross compiler where this crt0.o is?

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 4:30 am
by Icee
Your LDFLAGS should include a -nostdlib flag which implies -nostartfiles which will stop the linker from trying to locate crt0.o. You'll also need -lgcc when linking.

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 5:27 am
by iansjack
I think that Icee's advice is better than mine, so I'd recommend that you try that first.

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 8:22 am
by SimonHA
So far so good. Here is the updated Makefile:

Code: Select all

# Target definitions.
ARCH 			= arch/arm
TARGET_BOARD	= pi-zero
TARGET_CPU		= arm1176jzf-s

# Compiler setup.
COMPILER = /home/simonha/opt/cross/bin/arm-none-eabi
AS = $(COMPILER)-as
CC = $(COMPILER)-g++
LD = $(COMPILER)-g++
CP = $(COMPILER)-objcopy
OD = $(COMPILER)-objdump

ASFLAGS	= -mcpu=$(TARGET_CPU)
CFLAGS 	= -mcpu=$(TARGET_CPU) -ffreestanding -Wall -Wextra -fpic -std=c++11
LDFLAGS = -nostdlib -lgcc

# Directory setup.
BUILD = build/
SOURCE = src/

# The name of the output file to generate.
KERNEL_TARGET = kernel.img

# The name of the assembler listing file to generate.
LIST = kernel.list

# The name of the map file to generate.
MAP = kernel.map

# The name of the linker script to use.
LINKER = $(ARCH)/$(TARGET_BOARD)/kernel.ld

# Header includes
HEADER_INCLUDES = \
	-I$(SOURCE) \
	-I$(SOURCE)/lib/libc/include \
	-I$(ARCH) \
	-I$(ARCH)/$(TARGET_BOARD)

# Assembly files.
KERNEL_AS = \
	$(wildcard $(ARCH)/kernel/*.s) \
	$(wildcard $(ARCH)/$(TARGET_BOARD)/lib/*.s)
	
# Source files.
KERNEL_SRC = \
	$(wildcard $(ARCH)/kernel/*.cpp) \
	$(wildcard $(ARCH)/$(TARGET_BOARD)/driver/*.cpp) \
	$(wildcard $(SOURCE)/kernel/*.cpp)

# Kernel C-library files.
KERNEL_C_LIB = \
	$(wildcard $(SOURCE)/lib/libc/string/*.c)

KERNEL_AS_OBJ =  $(patsubst %.s, %.o, $(KERNEL_AS))
KERNEL_SRC_OBJ = $(patsubst %.cpp, %.o, $(KERNEL_SRC))
KERNEL_C_LIB_OBJ = $(patsubst %.c, %.o, $(KERNEL_C_LIB))

# Rule to make everything.
all: build_kernel_c_lib build_kernel build_binary build_list

# Rule to make kernel C library.
build_kernel_c_lib: $(KERNEL_C_LIB_OBJ)
%.o : %.c
	mkdir -p $(dir $(BUILD)$@)
	$(CC) $(CFLAGS) $(HEADER_INCLUDES) -c $< -o $(BUILD)$@

# Rule to make the object files.
build_kernel: $(KERNEL_AS_OBJ) $(KERNEL_SRC_OBJ)
%.o : %.s
	mkdir -p $(dir $(BUILD)$@)
	$(AS) $(ASFLAGS) $< -o $(BUILD)$@ 
%.o : %.cpp
	mkdir -p $(dir $(BUILD)$@)
	$(CC) $(CFLAGS) $(HEADER_INCLUDES) -c $< -o $(BUILD)$@

# Rule to make the kernel image file.
build_binary: $(KERNEL_AS_OBJ) $(KERNEL_SRC_OBJ) $(KERNEL_C_LIB_OBJ)
	$(LD) $(LDFLAGS) \
	$(addprefix $(BUILD), $(KERNEL_C_LIB_OBJ)) \
	$(addprefix $(BUILD), $(KERNEL_AS_OBJ)) \
	$(addprefix $(BUILD), $(KERNEL_SRC_OBJ)) \
	-T $(LINKER)  -o $(BUILD)MinOS.elf
	$(LD) $(LDFLAGS) -Map $(BUILD)$(MAP)
	$(CP) $(BUILD)MinOS.elf -O binary $(BUILD)$(KERNEL_TARGET)

# Rule to make the listing file.
build_list: $(BUILD)MinOS.elf
	$(OD) -D $(BUILD)MinOS.elf > $(BUILD)$(LIST)

# Rule to clean the project.
clean:
	rm -f $(addprefix $(BUILD), $(KERNEL_C_LIB_OBJ))
	rm -f $(addprefix $(BUILD), $(KERNEL_AS_OBJ))
	rm -f $(addprefix $(BUILD), $(KERNEL_SRC_OBJ))
	rm -f $(BUILD)MinOS.elf
	rm -f $(BUILD)$(MAP)
	rm -f $(BUILD)$(KERNEL_TARGET)
	rm -f $(BUILD)$(LIST)
	find $(BUILD) -type d -empty -delete
The linker finds the libgcc but does not seem to find the required functions such as '__aeabi_uidiv'?

Code: Select all

mkdir -p build/src//lib/libc/string/
/home/simonha/opt/cross/bin/arm-none-eabi-g++ -mcpu=arm1176jzf-s -ffreestanding -Wall -Wextra -fpic -std=c++11 -Isrc/ -Isrc//lib/libc/include -Iarch/arm -Iarch/arm/pi-zero -c src//lib/libc/string/strlen.c -o build/src//lib/libc/string/strlen.o
mkdir -p build/arch/arm/kernel/
/home/simonha/opt/cross/bin/arm-none-eabi-as -mcpu=arm1176jzf-s arch/arm/kernel/start.s -o build/arch/arm/kernel/start.o 
mkdir -p build/arch/arm/pi-zero/lib/
/home/simonha/opt/cross/bin/arm-none-eabi-as -mcpu=arm1176jzf-s arch/arm/pi-zero/lib/ok_led.s -o build/arch/arm/pi-zero/lib/ok_led.o 
mkdir -p build/arch/arm/pi-zero/driver/
/home/simonha/opt/cross/bin/arm-none-eabi-g++ -mcpu=arm1176jzf-s -ffreestanding -Wall -Wextra -fpic -std=c++11 -Isrc/ -Isrc//lib/libc/include -Iarch/arm -Iarch/arm/pi-zero -c arch/arm/pi-zero/driver/uart.cpp -o build/arch/arm/pi-zero/driver/uart.o
mkdir -p build/src//kernel/
/home/simonha/opt/cross/bin/arm-none-eabi-g++ -mcpu=arm1176jzf-s -ffreestanding -Wall -Wextra -fpic -std=c++11 -Isrc/ -Isrc//lib/libc/include -Iarch/arm -Iarch/arm/pi-zero -c src//kernel/kernel.cpp -o build/src//kernel/kernel.o
/home/simonha/opt/cross/bin/arm-none-eabi-g++ -nostdlib -lgcc \
build/src//lib/libc/string/strlen.o \
build/arch/arm/kernel/start.o build/arch/arm/pi-zero/lib/ok_led.o \
build/arch/arm/pi-zero/driver/uart.o build/src//kernel/kernel.o \
-T arch/arm/pi-zero/kernel.ld  -o build/MinOS.elf
build/arch/arm/pi-zero/driver/uart.o: In function `uart::init(unsigned long)':
uart.cpp:(.text+0x64): undefined reference to `__aeabi_uidiv'
uart.cpp:(.text+0x8c): undefined reference to `__aeabi_uidiv'
build/arch/arm/pi-zero/driver/uart.o:(.ARM.exidx+0x10): undefined reference to `__aeabi_unwind_cpp_pr1'
build/src//kernel/kernel.o:(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr1'
collect2: error: ld returned 1 exit status
Makefile:80: recipe for target 'build_binary' failed
make: *** [build_binary] Error 1
[Finished in 0.7s with exit code 2]
[shell_cmd: make]
[dir: /media/sf_MinOS]
[path: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games]

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 9:35 am
by xenos
This might sound trivial, but did you actually compile libgcc (with "make all-target-libgcc; make install-targel-libgcc" IIRC) when building your cross compiler? If you did, you can check whether it contains these functions.

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 10:50 am
by SimonHA
Yes I followed the instructions from the tutorial thoroughly and from a dump (objdump libgcc.a -t) of the file
"/home/simonha/opt/cross/lib/gcc/arm-none-eabi/6.2.0/libgcc.a", which I got from the linker I can find it:

Code: Select all

_udivsi3.o:     file format elf32-little

SYMBOL TABLE:
00000000 l    d  .text	00000000 .text
00000000 l    d  .data	00000000 .data
00000000 l    d  .bss	00000000 .bss
00000000 l       .text	00000000 $a
00000000 l       .text	00000000 .udivsi3_skip_div0_test
00000000 l    d  .debug_frame	00000000 .debug_frame
00000010 l       .debug_frame	00000000 $d
00000000 l    d  .debug_info	00000000 .debug_info
00000000 l    d  .debug_abbrev	00000000 .debug_abbrev
00000000 l    d  .debug_line	00000000 .debug_line
00000000 l    d  .debug_aranges	00000000 .debug_aranges
00000000 l    d  .ARM.attributes	00000000 .ARM.attributes
00000000 g     F .text	000000f4 .hidden __udivsi3
00000000 g     F .text	00000000 .hidden __aeabi_uidiv
000000f4 g     F .text	00000020 .hidden __aeabi_uidivmod
00000000         *UND*	00000000 __aeabi_idiv0

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 11:08 am
by Octocontrabass
SimonHA wrote:The linker finds the libgcc but does not seem to find the required functions such as '__aeabi_uidiv'?
You need to put -lgcc after your object files instead of before.

Re: Issue with compiling "Hello World" OS setup

Posted: Fri Nov 11, 2016 12:45 pm
by SimonHA
Thank you. That did the trick! I also needed to add -fno-exceptions to the G++ compiler. Now it builds :)