sprint_symbol函数功能描述:该函数根据一个内存中的地址address查找一个内核符号,并将该符号的基本信息,如符号名name、它在内核符号表中的偏移offset和大小size、所属的模块名(如果有的话)等信息连接成字符串赋值给文本缓冲区buffer。
其中所查找的内核符号可以是原本就存在于内核中的符号,也可以是位于动态插入的模块中的符号。
文章目录
sprint_symbol文件包含
sprint_symbol函数定义
在内核源码中的位置:linux-3.19.3/kernel/kallsyms.c
函数定义格式:
sprint_symbol输入参数说明
buffer
:文本缓冲区,它用来记录内核符号的信息,它是一个输出型参数。
address
:内核符号中的某一地址,为输入型参数。
sprint_symbol返回参数说明
返回值是一个int型,它表示内核符号基本信息串的长度,即buffer所表示的字符串的长度。
sprint_symbol实例解析
编写测试文件:sprint_symbol.c
头文件及全局变量声明如下:
模块初始化函数:
模块退出函数:
模块初始化及退出函数调用:
实例运行结果及分析:
首先编译模块,执行命令insmod sprint_symbol.ko插入模块,然后执行命令dmesg -c,会出现如图所示的结果。
结果分析:
测试程序中调用了find_symbol()内核函数,它的功能是根据所给的模块名字来获得模块描述符指针的。
在测试程序中首先声明一个文本缓冲区buffer,其容量为KSYM_SYMBOL_LEN,它是一个宏,在linux-3.19.3/include/linux/kallsyms.h文件中定义,是内核指定的存储内核符号基本信息的长度。
测试程序分成三个部分来测试函数sprint_symbol()的功能。
第一部分是将参数address赋值为__builtin_return_address(0)
,它指当前函数的返回地址,也即测试程序中sprint_symbol_init()
的返回地址。由输出信息可知,buffer的内容为“do_one_initcall+0xfe/0x189”,其中“do_one_initcall”为内核符号名,0xfe为address相对于该符号起始地址的偏移,0x189则为符号所占内存空间的大小。可以看到buffer中没有关于内核模块名的信息,这是因为do_one_initcall原本就存在于内核中,它不属于某一通过动态加载而插入内核的模块。而ret = 26则表示buffer缓冲区的内容为26字节。
第二部分是将参数address赋值为某一模块的内存起始地址,该模块通过find_symbol()函数查找得到。输出信息中buffer的内容与第一部分的类似,只是最后增加了“[test_module]”,它是符号所属的模块名。
第三部分将当前模块中符号a_symbol的地址加上偏移量5赋值给address,输出信息与第二部分类似。这里说明一下buffer中关于该符号的偏移量0x5,它是参数address相对于符号起始地址的偏移量,如果将address赋值为a_symbol的地址,则buffer中关于符号的偏移量将为0x0。