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)

Lets say my module is helloworld.ko
In order to display symbol table, we use following command.
 $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".

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.
 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.  

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.
 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

Popular posts from this blog

Linux Device Drivers - Part 4 : Linux Kernel Moduels (LKM) and types of LKM's

Linux Device Drivers Part - 5 : Building and Compiling Kernel Moduels

Linux Device Drivers - Part 8 : Kernel Symbol Tables