0

as I am developing my "OsDev" project, where I am learning a new stuff (for somebody who did not code in C/C++ for a long time due to web development it is kinda "new"). I figured out in the other thread, that calling a C++ function from ASM needs to have a extern "C" prefix but now I have problem with the lining of standard libraries as a for example cstdio etc. I stuck with this message.

kc.o: In function `kmain':
kernel.cpp:(.text+0x3e4): undefined reference to `strlen`

C++

#include <string.h>
#include <cstdio>

#include "inc/screen.h"

extern "C" void kmain()
{
    clearScreen();
    kernel_print((char*)"Hello Github! :-)", 0x04);
}

and if I try to use strlen() it won't link. (BTW. including screen.h is working for some reason). Compiling script

nasm -f elf32 kernel.asm -o kasm.o
g++ -c kernel.cpp -o kc.o -lgcc -m32  -Wall -Wextra -O2
ld -m elf_i386 -T link.ld -o kernel.bin kasm.o kc.o

link.ld

OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
 {
   . = 0x100000;
   .text : { *(.text) }
   .data : { *(.data) }
   .bss  : { *(.bss)  }
 }

Thanks for any suggestions. :)

Ondřej Langr
  • 43
  • 1
  • 4
  • 3
    "calling a C++ function from ASM needs to have a extern "C" prefix" - No it does not. It certainly makes things easier by ensuring a C calling convention and no C++ name mangling, but there's no *requirement* here. You can (in principle) call *any* function from asm - regardless of language - it just may not be easy - and you need to know what you are doing (in my experience; the biggest barrier). – Jesper Juhl Apr 17 '18 at 21:43
  • Oh, ok. I just read that somewhere (about name mangling) and I named it just as a "simpler". In conclusion it does not solve my linking problem I guess. So.. :/ – Ondřej Langr Apr 17 '18 at 21:47
  • 1
    Make sure you link with libc statically. Even then, there is absolutely no guarantee which parts will work in your toy OS. `strlen` probably will if you get that far. `-lgcc` looks very suspicious too and your linker script as well (for example it doesn't seem to copy `.rodata`) – Jester Apr 17 '18 at 21:50
  • I think `-lgcc` is ignored on your `gcc -c` command line, because you're only creating a `.o`, not linking. It doesn't create a partially-linked object file (because that's not a thing), and it doesn't statically merge in some code from a static library either. **Put the libraries you need on your `ld` command line**. – Peter Cordes Apr 18 '18 at 00:15
  • @Jester: Hmm, glibc `strlen` might use SSE2 without checking. In which case [How do I enable SSE for my freestanding bootable code?](//stackoverflow.com/q/31563078) But maybe the version you get from statically linking 32-bit glibc won't. – Peter Cordes Apr 18 '18 at 00:16

1 Answers1

0

Your code cannot work as kernel's can't directly use shared libraries.

Why can't I use shared libraries directly in my kernel?

When an application is loaded by the operating system, all the required files are brought into its address space. This includes the executable file and any dynamic libraries (all ABI-conforming ELF applications will always link with a system library - the C Standard Library or just libc).

But while loading the kernel, only the original executable is loaded. Multiboot 2 (with GRUB bootloader) will allow you to load kernel-modules which can be dynamic libraries. But still, your kernel must know how to link itself and the kernel-modules in physical memory. To do so, you must implement a ELF parser and dynamic linker in your kernel.

Before implementing one, make sure your kernel is mature enough to systematically handle dynamic memory allocation, pagination, and other basic features.

How can I use the sweet features of libc?

Usually, you won't use all of the userspace functionality of libc. But things like memcpy, strlen, strcpyn and so on are absolutely necessary. You will have to implement these functions on your own, but the better part here is that, you can change the names of these functions. For example, if you prefere camelCase for function names, then you can also use function names like copyMemory, lengthOfString, etc.

https://github.com/SukantPal/Silcos-Kernel

I have built my own kernel, which has a few implementations of the required functions in KernelHost/Source/Util/CircuitPrimitive.cpp. You can look into that. Also, it has a full-fledged module linker. (KernelHost, ModuleFramework, etc. those parent folders contain separate kernel-module source code).

Make sure not to use the standard C headers in your kernel, as for now. Implement all required functions on your own, including printf

Shukant Pal
  • 706
  • 6
  • 19