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]