• 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. CSS常见反爬技术

    目录 利用字体 反爬原理 应对措施 难点: 利用背景 反爬原理 应对措施 利用伪类 反爬原理 应对措施 利用元素定位 反爬原理 应对措施 利用字符切割 反爬原理 应对措施 利用字体 反爬原理 反爬原理 ...

  2. MySQL【灵魂拷问】

    MySQL 一直是本人薄弱的部分,后面会多总结 MySQL 的文章,毕竟 MySQL 涉及到数据存储.锁.磁盘寻道.分页等操作系统概念,而且互联网对 MySQL 的注重程度是不言而喻的,后面要加紧对 ...

  3. ASP.Net Core3.1 生成二维码填坑

    ASP.Net Core3.1 使用QrCode生成二维码 部署到Linux报错 The type initializer for 'System.DrawingCore.GDIPlus' threw ...

  4. lambda函数小结

    C++中的lambda函数 lambda函数是函数式编程中的概念,由C++11引入,成为现代C++中重要的特性. 所谓lambda函数就是匿名函数,语法结构: [capture list] (para ...

  5. 【源码项目】C语言编程之火车票管理系统!(最强代码)

    大学计算机软件技术基础课程设计任务书 一.题目: 火车票信息管理系统: 二.目的与要求 : ● 目的培养学生综合利用C++语言进行程序设计的能力, ● 培养学生的编程能力.用计算机解决实际问题的能力, ...

  6. 【换根DP】小奇的仓库

    题目背景 小奇采的矿实在太多了,它准备在喵星系建个矿石仓库.令它无语的是,喵星系的货运飞船引擎还停留在上元时代! 题目内容 喵星系有\(n\)个星球,星球以及星球间的航线形成一棵树. 从星球\(a\) ...

  7. linux(centos8):安装java jdk 14 (java 14.0.2)

    一,下载jdk14 官方网站: https://www.oracle.com/java/ 下载页面: https://www.oracle.com/cn/java/technologies/javas ...

  8. vue知识点15

    1.回调地狱的三种方案:函数    promise     async await          2. 子组件与子组件之间的传递: 可以借用公共父元素.子组件A  this.$emit(" ...

  9. PowerShell类grep

    PowerShell类grep 方法一: windows下没有grep不过有findstr, 功能差不多 方法二: powershell自带的正择功能 xxx | where {$_ -match & ...

  10. 没事学学KVM(二)创建一台虚拟机

    首先通过VMware创建一台虚机,建议内存大于1G,并开启CPU 的inter vt-x功能,安装好对应的软件后,yum install -y qemu-kvm* virt-* libvirt* 准备 ...