kallsyms子系统

作用

在2.6版的内核中,为了更方便的调试内核代码,开发者考虑将内核代码中所有函数以及所有非栈变量的地址抽取出来,形成是一个简单的数据块(data blob:符号和地址对应),并将此链接进 vmlinux 中去。如此,在需要的时候,内核就可以将符号地址信息以及符号名称都显示出来,方便开发者对内核代码的调试。完成这一地址抽取+数据快组织封装功能的相关子系统就称之为 kallsyms。反之,如果没有 kallsyms 的帮助,内核只能将十六进制的符号地址呈现给外界,因为它能理解的只有符号地址,而并不包括人类可读的符号名称。

内核相关配置选项

CONFIG_KALLSYMS 导出所有内核函数符号

CONFIG_KALLSYMS_ALL 导出所有内核符号,并且包含变量符号

/proc/kallsyms中标志的含义

  • T The symbol is in the text(code) section

  • D The symbol is in the initialized data section

  • R The sysbol is in a read only data section

  • t static

  • d static

  • R const

  • r static const

/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

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

  5. /proc/kallsyms包含了内核中的函数符号(包括没有EXPORT_SYMBOL)、全局变量(用EXPORT_SYMBOL导出的全局变量)

/proc/kallsyms和System.map的区别

/proc/kallsyms 包含内核静态代码中的符号和动态加载模块的符号 System.map 仅包含内核静态代码中的符号

什么情况下内核符号不会出现在/proc/kallsyms中

只有两种情况下内核的符号不会出现在/proc/kallsyms下

  1. 内核函数被定义为static,并且在编译时内核将函数优化为inline,也就是说函数在编译时被编译器展开

  2. 函数被#define宏包含,在编译时编译条件未打开,没有被编入内核

参考

Last updated

Was this helpful?