博客
关于我
GDB读取动态库中定义的全局变量错误
阅读量:640 次
发布时间:2019-03-14

本文共 1834 字,大约阅读时间需要 6 分钟。

      最近看了一篇getopt使用的文章,为了追踪其执行的逻辑,于是采用GDB挂载调试的方式进行查看。但却出现了GDB打印全局变量optind的时候出现错误。

问题发现和描述

      首先optind是使用getopt时候的全局变量,表示使用getopt时候的下一个argv的指针索引。在应用程序调试的时候设置了多个参数,但是随着多次调用getopt,全局变量optind通过gdb打印出来的值却总是1, 但是通过程序打印出来的optind确实是逐步变化的。奇怪了,gdb怎么会有这么明显的bug呢?

      于是我在程序中打印出optind的地址为0x600D60.

      +++++++++++++++++++++

      The optind address is 0x600d60.

      +++++++++++++++++++++

      那么我们看看gdb打印出来的optind的地址又是多少呢? 如下所示,OMG,他们的地址居然不一样!

      +++++++++++++++++++++

      (gdb) p &optind

      $1 = (int *) 0x3bcfd5210c

      +++++++++++++++++++++

问题的探讨

      根据多方面的探索,后来查看到,这个涉及到一个“Copy Relocation”的技术。也就是动态库中存在全局变量的时候,在编译阶段已经在程序的.BSS段中预留了控件给动态库中的全局变量,然后当程序初始化的时候,会拷贝动态库中的全局变量到程序预留的.BSS段控件;其他所有的动态库,也将访问通过前面所说的.BSS段中的全局变量来访问原先动态库中定义的全局变量。 具体关于Copy Relocation的机制可以参考文章:http://www.shrubbery.net/solaris9ab/SUNWdev/LLM/p22.html#CHAPTER4-84604

      回到原先的问题,那么GDB打印出来并不是程序中.BSS通过Copy Relocation产生的全局变量optind, 而是打印的libc.so中原有的变量的值。

      那么怎么打印出正确的值呢?

      首先我们通过"Info var optind"查看下optind相关的信息,可以看到两处指名了optind的出处,第一处其实说明了这个是在libc.so中定义的,而gdb默认打印的也是libc.so中定义的,第二处就是之前所说的通过"Copy Relocation"技术存储的optind的实际使用的地址,其地址也是"0x600D60"。

      ++++++++++++++++++++

      (gdb) info var optind

      All variables matching regular expression "optind":
      File /usr/include/getopt.h:
      static int optind;
      Non-debugging symbols:
      0x0000000000600d60  optind@@GLIBC_2.2.5

      ++++++++++++++++++++      

      现在我们就可以通过命令[p 'optind@@GLIBC_2.2.5']打印出实际使用的optind的值。

      其实一个简单的问题背后,会隐藏着很多技术和机制。而要真正的明白问题产生的根本原因,目前所掌握的知识还远远不够,楼主一定还需再接再厉。以后还会针对这个问题引申出来的GOT,Copy Relocation等好好的研究研究。

参考

1.  gdb does not print right value!

http://www.linuxquestions.org/questions/programming-9/gdb-does-not-print-right-value-908538/

2. optind 

https://sourceware.org/ml/gdb/2003-12/msg00160.html

3. Copy Relocation

http://www.shrubbery.net/solaris9ab/SUNWdev/LLM/p22.html#CHAPTER4-84604

4. What's the purpose of copy relocation?

http://stackoverflow.com/questions/26863009/whats-the-purpose-of-copy-relocation

转载地址:http://ougoz.baihongyu.com/

你可能感兴趣的文章
NIFI1.21.0最新版本安装_配置使用HTTP登录_默认是用HTTPS登录的_Https登录需要输入用户名密码_HTTP不需要---大数据之Nifi工作笔记0051
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增加修改实时同步_使用JsonPath及自定义Python脚本_03---大数据之Nifi工作笔记0055
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_插入修改删除增量数据实时同步_通过分页解决变更记录过大问题_01----大数据之Nifi工作笔记0053
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表或全表增量同步_实现指定整库同步_或指定数据表同步配置_04---大数据之Nifi工作笔记0056
查看>>
NIFI1.23.2_最新版_性能优化通用_技巧积累_使用NIFI表达式过滤表_随时更新---大数据之Nifi工作笔记0063
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_根据binlog实现数据实时delete同步_实际操作04---大数据之Nifi工作笔记0043
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置binlog_使用处理器抓取binlog数据_实际操作01---大数据之Nifi工作笔记0040
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_实现数据插入数据到目标数据库_实际操作03---大数据之Nifi工作笔记0042
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_生成插入Sql语句_实际操作02---大数据之Nifi工作笔记0041
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_03_来吧用NIFI实现_数据分页获取功能---大数据之Nifi工作笔记0038
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_不带分页处理_01_QueryDatabaseTable获取数据_原0036---大数据之Nifi工作笔记0064
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_无分页功能_02_转换数据_分割数据_提取JSON数据_替换拼接SQL_添加分页---大数据之Nifi工作笔记0037
查看>>
NIFI从PostGresql中离线读取数据再导入到MySql中_带有数据分页获取功能_不带分页不能用_NIFI资料太少了---大数据之Nifi工作笔记0039
查看>>
nifi使用过程-常见问题-以及入门总结---大数据之Nifi工作笔记0012
查看>>
NIFI分页获取Mysql数据_导入到Hbase中_并可通过phoenix客户端查询_含金量很高的一篇_搞了好久_实际操作05---大数据之Nifi工作笔记0045
查看>>
NIFI分页获取Postgresql数据到Hbase中_实际操作---大数据之Nifi工作笔记0049
查看>>
NIFI同步MySql数据_到SqlServer_错误_驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server_Navicat连接SqlServer---大数据之Nifi工作笔记0047
查看>>
NIFI同步MySql数据源数据_到原始库hbase_同时对数据进行实时分析处理_同步到清洗库_实际操作06---大数据之Nifi工作笔记0046
查看>>
Nifi同步过程中报错create_time字段找不到_实际目标表和源表中没有这个字段---大数据之Nifi工作笔记0066
查看>>