Symbol machine_power_off
is marked with "T" in /proc/kallsyms
:
$ grep -w machine_power_off /proc/kallsyms
ffffffff8102391b T machine_power_off
But it is not exported. Is "T" in kallsyms necessary and sufficient for a symbol to be exported? Is being exported necessary and sufficient for using in other modules?
My module using it is compiled with a warning:
WARNING: "machine_power_off" [/path/to/module.ko] undefined!
On host machine (3.2.0-4-amd64) I can load this module, but on VirtualBox (3.16.0-4-amd64) it produces the following message:
insmod: ERROR: could not insert module module.ko: Unknown symbol in module
Why is this module loaded in my host system, but not in VirtualBox?
Mark "T" in /proc/kallsyms
means that symbol is globally visible, and can be used in other kernel's code (e.g. by drivers, compiled built-in).
But for being usable in kernel module's code, symbol is needed to be exported using EXPORT_SYMBOL
or similar. List of exported symbols is maintained separately from list of all symbols in the kernel.
Exported symbols can be found in file /lib/modules/<kernel-version>/build/Module.symvers
.
(this file should exist for possibility to build kernel modules against given kernel).
To use kernel symbols that are global, but not exported (such as the machine_power_off
symbol that you mention), you can use kallsyms_lookup
in your module code:
#include <linux/kallsyms.h>
static void (*machine_power_off_p)(void);
machine_power_off_p = (void*) kallsyms_lookup_name("machine_power_off");
Now you can call the machine_power_off
function via the machine_power_off_p
pointer:
(*machine_power_off_p)();