Skip to content
Advertisement

init function not present in kallsyms

I wrote a simple hello world kernel module

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>

MODULE_LICENSE("GPL");
static int __init test_hello_init(void)
{
    printk(KERN_INFO"%s: In initn", __func__);
    return 0;
}

static void __exit test_hello_exit(void)
{
    printk(KERN_INFO"%s: In exitn", __func__);
}

module_init(test_hello_init);
module_exit(test_hello_exit);

After loading the module, i am checking what all symbols are added into /proc/kallsysms. I don’t observe test_hello_init. Why don’t we have it

0000000000000000 r __func__.20413   [hello]
0000000000000000 t test_hello_exit  [hello]
0000000000000000 r __func__.20417   [hello]
0000000000000000 r _note_6  [hello]
0000000000000000 d __this_module    [hello]
0000000000000000 t cleanup_module   [hello]

Advertisement

Answer

Using Linux kernel 5.8 source as a reference, the module’s symbol table for “kallsyms” is set up by the call to add_kallsyms() (in “kernel/module.c”) at module load time (call path: syscall init_module(), load_module(), post_relocation(), add_kallsyms()), before the module has been fully initialized. It adds the module’s full symbol table (pointed to by the module’s kallsyms member), and also constructs a cut-down, core symbol table (in the module’s core_kallsyms member) for use after the module has been initialized.

The switch from the full symbol table to the core symbol table occurs at the call

    /* Switch to core kallsyms now init is done: kallsyms may be walking! */
    rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);

from do_init_module() (call path: syscall init_module(), load_module(), do_init_module()). This occurs after the module’s init function (if it has one) has been called.

do_init_module() is also responsible for discarding the module’s initial memory section (containing functions marked __init and data marked __initdata) once the module is initialized successfully. This is done by adding a pointer to the module’s init section to the static init_free_list list and scheduling a work item to free any sections on the list:

    freeinit = kmalloc(sizeof(*freeinit), GFP_KERNEL);
    freeinit->module_init = mod->init_layout.base;
    if (llist_add(&freeinit->node, &init_free_list))
        schedule_work(&init_free_wq);

The scheduled work function is do_free_init(). That exchanges init_free_list with an empty list and iterates through the original copy of init_free_list to free the module’s initial memory section:

    list = llist_del_all(&init_free_list);
    llist_for_each_safe(pos, n, list) {
        initfree = container_of(pos, struct mod_initfree, node);
        module_memfree(initfree->module_init);
        kfree(initfree);
    }
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement