其实问题的本质是对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, ObjectFile (source file name), Section = memory section, Notype = untyped absolute symbol or undefined
  • Bind = 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 relocation
  • Name = 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

nm和readelf命令的区别的更多相关文章

  1. Linux 休眠,挂起(待机),关机等几个命令的区别及如何实现;如何启用Ubuntu的休眠模式

    这里对linux 的几个命令整理下,有:休眠,挂起,待机,关机等几个命令的区别及如何实现. 休眠是一种更加省电的模式,它将内存中的数据保存于硬盘中,所有设备都停止工作.当再次使用时需按开关机键,机器将 ...

  2. [转]Ubuntu中apt与apt-get命令的区别

    转载于https://www.sysgeek.cn/apt-vs-apt-get/ Ubuntu 16.04 发布时,一个引人注目的新特性便是 apt 命令的引入.其实早在 2014 年,apt 命令 ...

  3. apt与apt-get命令的区别与解释

    [apt与apt-get命令的区别与解释] Ubuntu 16.04 发布时,一个引人注目的新特性便是 apt 命令的引入.其实早在 2014 年,apt 命令就已经发布了第一个稳定版,只是直到 20 ...

  4. [转]Linux中set,env和export这三个命令的区别

    转自:http://www.2cto.com/os/201306/223758.html Linux中set,env和export这三个命令的区别   set命令显示当前shell的变量,包括当前用户 ...

  5. cmd命令和linux命令的区别

    cmd命令和linux命令看起来很相似,都是在一个控制台输入一些特定的指令去完成一些特定的操作.可是用过的朋友就会发现这些指令是有很多不同的,可是到底有什么不同,要说又说不上来,所以要了解一下. cm ...

  6. grep与find命令的区别

    grep与find命令的区别:grep搜索的是文本,find搜索的是文件,换句话说就是grep是查找匹配条件的行,find是搜索匹配条件的文件. grep文本搜索/过滤 用法:grep[参数]搜索字符 ...

  7. spss命令数据整理中compute与record命令的区别

    spss命令数据整理中compute与record命令的区别 record修改存在的变量,或者生成新的变量 spss变量定义说明 1.Name:变量名,定义规则与其它软件中的雷同,如第一个字符必须为字 ...

  8. centos7也支持service命令启动服务吗,对于centos7 中的systemctl和旧的service命令的区别和联系

    一.centos7也支持service命令启动服务吗 CentOS 7.0中一个最主要的改变,就是切换到了systemd.它用于替代红帽企业版Linux前任版本中的SysV和Upstart,对系统和服 ...

  9. binary hacks读数笔记(readelf命令)

    可以用readelf命令来查看elf文件内容,跟objdump相比,这个命令更详细. 1. readelf -h SimpleSection.o ELF Header: Magic: 7f 45 4c ...

随机推荐

  1. POST多个参数到Web API控制器

    交互基于Json的方式打包传递就不介绍了,主要设置请求头为 contentType: "application/json", //必须有 数据位Json格式的字符串,在服务器端定义 ...

  2. 给logstash 模板添加触发器

  3. df 和du 命令统计磁盘空间不准确

    Linux & Unix 中 df 和 du 命令统计磁盘空间数值不一致 经常会使用 df 和 du 分别查看磁盘空闲空间和占用空间,偶尔会发现 df(空闲空间) 会小于磁盘大小减去 du(占 ...

  4. java开发经验分享(一)

    一. 编码 1. 约束自己,规范编码习惯 充足的代码注释.标准缩进的格式.注意命名规范.参考<开发管理规范> "看上去"专业能促进代码质量.越是难看的代码,在它的演化过 ...

  5. HDU--3466(0-1背包+贪心/后效性)

    题意是: 给你一些钱 m ,然后在这个国家买东西, 共有 n 件物品,每件物品有  价格 P    价值 V    还有一个很特别的属性 Q, Q 指 你如过想买这件物品 你的手中至少有这钱Q . 虽 ...

  6. java_重写与重载的区别

    重写与重载的区别 重载(Overloading)和重写(Overriding)是Java中两个比较重要的概念.但是对于新手来说也比较容易混淆.本文通过两个简单的例子说明了他们之间的区别. 定义 重载 ...

  7. uva 111 History Grading(最长公共子序列)

    题目连接:111 - History Grading 题目大意:给出一个n 代表序列中元素的个数, 然后是一个答案, 接下来是若干个同学的答案(直到文件结束为止), 求出两个序列的最长公共子序列, 注 ...

  8. unity的坑

    http://dearymz.blog.163.com/blog/static/20565742013341916919/ 编辑器: Hierarchy窗口中是场景中的Game Object列表 Pr ...

  9. IT痴汉的工作现状25-技术之养成

    要想成为技术大牛,除了天赋以外,更与后天的刻苦努力分不开.伟仔我天生愚顿.工作多年后仍与大牛相差甚远,更加觉得技术的养成是一个异常困难的过程. 是我不用功吗?我不这样觉得.伟仔尽管是个懒人,但对于技术 ...

  10. top 命令SQLServer-sybase-oracle

    SQLServer: select top 10 * from tablename; select top 10 percent from tablename; select * from table ...