How should I package debug info for clang/clang tool efficiently?

By efficiency, I mean that everything related to debug stuff lives in a different file to reduce memory consumption in the regular case when no crash happens.
However, on a crash, I’d like llvm-symbolizer to find the related debug info file and use it for symbolizing the stack trace.

Do you have any guidance on how can I accomplish this?

I already tried a couple of options, but none of them really worked:

  • objcopy --only-keep-debug; strip clang then --add-gnu-debuglink: Did not symbolize. While the debinfo file was unacceptably huge.
  • building with -gsplit-dwarf then packing the dwo files into a single dwp file; strip clang then --add-gnu-debuglink to the dwp: Did not symbolize. The size of the dwp file was sensible, so I’d like to pursue this direction.

Currently I’m building clang with -DCMAKEBUILD_TYPE=RelWithDebInfo -DBUILD_SHARED_LIBS=OFF -DLLVM_USE_SPLIT_DWARF=ON CMake options.

cd build/bin
llvm-dwp -e=clang-14 -o=clang-14.dwp
llvm-objcopy --add-gnu-debuglink=clang-14.dwp clang-14
llvm-strip -g clang-14
mkdir .debug
mv clang-14.dwp .debug/

But the line locations are not resolved in the stack traces.

@dblaikie Do you know anyone who could give me some hints?

reduce memory consumption in the regular case when no crash happens

What memory usage, exactly? The debug info sections in the binary (when not using Split DWARF or strip/debuglink/etc) shouldn’t be loaded into memory. I wouldn’t expect they’d effect memory usage of the running program if the debug info is never touched/loaded/etc.

only-keep-debug+debuglink

Seems to work for me? So might need more info about that

$ clang++-tot test.cpp -g
$ cp a.out a.out.debug
$ objcopy --only-keep-debug a.out.debug
$ llvm-symbolizer --obj=a.out 0x401110
main
/usr/local/google/home/blaikie/dev/scratch/test.cpp:1:0
$ strip a.out
$ llvm-symbolizer --obj=a.out 0x401110
??
??:0:0
$ objcopy --add-gnu-debuglink=a.out.debug a.out
$ llvm-symbolizer --obj=a.out 0x401110
main
/usr/local/google/home/blaikie/dev/scratch/test.cpp:1:0

While the debinfo file was unacceptably huge.

I’m not sure why the debuginfo would be significantly different in size here compared to with Split DWARF (well, if you’re using DWARFv5 - if you’re using DWARFv4, then yeah, there’s some benefits available to v4+Split DWARF that aren’t available to v4 non-split, but these were all rolled into v5 so they should be equally available in v5 split and non-split)

  • building with -gsplit-dwarf then packing the dwo files into a single dwp file; strip clang then --add-gnu-debuglink to the dwp : Did not symbolize. The size of the dwp file was sensible, so I’d like to pursue this direction.

I don’t think anyone’s made debuglink+dwp have any connection - currently the only way to find a dwp file from an executable is for the dwp file to be named <executable>.dwp, or to pass it explicitly to the symbolizer:

$ llvm-symbolizer --obj=a.out 0x401131
main
/usr/local/google/home/blaikie/dev/scratch/test.cpp:4:3
$ llvm-symbolizer --obj=a.out 0x401131 --dwp=x.dwp
f2()
/usr/local/google/home/blaikie/dev/scratch/test.cpp:4:3
main
/usr/local/google/home/blaikie/dev/scratch/test.cpp:7:3

(testing with some inlining, showing. that without the dwp file it can get the line number, but doesn’t have the inlining)

Thanks for the thorough answer!
I’ll look into this.