[llvm-branch-commits] [llvm] fd623ba - Fix crash after looking up dwo_id=0 in CU index.

Tom Stellard via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Nov 25 22:44:57 PST 2020


Author: Jorge Gorbe Moya
Date: 2020-11-26T01:44:01-05:00
New Revision: fd623ba8061dda6f489390ada6b11dff58a4d470

URL: https://github.com/llvm/llvm-project/commit/fd623ba8061dda6f489390ada6b11dff58a4d470
DIFF: https://github.com/llvm/llvm-project/commit/fd623ba8061dda6f489390ada6b11dff58a4d470.diff

LOG: Fix crash after looking up dwo_id=0 in CU index.

In the current state, if getFromHash(0) is called and there's no CU with
dwo_id=0, the lookup will stop at an empty slot, then the check
`Rows[H].getSignature() != S` won't cause the lookup to fail and return
a nullptr (as it should), because the empty slot has a 0 in the
signature field, and a pointer to the empty slot will be incorrectly
returned.

This patch fixes this by using the index field in the hash entry to
check for empty slots: signature = 0 can match a valid hash but
according to the spec the index for an occupied slot will always be
non-zero.

Differential Revision: https://reviews.llvm.org/D91670

(cherry picked from commit 314a0d73a8444e3b0c1a0d0de7d615d9448af1c9)

Added: 
    llvm/test/tools/llvm-symbolizer/split-dwarf-zero-signature-not-found.s

Modified: 
    llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
index 3d4cecce27db1..d27fd08db14e3 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
@@ -286,10 +286,14 @@ const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const {
 
   auto H = S & Mask;
   auto HP = ((S >> 32) & Mask) | 1;
-  while (Rows[H].getSignature() != S && Rows[H].getSignature() != 0)
+  // The spec says "while 0 is a valid hash value, the row index in a used slot
+  // will always be non-zero". Loop until we find a match or an empty slot.
+  while (Rows[H].getSignature() != S && Rows[H].Index != nullptr)
     H = (H + HP) & Mask;
 
-  if (Rows[H].getSignature() != S)
+  // If the slot is empty, we don't care whether the signature matches (it could
+  // be zero and still match the zeros in the empty slot).
+  if (Rows[H].Index == nullptr)
     return nullptr;
 
   return &Rows[H];

diff  --git a/llvm/test/tools/llvm-symbolizer/split-dwarf-zero-signature-not-found.s b/llvm/test/tools/llvm-symbolizer/split-dwarf-zero-signature-not-found.s
new file mode 100644
index 0000000000000..de3cc738e1ff1
--- /dev/null
+++ b/llvm/test/tools/llvm-symbolizer/split-dwarf-zero-signature-not-found.s
@@ -0,0 +1,118 @@
+## This test checks that looking up a zero hash in the .debug_cu_index hash
+## table works correctly when there's no CU with signature = 0.
+##
+## LLVM used to check just the signature bits to decide if the hash lookup ended
+## at a match or at an empty slot. This is wrong when signature = 0 because
+## empty slots have all zeros in the signature field too, and LLVM would return
+## the empty slot as a valid result.
+
+# REQUIRES: x86-registered-target
+
+# RUN: llvm-mc --filetype=obj --triple x86_64 %s -o %t --defsym MAIN=0
+# RUN: llvm-mc --filetype=obj --triple x86_64 %s -o %t.dwp
+# RUN: llvm-symbolizer --obj=%t --dwp=%t.dwp 0x0 | FileCheck %s
+
+## This expected output is very uninteresting, but it's better than a crash.
+# CHECK: ??:0:0
+
+        .section        .debug_abbrev,"", at progbits
+        .byte   1                       # Abbreviation Code
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   0                       # DW_CHILDREN_no
+        .ascii  "\260B"                 # DW_AT_GNU_dwo_name
+        .byte   8                       # DW_FORM_string
+        .ascii  "\261B"                 # DW_AT_GNU_dwo_id
+        .byte   7                       # DW_FORM_data8
+        .ascii  "\263B"                 # DW_AT_GNU_addr_base
+        .byte   23                      # DW_FORM_sec_offset
+        .byte   85                      # DW_AT_ranges
+        .byte   23                      # DW_FORM_sec_offset
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   0                       # EOM(3)
+
+## Create two CUs, with dwo_ids 0 and 1 respectively.
+.ifdef MAIN
+.irpc I,01
+        .data
+A\I:
+        .long \I
+
+        .text
+F\I:
+        nop
+
+        .section        .debug_info,"", at progbits
+.Lcu_begin\I:
+        .long   .Ldebug_info_end\I-.Ldebug_info_start\I # Length of Unit
+.Ldebug_info_start\I:
+        .short  4                       # DWARF version number
+        .long   .debug_abbrev           # Offset Into Abbrev. Section
+        .byte   8                       # Address Size (in bytes)
+        .byte   1                       # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit
+        .asciz  "A.dwo"                 # DW_AT_GNU_dwo_name
+        .quad   \I                      # DW_AT_GNU_dwo_id
+        .long   .debug_addr             # DW_AT_GNU_addr_base
+        .long   .Lranges\I              # DW_AT_ranges
+.Ldebug_info_end\I:
+
+        .section        .debug_addr,"", at progbits
+        .quad   A\I
+        .quad   F\I
+
+        .section        .debug_ranges,"", at progbits
+.Lranges\I:
+        .quad   F\I
+        .quad   F\I+1
+        .quad   0
+        .quad   0
+.endr
+.else
+## Deliberately omit compile unit 0 in the DWP. We want to check the case where
+## a signature = 0 matches an empty hash slot in .debug_cu_index and the index
+## in the parallel table has to be checked.
+        .section        .debug_abbrev.dwo,"e", at progbits
+.Labbrev1:
+        .byte   1                       # Abbreviation Code
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   0                       # DW_CHILDREN_no
+        .byte   37                      # DW_AT_producer
+        .byte   8                       # DW_FORM_string
+        .byte   3                       # DW_AT_name
+        .byte   8                       # DW_FORM_string
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   0                       # EOM(3)
+.Labbrev_end1:
+
+        .section        .debug_info.dwo,"e", at progbits
+.Lcu_begin1:
+        .long   .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+        .short  4                       # DWARF version number
+        .long   0                       # Offset Into Abbrev. Section
+        .byte   8                       # Address Size (in bytes)
+        .byte   1                       # Abbrev DW_TAG_compile_unit
+        .asciz  "Hand-written DWARF"    # DW_AT_producer
+        .byte   '1', '.', 'c', 0        # DW_AT_name
+.Ldebug_info_end1:
+
+        .section        .debug_cu_index,"", at progbits
+        .long   2                       # DWARF version number
+        .long   2                       # Section count
+        .long   1                       # Unit count
+        .long   8                       # Slot count
+
+        .quad   1, 0, 0, 0, 0, 0, 0, 0  # Hash table
+        .long   1, 0, 0, 0, 0, 0, 0, 0  # Index table
+
+        .long   1                       # DW_SECT_INFO
+        .long   3                       # DW_SECT_ABBREV
+
+        .long .Lcu_begin1-.debug_info.dwo
+        .long .Labbrev1-.debug_abbrev.dwo
+
+        .long .Ldebug_info_end1-.Lcu_begin1
+        .long .Labbrev_end1-.Labbrev1
+
+.endif


        


More information about the llvm-branch-commits mailing list