• Q1:线上问题的process 都为release版本!不带调试信息怎么查?(目前有时需要查线上问题, 不得不解决这个问题)  

    •   之前查问题都是编译环境编译一个带有debug信息的版本进行替换来调试,但是这是对必现问题,使用gdb调试没问题,如果是非必现问题呢?替换进程重新运行现象就会消失!
    • 解决方法:使用objcoy将信息表分离, 在打包环境编译进程时, makefile 中加入 -ggdb -O0 编译完成后使用objcopy 分离出调试信息, 然后strip 掉debug信息。
    • objcopy --only-keep-debug  test test.symbol         //拷贝出一个符号表文件
    • objcopy --strip-debug test   test.bin              //拷贝出一个执行文件
    • 分离出的调试信息debugsymbol还可以链接回可执行文件test中

      objcopy --add-gnu-debuglink test.symbol test

      然后就可以正常用addr2line等需要读取调试信息的程序了

      addr2line -e test 0x401c23

  • Q2: strip -s bin后的进程其符号表被去掉了,那么进程是怎样动态链接的呢? 动态链接是通过符号表完成重定位装载!!!
    • 实际上strip 后会发现strip后的so只少了symtab和strtab 以及debug信息!!保存链接符号的dynsym和dynstr都没有被strip掉
    • .dynsym

      为了表示动态链接这些模块之间的符号导入导出关系,ELF专门有一个叫做动态符号表(Dynamic Symbol Table)的段用来保存这些信息,

这个段的段名通常叫做 .dynsym(Dynamic Symbol)

与“.symtab”不同的是,“.dynsym”只保存了与动态链接相关的符号,对于那些模块内部的符号,比如模块私有变量则不保存。很多时候动态链接的模块同时拥有“.dynsym”和“.symtab”两个表,“.symtab”中往往保存了所有符号,包括“.dynsym”中的符号
 

.dynamic

动态链接ELF中最重要的结构应该是 .dynamic 段 ,这个段里面保存了动态链接器所需要的基本信息,比如依赖于哪些共享对象、动态链接符号表的位置、动态链接重定位表的位置、共享对象初始化代码的地址等

.dynstr

与“.symtab”类似,动态符号表也需要一些辅助的表,比如用于保存符号名的字符串表。静态链接时叫做符号字符串表“.strtab”(String Table),在这里就是动态符号字符串表 .dynstr

.symtab &dynsym

静态链接中有一个专门的段叫符号表 -- “.symtab”(Symbol Table), 里面保存了所有关于该目标文件的符号的定义和引用。动态链接中同样有一个段叫 动态符号表 -- “.dynsym”(Dynamic Symbol) 但.dynsym 相对于 .symtab 只保存了与动态链接相关的导入导出符号
 
 
readelf -S test
There are 35 section headers, starting at offset 0x7b2fc: Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 000080f4 0000f4 000014 00 A 0 0 1
[ 2] .hash HASH 00008108 000108 000658 04 A 3 0 4
[ 3] .dynsym DYNSYM 00008760 000760 000cf0 10 A 4 1 4
[ 4] .dynstr STRTAB 00009450 001450 00137b 00 A 0 0 1
[ 5] .gnu.version VERSYM 0000a7cc 0027cc 00019e 02 A 3 0 2
[ 6] .gnu.version_r VERNEED 0000a96c 00296c 000060 00 A 4 3 4
[ 7] .rel.dyn REL 0000a9cc 0029cc 000070 08 A 3 0 4
[ 8] .rel.plt REL 0000aa3c 002a3c 0005a8 08 A 3 10 4
[ 9] .init PROGBITS 0000afe4 002fe4 000010 00 AX 0 0 4
[10] .plt PROGBITS 0000aff4 002ff4 000890 04 AX 0 0 4
[11] .text PROGBITS 0000b884 003884 00f158 00 AX 0 0 4
[12] .fini PROGBITS 0001a9dc 0129dc 000010 00 AX 0 0 4
[13] .rodata PROGBITS 0001a9ec 0129ec 003838 00 A 0 0 4
[14] .eh_frame PROGBITS 0001e224 016224 000004 00 A 0 0 4
[15] .init_array INIT_ARRAY 00026228 016228 000004 00 WA 0 0 4
[16] .fini_array FINI_ARRAY 0002622c 01622c 000004 00 WA 0 0 4
[17] .jcr PROGBITS 00026230 016230 000004 00 WA 0 0 4
[18] .dynamic DYNAMIC 00026234 016234 000188 08 WA 4 0 4
[19] .got PROGBITS 000263bc 0163bc 0002e0 04 WA 0 0 4
[20] .data PROGBITS 0002669c 01669c 00003c 00 WA 0 0 4
[21] .bss NOBITS 000266d8 0166d8 0074a0 00 WA 0 0 8
[22] .comment PROGBITS 00000000 0166d8 000068 01 MS 0 0 1
[23] .ARM.attributes ARM_ATTRIBUTES 00000000 016740 00002f 00 0 0 1
[24] .debug_aranges PROGBITS 00000000 01676f 000108 00 0 0 1
[25] .debug_info PROGBITS 00000000 016877 0398ba 00 0 0 1
[26] .debug_abbrev PROGBITS 00000000 050131 001e7e 00 0 0 1
[27] .debug_line PROGBITS 00000000 051faf 005827 00 0 0 1
[28] .debug_frame PROGBITS 00000000 0577d8 00162c 00 0 0 4
[29] .debug_str PROGBITS 00000000 058e04 01788b 01 MS 0 0 1
[30] .debug_loc PROGBITS 00000000 07068f 009e6d 00 0 0 1
[31] .debug_ranges PROGBITS 00000000 07a4fc 000cc0 00 0 0 1
[32] .shstrtab STRTAB 00000000 07b1bc 000140 00 0 0 1
[33] .symtab SYMTAB 00000000 07b874 003760 10 34 548 4
[34] .strtab STRTAB 00000000 07efd4 002e81 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (noread), p (processor specific) arm-openwrt-linux-strip -s test There are 25 section headers, starting at offset 0x1683c: Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 000080f4 0000f4 000014 00 A 0 0 1
[ 2] .hash HASH 00008108 000108 000658 04 A 3 0 4
[ 3] .dynsym DYNSYM 00008760 000760 000cf0 10 A 4 1 4
[ 4] .dynstr STRTAB 00009450 001450 00137b 00 A 0 0 1
[ 5] .gnu.version VERSYM 0000a7cc 0027cc 00019e 02 A 3 0 2
[ 6] .gnu.version_r VERNEED 0000a96c 00296c 000060 00 A 4 3 4
[ 7] .rel.dyn REL 0000a9cc 0029cc 000070 08 A 3 0 4
[ 8] .rel.plt REL 0000aa3c 002a3c 0005a8 08 A 3 10 4
[ 9] .init PROGBITS 0000afe4 002fe4 000010 00 AX 0 0 4
[10] .plt PROGBITS 0000aff4 002ff4 000890 04 AX 0 0 4
[11] .text PROGBITS 0000b884 003884 00f158 00 AX 0 0 4
[12] .fini PROGBITS 0001a9dc 0129dc 000010 00 AX 0 0 4
[13] .rodata PROGBITS 0001a9ec 0129ec 003838 00 A 0 0 4
[14] .eh_frame PROGBITS 0001e224 016224 000004 00 A 0 0 4
[15] .init_array INIT_ARRAY 00026228 016228 000004 00 WA 0 0 4
[16] .fini_array FINI_ARRAY 0002622c 01622c 000004 00 WA 0 0 4
[17] .jcr PROGBITS 00026230 016230 000004 00 WA 0 0 4
[18] .dynamic DYNAMIC 00026234 016234 000188 08 WA 4 0 4
[19] .got PROGBITS 000263bc 0163bc 0002e0 04 WA 0 0 4
[20] .data PROGBITS 0002669c 01669c 00003c 00 WA 0 0 4
[21] .bss NOBITS 000266d8 0166d8 0074a0 00 WA 0 0 8
[22] .comment PROGBITS 00000000 0166d8 000068 01 MS 0 0 1
[23] .ARM.attributes ARM_ATTRIBUTES 00000000 016740 00002f 00 0 0 1
[24] .shstrtab STRTAB 00000000 01676f 0000ca 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (noread), p (processor specific) //可以发现符号表symtab 消失了
 
  • 同时执行nm xxx 的时候显示 no symbols  说明 nm 是读取的symtab表项
注意在cp debug.symtab到线上环境时, 需要将debug.symtabl 放在正确的位置 一般都是进程当前路径或者usr/lib/debug+ rottpath
或者利用gdb的命令设置搜索路径:set debug-file-directory directories
具体情况strace 就可以看到如下:
open("/fp/lib/log_plugins/libto_logs.so.debug.symbol", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/fp/lib/log_plugins/.debug/libto_logs.so.debug.symbol", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/debug//fp/lib/log_plugins/libto_logs.so.debug.symbol", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/debug/old_rootfs/fp/lib/log_plugins/libto_logs.so.debug.symbol", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
write(1, "(no debugging symbols found)...d"..., 37(no debugging symbols found)...done.
  • -fpic:使用-fPIC时,生成的代码时与位置无关的代码。那么在加载动态库时,就不会加载到固定位置,那么每个symbol都可以加载成功。当没有-fPIC时,程序会发现该位置已有对应的symbol,自然就不会二次加载了。(这个对于在线升级动态库有比较大的帮助)
  • gcc参数 -rdynamic 用来通知链接器将所有符号添加到动态符号表中(目的是能够通过使用 dlopen 来实现向后跟踪).表示main函数调用dlopen 打开xxx
  • gcc main.c -ldl -rdynamic -O  test.bin  # gcc -shared -fPIC -nostartfiles -o testlib.so testlib.c
    gcc参数 -fPIC 作用: 当使用.so等类的库时,当遇到多个可执行文件共用这一个库时, 在内存中,这个库就不会被复制多份,让每个可执行文件一对一的使用,而是让多个可执行文件指向一个库文件,达到共用. 宗旨:节省了内存空间,提高了空间利用率
 

对“线上问题 不能gdb调试怎么处理??“”的思考的更多相关文章

  1. mac上eclipse用gdb调试(转)

    mac上eclipse用gdb调试 With its new OS release, Apple has discontinued the use of GDB in OS X. Since 2005 ...

  2. 一次线上Redis类转换异常排查引发的思考

    之前同事反馈说线上遇到Redis反序列化异常问题,异常如下: XxxClass1 cannot be cast to XxxClass2 已知信息如下: 该异常不是必现的,偶尔才会出现: 出现该异常后 ...

  3. 调试工具-fiddler:本地资源替换线上调试

    Fiddler是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的“进出”Fiddler的数据(指cookie,html,js,css等文件,这 ...

  4. 用fiddler替换线上网页资源调试界面

    fiddler 是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有进出fiddler的数据(指cookie,html,js,css等文件,这些都 ...

  5. linux inode 详解 / 线上inode爆满解决方案

    本文大量参考阮一峰大神博客,整理笔记 之所以写inode文章是由于一次线上问题,引发对inode深入的思考. 磁盘的inode监控与磁盘空间的监控同等重要,线上服务器一定要做好磁盘inode与磁盘空间 ...

  6. 如何用 fiddler 调试线上代码

    有时代码上线了,突然就碰到了坑爹的错误.或者有时看别人家线上的代码,对于一个文件想 fork 下来试试效果又不想把全部文件拉到本地,都可以使用 fiddler 的线上调试功能. 比方说我们打开携程的首 ...

  7. 如何使用Fiddler调试线上JS代码

    大家平时肯定都用过火狐的Firebug或者谷歌的调试工具来调试JS,但遗憾的是我们不能像编辑html,css那样来直接新增或者删除JS代码. 虽然可以通过调试工具的控制台来动态执行JS代码,但有时候却 ...

  8. 线上应用调试利器 --Arthas

    在之前的文章中,我介绍了使用 Btrace 工具进行线上代码的debug (https://www.cnblogs.com/yougewe/p/10180483.html),其大致原理就是通过字节码注 ...

  9. 硬盘上的一些算法小题目||and今天看了下林锐的书以及gdb调试 及一些变成算法小题目

    gdb调试:观察点,断点,事件捕捉点.step 进入函数,next 跳过函数,until 跳出循环,finish 结束函数 林锐:书后试题 & c++的对象模型图 看了二叉树的非递归遍历, 链 ...

随机推荐

  1. 持续集成工具之Jenkins使用配置

    在上一篇博客中,我们主要介绍了DevOps理念以及java环境和jenkins的安装,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13805666.html: ...

  2. 苏州6617.9373(薇)xiaojie:苏州哪里有xiaomei

    苏州哪里有小姐服务大保健[微信:6617.9373倩儿小妹[苏州叫小姐服务√o服务微信:6617.9373倩儿小妹[苏州叫小姐服务][十微信:6617.9373倩儿小妹][苏州叫小姐包夜服务][十微信 ...

  3. 【嵌入式】C语言高级编程▁▁▁嵌入式C语言入门编程学习!

    ✍  1.C 语言标准 什么是 C 语言标准呢? 我们生活的现实世界,就是由各种标准构成的,正是这些标准,我们的社会才会有条不紊的运行. 比如我们过马路,遵循的交通规则就是一个标准:红灯停,绿灯行,黄 ...

  4. 搭建分布式 Redis Cluster 集群与 Redis 入门

    目录 Redis 集群搭建 Redis 是啥 集群(Cluster) Redis Cluster 说明 Redis Cluster 节点 Redis Cluster 集群模式 不能保证一致性 创建和使 ...

  5. Geoserver发布shp文件

    Geoserver是著名的开源GIS软件之一.也是项目中常用的地图服务软件.基于geoserver和Openlayers就可以构建一个免费的开源GIS项目. Geoserver除了浏览以外,其他譬如发 ...

  6. JS错误写法[清除DOM]

    前言 我现在总结一下我之前敲代码犯的错误,清除DOM元素,我们开始写代码吧! HTML <h1 style="font-size: 18px;font-weight: bold;col ...

  7. day04基本数据类型

    内容补充 编译器和解释器:牵扯到编译型语言和解释型语言 编译型语言:JAVA C C# C++ 写好的代码交给编译器,编译器会编译成一个新的文件交给计算机执行 解释型语言:python PHP 写好的 ...

  8. c库中sprintf

    用法:sprintf指的是字符串格式化命令,主要功能是把某个数据写入某个字符串中: 我的理解就是,将某个其它类型的数据按着某一格式写入char *a,因此叫格式化命令: 语法: #include< ...

  9. 编写shell脚本的规范

    目录 编写shell脚本的一些规范 解释器 添加脚本版本和注释功能 添加脚本调试 变量命名 全局变量和局部变量 命名规范 函数命名 脚本命名 函数 引用模块或文件 脚本日志 配置文件 其他 编写she ...

  10. 常用数据结构-namedtuple(命名元祖)

    namedtuple从根本上来说是一个带有数据名称的元祖.它包含元祖的所有特性,但也有一些元祖没有的额外特性.使用namedtuple可以很容易创建轻量级对象类型. namedtuple将是你的代码更 ...