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

您所在的位置:网站首页 删除符号表信息怎么删 Linux环境Release版本的符号表剥离及调试方法

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

2024-07-10 16:23| 来源: 网络整理| 查看: 265

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 ]; then rm -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文件格式学习

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3