Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
SimonHA
Posts: 12 Joined: Thu Nov 10, 2016 4:00 pm
Post
by SimonHA » Thu Nov 10, 2016 4:05 pm
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
iansjack
Member
Posts: 4706 Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK
Post
by iansjack » Thu Nov 10, 2016 4:38 pm
There appears to be a rogue ")" at the end of the line:
build_binary: $(KERNEL_AS_OBJ) $(KERNEL_SRC_OBJ) $(KERNEL_C_LIB_OBJ))
SimonHA
Posts: 12 Joined: Thu Nov 10, 2016 4:00 pm
Post
by SimonHA » Fri Nov 11, 2016 3:01 am
Okay, that is a bit embarrassing
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?
iansjack
Member
Posts: 4706 Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK
Post
by iansjack » Fri Nov 11, 2016 3:15 am
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().
SimonHA
Posts: 12 Joined: Thu Nov 10, 2016 4:00 pm
Post
by SimonHA » Fri Nov 11, 2016 3:50 am
Okay, thank you for your help. How do I tell my cross compiler where this crt0.o is?
Icee
Member
Posts: 100 Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia
Post
by Icee » Fri Nov 11, 2016 4:30 am
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.
iansjack
Member
Posts: 4706 Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK
Post
by iansjack » Fri Nov 11, 2016 5:27 am
I think that Icee's advice is better than mine, so I'd recommend that you try that first.
SimonHA
Posts: 12 Joined: Thu Nov 10, 2016 4:00 pm
Post
by SimonHA » Fri Nov 11, 2016 8:22 am
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]
xenos
Member
Posts: 1121 Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:
Post
by xenos » Fri Nov 11, 2016 9:35 am
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.
SimonHA
Posts: 12 Joined: Thu Nov 10, 2016 4:00 pm
Post
by SimonHA » Fri Nov 11, 2016 10:50 am
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
SimonHA
Posts: 12 Joined: Thu Nov 10, 2016 4:00 pm
Post
by SimonHA » Fri Nov 11, 2016 12:45 pm
Thank you. That did the trick! I also needed to add -fno-exceptions to the G++ compiler. Now it builds