符号表,nm命令,EXPORT_SYMBOL 与 EXPORT_SYMBOL_GPL

http://blog.csdn.net/zuosifengli/article/details/7239622

http://shaojiashuai123456.iteye.com/blog/840015

http://www.cnblogs.com/itech/archive/2012/09/16/2687423.html


EXPORT_SYMBOL 与 EXPORT_SYMBOL_GPL
-----导出的符号可以被其他模块使用,不过使用之前一定要声明一下。EXPORT_SYMBOL_GPL()只适用于包含GPL许可权的模块。EXPORT_SYMBOL_GPL的符号必须要用MODULE_LICENSE("GPL")或者用MODULE_LICENSE("Dual BSD/GPL")之后才能在模块中引用。

如编写某个内核模块,依赖内核函数,需要确定此内核函数是否使用此声明过。如EXPORT_SYMBOL(inet_sendpage);

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

在内核中寻找内核符号表
在用户空间中可以用如下方法得到:

1. 从/usr/src/linux/System.map文件直接得到地址。
例如,要得到 do_fork 的地址,可以在命令行执行 $grep do_fork /usr/src/linux/System.map


2. 使用 nm 命令
$nm vmlinux


3. 从 /proc/kallsyms文件获得地址。
$cat /proc/kallsymsffffffffc000a5f8 B sync2dp_apv4_del [fptun]ffffffff85e0cda0 u hostapd_outputs [fptun]
ffffffff836cdeb8 u ip_route_input [fptun]
ffffffffc000a5d0 b user_miss_message [fptun]
ffffffff836ab080 t nfnetlink_rcv
ffffffff836ab0e8 T nfnetlink_unicast
ffffffffc0b0cda0 r C.498.29173 [route_cache]
c000000000071570 ? __mod_license577 [route_cache]
0000000000000000 a sp_rc.c [route_cache]

其中第一列是该符号在内核地址空间中的地址;

第二列是符号属性,小写表示局部符号,大写表示全局符号,具体含义参考man nm; 

第三列表示符号字符串. 这里只显示EXPORT_SYMBOL,EXPROT_SYMBOL_GPL处理过的符号。


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

功能

列出.o .a .so中的符号信息,包括诸如符号的值,符号类型及符号名称等。所谓符号,通常指定义出的函数,全局变量等等。

使用

nm [option(s)] [file(s)]

有用的options:

  • -A 在每个符号信息的前面打印所在对象文件名称;
  • -C 输出demangle过了的符号名称;
  • -D 打印动态符号;
  • -l 使用对象文件中的调试信息打印出所在源文件及行号;
  • -n 按照地址/符号值来排序;
  • -u 打印出那些未定义的符号;

常见的符号类型:

  • A 该符号的值在今后的链接中将不再改变;
  • B 该符号放在BSS段中,通常是那些未初始化的全局变量;
  • D 该符号放在普通的数据段中,通常是那些已经初始化的全局变量;
  • T 该符号放在代码段中,通常是那些全局非静态函数;
  • U 该符号未定义过,需要自其他对象文件中链接进来;
  • W 未明确指定的弱链接符号;同链接的其他对象文件中有它的定义就用上,否则就用一个系统特别指定的默认值。

注意几点:

  • -C 总是适用于c++编译出来的对象文件。还记得c++中有重载么?为了区分重载函数,c++编译器会将函数返回值/参数等信息附加到函数名称中去形成一个mangle过的符号,那用这个选项列出符号的时候,做一个逆操作,输出那些原始的、我们可理解的符号名称。
  • 使用 -l 时,必须保证你的对象文件中带有符号调式信息,这一般要求你在编译的时候指定一个 -g 选项,见 Linux:Gcc
  • 使用nm前,最好先用Linux:File查看对象文件所属处理器架构,然后再用相应交叉版本的nm工具。


举例

更详细的内容见man page。这里举例说明:

nm -u hello.o
显示hello.o 中的未定义符号,需要和其他对象文件进行链接.
nm -A /usr/lib/* 2>/dev/null | grep "T memset"

在 /usr/lib/ 目录下找出哪个库文件定义了memset函数. 




-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Linux内核符号表/proc/kallsyms的形成过程
---------------------------------------------------------------------------

./scripts/kallsyms.c负责生成System.map
./kernel/kallsyms.c负责生成/proc/kallsyms

./scripts/kallsyms.c解析vmlinux(.tmp_vmlinux)生成kallsyms.S(.tmp_kallsyms.S),然后内核编译过程中将kallsyms.S(内核符号表)编入内核镜像uImage
内核启动后./kernel/kallsyms.c解析uImage形成/proc/kallsyms


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

如何将内核中的函数、全局变量、静态变量都导出到/proc/kallsyms
------------------------------------------------------------------------
./scripts/kallsyms
static int all_symbols = 0;
==>
static int all_symbols = 1;

 

 

引入kallsyms
------------------------------------------------------------------------
    在2.6内核中,为了更好地调试内核,引入了kallsyms。kallsyms抽取了内核用到的所有函数地址(全局的、静态的)和非栈数据变量地址,生成一个数据块,作为只读数据链接进kernel image,相当于内核中存了一个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
        [*]     Include all symbols in kallsyms
        [*]     Do an extra kallsyms pass  

 

注: 配置CONFIG_KALLSYMS_ALL之后,就不需要修改all_symbol静态变量为1了


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值