diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1077,33 +1077,6 @@ return None; } -static Optional -getLocationFrameOffset(DWARFCompileUnit *CU, DWARFFormValue &FormValue, - Optional FrameBaseReg) { - if (Optional> Location = FormValue.getAsBlock()) { - return getExpressionFrameOffset(*Location, FrameBaseReg); - } else if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { - uint64_t Offset = *FormValue.getAsSectionOffset(); - const DWARFLocationTable &LocTable = CU->getLocationTable(); - Optional FrameOffset; - Error E = LocTable.visitLocationList( - &Offset, [&](const DWARFLocationEntry &Entry) { - if (Entry.Kind == dwarf::DW_LLE_base_address || - Entry.Kind == dwarf::DW_LLE_base_addressx || - Entry.Kind == dwarf::DW_LLE_end_of_list) { - return true; - } - if ((FrameOffset = getExpressionFrameOffset(Entry.Loc, FrameBaseReg))) - return false; - return true; - }); - if (E) - return None; - return FrameOffset; - } - return None; -} - void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die, std::vector &Result) { if (Die.getTag() == DW_TAG_variable || @@ -1119,8 +1092,19 @@ (*Expr)[0] <= DW_OP_reg31) { FrameBaseReg = (*Expr)[0] - DW_OP_reg0; } - if (auto LocationAttr = Die.find(DW_AT_location)) - Local.FrameOffset = getLocationFrameOffset(CU, *LocationAttr, FrameBaseReg); + + if (Expected> Loc = + Die.getLocations(DW_AT_location)) { + for (const auto &Entry : *Loc) { + if (Optional FrameOffset = + getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) { + Local.FrameOffset = *FrameOffset; + break; + } + } + } else { + consumeError(Loc.takeError()); + } if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset)) Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant(); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -495,8 +495,18 @@ return createStringError(inconvertibleErrorCode(), "No %s", dwarf::AttributeString(Attr).data()); - if (Optional Off = Location->getAsSectionOffset()) - return U->findLoclistFromOffset(*Off); + if (Optional Off = Location->getAsSectionOffset()) { + uint64_t Offset = *Off; + + if (Location->getForm() == DW_FORM_loclistx) { + if (auto LoclistOffset = U->getLoclistOffset(Offset)) + Offset = *LoclistOffset; + else + return createStringError(inconvertibleErrorCode(), + "Loclist table not found"); + } + return U->findLoclistFromOffset(Offset); + } if (Optional> Expr = Location->getAsBlock()) { return DWARFLocationExpressionsVector{ diff --git a/llvm/test/DebugInfo/AArch64/frame-loclistx.s b/llvm/test/DebugInfo/AArch64/frame-loclistx.s new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/AArch64/frame-loclistx.s @@ -0,0 +1,283 @@ +## Test dwarf-5 DW_AT_location [DW_FORM_loclistx]. + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android -o %t.o %s +# RUN: echo 'FRAME %t.o 0x4' | llvm-symbolizer | FileCheck %s + +## DW_AT_location (indexed (0x0) loclist = 0x00000010: +## [0x0000000000000010, 0x0000000000000018): DW_OP_consts +1, DW_OP_stack_value +## [0x0000000000000018, 0x0000000000000028): DW_OP_breg29 W29-4) +# CHECK: f +# CHECK-NEXT: x +# CHECK-NEXT: {{.*}}dbg.cc:5 +# CHECK-NEXT: -4 4 ?? + + .text + .file "dbg.cc" + .file 0 "/tmp" "/tmp/dbg.cc" md5 0xb9e2d9cf63655505d60c734686e688fd + .file 1 "dbg.cc" md5 0xb9e2d9cf63655505d60c734686e688fd + .globl f # -- Begin function f + .p2align 2 + .type f,@function +f: # @f +.Lfunc_begin0: + .loc 1 4 0 # dbg.cc:4:0 + .cfi_startproc +# %bb.0: + sub sp, sp, #32 # =32 + stp x29, x30, [sp, #16] # 16-byte Folded Spill + add x29, sp, #16 # =16 + .cfi_def_cfa w29, 16 + .cfi_offset w30, -8 + .cfi_offset w29, -16 + mov w8, #1 +.Ltmp0: + #DEBUG_VALUE: f:x <- 1 + .loc 1 6 3 prologue_end # dbg.cc:6:3 + sub x0, x29, #4 # =4 + .loc 1 5 7 # dbg.cc:5:7 + stur w8, [x29, #-4] +.Ltmp1: + #DEBUG_VALUE: f:x <- [DW_OP_constu 4, DW_OP_minus, DW_OP_deref] $fp + .loc 1 6 3 # dbg.cc:6:3 + bl use +.Ltmp2: + .loc 1 7 1 # dbg.cc:7:1 + ldp x29, x30, [sp, #16] # 16-byte Folded Reload + add sp, sp, #32 # =32 + ret +.Ltmp3: +.Lfunc_end0: + .size f, .Lfunc_end0-f + .cfi_endproc + # -- End function + .section .debug_str_offsets,"",@progbits + .word 32 + .hword 5 + .hword 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 10.0.0 (git@github.com:llvm/llvm-project.git 57e2b50509793c72f562e8a08523f7ab664adfcd)" # string offset=0 +.Linfo_string1: + .asciz "/tmp/dbg.cc" # string offset=101 +.Linfo_string2: + .asciz "/tmp" # string offset=113 +.Linfo_string3: + .asciz "use" # string offset=118 +.Linfo_string4: + .asciz "f" # string offset=122 +.Linfo_string5: + .asciz "x" # string offset=124 +.Linfo_string6: + .asciz "int" # string offset=126 + .section .debug_str_offsets,"",@progbits + .word .Linfo_string0 + .word .Linfo_string1 + .word .Linfo_string2 + .word .Linfo_string3 + .word .Linfo_string4 + .word .Linfo_string5 + .word .Linfo_string6 + .section .debug_loclists,"",@progbits + .word .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 # Length +.Ldebug_loclist_table_start0: + .hword 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .word 1 # Offset entry count +.Lloclists_table_base0: + .word .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 1 # 1 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 2 # Loc expr size + .byte 141 # DW_OP_breg29 + .byte 124 # -4 + .byte 0 # DW_LLE_end_of_list +.Ldebug_loclist_table_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 72 # DW_TAG_call_site + .byte 0 # DW_CHILDREN_no + .byte 127 # DW_AT_call_origin + .byte 19 # DW_FORM_ref4 + .byte 125 # DW_AT_call_return_pc + .byte 1 # DW_FORM_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .word .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .hword 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .word .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x4d DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .hword 33 # DW_AT_language + .byte 1 # DW_AT_name + .word .Lstr_offsets_base0 # DW_AT_str_offsets_base + .word .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .word .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .word .Laddr_table_base0 # DW_AT_addr_base + .word .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0xa DW_TAG_subprogram + .byte 3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_declaration + # DW_AT_external + .byte 3 # Abbrev [3] 0x2b:0x5 DW_TAG_formal_parameter + .word 49 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x31:0x1 DW_TAG_pointer_type + .byte 5 # Abbrev [5] 0x32:0x22 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .word .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 109 + # DW_AT_call_all_calls + .byte 4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + # DW_AT_external + .byte 6 # Abbrev [6] 0x3d:0x9 DW_TAG_variable + .byte 0 # DW_AT_location + .byte 5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .word 84 # DW_AT_type + .byte 7 # Abbrev [7] 0x46:0xd DW_TAG_call_site + .word 39 # DW_AT_call_origin + .xword .Ltmp2-.Lfunc_begin0 # DW_AT_call_return_pc + .byte 0 # End Of Children Mark + .byte 8 # Abbrev [8] 0x54:0x4 DW_TAG_base_type + .byte 6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_addr,"",@progbits + .word .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .hword 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .xword .Lfunc_begin0 +.Ldebug_addr_end0: + .ident "clang version 10.0.0 (git@github.com:llvm/llvm-project.git 57e2b50509793c72f562e8a08523f7ab664adfcd)" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: