Failed to compile my OS Kernel

Hi, I'm creating an OS on Ubuntu and I create my project using cmake.
Here is the CMakeLists.txt content of my file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
cmake_minimum_required(VERSION 3.16.3)

# Set the active output directories:
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY build/x86_64/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY build/x86_64/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY build/x86_64/bin)

project(kernel)

set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 1)

set(CMAKE_CXX_STANDAED 17)

set(KERNEL_BIN "x86_64-kernel.bin")

set(LINKER_SCRIPT targets/x86_64/linker.ld)
set(GRUB_CFG targets/x86_64/iso/boot/grub/grub.cfg)

set(CMAKE_ASM_NASM_OBJECT_FORMAT "elf64")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-red-zone -mcmodel=large -mno-sse -ffreestanding -nostdlib -fno-pie -fno-pic -no-pie")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mno-red-zone -mcmodel=large -mno-sse -ffreestanding -nostdlib -fno-pie -fno-pic -no-pie")
set(CMAKE_ASM_FLAGS "{CMAKE_ASM_FLAGS} -felf64")

set(CMAKE_CXX_COMPILER "/usr/bin/gcc")
set(CMAKE_C_COMPILER "/usr/bin/g++")
set(CMAKE_LINKER "/usr/bin/ld")

enable_language(ASM_NASM)

file(GLOB KERNEL_C_MODULES src/impl/kernel/*.c)
file(GLOB X86_64_C_MODULES src/impl/x86_64/*.c)
file(GLOB BOOT_ASM_MODULES src/impl/x86_64/boot/*.asm)

add_executable(
    ${KERNEL_BIN}
    
    ${KERNEL_C_MODULES}
    ${X86_64_C_MODULES}
    ${BOOT_ASM_MODULES}
)

set(CMAKE_LINKER "/usr/bin/ld")
set(CMAKE_LINKER_FLAGS "-n -o -T ${LINKER_SCRIPT}")
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> ${CMAKE_LINKER_FLAGS} <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

include_directories(src/intf)
target_include_directories(${KERNEL_BIN} PUBLIC src/intf)

set_target_properties(${KERNEL_BIN} PROPERTIES LINK_FLAGS "-n -T ${LINKER_SCRIPT}")

add_custom_command(TARGET ${KERNEL_BIN} POST_BUILD
    COMMAND mkdir -p dist/x86_64/boot/grub
    COMMAND cp ${KERNEL_BIN} dist/x86_64/boot/${KERNEL_BIN}
    COMMAND cp ${GRUB_CFG} dist/x86_64/boot/grub
    COMMAND grub-mkrescue -o kernel.iso dist/x86_64/
    COMMAND rm -r dist/
    )
 */


When I compile the files, that's the output I get:

Using built-in specs.
COLLECT_GCC=/usr/bin/g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-HskZEa/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) 
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-mno-red-zone' '-mcmodel=large' '-mno-sse' '-ffreestanding' '-nostdlib' '-fno-pic' '-no-pie' '-v' '-n' '-T' 'targets/x86_64/linker.ld' '-o' 'build/x86_64/bin/x86_64-kernel.bin' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cc89YgW3.res --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o build/x86_64/bin/x86_64-kernel.bin -n -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/x86_64-kernel.bin.dir/src/impl/kernel/main.c.o CMakeFiles/x86_64-kernel.bin.dir/src/impl/x86_64/print.c.o CMakeFiles/x86_64-kernel.bin.dir/src/impl/x86_64/terminal.c.o CMakeFiles/x86_64-kernel.bin.dir/src/impl/x86_64/boot/header.asm.o CMakeFiles/x86_64-kernel.bin.dir/src/impl/x86_64/boot/main.asm.o CMakeFiles/x86_64-kernel.bin.dir/src/impl/x86_64/boot/main64.asm.o -T targets/x86_64/linker.ld
/usr/bin/ld: CMakeFiles/x86_64-kernel.bin.dir/src/impl/x86_64/boot/main64.asm.o: in function `long_mode_start':
/home/odedbe/Desktop/GitHub/LearnOS/LearnOS/src/impl/x86_64/boot/main64.asm:(.text+0xf): undefined reference to `kernel_main'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/x86_64-kernel.bin.dir/build.make:135: build/x86_64/bin/x86_64-kernel.bin] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/x86_64-kernel.bin.dir/all] Error 2
make: *** [Makefile:84: all] Error 2


And here is the code which the compiler tells me about:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
global long_mode_start
extern kernel_main

section .text
bits 64  ; OS target.
long_mode_start:
    ; Load null into all data segment registers
    mov ax, 0
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    ; Call the kernel's main:
    call kernel_main    

    hlt  ; Don't run any further instructions.


How can I fix this problem?

Thanks.
Last edited on
I've only used CMake once or twice, so apologies if this is obvious, but are you compiling as C, or C++? And what are the actual compiler commands that CMake is generating which you eventually call? Last, where in your source code is kernel_main defined?
Last edited on
Well, I'm using C and my kernel_main is defined in main.c which I'm also compiling.
I'm not sure how I can check for the exact commands which the makefile executes because the cmake makes it much more complicated to check.
Last edited on
Others might be able to provide more help if you add the -v flag to gcc, to output more verbose information.
And where can I do that in the CMake file?
OK, I found out that I need to use:
 
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -v")
Looks like you can also do the following: https://sidvind.com/wiki/CMake/Verbose_output
To make the verbosity be on CMake's side, and not the compiler side.

The first way is to simply run make with the additional argument "VERBOSE=1". This will show each command being run for this session, which is the most useful way to see if the flags is correct.

% make VERBOSE=1


The second way is to permanently disable the pretty output in your CMakeLists.txt by setting CMAKE_VERBOSE_MAKEFILE.

Code: CMakeLists.txt

set( CMAKE_VERBOSE_MAKEFILE on )
Last edited on
Thanks!
Hmm I still don't see the command which is compiling main.c. Or the assembly. Maybe it isn't re-creating the .o files, try cleaning everything?

(BTW, I don't want to get your hopes up: I am not saying I will be able to solve this for you, I am just trying to get as much as information as possible to increase the chances of somebody being able to help you.)

https://forum.osdev.org seems to be the place where others are posting similar questions. There could still be somebody here that can help you, but if it turns out nobody else can help you here, you might have more luck there.
Last edited on
OK, I'll try to ask there with more details.

Thank you for your help!
Does anything resembling kernel_main exist within
objdump -t main.c.o

According to your linker commands it would be located at:
objdump -t CMakeFiles/x86_64-kernel.bin.dir/src/impl/kernel/main.c.o
Last edited on
Yes, I do see the files in 'CMakeFiles'
Last edited on
Yes but does "kernel_main" or similar show up in the output of
objdump -t main.c.o
?

objdump -t main.c.o | grep "kernel_main"
Last edited on
The code you showed, is that main64.asm? You're not very clear in the information you present.

I don't see a main.o in your link command.
Registered users can post here. Sign in or register to post.