[PATCH] D46628: [ELF] Add --strip-debug-non-line option

David Blaikie via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 26 08:43:30 PDT 2019


dblaikie added a comment.

In D46628#1558438 <https://reviews.llvm.org/D46628#1558438>, @luciang wrote:

> I found that clang 9 (and previous versions) also generates non CU info in `.debug_info` with `-gmlt`:
>
>   $ echo 'struct A { A() {} int a = 0; }; struct B { B(); A a; }; B::B() {}' | clang++ -x c++ -O2 -gmlt -o clang-02-gmlt.o -c - && llvm-dwarfdump --debug-info clang-02-gmlt.o
>   clang-02-gmlt.o:	file format ELF64-x86-64
>  
>   .debug_info contents:
>   0x00000000: Compile Unit: length = 0x00000051 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000055)
>  
>   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	("-")
>                 DW_AT_stmt_list	(0x00000000)
>                 DW_AT_comp_dir	("/tmp/test")
>                 DW_AT_low_pc	(0x0000000000000000)
>                 DW_AT_high_pc	(0x0000000000000007)
>  
>   0x0000002a:   DW_TAG_subprogram
>                   DW_AT_name	("A")
>  
>   0x0000002f:   DW_TAG_subprogram
>                   DW_AT_low_pc	(0x0000000000000000)
>                   DW_AT_high_pc	(0x0000000000000007)
>                   DW_AT_name	("B")
>  
>   0x00000040:     DW_TAG_inlined_subroutine
>                     DW_AT_abstract_origin	(0x0000002a "A")
>                     DW_AT_low_pc	(0x0000000000000000)
>                     DW_AT_high_pc	(0x0000000000000006)
>                     DW_AT_call_file	("/tmp/test/<stdin>")
>                     DW_AT_call_line	(1)
>  
>   0x00000053:     NULL
>  
>   0x00000054:   NULL
>
>
> Note that dropping with `-O0` or `-O1` `.debug_info` the `DW_TAG_subprogram` and `DW_TAG_inlined_subroutine` DIEs are not generated. `-Os`, `-O2` and `-O3` do.
>
>   $ echo 'struct A { A() {} int a = 0; }; struct B { B(); A a; }; B::B() {}' | clang++ -x c++ -O0 -gmlt -o clang-02-gmlt.o -c - && llvm-dwarfdump --debug-info clang-02-gmlt.o
>   clang-02-gmlt.o:	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	("-")
>                 DW_AT_stmt_list	(0x00000000)
>                 DW_AT_comp_dir	("/tmp/test")
>                 DW_AT_low_pc	(0x0000000000000000)
>                 DW_AT_ranges	(0x00000000
>                    [0x0000000000000000, 0x000000000000001b)
>                    [0x0000000000000000, 0x0000000000000014))
>
>
>
>
>  ---
>
> The proposed `--strip-debug-non-line` is an improvement on top of what current gcc/clang produce with `-g1` or `-gmlt`:
>
>   $ echo 'struct A { A() {} int a = 0; }; struct B { B(); A a; }; B::B() {}; int main(){ return 0;}' | clang++ -x c++ -O2 -gmlt -o clang-02-gmlt-strip -fuse-ld=lld -Wl,--strip-debug-non-line - && llvm-dwarfdump --debug-info clang-02-gmlt-strip
>   clang-02-gmlt-strip:	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	("-")
>                 DW_AT_stmt_list	(0x00000000)
>                 DW_AT_comp_dir	("/tmp/test")
>                 DW_AT_low_pc	(0x0000000000201100)
>                 DW_AT_high_pc	(0x0000000000201113)
>
>
> vs
>
>   $ echo 'struct A { A() {} int a = 0; }; struct B { B(); A a; }; B::B() {}; int main(){ return 0;}' | clang++ -x c++ -O2 -gmlt -o clang-02-gmlt -fuse-ld=lld  - && llvm-dwarfdump --debug-info clang-02-gmlt
>   clang-02-gmlt:	file format ELF64-x86-64
>  
>   .debug_info contents:
>   0x00000000: Compile Unit: length = 0x00000051 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000055)
>  
>   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	("-")
>                 DW_AT_stmt_list	(0x00000000)
>                 DW_AT_comp_dir	("/tmp/test")
>                 DW_AT_low_pc	(0x0000000000201100)
>                 DW_AT_high_pc	(0x0000000000201113)
>  
>   0x0000002a:   DW_TAG_subprogram
>                   DW_AT_name	("A")
>  
>   0x0000002f:   DW_TAG_subprogram
>                   DW_AT_low_pc	(0x0000000000201100)
>                   DW_AT_high_pc	(0x0000000000201107)
>                   DW_AT_name	("B")
>  
>   0x00000040:     DW_TAG_inlined_subroutine
>                     DW_AT_abstract_origin	(0x0000002a "A")
>                     DW_AT_low_pc	(0x0000000000201100)
>                     DW_AT_high_pc	(0x0000000000201106)
>                     DW_AT_call_file	("/tmp/test/<stdin>")
>                     DW_AT_call_line	(1)
>  
>   0x00000053:     NULL
>  
>   0x00000054:   NULL
>
>
> (I'll look into what triggers `-gmlt` + `-O2` to generate the extra debug sections separately).


While all this (the behavior of gmlt) seems unrelated to this patch, really (I agree/understand your description - if you really want to be able to compile things once and link them into debug-ish and non-debug-ish forms, something like the --strip-debug-non-line sounds nice though I can also understand some push-back against it, since it's necessarily going to make broken DWARF, well, except in DWARFv5 where there's an intentional way to support line-table-only debug info (the line table has its own string table, so you can strip /everything/ (including debug_info) except debug_line and debug_line_str, I believe) - perahps that'd be a good way to implement this in a more principled way - work for DWARFv5 only (it wouldn't necessarily need/want to check DWARF version, but be designed to work correctly for DWARFv5 & be weird/bad/problematic before that))

So, while the behavior of gmlt doesn't seem too relevant - I can explain what it does, why GCC's and Clang's are designed the way they are. Their goal is to be able to produce correct back traces, that means needing to describe inline stack frames. Both GCC and Clang used to describe all functions - but I made changes to Clang to reduce the cost of this feature by only describing functions that have inlining in them (or are inlined/need to share a description for that purpose). So the simplest test case that always produces more than just the CU DIE is:

  void f1();
  __attribute__((always_inline)) void f2() {
    f1();
  }
  void f3() {
    f2();
  }


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D46628/new/

https://reviews.llvm.org/D46628





More information about the llvm-commits mailing list