3

The kernel module can not call libc since libc run under user space.
There are some other kernel specified APIs just like printk() to make modules work fine.
As I understand that libc is a collection of several standard c function obj(s).
It is supposed to exist a collection (or library) to include several kernel standard function objects.
So I can link my kernel module with these kernel standard libraries to do work, right ?

briefly speaking , my question is as followings ...

in user space :
aaa.o link bbb.o to call myfunc()
aaa.o link libc.so to call printf()

in kernel space :
aaa.ko link bbb.ko call myfunc() ? this is Question1
aaa.ko link xxx to call printk() ? what is xxx called , Question2

thanks !

summerdog
  • 71
  • 1
  • 6

3 Answers3

8

Kernel modules can only call kernel functions (which are in the fixed part of the kernel). They don't and can't use any external libraries.

So there is no kernel standard library (it is the kernel itself which contains printk).

Conceptually, kernel code is in the freestanding dialect of C; it does not use any C standard library functions (for obscure reasons, Linux kernel code is not compiled with -ffreestanding dialect option to gcc )

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • I am confused about the module build process. In compile time, GCC checked the header files which be included by my module (e.g. init.h module.h) since I specified the kernel header directory. In link time, GCC check the definition of functions which be called by my module (e.g. printk() ) , how can it PASS without any error if no any libraries offer the definition of function to my module ??? I known module call kernel function in 'run time'. thanks ! – summerdog Apr 03 '14 at 02:17
2

You get a .ko file which is a kernel object file. GCC does not link it. The kernel you insert it to does, at runtime.

xiay
  • 855
  • 8
  • 19
0

Question 2

aaa.ko link xxx to call printk() ? what is xxx called

This is still a dynamic runtime relocation, just like in userspace, except there is no library mapped in. So the dynamic linker, ld.so, doesnt handle the reloactions, but instead the insmod(2) function does. Actually insmod(2) does little more than map in the .ko and pass the request off to the syscall, sys_init_module.

In /include/linux/syscall.h you can see that init_module is defined in kernel/module.c. I am using the 5.4.x release for reference. If you walk through the code, you will see a series of calls like this: init_module() -> load_module() -> simplify_symbols() -> lookup_symbol().

Since the .ko is an ELF object, it has a symbol table and relocation section just like any userspace ELF binary. Simplify_symbols walks the module's symbol table and resolves the relocatable symbols at runtime, when the addresses can be known.

For a userland process, libraries have to be mapped into the process memory. For a kernel module, its the opposite. The module is mapped into the kernels memory where all the functions exist, they just have to be resolved/found. To be resolved, the kernel has a symbol table at a fixed location, early in its memory, not affected by ASLR. Lookup_symbol searches the kernel symbol table using the symbol's name, and resolves its address.

This is a very abbreviated and simplified description of the process. All you need to grasp is that insmod makes a syscall to init_module, that resolves the function addresses at runtime by searching the kernel symbol table. The addresses in the module code are then fixed-up with real addresses (or more likely offsets to the addresses).

Question 1

aaa.ko link bbb.ko call myfunc()

When a module is loaded into memory, it becomes part of the kernel code. Every use of the EXPORT_SYMBOL() macro in a module will add those symbols to the Kernel Symbol Table. So bbb.ko would include the line EXPORT_SYMBOL(myfunc), which causes it to be added to the kernel symbol table when the module is loaded. When module aaa.ko has to resolve myfunc(), it will do so just like process described in question 2.

Contrived Example
The kernel core exports many useful functions and variables by default that are useful for most kernel developers, such as printk, as you mentioned. Printk is defined in kernel/printk/printk.c and you can see that immediately following the fucntion is EXPORT_SYMBOL(printk), because all symbols have to be explicitly exported globally. You could validate it like this:

$sudo grep -E '\bprintk\b' /proc/kallsyms  
<some address> T printk  

After you loaded the hypothetical bbb.ko module with the exported function myfunc, you would also be able to find it in the kernel symbol table:

$sudo grep -E '\bmyfunc\b' /proc/kallsyms  
<some address> T myfunc  [bbb]  
typedeaf
  • 1,511
  • 13
  • 8