1.符号的作用
简单的说符号就是一个函数名或者变量名。
2.内核符号表
就像自己编写的C程序一样有自己的函数名与变量名一样,内核中也有变量名与函数名,所以就存在内核符号表。在编译linux内核时编译完后会存在一个叫System.map的文件,这个就是内核符号表文件。
3.内核符号表的作用
当我们在使用gdb调试程序时,会输出变量名与函数名,但是在计算机运行时是不识别变量名与函数名的,是用的一个一个的地址,符号表就是用来做地址与变量或者函数名之间映射的。
由上面的分析可以知道System.map这个文件就是做内核的程序地址与变量名或者函数名的映射的。
4.内核符号表的应用
内核符号表最常用在内核的oops调试中。
当出现一个oops时,系统就会显示出用于调试问题的相关信息,比如所有CPU寄存器 中的内容以及页描述符表的位置等,尤其会象下面那样打印出EIP(指令指针)的内容:
EIP: 0010:[<00000000>]
Call Trace: []
为了帮助我们使用oops输出符号信息,Linux使用了一个称为klogd(内核日志后台程序)的 后台程序,klogd会截取内核oops并且使用syslogd将其记录下来,并将某些像c010b860 的信息转换成我们可以识别和使用的信息。换句话说,klogd是一个内核消息记录器(logger), 它可以进行名字-地址之间的解析。一旦klogd开始转换内核消息,它就使用手头的记录器, 将整个系统的消息记录下来,通常是使用syslogd记录器。
为了进行名字-地址解析,klogd就要用到System.map文件。
5.klogd的符号解析过程
klogd符号解析分两种
一.静态解析
静态转换,将使用System.map文件
二.动态解析
动态转换,假设你加载了一个产生oops的内核模块。于是就会产生一个oops消息,klogd就会截获它,并发现该oops发生在d00cf810处。由于该地址属于动态加载模块,因此在System.map文件中没有对应条目。klogd将会在其中寻找并会毫无所获,于是断定是一个可加载模块产生了oops。此时klogd就会向内核查询该可加载模块输出的符号。即使该模块的编制者没有输出其符号,klogd也起码会知道是哪个模块产生了oops,这总比对一个oops一无所知要好。