首页 > *nix技术, 跟踪调试 > 独立的调试符号文件

独立的调试符号文件

2013年4月29日 发表评论 阅读评论 830 次浏览

也许,我们还记得各大Linux发型版提供的debuginfo安装包,比如fedora:http://fedoraproject.org/wiki/Packaging:Debuginfo,这种将可执行程序与调试符号分离的方案好处多多。一方面,缩减了可执行程序的文件大小,在一定程度上提高了程序的执行性能,另一方面,对应的调试符号文件也方便了一些不时之需。本文就来看一下与此相关的两个问题。

一,如何给应用程序创建对应的调试符号文件?
这很简单,看个演示实例。有代码如下:

[root@lenky gdb]# cat t.c
#include <stdio.h> 

int main(int argc, char *argv[])
{
        printf("Hello world!\n");
    return 0;
} 

依次执行命令如下:

[root@lenky gdb]# ls -l
total 4
-rw-r--r--. 1 root root 103 Mar 20 07:52 t.c
[root@lenky gdb]# gcc -g t.c -o t
[root@lenky gdb]# ls -l
total 12
-rwxr-xr-x. 1 root root 7717 Mar 20 07:58 t
-rw-r--r--. 1 root root  103 Mar 20 07:52 t.c
[root@lenky gdb]# objcopy --only-keep-debug t t.debuginfo
[root@lenky gdb]# objcopy --strip-debug t
[root@lenky gdb]# objcopy --add-gnu-debuglink=t.debuginfo t
[root@lenky gdb]# ls -l
total 20
-rwxr-xr-x. 1 root root 6470 Mar 20 07:58 t
-rw-r--r--. 1 root root  103 Mar 20 07:52 t.c
-rwxr-xr-x. 1 root root 6109 Mar 20 07:58 t.debuginfo

OK,可执行程序t和对应的调试符号文件t.debuginfo就生成了。
几条命令,给以分别解释一下:
1,gcc -g t.c -o t
这个无需多说,值得注意的是,-g和-O2可以同时使用。
2,objcopy –only-keep-debug t t.debuginfo
将可执行程序文件t内的与调试相关的信息拷贝到文件t.debuginfo内。也可以这样:

cp t t.debuginfo
strip --only-keep-debug t.debuginfo

3,objcopy –strip-debug t
删除可执行程序文件t内的调试相关信息。也可以直接使用strip命令,不过strip命令会把symtab也删除掉,导致在没有debuginfo文件的情况下,打印堆栈信息会受到影响,比如变得不那么清晰。
4,objcopy –add-gnu-debuglink=t.debuginfo t
在可执行程序文件t内添加一个名为.gnu_debuglink的section段,该段内包含有debuginfo文件的name名称和checksum校验和,以确保后续在进行实际调试时,可执行程序和对应的调试符号文件是一致的。

在参考1链接里,某牛给了一个shell脚本,那么整个过程可以直接这样:

[root@lenky gdb]# cat cdbi.sh
#!/bin/bash

scriptdir=`dirname ${0}`
scriptdir=`(cd ${scriptdir}; pwd)`
scriptname=`basename ${0}`

set -e

function errorexit()
{
  errorcode=${1}
  shift
  echo $@
  exit ${errorcode}
}

function usage()
{
  echo "USAGE ${scriptname} <tostrip>"
}

tostripdir=`dirname "$1"`
tostripfile=`basename "$1"`

if [ -z ${tostripfile} ] ; then
  usage
  errorexit 0 "tostrip must be specified"
fi

cd "${tostripdir}"

debugdir=.debug
debugfile="${tostripfile}.debug"

if [ ! -d "${debugdir}" ] ; then
  echo "creating dir ${tostripdir}/${debugdir}"
  mkdir -p "${debugdir}"
fi
echo "stripping ${tostripfile}, putting debug info into ${debugfile}"
objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"
chmod -x "${debugdir}/${debugfile}"
[root@lenky gdb]# !gcc
gcc -g t.c -o t
[root@lenky gdb]# ./cdbi.sh t
stripping t, putting debug info into t.debug
[root@lenky gdb]# ls -l .debug/
total 8
-rw-r--r--. 1 root root 6109 Mar 20 08:33 t.debug
[root@lenky gdb]# ls -la
total 28
drwxr-xr-x. 3 root root 4096 Mar 20 08:33 .
drwxr-xr-x. 3 root root 4096 Mar 20 07:49 ..
-rwxr-xr-x. 1 root root  874 Mar 20 08:31 cdbi.sh
drwxr-xr-x. 2 root root 4096 Mar 20 08:33 .debug
-rwxr-xr-x. 1 root root 4360 Mar 20 08:33 t
-rw-r--r--. 1 root root  103 Mar 20 07:52 t.c

二,如何使用gdb调试带有调试符号文件的应用程序?
其实想想也知道,这只需解决一个问题,即如何把应用程序与调试符号文件关联起来。
gdb会按照一定的规则去搜索对应路径,找寻应用程序的调试符号文件,比如gdb会自动查找可执行程序所在目录下的.debug文件夹:

[root@lenky ~]# pwd
/root
[root@lenky ~]# gdb /home/work/gdb/t -q
Reading symbols from /home/work/gdb/t...Reading symbols from /home/work/gdb/.debug/t.debug...done.
done.
(gdb)

拷贝到/tmp目录执行试试:

[root@lenky ~]# cp /home/work/gdb/t /tmp/
[root@lenky ~]# gdb /tmp/t -q
Reading symbols from /tmp/t...Missing separate debuginfo for /tmp/t
Try: yum --disablerepo='*' --enablerepo='*-debuginfo' install /usr/lib/debug/.build-id/01/f1df7f4971caacd934aca9523c4e4b5ae95332.debug
(no debugging symbols found)...done.
(gdb) q

提示找不到调试符号文件,把.debug文件夹也拷贝过去就OK了:

[root@lenky ~]# cp -r /home/work/gdb/.debug/ /tmp/
[root@lenky ~]# gdb /tmp/t -q
Reading symbols from /tmp/t...Reading symbols from /tmp/.debug/t.debug...done.
done.
(gdb)

把调试符号文件放到同一个目录也可以:

[root@lenky ~]# rm -fr /tmp/.debug/
[root@lenky ~]# cp /home/work/gdb/.debug/t.debug /tmp/
[root@lenky ~]# gdb /tmp/t -q
Reading symbols from /tmp/t...Reading symbols from /tmp/t.debug...done.
done.
(gdb)

下面再介绍另外几种主动设置方法:
1,通过gdb启动参数-s指定:

[root@lenky ~]# gdb -s /home/work/gdb/.debug/t.debug -e /tmp/t -q
Reading symbols from /home/work/gdb/.debug/t.debug...done.
(gdb)

注意:可执行程序必须通过-e指定,否则貌似gdb会拿它覆盖-s参数,比如如下:

[root@lenky ~]# gdb -s /home/work/gdb/.debug/t.debug /tmp/t -q
Reading symbols from /tmp/t...Missing separate debuginfo for /tmp/t
Try: yum --disablerepo='*' --enablerepo='*-debuginfo' install /usr/lib/debug/.build-id/01/f1df7f4971caacd934aca9523c4e4b5ae95332.debug
(no debugging symbols found)...done.
(gdb)

可以看到,gdb直接尝试从文件/tmp/t内读取符号了,而不是文件t.debug。

2,利用gdb的命令设置搜索路径:set debug-file-directory directories
这是gdb官方文档提到的,可以设置搜索路径的命令,但是貌似并没有起作用,或者是我漏掉了什么。具体不说了,请看参考5。

参考:
1,How to generate gcc debug symbol outside the build target?
http://stackoverflow.com/questions/866721/how-to-generate-gcc-debug-symbol-outside-the-build-target
2,Creating separate debug info
https://blogs.oracle.com/dbx/entry/creating_separate_debug_info
3,man objcopy
4,.gnu_debuglink or Debugging system libraries with source code
https://blogs.oracle.com/dbx/entry/gnu_debuglink_or_debugging_system
5,18.2 Debugging Information in Separate Files
http://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
6,http://www.technovelty.org/code/separate-debug-info.html

转载请保留地址:http://lenky.info/archives/2013/04/29/2261http://lenky.info/?p=2261


备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。

法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以或书面等方式告知,本站将及时删除相关内容或链接。

分类: *nix技术, 跟踪调试 标签: ,
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.