kallsyms 压缩_linux内核kallsyms机制分析

本文详细分析了Linux内核中的kallsyms机制,包括kallsyms的生成过程、内核符号表的形成、查找算法以及符号属性。kallsyms用于生成内核符号表,帮助调试和解析内核符号,如函数地址和名称,支持内核符号的查找和地址解析。
摘要由CSDN通过智能技术生成

一、前言

Linux内核是一个整体结构,而模块是插入到内核中的插件。尽管内核不是一个可安装模块,但为了方便起见,Linux把内核也看作一个模块。那么模块与模块之间如何进行交互呢,一种常用的方法就是共享变量和函数。但并不是模块中的每个变量和函数都能被共享,内核只把各个模块中主要的变量和函数放在一个特定的区段,这些变量和函数就统称为符号。

因此,内核也有一个module结构,叫做kernel_module。另外,从kernel_module开始,所有已安装模块的module结构都链在一起成为一条链,内核中的全局变量module_list就指向这条链:

struct module *module_list = &kernel_module;

一般来说,内核只会导出由EXPORT_PARM宏指定的符号给模块使用。为了使debugger提供更好的调试功能,需要使用kallsyms工具为内核生成__kallsyms段数据,该段描述所有不处在堆栈上的内核符号。这样debugger就能更好地解析内核符号,而不仅仅是内核指定导出的符号。

二、简介

在v2.6.0 的内核中,为了更好地调试内核,引入新的功能kallsyms.kallsyms把内核用到的所有函数地址和名称连接进内核文件,当内核启动后,同时加载到内存中.当发生oops,例如在内核中访问空地址时,内核就会解析eip位于哪个函数中,并打印出形如:

EIP is at cleanup_module+0xb/0x1d [client]的信息,

调用栈也用可读的方式显示出来.

Call Trace:

[] sys_delete_module+0x191/0x1ce

[] do_page_fault+0x189/0x51d

[] syscall_call+0x7/0xb

当然功能不仅仅于此,还可以查找某个函数例如的sys_fork的地址,然后hook它,kprobe就是这么干的。在v2.6.20 中,还可以包含所有符号的地址,应此功能更强大,就相当于内核中有了System.map了,此时查找sys_call_table的地址易如反掌。

三.sym的生成

1.形成过程

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

2.内核配置

在2.6 内核中,为了更好地调试内核,引入了kallsyms。kallsyms抽取了内核用到的所有函数地址(全局的、静态的)和非栈数据变量地址,生成一个数据块,作为只读数据链接进kernel p_w_picpath,相当于内核中存了一个System.map。需要配置CONFIG_KALLSYMS。

.config

CONFIG_KALLSYMS=y 符号表中包含所有的函数

CONFIG_KALLSYMS_ALL=y 符号表中包括所有的变量(包括没有用EXPORT_SYMBOL导出的变量)

CONFIG_KALLSYMS_EXTRA_PASS=y

make menuconfig

General setup --->

[*] Configure standard kernel features (for small systems) --->

[*] Load all symbols for debugging/ksymoops (选中此项,才有/proc/kallsyms接口文件, oops问题,选中此选项即可,子选项可以忽略)

[*] Include all symbols in kallsyms

[*] Do an extra kallsyms pass

3.编译生成列表

内核编译的最后阶段,make会执行

nm -n vmlinux|scripts/kallsyms

nm -n vmlinux生成所有的内核符号,并按地址排序,形如

......

c0100000 T startup_32

c0100000 A _text

c01000c6 t checkCPUtype

c0100147 t is486

c010014e t is386

c010019f t L6

c01001a1 t check_x87

c01001ca t setup_idt

c01001e7 t rp_sidt

c01001f4 t ignore_int

c0100228 T calibrate_delay

c0100228 T stext

c0100228 T _stext

c010036b t rest_init

c0100410 t do_pre_smp_initcalls

c0100415 t run_init_process

......

v2.6.0 的行数是2.5万左右

4.处理列表

scripts/kallsyms则处理这个列表,并生成连接所需的S文件kallsyms.S。在linux3.12中使用/scripts/kallsyms处理此列表。v2.6.0中形如:

#include

#if BITS_PER_LONG == 64

#define PTR .quad

#define ALGN .align 8

#else

#define PTR .long

#define ALGN .align 4

#endif

.data

.globl kallsyms_addresses

ALGN

kallsyms_addresses:

PTR 0xc0100228

PTR 0xc010036b

PTR 0xc0100410

PTR 0xc0100415

PTR 0xc010043c

PTR 0xc0100614

...

.globl kallsyms_num_syms

ALGN

kallsyms_num_syms:

PTR 11228

.globl kallsyms_names

ALGN

kallsyms_names:

.byte 0x00

.asciz "calibrate_delay"

.byte 0x00

.asciz "stext"

.byte 0x00

.asciz "_stext"

...

生成的符号表部分如下:

/*

......

c1618b03 t __raw_write_unlock_irq.constprop.29

c1618b19 T panic

c1618c91 T printk

......

c16a4d6b r __func__.17404

c16a4d78 R kallsyms_addresses

c16ef0dc R kallsyms_num_syms

c16ef0e0 R kallsyms_names

c17d5468 R kallsyms_markers

c17d590c R kallsyms_token_table

c17d5c78 R kallsyms_token_index

......

*/

5.生成的符号数组解析

1)kallsyms_addresses数组包含所有内核函数的地址(经过排序的),v2.6.0 中相同的地址在kallsyms_addresses中只允许出现一次,到后面的版本例如相同的地址可以出现多次,这样就允许同地址函数名的出现。

例如:

kall

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值