mstorsjo updated this revision to Diff 233586. mstorsjo edited the summary of this revision. mstorsjo added a comment.
Added ArchSpec::GetOpcodeLoadAddress() (didn't refactor Architecture to use it yet, so this is still duplicated code with the ArchitectureArm and ArchitectureMips plugins, but posting for feedback). Changed the existing DWARFCallFrameInfo to use it for clearing the lowest bit, and added a Finalize pass to both LineTable and DWARFDebugAranges for fixing it up. DWARFDebugInfoEntry still has the calls scattered around, as there's many different call paths, and once parsed, the data ends up in many different places. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70840/new/ https://reviews.llvm.org/D70840 Files: lldb/include/lldb/Symbol/LineTable.h lldb/include/lldb/Utility/ArchSpec.h lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h lldb/source/Symbol/DWARFCallFrameInfo.cpp lldb/source/Symbol/LineTable.cpp lldb/source/Utility/ArchSpec.cpp lldb/test/Shell/SymbolFile/DWARF/thumb-windows.s
Index: lldb/test/Shell/SymbolFile/DWARF/thumb-windows.s =================================================================== --- /dev/null +++ lldb/test/Shell/SymbolFile/DWARF/thumb-windows.s @@ -0,0 +1,183 @@ +# Test that a linked windows executable, with a thumb bit in many address +# fields, gets the thumb bit stripped out from addresses. + +# If the thumb bit isn't stripped out from subprogram ranges, 0x401006 is +# associated with the function "entry", while it actually is the start of +# the function "other". +# If the thumb bit isn't stripped out from line tables, the LineEntry +# points to the wrong line. + +# REQUIRES: lld, arm + +# RUN: llvm-mc -triple armv7-windows-gnu %s -filetype=obj > %t.o +# RUN: lld-link %t.o -out:%t.exe -debug:dwarf -entry:entry -subsystem:console -lldmingw +# RUN: %lldb %t.exe -o "image lookup -v -a 0x401006" -b | FileCheck %s + +# CHECK-LABEL: image lookup -v -a 0x401006 +# CHECK: Function: {{.*}}, name = "other", range = [0x00401006-0x0040100c) +# CHECK: LineEntry: [0x00401006-0x0040100a): /path/to/src/dwarf-thumb.c:7:12 + + .text + .syntax unified + .file "dwarf-thumb.c" + .file 1 "" "dwarf-thumb.c" + .def entry; + .scl 2; + .type 32; + .endef + .globl entry @ -- Begin function entry + .p2align 1 + .code 16 @ @entry + .thumb_func +entry: +.Lfunc_begin0: + .loc 1 2 0 @ dwarf-thumb.c:2:0 + .cfi_sections .debug_frame + .cfi_startproc + .loc 1 4 9 prologue_end @ dwarf-thumb.c:4:9 + mov r1, r0 +.Ltmp0: + b other +.Ltmp1: +.Lfunc_end0: + .cfi_endproc + @ -- End function + .def other; + .scl 2; + .type 32; + .endef + .globl other @ -- Begin function other + .p2align 1 + .code 16 @ @other + .thumb_func +other: +.Lfunc_begin1: + .loc 1 6 0 @ dwarf-thumb.c:6:0 + .cfi_startproc + .loc 1 7 12 prologue_end @ dwarf-thumb.c:7:12 + add.w r0, r1, r1, lsl #1 + .loc 1 7 2 is_stmt 0 @ dwarf-thumb.c:7:2 + bx lr +.Ltmp2: +.Lfunc_end1: + .cfi_endproc + @ -- End function + .section .debug_str,"dr" +.Linfo_string: +.Linfo_string1: + .asciz "dwarf-thumb.c" +.Linfo_string2: + .asciz "/path/to/src" +.Linfo_string3: + .asciz "other" +.Linfo_string6: + .asciz "entry" + .section .debug_loc,"dr" +.Lsection_debug_loc: +.Ldebug_loc0: + .long .Lfunc_begin0-.Lfunc_begin0 + .long .Ltmp0-.Lfunc_begin0 + .short 1 @ Loc expr size + .byte 80 @ DW_OP_reg0 + .long .Ltmp0-.Lfunc_begin0 + .long .Lfunc_end0-.Lfunc_begin0 + .short 1 @ Loc expr size + .byte 81 @ DW_OP_reg1 + .long 0 + .long 0 + .section .debug_abbrev,"dr" +.Lsection_abbrev: + .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 14 @ DW_FORM_strp + .byte 16 @ DW_AT_stmt_list + .byte 23 @ DW_FORM_sec_offset + .byte 27 @ DW_AT_comp_dir + .byte 14 @ DW_FORM_strp + .byte 17 @ DW_AT_low_pc + .byte 1 @ DW_FORM_addr + .byte 18 @ DW_AT_high_pc + .byte 6 @ DW_FORM_data4 + .byte 0 @ EOM(1) + .byte 0 @ EOM(2) + + .byte 6 @ Abbreviation Code + .byte 46 @ DW_TAG_subprogram + .byte 1 @ DW_CHILDREN_yes + .byte 17 @ DW_AT_low_pc + .byte 1 @ DW_FORM_addr + .byte 18 @ DW_AT_high_pc + .byte 6 @ DW_FORM_data4 + .byte 64 @ DW_AT_frame_base + .byte 24 @ DW_FORM_exprloc + .ascii "\227B" @ DW_AT_GNU_all_call_sites + .byte 25 @ DW_FORM_flag_present + .byte 3 @ DW_AT_name + .byte 14 @ DW_FORM_strp + .byte 58 @ DW_AT_decl_file + .byte 11 @ DW_FORM_data1 + .byte 59 @ DW_AT_decl_line + .byte 11 @ DW_FORM_data1 + .byte 39 @ DW_AT_prototyped + .byte 25 @ DW_FORM_flag_present + .byte 73 @ DW_AT_type + .byte 19 @ DW_FORM_ref4 + .byte 63 @ DW_AT_external + .byte 25 @ DW_FORM_flag_present + .byte 0 @ EOM(1) + .byte 0 @ EOM(2) + .byte 0 @ EOM(3) + .section .debug_info,"dr" +.Lsection_info: +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 @ Length of Unit +.Ldebug_info_start0: + .short 4 @ DWARF version number + .secrel32 .Lsection_abbrev @ Offset Into Abbrev. Section + .byte 4 @ Address Size (in bytes) + .byte 1 @ Abbrev [1] 0xb:0xbf DW_TAG_compile_unit + .byte 0 @ DW_AT_producer + .short 12 @ DW_AT_language + .secrel32 .Linfo_string1 @ DW_AT_name + .secrel32 .Lline_table_start0 @ DW_AT_stmt_list + .secrel32 .Linfo_string2 @ DW_AT_comp_dir + .long .Lfunc_begin0 @ DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 @ DW_AT_high_pc + + .byte 6 @ Abbrev [6] 0x4f:0x39 DW_TAG_subprogram + .long .Lfunc_begin0 @ DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 @ DW_AT_high_pc + .byte 1 @ DW_AT_frame_base + .byte 91 + @ DW_AT_GNU_all_call_sites + .secrel32 .Linfo_string6 @ DW_AT_name + .byte 1 @ DW_AT_decl_file + .byte 2 @ DW_AT_decl_line + @ DW_AT_prototyped + .long 60 @ DW_AT_type + @ DW_AT_external + .byte 0 @ End Of Children Mark + .byte 6 @ Abbrev [6] 0x88:0x2e DW_TAG_subprogram + .long .Lfunc_begin1 @ DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 @ DW_AT_high_pc + .byte 1 @ DW_AT_frame_base + .byte 91 + @ DW_AT_GNU_all_call_sites + .secrel32 .Linfo_string3 @ DW_AT_name + .byte 1 @ DW_AT_decl_file + .byte 6 @ DW_AT_decl_line + @ DW_AT_prototyped + .long 60 @ DW_AT_type + @ DW_AT_external + .byte 0 @ End Of Children Mark +.Ldebug_info_end0: + .addrsig + .section .debug_line,"dr" +.Lsection_line: +.Lline_table_start0: Index: lldb/source/Utility/ArchSpec.cpp =================================================================== --- lldb/source/Utility/ArchSpec.cpp +++ lldb/source/Utility/ArchSpec.cpp @@ -1464,3 +1464,24 @@ if (!environ_str.empty()) s << "-" << environ_str; } + +addr_t ArchSpec::GetOpcodeLoadAddress(addr_t opcode_addr, + AddressClass addr_class) const { + switch (addr_class) { + case AddressClass::eData: + case AddressClass::eDebug: + return LLDB_INVALID_ADDRESS; + default: + break; + } + + if (!IsValid()) + return opcode_addr; + if (m_triple.getArch() == llvm::Triple::arm || + m_triple.getArch() == llvm::Triple::thumb || + m_triple.isMIPS()) { + return opcode_addr & ~(1ull); + } else { + return opcode_addr; + } +} Index: lldb/source/Symbol/LineTable.cpp =================================================================== --- lldb/source/Symbol/LineTable.cpp +++ lldb/source/Symbol/LineTable.cpp @@ -154,6 +154,12 @@ #undef LT_COMPARE } +void LineTable::Finalize() { + ArchSpec arch = m_comp_unit->GetModule()->GetArchitecture(); + for (Entry &entry : m_entries) + entry.file_addr = arch.GetOpcodeLoadAddress(entry.file_addr); +} + uint32_t LineTable::GetSize() const { return m_entries.size(); } bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) { Index: lldb/source/Symbol/DWARFCallFrameInfo.cpp =================================================================== --- lldb/source/Symbol/DWARFCallFrameInfo.cpp +++ lldb/source/Symbol/DWARFCallFrameInfo.cpp @@ -423,12 +423,7 @@ Timer scoped_timer(func_cat, "%s - %s", LLVM_PRETTY_FUNCTION, m_objfile.GetFileSpec().GetFilename().AsCString("")); - bool clear_address_zeroth_bit = false; - if (ArchSpec arch = m_objfile.GetArchitecture()) { - if (arch.GetTriple().getArch() == llvm::Triple::arm || - arch.GetTriple().getArch() == llvm::Triple::thumb) - clear_address_zeroth_bit = true; - } + ArchSpec arch = m_objfile.GetArchitecture(); lldb::offset_t offset = 0; if (!m_cfi_data_initialized) @@ -503,8 +498,7 @@ lldb::addr_t addr = GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); - if (clear_address_zeroth_bit) - addr &= ~1ull; + addr = arch.GetOpcodeLoadAddress(addr); lldb::addr_t length = GetGNUEHPointer( m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -25,6 +25,7 @@ #include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolFile.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Flags.h" #include "lldb/Utility/RangeMap.h" @@ -316,6 +317,8 @@ lldb_private::FileSpec GetFile(DWARFUnit &unit, size_t file_idx); + lldb_private::ArchSpec GetArchSpec() const; + protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1027,6 +1027,8 @@ } } + line_table_up->Finalize(); + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) { // We have an object file that has a line table with addresses that are not // linked. We need to link the line table and convert the addresses that @@ -3995,3 +3997,7 @@ }); return m_dwp_symfile.get(); } + +ArchSpec SymbolFileDWARF::GetArchSpec() const { + return m_objfile_sp->GetArchitecture(); +} Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -783,6 +783,7 @@ const bool minimize = false; m_func_aranges_up->Sort(minimize); + m_func_aranges_up->Finalize(m_dwarf.GetArchSpec()); } return *m_func_aranges_up; } Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -236,6 +236,7 @@ SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule(); + ArchSpec arch = dwarf.GetArchSpec(); if (abbrevDecl) { const DWARFDataExtractor &data = cu->GetData(); @@ -256,6 +257,7 @@ switch (attr) { case DW_AT_low_pc: lo_pc = form_value.Address(); + lo_pc = arch.GetOpcodeLoadAddress(lo_pc); if (do_offset) hi_pc += lo_pc; @@ -271,6 +273,7 @@ form_value.Form() == DW_FORM_addrx || form_value.Form() == DW_FORM_GNU_addr_index) { hi_pc = form_value.Address(); + hi_pc = arch.GetOpcodeLoadAddress(hi_pc); } else { hi_pc = form_value.Unsigned(); if (lo_pc == LLDB_INVALID_ADDRESS) @@ -729,13 +732,15 @@ dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC( const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, bool check_specification_or_abstract_origin) const { + SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); + ArchSpec arch = dwarf.GetArchSpec(); DWARFFormValue form_value; if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr, check_specification_or_abstract_origin)) { dw_form_t form = form_value.Form(); if (form == DW_FORM_addr || form == DW_FORM_addrx || form == DW_FORM_GNU_addr_index) - return form_value.Address(); + return arch.GetOpcodeLoadAddress(form_value.Address()); // DWARF4 can specify the hi_pc as an <offset-from-lowpc> return lo_pc + form_value.Unsigned(); @@ -752,9 +757,12 @@ bool DWARFDebugInfoEntry::GetAttributeAddressRange( const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, uint64_t fail_value, bool check_specification_or_abstract_origin) const { + SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); + ArchSpec arch = dwarf.GetArchSpec(); lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value, check_specification_or_abstract_origin); if (lo_pc != fail_value) { + lo_pc = arch.GetOpcodeLoadAddress(lo_pc); hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value, check_specification_or_abstract_origin); if (hi_pc != fail_value) @@ -1015,6 +1023,8 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, DWARFUnit *cu, DWARFDebugInfoEntry **function_die, DWARFDebugInfoEntry **block_die) { + SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); + ArchSpec arch = dwarf.GetArchSpec(); bool found_address = false; if (m_tag) { bool check_children = false; @@ -1124,8 +1134,10 @@ dw_addr_t lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (lo_pc != LLDB_INVALID_ADDRESS) { + lo_pc = arch.GetOpcodeLoadAddress(lo_pc); dw_addr_t hi_pc = GetAttributeHighPC(cu, lo_pc, LLDB_INVALID_ADDRESS); if (hi_pc != LLDB_INVALID_ADDRESS) { + hi_pc = arch.GetOpcodeLoadAddress(hi_pc); // printf("\n0x%8.8x: %30s: address = 0x%8.8x [0x%8.8x - 0x%8.8x) ", // m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc); if ((lo_pc <= address) && (address < hi_pc)) { Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -65,6 +65,7 @@ const bool minimize = true; m_cu_aranges_up->Sort(minimize); + m_cu_aranges_up->Finalize(m_dwarf.GetArchSpec()); return *m_cu_aranges_up; } Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h @@ -10,6 +10,7 @@ #define SymbolFileDWARF_DWARFDebugAranges_h_ #include "lldb/Core/dwarf.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/RangeMap.h" #include "llvm/Support/Error.h" @@ -34,6 +35,8 @@ void Sort(bool minimize); + void Finalize(const lldb_private::ArchSpec &arch); + void Dump(lldb_private::Log *log) const; dw_offset_t FindAddress(dw_addr_t address) const; Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -86,6 +86,13 @@ m_aranges.CombineConsecutiveEntriesWithEqualData(); } +void DWARFDebugAranges::Finalize(const ArchSpec &arch) { + for (size_t i = 0; i < m_aranges.GetSize(); i++) { + RangeToDIE::Entry *entry = m_aranges.GetMutableEntryAtIndex(i); + entry->base = arch.GetOpcodeLoadAddress(entry->base); + } +} + // FindAddress dw_offset_t DWARFDebugAranges::FindAddress(dw_addr_t address) const { const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address); Index: lldb/include/lldb/Utility/ArchSpec.h =================================================================== --- lldb/include/lldb/Utility/ArchSpec.h +++ lldb/include/lldb/Utility/ArchSpec.h @@ -502,6 +502,21 @@ void SetFlags(std::string elf_abi); + /// Get \a load_addr as an opcode for this target. + /// + /// Take \a load_addr and potentially strip any address bits that are + /// needed to make the address point to an opcode. For ARM this can + /// clear bit zero (if it already isn't) if \a load_addr is a + /// thumb function and load_addr is in code. + /// If \a addr_class is set to AddressClass::eInvalid, then the address + /// adjustment will always happen. If it is set to an address class + /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be + /// returned. + + lldb::addr_t + GetOpcodeLoadAddress(lldb::addr_t addr, + AddressClass addr_class = AddressClass::eInvalid) const; + protected: bool IsEqualTo(const ArchSpec &rhs, bool exact_match) const; void UpdateCore(); Index: lldb/include/lldb/Symbol/LineTable.h =================================================================== --- lldb/include/lldb/Symbol/LineTable.h +++ lldb/include/lldb/Symbol/LineTable.h @@ -78,6 +78,8 @@ // Insert a sequence of entries into this line table. void InsertSequence(LineSequence *sequence); + void Finalize(); + /// Dump all line entries in this line table to the stream \a s. /// /// \param[in] s
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits