内核符号表的生成和查找过程

本文详细介绍了内核符号表的生成过程,包括System.map和/proc/kallsyms的区别,以及内核如何在运行时查找符号。内核在编译时嵌入符号表,通过scripts/kallsyms工具生成汇编文件,然后经过多步骤编译链接,形成最终的kallsyms.o。查找符号时,内核使用kallsyms_lookup()函数,结合kallsyms_addresses、kallsyms_names、kallsyms_markers等全局变量进行高效查找。
摘要由CSDN通过智能技术生成

在内核中维护者一张符号表,记录了内核中所有的符号(函数、全局变量等)的地址以及名字,这个符号表被嵌入到内核镜像中,使得内核可以在运行过程中随时获得一个符号地址对应的符号名。而内核代码中可以通过 printk("%pS\n", addr) 打印符号名。

本文介绍内核符号表的生成和查找过程。

1. System.map和/proc/kallsyms

System.map文件是编译内核时生成的,它记录了内核中的符号列表,以及符号在内存中的虚拟地址。这个文件通过nm命令生成,具体可参考内核目录下的scripts/mksysmap脚本。System.map中每个条目由三部分组成,例如:

f0081e80 T alloc_vfsmnt

即“地址  符号类型  符号名”

其中符号类型有如下几种:

  •   A =Absolute
  •   B =Uninitialised data (.bss)
  •   C = Comonsymbol
  •   D =Initialised data
  •   G =Initialised data for small objects
  •   I = Indirectreference to another symbol
  •   N =Debugging symbol
  •   R = Readonly
  •   S =Uninitialised data for small objects
  •   T = Textcode symbol
  •   U =Undefined symbol
  •   V = Weaksymbol
  •   W = Weaksymbol
  •  Corresponding small letters are local symbols

/proc/kallsyms文件是在内核启动后生成的,位于文件系统的/proc目录下,实现代码见kernel/kallsyms.c。前提是内核必须打开CONFIG_KALLSYMS编译选项。它和System.map的区别是它同时包含了内核模块的符号列表。

通常情况下我们只需要_stext~_etext_sinittext~_einittext之间的符号,如果需要将nm命令获得的所有符号都记录下来,则需要开启内核的CONFIG_KALLSYMS_ALL编译选项,不过一般是不需要打开的。

2. 内核符号表

内核在执行过程中,可能需要获得一个地址所在的函数,比如在输出某些调试信息的时候。一个典型的例子就是使用dump_stack()函数打印栈回溯信息。

但是内核在查找一个地址对应的函数名时,没有求助于上述两个文件,而是在编译内核时,向vmlinux嵌入了一个符号表,这样做可能是为了方便快速的查找并避免文件操作带来的不良影响。

2.1 内核符号表的结构

内嵌的符号表是通过内核目录下的scripts/kallsyms工具生成的,工具的源码为相同目录下的kallsyms.c。这个工具的用法如下:

nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S

可见同样是通过nm命令得到vmlinux的符号表,并将这些符号表信息进行调整,最终生成一个汇编文件。这个汇编文件中包含了6个全局变量:kallsyms_addresses,kallsyms_num_syms,kallsyms_names,kallsyms_markers,kallsyms_token_tablekallsyms_token_index,其中:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值