Linux Device Drivers Part 9 - More about Symbol tables
In this part we will discuss about following topics
- About undefined symbol error and steps to solve it
- Is it mandatory to export the symbols ?
- Location of symbol table
- About system.map file in Linux
1. About undefined symbol error and steps to solve it
The most common and most frustrating failure in loading an LKM is unresolved symbol, like this:
insmod: error inserting 'helloworld.ko': -1 Unknown symbol in module
To debug this error,
1. Use nm utility
2. Know symbol definitions (in next slide)
2. Know symbol definitions (in next slide)
Lets say my module is helloworld.ko
In order to display symbol table, we use following command.
Output of this command is
$nm helloworld.ko.
Output of this command is
00000000 r ____versions
0000002c r __mod_author22
00000000 r __mod_description24
00000020 r __mod_license23
00000040 r __mod_srcversion30
00000080 r __mod_vermagic5
00000063 r __module_depends
00000000 D __this_module
00000000 r _rheldata
00000000 T cleanup_module
00000000 B g_value
00000000 t hello_exit
00000000 t hello_init
00000000 T init_module
U printk
In this list, try to find the Undefined symbol tag / Unknown symbol tag (in second column of symbol table).
Once Symbol table is handy, we need to know about symbol types.
Some of these types are:
A for absolute
B or b for uninitialized data section (called BSS)
D or d for initialized data section
G or g for initialized data section for small objects (global)
i for sections specific to DLLs
N for debugging symbol
p for stack unwind section
R or r for read only data section
S or s for uninitialized data section for small objects
T or t for text (code) section
U for undefined
V or v for weak object
W or w for weak objects which have not been tagged so
- for stabs symbol in an a.out object file
2. Is it mandatory to export the symbols ?
Now with symbol table and symbol types in hand, we need to check which symbol type is relevant to our error. From above symbol types, "U for undefined" is relevant "Unknown symbol in module".
Now with symbol table and symbol types in hand, we need to check which symbol type is relevant to our error. From above symbol types, "U for undefined" is relevant "Unknown symbol in module".
So, the symbols which are having U in the symbol table (second column) displayed are g_value and printk. printk will be resolved by Kernel while loading the module because relevant header files are included. So, we need to concentrate on g_value and why its displayed.
In order to resolve this, you need to either export this in any other module where the definition exists or you need to make this local to this module.
To know answer for this question, you can think of kernel symbols as being visible at three different levels in the Kernel source code:
"static", - visible only within their own source file (just like standard user space programming),
"external" - potentially visible to any other code built into the kernel itself, and
"exported - visible and available to any loadable module
From above statement it’s obvious that if you are writing a Linux Kernel Module, it’s mandatory to export your module symbols if you want other module to benefit using them.
3. Location of Symbol tables
The symbol exported by the statically Linked kernel and all linked-in modules can be retrieved by reading the /proc/kallsyms file or using the query_modue() system call.
Take a look at /proc/kallsyms entry by typing following command in your terminal.
Every entry in this file represents an exported (public) kernel symbol, which can be accessed by a Linux Kernel Module.
If you would like to get symbol table of a particular module or kernel object, you can use “nm” command
4.About System.map file in Linux
Every kernel image that you build has a symbol table with it . The linux kernel symbol table contains names and addresses of all the kernel symbols.
In Linux, the System.map file is a symbol table used by the kernel.
Because addresses may change from one build to the next, a new System.map is generated for each build of the kernel.
The System.map is required when the address of a symbol name, or the symbol name of an address, is needed. It is especially useful for debugging kernel panics and kernel oopses.
After building the Linux kernel, System.map is located in the root of the source directory. Try typing “locate System.map” command in terminal.
These topics are also explained in detail with practical session in below video.
If you like it, please do subscribe and shed your comments.
In order to resolve this, you need to either export this in any other module where the definition exists or you need to make this local to this module.
To know answer for this question, you can think of kernel symbols as being visible at three different levels in the Kernel source code:
"static", - visible only within their own source file (just like standard user space programming),
"external" - potentially visible to any other code built into the kernel itself, and
"exported - visible and available to any loadable module
From above statement it’s obvious that if you are writing a Linux Kernel Module, it’s mandatory to export your module symbols if you want other module to benefit using them.
The symbol exported by the statically Linked kernel and all linked-in modules can be retrieved by reading the /proc/kallsyms file or using the query_modue() system call.
Take a look at /proc/kallsyms entry by typing following command in your terminal.
cat /proc/kallsyms
Every entry in this file represents an exported (public) kernel symbol, which can be accessed by a Linux Kernel Module.
If you would like to get symbol table of a particular module or kernel object, you can use “nm” command
$nm KernelModule.ko.
Every kernel image that you build has a symbol table with it . The linux kernel symbol table contains names and addresses of all the kernel symbols.
In Linux, the System.map file is a symbol table used by the kernel.
Because addresses may change from one build to the next, a new System.map is generated for each build of the kernel.
The System.map is required when the address of a symbol name, or the symbol name of an address, is needed. It is especially useful for debugging kernel panics and kernel oopses.
After building the Linux kernel, System.map is located in the root of the source directory. Try typing “locate System.map” command in terminal.
locate System.map
These topics are also explained in detail with practical session in below video.
If you like it, please do subscribe and shed your comments.
Comments
Post a Comment