其实问题的本质是对elf格式的理解问题,因为是查看so库的符号表发现的问题。
事情起因是这样的,由于我的一个程序编译的时候出现了undefined reference to “XXX”的错误,需要链接特定的so库,发现用nm [file]找不到“XXX”函数符号,结果用readelf -s [file] 就找到了。其实问题是我对so理解的不深刻。
一般来说,对于一个so库有两个符号表,一个是“正常的”(在.symtab和.strtab节中)。一个是动态的(.dynsym和.dynstr节中)。如果这个两个表被移除,那么so库就完全没有用了。动态符号表的符号只被用于动态加载器运行时的加载。而“正常”的符号表,一般是用来调试的,里面的函数符号,是没有被导出的(一般是一些静态函数),所以不可能被外部程序使用。“正常”的符号表里面的函数符号,也不会在动态符号表中。
可以用 nm -D
和 readelf -s这两个命令来显示一个so文件的动态符号表信息。链接器去查找的也是动态符号表中的函数符号.
readelf -s 出来的函数符号意义解释:
考虑一下输出:
符号表 .symtab
包含了一下1203个入口项:
Num: Value Size Type Bind Vis Ndx Name
310: a0008120 0 NOTYPE GLOBAL DEFAULT ABS _gp
734: a0000010 32 OBJECT GLOBAL DEFAULT 77 v
818: 9d000018 496 FUNC GLOBAL DEFAULT 71 main
849: a0000124 4 OBJECT GLOBAL DEFAULT 78 phrase
955: a0000000 9 OBJECT GLOBAL DEFAULT 77 peppers
1020: a000023c 192 OBJECT GLOBAL DEFAULT 80 bins
Num:
= 符号序号Value
= 符号的地址Size
= 符号的大小Type
= 符号类型:Func
= Function,Object
,File
(source file name),Section
= memory section,Notype
= untyped absolute symbol or undefinedBind
=GLOBAL
绑定意味着该符号对外部文件的可见.LOCAL
绑定意味着该符号只在这个文件中可见.WEAK
有点像GLOBAL, 该符号可以被重载.Vis
= Symbols can be default, protected, hidden or internal.Ndx
= The section number the symbol is in. ABS means absolute: not adjusted to any section address's relocationName
= symbol name
references:
http://stackoverflow.com/questions/9961473/nm-vs-readelf-s
http://stackoverflow.com/questions/3065535/what-are-the-meanings-of-the-columns-displayed-by-readelf
http://osily.lofter.com/post/161c56_3dfd53