Kernel symbols are names of functions and variables. Global symbols are those
which are available outside the file they are declared in. Global symbols
in the Linux kernel currently running on a system are available through
`/proc/kallsyms` file. This includes symbols defined inside kernel modules
Global symbols are of two types:
- those explicitly exported through EXPORT_SYMBOL_GPL and EXPORT_SYMBOL
- those which are not declared with `static` C keyword and hence visible to
code which is statically linked with the kernel itself and may be available
outside the kernel image.
The first type, explicitly exported ones, are denoted with capital letter in
output of `cat /proc/kallsyms` – e.g. T if the symbol is in text section, i.e.
a function name. The second type are denoted with small letter – e.g. t for a
function which isn’t exported via EXPORT_SYMBOL_GPL or EXPORT_SYMBOL.
Inside kernel code, we can access symbols which are exported explicity by
simply using them like other variables, e.g. by calling printk() function.
For global symbols which aren’t explicitly exported, but are still available,
we can attempt to access them by calling kallsyms_lookup_name() function,
defined in kernel/kallsyms.c:
unsigned long kallsyms_lookup_name(const char *name);
This takes symbol name as argument and returns its address in memory, i.e. a
pointer to it. The calling code can dereference the pointer to make use of that
symbol. If the symbol isn’t found, the function returns NULL.