Add support for gold's --strip-debug-non-line added in May 2008 (see: https://sourceware.org/ml/binutils/2008-05/msg00232.html)
Stripping strategy:
- .debug_info
- .debug_info is usually the largest debug section, but for file:lineno info we don't need most of the DIEs in it.
- The top-level DIE corresponds to the CU and contains the name of the path to the file DW_AT_comp_dir/DW_AT_name.
- Keep top-level compilation unit DIEs and skip children (recursively).
- .debug_abbrev - only keep DW_TAG_compile_unit abbreviations for these top-level compilation unit DIEs
- .debug_aranges - update offsets into .debug_info as they changed after stripping children of entries.
Test Plan: check-lld: added single-CU and multi-CU tests
Also tested manually that gdb is able to print file:lineno info.
$ cat foo.cpp #include <stdexcept> void foo() { throw std::exception(); } $ cat bar.cpp void foo(); int main() { foo(); }
$ clang++ -g -gdwarf-aranges -c -o bar.o bar.cpp $ clang++ -g -gdwarf-aranges -c -o foo.o foo.cpp $ clang++ foo.o bar.o -fuse-ld=lld -Xlinker --no-threads -Xlinker --strip-debug-non-line -o bar-lld-strip-debug-non-line
$ llvm-dwarfdump bar-lld-strip-debug-non-line bar-lld-strip-debug-non-line: file format ELF64-x86-64 .debug_info contents: 0x00000000: Compile Unit: length = 0x00000026 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x0000002a) 0x0000000b: DW_TAG_compile_unit DW_AT_producer ("clang version 9.0.0 (https://github.com/llvm/llvm-project 01a99c0aa5ae5be47ea62bd6c87ca6bb63f5a454)") DW_AT_language (DW_LANG_C_plus_plus) DW_AT_name ("bar.cpp") DW_AT_stmt_list (0x00000000) DW_AT_comp_dir ("/home/lucian/local/github/llvm-project/test") DW_AT_low_pc (0x0000000000201100) DW_AT_high_pc (0x000000000020110d) 0x0000002a: Compile Unit: length = 0x00000026 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000054) 0x00000035: DW_TAG_compile_unit DW_AT_producer ("clang version 9.0.0 (https://github.com/llvm/llvm-project 01a99c0aa5ae5be47ea62bd6c87ca6bb63f5a454)") DW_AT_language (DW_LANG_C_plus_plus) DW_AT_name ("foo.cpp") DW_AT_stmt_list (0x00000042) DW_AT_comp_dir ("/home/lucian/local/github/llvm-project/test") DW_AT_low_pc (0x0000000000000000) DW_AT_ranges (0x00000000 [0x0000000000201110, 0x0000000000201154) [0x0000000000201160, 0x0000000000201181))
$ llvm-dwarfdump --verify bar-lld-strip-debug-non-line | less Verifying bar-lld-strip-debug-non-line: file format ELF64-x86-64 Verifying .debug_abbrev... Verifying .debug_info Unit Header Chain... Verifying .debug_info references... Verifying .debug_types Unit Header Chain... No errors.
gdb ./bar-lld-strip-debug-non-line-compress-debug-sections -batch --ex run --ex bt --ex quit 3.6.3rc1+ (default, Feb 5 2019, 15:51:57) [GCC 5.x 20180625 (Facebook) 5.5.0+] Script information not found in binary, assuming oldest version Type "fbload" to load fb-specific gdb extensions. terminate called after throwing an instance of 'std::exception' what(): std::exception Program received signal SIGABRT, Aborted. 0x00007ffff7225277 in raise () from /lib64/libc.so.6 #0 0x00007ffff7225277 in raise () from /lib64/libc.so.6 #1 0x00007ffff7226968 in abort () from /lib64/libc.so.6 #2 0x00007ffff7b347d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6 #3 0x00007ffff7b32746 in ?? () from /lib64/libstdc++.so.6 #4 0x00007ffff7b32773 in std::terminate() () from /lib64/libstdc++.so.6 #5 0x00007ffff7b32993 in __cxa_throw () from /lib64/libstdc++.so.6 #6 0x0000000000201154 in foo() () at foo.cpp:2 #7 0x0000000000201109 in main () at bar.cpp:2 A debugging session is active. Inferior 1 [process 3496864] will be killed. Quit anyway? (y or n) [answered Y; input not from terminal]
Since there is a total order, this can be ordered by the strip level: None, DebugNonLine, Debug, All.