Linux环境Release版本符号表剥离及调试方法


目录

Linux环境Release版本符号表剥离及调试方法

前言

1 Release版本剥离符号表

1.1 编译时,进行so库调试信息的剥离

1.2 使用objcopy工具进行调试信息剥离

1.3 打包时,进行debug包生成

2 Release版本的调试

3 最后,开始挖坑


前言


遇到了版本过大,超过了硬件限制的问题,当下的思路是:

将版本所有的动态库(内部+三方动态库)的gdb调试辅助信息进行剥离,同时发布对应的debug包。如果需要使用gdb进行调试时,取用相应版本的debug包,解压放入设备固定目录,该目录由设备启动脚本修改.gdbinit文件,设置gdb寻找符号表文件的目录。

这个方案下来,优势是相比于裁剪库、优化压缩工具、编译规则来说,版本包可以大幅度缩减50%,同时发布版本隐藏了代码的相关本地变量等信息,增加了安全项。缺点是后期维护调试比较麻烦,需要获取同期发布的debug包,并下载解压到设备。

这里对方案实现做了一些表述以及自己探索的结果,同时对自己想要扩展的知识挖个坑,后续提醒自己填上。


1 Release版本剥离符号表


项目版本有Debug版本与Release版本之分,从我所在的项目看,Release版本在编译规则中做了代码优化,在性能上往往更强一点,同时也是集成测试的测试版本。之前常听前辈讲Release版本往往比Debug要小,现在我想我悟了:Release版本剥离了调试信息、符号表等。

项目中,每个组件代码经过预编译、编译、链接最终会成为一个或多个so库,每个lib端也会成为一个so库,最终通过打包脚本,将编译中生成的动态库存放在各自固定目录中,最终压缩生成发布的版本。我们需要做的是将编译生成的so库与第三方库进行调试信息、符号表的剥离。


1.1 编译时,进行so库调试信息的剥离


调试信息的剥离时机一定是在编译(链接步骤之后)时进行的,因为:

  • 如果在项目打包脚本中进行,势必需要设置相应的环境变量(source一把交叉工具链的脚本),而往往需要打包的是不同cpu类型的产品版本
  • 打包过程中势必要遍历整个项目目录的so库,打包脚本运行时间会增长很多

1.2 使用objcopy工具进行调试信息剥离


剥离工具有很多:objcopy、strip、eu-strip等等,各有各的优势,但看平台给的编译工具链中有objcopy工具,故选用objcopy。

个人理解这些工具都是对elf文件中各个段的一些增删改查操作。

符号表剥离步骤如下:

(1)复制*.so中的调试信息段到*.so.debug中去

这些gdb调试信息生成的时机:编译时,gcc增加-c参数,将会在生成的动态库中保留gdb调试所需要的辅助信息(.debug_*段,并且增大.symtab段)。

#查看so库段信息,发现有gdb的辅助信息
readelf -S test.so

查询结果:

复制test.so中的调试信息到test.so.debug文件中  :

#复制test.so中的调试信息到test.so.debug文件中
objcopy --only-keep-debug test.so test.so.debug

观察生成的test.so.debug文件:

#查看objcopy复制后的文件中有什么
readelf -a test.so.debug
  • 52Byte的ELF文件头,完全复制了过来

  • 段表头,完全复制

  • 复制了.symtab段,其余并未复制

(2)删除so库中的调试信息段

剥离test.so中的相关gdb调试段: .debug* + .symtab段

#剥离test.so中的相关gdb调试段: .debug\* + .symtab段
objcopy --strip-debug --strip-unneeded test.so

查看test.so的段信息,发现已经删除了 .debug* + .symtab段:

查看减少的大小,基本符合test.so.bak=test.so+test.so.debug:

(3)增加so库.gnu_debuglink段

进行test.so和test.so.debug文件间的关联,方便后续gdb调试时进行连接,注意这里的关联仅仅是文件名字的关联,不是路径的关联!

#进行test.so和test.so.debug文件间的关联
objcopy --add-gnu-debuglink=test.so.debug test.so

确认是否进行了关联:

#查看test.so新增的段
objdump -s -j .gnu_debuglink test.so

1.3 打包时,进行debug包生成


打包Release版本时,进行debug包的生成:

  • 一方面,是因为gdb调试时会对库进行crc校验,需要so与so.debug版本符合,所以需要同时发布debug包
  • 另一方面,由于gdb查找符号表的规则限制,我们需要保证debug包中.so.debug的路径与设备上.so的实际路径保持一致(cp命令有个参数很神奇,--path可以在copy时同步创建目录,但是不建议,项目版本中so库有300+)

事实上调试某个进程时,将会涉及非常多的so库,这个时候,不可能挨个指定so库的debug符号表,所以我们需要保证设备上so库的路径与.so.debug存放路径的关系是:

.so.debug路径=gdb符号表默认路径+.so路径

即假如所调试进程涉及了/mnt/work/path1/a.so和/mnt/work/paht2/b.so,那么相应的.so.debug存放路径为:

/gdb默认符号表路径/mnt/work/path1/a.so.debug和/gdb默认符号表路径/mnt/work/path2/a.so.debug


2 Release版本的调试


(1) 版本启动脚本中,进行gdb配置文件修改,设置查找符号表的路径:

#修改gdb配置文件
cd ~
if [ -f .gdbinit ]; thenrm -f .gdbinit
fi
touch .gdbinit
echo "set debug-file-directory /dev/shm/strip" >> .gdbinit

(2)将生成的debug包解压缩至/dev/shm/strip目录下(debug包目录结构有要求,见1.3)

至此就可以正常使用gdb进行调试Release版本的相关进程、调试coredump文件了。


3 最后,开始挖坑


  • 项目makfile编写规则研究
  • 动态库装载的学习,研究下项目版本的启动流程
  • ELF文件格式学习

Linux环境Release版本的符号表剥离及调试方法相关推荐

  1. 转Linux环境下段错误的产生原因及调试方法小结

    Linux环境下段错误的产生原因及调试方法小结 转载于:https://www.cnblogs.com/objectDetect/p/7575659.html

  2. Linux环境下段错误的产生原因及调试方法小结

    From:http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html 最近在Linux环境下做C语言项目,由于是在一个原有项目基 ...

  3. [转]Linux环境下段错误的产生原因及调试方法小结

    最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的"段错误"(Segme ...

  4. Linux环境下段错误的产生原因及调试方法

    1. 段错误是什么 一句话来说,段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址.访问了系统保护的内存地址.访问了只读的内存地址等等情况.这里贴一个对于" ...

  5. linux升级网卡fw,一种linux环境下覆盖多品牌硬盘的FW升级方法与流程

    本发明属于服务器硬盘升级技术领域,具体涉及一种linux环境下覆盖多品牌硬盘的FW升级方法. 背景技术: 随着浪潮服务器的不断发展和壮大,作为国内最大的服务器供应商,服务器市场已经囊括各个领域,客户对 ...

  6. TRACE32——加载符号表信息用于调试

    TRACE32--加载符号表信息用于调试 劳特巴赫TRACE32可以显示目标芯片上运行的源码,并且可以通过相应的按钮和命令在C源码和汇编码之间切换. 但有的时候,连上目标芯片后,并不需要重新烧写代码, ...

  7. linux程序运行段错误,Linux下的段错误产生的原因及调试方法

    Linux下的段错误产生的原因及调试方法 简而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址. 一般来 说,段错误就是指访问的内存超出 ...

  8. Android Native 代码 Release 编译 - 隐藏符号表

    使用 ndk-build NDK_DEBUG=0 可以编译 release 版本,但是符号表(Symbole table)仍然存在,如何隐藏呢? 在 Android.mk 文件中添加下面的配置: LO ...

  9. Linux | Linux环境与版本作业

    Linux 1.以下哪个命令输出Linux内核的版本信息: 2.linux 2.6.* 内核默认支持的文件系统有哪些? 3.linux查看cpu占用的命令是什么? 4.在Linux系统中, 为找到文件 ...

最新文章

  1. python 队列 一次取多个_Queue 队列模块-Python成为专业人士笔记
  2. App设计灵感之十二组精美的家具产品电商App设计案例
  3. xp和win 2003远程桌面强制进入命令_远程登录t人命令
  4. 它的斗争“和loser对话”短篇故事
  5. 做技术的为什么很难发财?
  6. mysql 不在另一个表中_MySQL选择查询从表中选择不在另一个表中的行?
  7. 以太坊ETH不能转账,状态一直是pending状态原因和解决方法
  8. c语言以空格分割字符串_如何统计字符串中单词的个数?
  9. 说服力——教你做出专业出彩的演示PPT
  10. How to Be Cool at College
  11. Ubuntu下Vim的常用操作命令——vi编辑器常用命令
  12. 360刷Android8,360N6安卓8.1新版刷机包(完整固件升级包安卓8.1)
  13. R 语言详细安装教程(保姆级)及 RStudio简易安装教程
  14. 51单片机外部中断使用示例程序
  15. 【和76】龙头企业在区域市场中竞合关系分析样例(温微观察13-6)
  16. poj3259 Wormholes floyd求负环
  17. 浏览器主页被修改的解决方案
  18. 从猎豹到山狮-苹果操作系统热衷于猫科动物代号
  19. 给btn添加hover、active、focus效果
  20. 班级优化大师显示网络或服务器异常,希沃班级优化大师常见问题总汇

热门文章

  1. 计算机分组交换的优点缺点,分组交换的优缺点分析
  2. git回退到某个版本并提交
  3. ScheduleThreadPoolExecutor 定时任务线程池原理
  4. 在Ubuntu18中安装Xen HVM 虚拟机
  5. sqlserver数据库数据类型详解
  6. win7计划任务报该任务映像己损坏或己篡改
  7. 买不到的数目(小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。 小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗)
  8. 普通用户(非root)使用nginx
  9. 【他山之石】GPT-4发布!史上最强大模型来了
  10. AWD-----监控不死马垃圾包资源库