如何在构建目标之外生成 gcc 调试符号?

发布于 2024-07-19 14:07:37 字数 101 浏览 10 评论 0原文

我知道我可以使用 -g 选项生成调试符号。 但是该符号嵌入在目标文件中。 gcc 可以在结果可执行文件/库之外生成调试符号吗? 就像windows VC++编译器的.pdb文件一样。

I know I can generate debug symbol using -g option. However the symbol is embeded in the target file. Could gcc generate debug symbol outside the result executable/library? Like .pdb file of windows VC++ compiler did.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

给不了的爱 2024-07-26 14:07:37

注意:使用高优化级别(-O3、-O4)编译的程序无法为优化变量、内联函数和展开循环生成许多调试符号,无论符号是嵌入(-g)还是提取(objcopy)到“.debug”文件。

替代方法是

  1. 将版本控制(VCS、git、svn)数据嵌入到程序中,以获得编译器优化的可执行文件(-O3、-O4)。
  2. 构建可执行文件的第二个非优化版本。

第一个选项提供了一种在以后通过完整的调试和符号重建生产代码的方法。 能够在不进行优化的情况下重新构建原始生产代码对于调试有巨大的帮助。 (注意:这假设测试是使用程序的优化版本完成的)。

您的构建系统可以创建一个 .c 文件,其中加载了编译日期、提交和其他 VCS 详细信息。 这是一个“make + git”示例:

program: program.o version.o 

program.o: program.cpp program.h 

build_version.o: build_version.c    

build_version.c: 
    @echo "const char *build1=\"VCS: Commit: $(shell git log -1 --pretty=%H)\";" > "$@"
    @echo "const char *build2=\"VCS: Date: $(shell git log -1 --pretty=%cd)\";" >> "$@"
    @echo "const char *build3=\"VCS: Author: $(shell git log -1 --pretty="%an %ae")\";" >> "$@"
    @echo "const char *build4=\"VCS: Branch: $(shell git symbolic-ref HEAD)\";" >> "$@"
    # TODO: Add compiler options and other build details

.TEMPORARY: build_version.c

编译程序后,您可以使用以下命令找到代码的原始“提交”:strings -a my_program | grep VCS

VCS: PROGRAM_NAME=my_program
VCS: Commit=190aa9cace3b12e2b58b692f068d4f5cf22b0145
VCS: BRANCH=refs/heads/PRJ123_feature_desc
VCS: AUTHOR=Joe Developer  [email protected]
VCS: COMMIT_DATE=2013-12-19

剩下的就是检查原始代码,重新编译而不优化,然后开始调试。

NOTE: Programs compiled with high-optimization levels (-O3, -O4) cannot generate many debugging symbols for optimized variables, in-lined functions and unrolled loops, regardless of the symbols being embedded (-g) or extracted (objcopy) into a '.debug' file.

Alternate approaches are

  1. Embed the versioning (VCS, git, svn) data into the program, for compiler optimized executables (-O3, -O4).
  2. Build a 2nd non-optimized version of the executable.

The first option provides a means to rebuild the production code with full debugging and symbols at a later date. Being able to re-build the original production code with no optimizations is a tremendous help for debugging. (NOTE: This assumes testing was done with the optimized version of the program).

Your build system can create a .c file loaded with the compile date, commit, and other VCS details. Here is a 'make + git' example:

program: program.o version.o 

program.o: program.cpp program.h 

build_version.o: build_version.c    

build_version.c: 
    @echo "const char *build1=\"VCS: Commit: $(shell git log -1 --pretty=%H)\";" > "$@"
    @echo "const char *build2=\"VCS: Date: $(shell git log -1 --pretty=%cd)\";" >> "$@"
    @echo "const char *build3=\"VCS: Author: $(shell git log -1 --pretty="%an %ae")\";" >> "$@"
    @echo "const char *build4=\"VCS: Branch: $(shell git symbolic-ref HEAD)\";" >> "$@"
    # TODO: Add compiler options and other build details

.TEMPORARY: build_version.c

After the program is compiled you can locate the original 'commit' for your code by using the command: strings -a my_program | grep VCS

VCS: PROGRAM_NAME=my_program
VCS: Commit=190aa9cace3b12e2b58b692f068d4f5cf22b0145
VCS: BRANCH=refs/heads/PRJ123_feature_desc
VCS: AUTHOR=Joe Developer  [email protected]
VCS: COMMIT_DATE=2013-12-19

All that is left is to check-out the original code, re-compile without optimizations, and start debugging.

紅太極 2024-07-26 14:07:37

到目前为止没有答案提到 eu-strip --strip-debug -f<输入>。

  • 这是由 elftils 包提供的。
  • 结果将是 文件中的调试符号已被删除,这些调试符号现在全部位于 中。

No answer so far mentions eu-strip --strip-debug -f <out.debug> <input>.

  • This is provided by elfutils package.
  • The result will be that <input> file has been stripped of debug symbols which are now all in <out.debug>.
夜夜流光相皎洁 2024-07-26 14:07:37

查看 strip 命令的“--only-keep-debug”选项。

从链接:

目的是该选项将与 --add-gnu-debuglink 结合使用来创建由两部分组成的可执行文件。 第一个是剥离的二进制文件,它将在 RAM 和发行版中占用更少的空间,第二个是调试信息文件,仅在需要调试能力时才需要。

Check out the "--only-keep-debug" option of the strip command.

From the link:

The intention is that this option will be used in conjunction with --add-gnu-debuglink to create a two part executable. One a stripped binary which will occupy less space in RAM and in a distribution and the second a debugging information file which is only needed if debugging abilities are required.

坐在坟头思考人生 2024-07-26 14:07:37

使用调试信息进行编译:

gcc -g -o main main.c

分离调试信息:

objcopy --only-keep-debug main main.debug

cp main main.debug
strip --only-keep-debug main.debug

从原始文件中剥离调试信息:

objcopy --strip-debug main

strip --strip-debug --strip-unneeded main

通过 debuglink 模式进行调试:

objcopy --add-gnu-debuglink main.debug main
gdb main

您还可以分别使用 exec 文件和符号文件:

gdb -s main.debug -e main

gdb
(gdb) exec-file main
(gdb) symbol-file main.debug

详细信息:

(gdb) help exec-file
(gdb) help symbol-file

参考:
https://sourceware.org/gdb/onlinedocs/gdb/Files.html#Files
https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug -Files.html

Compile with debug information:

gcc -g -o main main.c

Separate the debug information:

objcopy --only-keep-debug main main.debug

or

cp main main.debug
strip --only-keep-debug main.debug

Strip debug information from origin file:

objcopy --strip-debug main

or

strip --strip-debug --strip-unneeded main

debug by debuglink mode:

objcopy --add-gnu-debuglink main.debug main
gdb main

You can also use exec file and symbol file separatly:

gdb -s main.debug -e main

or

gdb
(gdb) exec-file main
(gdb) symbol-file main.debug

For details:

(gdb) help exec-file
(gdb) help symbol-file

Ref:
https://sourceware.org/gdb/onlinedocs/gdb/Files.html#Files
https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html

能否归途做我良人 2024-07-26 14:07:37

您需要使用 objcopy 来分离调试information

objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"

我使用下面的 bash 脚本将调试信息分离到 .debug 目录中带有 .debug 扩展名的文件中。 这样我就可以将库和可执行文件打包到一个 tar 文件中,并将 .debug 目录打包到另一个 tar 文件中。 如果我想稍后添加调试信息,我只需提取调试 tar 文件,瞧,我就有了符号调试信息。

这是 bash 脚本:

#!/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}"

You need to use objcopy to separate the debug information:

objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"

I use the bash script below to separate the debug information into files with a .debug extension in a .debug directory. This way I can tar the libraries and executables in one tar file and the .debug directories in another. If I want to add the debug info later on I simply extract the debug tar file and voila I have symbolic debug information.

This is the bash script:

#!/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}"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文