kallsyms在进行源码调试时具有相当重要的作用。linux内核在编译的过程中,将内核中所有的符号(所有的内核函数以及已经装载的模块)及符号的地址以及符号的类型信息都保存在了/proc/kallsyms文件中。具体格式如下:符号地址,符号类型,符号名
c0100000 T startup_32
c0100000 A _text
c01000c6 t checkCPUtype
c0100147 t is
486c010014e t is
386c010019f t L
6c01001a1 t check_x
87c01001ca t setup_idt
c01001e7 t rp_sidt
c01001f4 t ignore_int
c0100228 T calibrate_delay为了弄清楚内核具体是怎样查询的,我们首先必须知道这些信息在内核中是怎样存储的。
内核为了存储这些信息,定义了如下变量:
extern const unsigned long kallsyms_num_symsextern const u8 kallsyms_token_table[] const u16 kallsyms_token_index[] extern const unsigned long kallsyms_addresses[] extern const unsigned long kallsyms_markers[] |
其中kallsyms_num_syms统计了内核中所有符号的个数;
kallsyms_addresses数组记录了所有内核符号的地址(已经按顺序排列好)
kallsyms_names数组是函数名组成的一个大串,而该串的具体格式为
<lenth><length byte dada>
也就是说对于每个符号而言,都存储的是length+1个字节的内容,其中第一个字节代表了该符号的总长度,而后面length个自己代表了符号的内容。
在这里需要说明一下为了方便符号的查找,linux内核做了两方面的工作:
将常用的串存储在数组kallsyms_token_table数组中,而kallsyms_token_index则代表了该串的索引。其中token就代表了这些常用的字符串