[PATCH] D71932: [DWARF] Better detect errors in Address Range Tables.

Igor Kudrin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 22 19:22:54 PDT 2020


ikudrin marked an inline comment as done.
ikudrin added inline comments.


================
Comment at: llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp:167-171
+      return createStringError(
+          errc::invalid_argument,
+          "address range table at offset 0x%" PRIx64
+          " has an invalid tuple (length = 0) at offset 0x%" PRIx64,
+          Offset, *offset_ptr - tuple_size);
----------------
dblaikie wrote:
> jhenderson wrote:
> > @ikudrin, I know this was committed a while back, but I only just ran into this.
> > 
> > Why was this check added? There's nothing in the DWARF spec that I know of that requires a non-zero length for all non-terminating entries. In our Sony linker, prior to the new tombstoning functionality that has recently been implemented, we would patch a reference in the .debug_aranges to have a zero length, and -1 for the address. This used to be fine, but recent versions of llvm-dwarfdump now can't dump this. Even without the Sony changes, there are occasionally functions in the DWARF with zero length (see also my post earlier today on the llvm-dev list for .debug_loc and zero length entry descriptions).
> Yep, +1 we should allow empty ranges here. Even with better tombstoning - a) backwards compatibility with existing implementations (ld.bfd) b) even with proper tombstoning, it'd effectively create an empty range (-2, -2) - though arguably in that case we should detect the tombstoning first, before considering the range size/other issues
> 
> Here's a reproduction with commonly accessible tools:
> 
> ```
> $ cat range2.cpp
> void f1() {
> }
> void f2() {
> }
> int main() {
>   f1();
> }
> $ clang++ range2.cpp -g -fuse-ld=bfd -ffunction-sections -gdwarf-aranges -Wl,-gc-sections
> $ llvm-dwarfdump -verify a.out
> Verifying a.out:        file format elf64-x86-64
> Verifying .debug_abbrev...
> Verifying .debug_info Unit Header Chain...
> error: DIE address ranges are not contained in its parent's ranges:
> 0x0000000b: DW_TAG_compile_unit
>               DW_AT_producer    ("clang version 12.0.0 (git at github.com:llvm/llvm-project.git 80e6844e28f10c1c2c31b301c3ef980c7a11ee6b)")
>               DW_AT_language    (DW_LANG_C_plus_plus_14)
>               DW_AT_name        ("range2.cpp")
>               DW_AT_stmt_list   (0x00000000)
>               DW_AT_comp_dir    ("/usr/local/google/home/blaikie/dev/scratch")
>               DW_AT_low_pc      (0x0000000000000000)
>               DW_AT_ranges      (0x00000000
>                  [0x0000000000401110, 0x0000000000401116)
>                  [0x0000000000000001, 0x0000000000000001)
>                  [0x0000000000401120, 0x000000000040112d))
> 
> 0x00000043:   DW_TAG_subprogram
>                 DW_AT_low_pc    (0x0000000000000000)
>                 DW_AT_high_pc   (0x0000000000000006)
>                 DW_AT_frame_base        (DW_OP_reg6)
>                 DW_AT_linkage_name      ("_Z2f2v")
>                 DW_AT_name      ("f2")
>                 DW_AT_decl_file ("/usr/local/google/home/blaikie/dev/scratch/range2.cpp")
>                 DW_AT_decl_line (3)
>                 DW_AT_external  (true)
> 
> Verifying .debug_info references...
> Verifying .debug_types Unit Header Chain...
> Errors detected.
> ```
> Similarly, with GCC (which produces debug_aranges by default):
> ```
> $ g++ range2.cpp -g -fuse-ld=bfd -ffunction-sections -Wl,-gc-sections
> $ llvm-dwarfdump -verify a.out
> Verifying a.out:        file format elf64-x86-64
> Verifying .debug_abbrev...
> Verifying .debug_info Unit Header Chain...
> error: DIE address ranges are not contained in its parent's ranges:
> 0x0000000b: DW_TAG_compile_unit
>               DW_AT_producer    ("GNU C++14 10.0.0 20200111 (experimental) -mtune=generic -march=x86-64 -g -fuse-ld=bfd -ffunction-sections")
>               DW_AT_language    (DW_LANG_C_plus_plus)
>               DW_AT_name        ("range2.cpp")
>               DW_AT_comp_dir    ("/usr/local/google/home/blaikie/dev/scratch")
>               DW_AT_ranges      (0x00000000
>                  [0x0000000000401102, 0x0000000000401109)
>                  [0x0000000000000001, 0x0000000000000001)
>                  [0x0000000000401109, 0x0000000000401119))
>               DW_AT_low_pc      (0x0000000000000000)
>               DW_AT_stmt_list   (0x00000000)
> 
> 0x0000004e:   DW_TAG_subprogram
>                 DW_AT_external  (true)
>                 DW_AT_name      ("f2")
>                 DW_AT_decl_file ("/usr/local/google/home/blaikie/dev/scratch/range2.cpp")
>                 DW_AT_decl_line (3)
>                 DW_AT_decl_column       (0x06)
>                 DW_AT_linkage_name      ("_Z2f2v")
>                 DW_AT_low_pc    (0x0000000000000000)
>                 DW_AT_high_pc   (0x0000000000000007)
>                 DW_AT_frame_base        (DW_OP_call_frame_cfa)
>                 DW_AT_GNU_all_call_sites        (true)
> 
> Verifying .debug_info references...
> Verifying .debug_types Unit Header Chain...
> Errors detected.
> ```
> Why was this check added? There's nothing in the DWARF spec that I know of that requires a non-zero length for all non-terminating entries.

I tried to follow the Standard here, see 6.1.2 at DWARFv5, p. 148:
> Each descriptor is a triple consisting of a segment selector, the beginning address within that segment of a range of text or data covered by some entry owned by the corresponding compilation unit, followed by the **non-zero** length of that range.

It looks like the DWARF spec should be updated to reflect the practice.

@jhenderson, it would be great if you prepare the fix. I'll be AFK for a couple of weeks.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D71932





More information about the llvm-commits mailing list