I am interested in creating an external symbol file which I reference from my ELF file using objcopy --add-gnu-debuglink=...
.
Now I know how to extract only the debug symbols (objcopy --only-keep-debug
) and how to only strip the debug symbols (objcopy --strip-debug
).
However, I'd like to strip all unneeded symbols. I know this can be done via objcopy --strip-unneeded
. The fact that debug and unneeded symbols are two different categories and two different command line switches suggests that there could be non-overlapping symbols.
Since unneeded symbols seem to encompass more than just the debug symbols, I'm afraid to lose some symbolic information when doing this (in GNU make):
stripped/%: %
objcopy --only-keep-debug $@ $@.dbg
objcopy --strip-unneeded $@
objcopy --add-gnu-debuglink=$@.dbg $@
Can anyone explain what kind of symbols may be removed via --strip-unneeded
that may not be removed with --strip-debug
? Or put differently: which symbols not kept in the external symbol file by --only-keep-debug
may get lost when running --strip-unneeded
on the original binary? Is there a way to retain these symbols in my external symbol file or is this a non-issue?
Goal is to be able to debug issues using the external debug symbols and not ending up missing some symbolic information and find out too late. So I don't want to lose symbolic information, I just want to remove it entirely from the program binary.
PS: I am aware of How to generate gcc debug symbol outside the build target? But that question and its answers don't touch the detail I am asking about.
I've just stumbled to the very same question.
Previously I just separated my built ELF-binaries with the objcopy's --only-keep-debug
, --strip-debug
, --add-gnu-debuglink
flags.
Now I need to save even more space and so I'm considering using --strip-unneeded
instead of --strip-debug
.
But like you I'm afraid that this may affect my debugging experience.
So, I've made several tests and come to the following conclusions:
--strip-unneeded
strips what is stripped by --strip-debug
and even more. I.e. 'debug' info is considered as a part of 'unneeded' info.--only-keep-debug
flag, not only store info stripped by the --strip-debug
, but also info stripped by the --strip-unneeded
.--strip-debug
vs --strip-unneeded
, provided the debug binaries created with the --only-keep-debug
.Details below:
I've created a very simple C++ project, which contains an executable and a shared library. The library contains a globally exported function, which is called by the application. Also the library contains several local functions (i.e. static or in the anonymous namespace), being called by the globally exported function. The code in the local functions just created a crash by just throwing an unhandled exception.
First, I've compiled both binaries with the -g -O0
flags.
Second, I've extracted the debug information from them in a separate binaries and linked these debug files to the original binaries. I.e., for both files:
objcopy --only-keep-debug $FILE $FILE.debug
objcopy --add-gnu-debuglink=$FILE.debug $FILE
After this point I had unstripped binaries also having separate correspondent linked debug binaries.
Then I've copied these files into two additional directories. In the first one I've done --strip-debug
against the original binaries and in another I've done --strip-unneeded
.
Considering file sizes, the original files where obviously the biggest, the files in strip-unneeded dir where the smallest, and the files in the strip-debug dir were in the middle.
Also, additionally running --strip-debug
against the files in the strip-unneeded dir has not changed the file sizes, meaning that --strip-debug
strips just some subset of what is stripped by --strip-unneeded
.
I've then compared section listing of all the three variants by running readelf -S
against all of them.
Looking at them, it could be seen that --strip-debug
strips the following sections: .debug_arranges
, .debug_info
, .debug_abbrev
, .debug_line
and .debug_str
, and also somewhat reduced the .symtab
and .strtab
sections.
--strip-unneeded
also additionally completely removes .symtab
and .strtab
sections.
I've then run readelf -S
against the debug binaries, which I'd got with the --only-keep-debug
flag. The sections there had all the sections removed by --strip-unneeded
. So, it not only contained .debug_arranges
, .debug_info
, .debug_abbrev
, .debug_line
and .debug_str
, but also .symtab
and .strtab
. And the sizes of the sections were almost identical to their original sizes.
I've then tried to step-by-step debug all the three variants and haven't noticed any difference between them. Also I've produced crashes and core dumps with all of them and then tried to debug against the core dumps - also no difference.
Versions used: gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609 GNU objcopy (GNU Binutils for Ubuntu) 2.26.1 GNU strip (GNU Binutils for Ubuntu) 2.26.1