Linux 内核符号表

时间:2022-06-16 06:08:08

一,什么是符号(Symbols)?

什么是Symbol  其实就是kernel中的变量(VariableName)或函数名称(Function Name),这样可以方便程序员在写程序时可以直接参照这一份Symbol的索引文件,找到所需要的kernel信息,这一份Symbol的索引文件又称为kernel symbol table

   

二,内核符号表(Kernel Symbol Table)?

2.1)定义:

内核符号表,就是在内核的内部函数或变量中,可供外部引用的函数和变量的符号表。

其实就是一个索引文件,它存在的目的就是让外部软件可以知道kernel文件内部实际分配的位置。


2.2)所在文件:

编译内核时,System.map文件用于存放内核符号表信息。

System.map文件位于/或者/boot/usr/src/linux/下)


2.3)文件的生成:

符号表是所有内核符号及其对应地址的一个列表,随着每次内核的编译,就会产生一个新的对应System.map文件,当内核运行出错时,通过System.map中的符号表解析,就可以查到一个地址值对应的变量名。System.map文件记录了所有代码的运行地址(所有函数和变量)。

【内核并不使用符号名。它是通过变量或函数的地址(指针)来使用变量或函数的。其实内核连System.map文件都不使用,只是生成用于调试用的。】


2.4system.map文件的格式:

   线性地址           类型        符号

ffffffff81002590       t       create_dev

ffffffff81009c00       T      show_regs

其中,类型若是小写字母则表示局部引用,若是大写字母则表示全局引用(外部).


2.5)内核符号表的存在意义:

1)把内核的符号地址,转化为程序猿可以看懂的符号名称。

内核符号表就是为程序员通过符号来访问程序体的对应地址(指针),建立了一个动态的,可变更的映射表格。

例如:

内核不会使用符号名create_dev,而会使用ffffffff81002590来引用这个变量。但程序猿们更喜欢符号名create_dev这样直观的名字。

所以就需要这么一个对应关系表。这个类似于网络里的DNS,没有谁愿意去记那没规律的IP地址,而记个网址就好记多了。

2)转换之后,就可以更方便的调试内核代码。

对于系统的oop消息、或者通过gdb的调试消息,都需要根据该对照表,将内核熟悉的函数地址转化为用户熟悉的函数名称,便于用户进行故障定位、运行监控。

而内核本身并不真正使用System.map,而只是用于做调试用。


2.6)内核符号表存储位置

2.6.1 System.map

磁盘中真实存在的文件,存储内核中静态编译的函数和变量地址,每个新编译内核对应一个System.map文件,当klogd输出内核消息时,会通过/boot/System.map来将函数、变量地址转换为名称,方便用户理解。该文件对应不同的编译内核有对应的实现文件。


2.6.2 /proc/kallsyms

内核启动时候创建,oops时定位错误,文件大小总为0,包含当前内核导出的、可供使用的变量或者函数;它只是内核数据的简单表示形式。


2.7System.map /proc/kallsyms 区别

二者相似点:

都是内核函数、变量的符号表,结构一致;对于可导出的内核变量、函数,其运行时在物理内存中的位置是一样的。

二者区别:

两者侧重点不同,

1System.map文件面向内核,对于内核中的没有导出的变量或者函数名,比如kthread_create_list链表头指针,也有其相应的内核地址,该文件一般是只读的、固定大小的,没有动态添加模块中的变量、函数名;

2)而kallsyms在内核启动过程中创建,并实时更新,反映的是系统的当前最新情况,其内部也包含内核或者是已加载模块导出的函数、变量名称。

所以和System.map文件有差别,kallsyms文件动态变化,大小不固定。

总结就是:

System.map文件较单纯,是在用户一开始编译就产生的固定文件,不会因为任何原因更改,除非被换掉。

/proc/kallsyms是一个在启动时由Linux kernel实时产生的文件,当系统有任何变更时,它就会马上做出修正。

因为这是动态的信息,当用户新增或删除一个module,都会自动做实时的修正(/proc下的都是这一类型的文件)

      

2.8)分类

Linux内核的符号表位于两个部分。

首先是内核的静态部分,也就是内核文件映像vmlinuz部分的符号表,对应于/proc/kallsymsSystem.map这两个文件。

还有一部分则是Linux可配置模块部分的符号表。

 

2.9)形成过程

 Linux内核符号表/proc/kallsyms的形成过程

1./scripts/kallsyms.c负责生成System.map

2./kernel/kallsyms.c负责生成/proc/kallsyms

3./scripts/kallsyms.c解析vmlinux(.tmp_vmlinux)生成kallsyms.S(.tmp_kallsyms.S),然后内核编译过程中将kallsyms.S(内核符号表)编入内核镜像uImage

内核启动后./kernel/kallsyms.c解析uImage形成/proc/kallsyms

要在一个内核中启用 kallsyms 功能,必须用进行内核配置,make menuconfig设置 CONFIG_KALLSYMS 选项为y;如果你要在 kallsyms 中包含全部符号信息,必须设置 CONFIG_KALLSYMS_ALL y

 

三,导出符号表

驱动程序中,如果该驱动程序中有被其他内核代码调用的部分,可以用EXPORT_SYMBOL导出到内核符号表中。

Linux 内核符号表