how to use strip in conjunction with split-dwarf?

I am currently trying to use the --gsplit-dwarf gcc flag in order to automatically create and separate debug symbols from build libraries/executables. More info on DWARF Obj files. However, what I have observed is that split-dwarf still leaves a lot of unnecessary information in the remaining .o file. What I would like to do is use strip to remove that info but still have it be compatible for debugging using the .dwo/.dwp files; however, it seems that this does not work. I want to strip the release executables for space savings and for further obfuscation, and was hoping split-dwarf would allow me to do so.

Additional reference

Example app app.cpp

 
int main()
{
  int a = 1;
  std::cout << "Split DWARF test" << std::endl;
 
  return 0;
}

Compiling:

g++ -c -gsplit-dwarf app.cpp -o app_dwarf.o

Linking:

g++ app_dwarf.o -o app_dwarf -fuse-ld=gold -Wl,--gdb-index

Examine the build artifact:

readelf -wi app_dwarf
Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
   Length:        0x30 (32-bit)
   Version:       4
   Abbrev Offset: 0x0
   Pointer Size:  8
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_low_pc      : 0x8da
    <14>   DW_AT_high_pc     : 0x9c
    <1c>   DW_AT_stmt_list   : 0x0
    <20>   DW_AT_GNU_dwo_name: (indirect string, offset: 0x0): app_dwarf.dwo
    <24>   DW_AT_comp_dir    : (indirect string, offset: 0xe): /home/ross/Desktop/dwarf_test
    <28>   DW_AT_GNU_pubnames: 1
    <28>   DW_AT_GNU_addr_base: 0x0
    <2c>   DW_AT_GNU_dwo_id  : 0xdf705add23e14a0b

Can see it references the dwo… this also works in GDB and does not work when I remove the dwo file. However, if I look at the symbol table for the build artifact (the executable), the full symbol table is still there.

If I strip the executable, the table is removed and the size is reduced, but it also strips away the debug_info that references the dwo file.

Also separately, shouldn’t the symbol table be included in the dwo file?

Hoping some direction can be provided here that will allow me to capture all of the debug info outside of the artifact itself to be kept for debugging at a later time.

The alternate way to do this would be a multi stage approach where we do something like:

g++ -g -o app_dwarf app.cpp 
objcopy --only-keep-debug app_dwarf app_dwarf.debug
objcopy --add-gnu-debuglink=app_dwarf.debug app_dwarf
strip --strip-unneeded app_dwarf

But would need to divide that up into compile and link steps so that build times and resources are affected less. I thought that was the whole point of the single gsplit-dwarf flag, though.

Answer

If I strip the executable, the table is removed and the size is reduced, but it also strips away the debug_info that references the dwo file.

Correct.

The right way is to keep the unstripped copy of the executable and the .dwp file, while distributing the stripped copy to end-users.

I thought that was the whole point of the single gsplit-dwarf flag, though.

No.

The motivation is explained here. To quote: “By splitting the debug information into two parts at compile time — one part that remains in the .o file and another part that is written to a parallel .dwo (“DWARF object”) file — we can reduce the total size of the object files processed by the linker.”

If the total size of object files processed by the linker isn’t a problem for you (it rarely is for binaries under 1 GiB), then you don’t really need fission (though it may still speed up your link a bit).