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.
5 Answers
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}"
-
9If you have a problem in production and need to attach the process with gdb, will you be able to provide the debug symbol file to GDB? And how, if so ? thnx – yves Baumes May 15 '09 at 02:19
-
3@yves Baumes Just add the .debug directory with the .debug files to your production box and GDB should pick them up. After the debug session you can remove them again. – lothar May 15 '09 at 02:25
-
Refer @Lance Richardson answer comments for an example. – GuruM Jul 19 '13 at 11:02
-
7Is it also possible to restore the original binary (e.g. stripped binary + .debug file = original binary) ? – Paul Praet Oct 02 '13 at 12:48
-
1Do you find any problems with omitting [`--build-id` linker option](https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html)? – jww Aug 28 '18 at 01:56
-
`putting debug info into ${debugfile}` should probably be `putting debug info into ${debugdir}/${debugfile}`. I was confused why was I not finding *.debg file, turns out the script puts it in debugdir, which is not mentioned in the print. – Hi-Angel Feb 03 '22 at 07:28
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

- 347,512
- 102
- 1,199
- 985

- 2,347
- 1
- 18
- 10
-
3And you should use ```objcopy --add-gnu-debuglink main main.debug``` to embed the name of the created debug file and a checksum. In this case gdb will try to find the debug code itself in a few distribution depended locations, no -s option is needed anymore. – Lothar Aug 04 '16 at 00:47
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>
.

- 15,037
- 12
- 64
- 93
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
- Embed the versioning (VCS, git, svn) data into the program, for compiler optimized executables (-O3, -O4).
- 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 joe.developer@somewhere.com
VCS: COMMIT_DATE=2013-12-19
All that is left is to check-out the original code, re-compile without optimizations, and start debugging.

- 97,681
- 90
- 411
- 885

- 1,441
- 12
- 19
-
5
-
4Oops, that may be from may 'suncc' days, where '-O5' was even an option. Here's a link to the gcc4.4.7 -O options: https://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Optimize-Options.html#Optimize-Options – J Jorgenson Sep 23 '15 at 17:44
-
9This does not address the common problem of trying to interpret a core dump that may not be easily reproducible. The advice in this answer is sound, *but* it does not address the question. – David Rodríguez - dribeas Jun 08 '16 at 10:26
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.

- 4,610
- 23
- 30
-
1Yes, I've tried it: gcc -ggdb -o test test.c; cp test test.debug; strip --only-keep-debug test.debug; strip test; objcopy --add-gnu-debuglink=test.debug test; Then it's ok to debug test – zhaorufei Oct 15 '10 at 23:58