Index: llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -286,10 +286,14 @@ 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]; Index: llvm/test/tools/llvm-symbolizer/split-dwarf-zero-signature-not-found.s =================================================================== --- /dev/null +++ llvm/test/tools/llvm-symbolizer/split-dwarf-zero-signature-not-found.s @@ -0,0 +1,112 @@ +# REQUIRES: x86-registered-target + +# RUN: llvm-mc --filetype=obj --triple x86_64-pc-linux %s -o %t --defsym MAIN=0 +# RUN: llvm-mc --filetype=obj --triple x86_64-pc-linux %s -o %t.dwp --defsym DWP=0 +# RUN: llvm-symbolizer --obj=%t --dwp=%t.dwp 0x0 | FileCheck %s +# CHECK-NOT: Stack dump + + .section .debug_abbrev,"",@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 + .text +F\I: + nop + + .section .debug_info,"",@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,"",@progbits + .quad A\I + .quad F\I + + .section .debug_ranges,"",@progbits +.Lranges\I: + .quad F\I + .quad F\I+1 + .quad 0 + .quad 0 +.endr +.endif + +.ifdef DWP +# This deliberately excludes compile unit 0. 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. +.irpc I,1 + .section .debug_abbrev.dwo,"e",@progbits +.Labbrev\I: + .byte \I*10+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_end\I: + + .section .debug_info.dwo,"e",@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 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte \I*10+1 # Abbrev DW_TAG_compile_unit + .asciz "Hand-written DWARF" # DW_AT_producer + .byte '0'+\I, '.', 'c', 0 # DW_AT_name +.Ldebug_info_end\I: +.endr + + .section .debug_cu_index,"",@progbits + .short 2 # DWARF version number + .short 0 # Reserved + .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 + +.irpc I,1 + .long .Lcu_begin\I-.debug_info.dwo + .long .Labbrev\I-.debug_abbrev.dwo +.endr +.irpc I,1 + .long .Ldebug_info_end\I-.Lcu_begin\I + .long .Labbrev_end\I-.Labbrev\I +.endr + +.endif