mstorsjo updated this revision to Diff 240118. mstorsjo added a comment. Herald added a reviewer: shafik.
Hopefully this is a bit less schizophrenic now. It's still quite RFC'y and many of the fixup loops could probably still be refactored, if someone suggests where to place the shared code. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70840/new/ https://reviews.llvm.org/D70840 Files: lldb/include/lldb/Expression/DWARFExpression.h lldb/include/lldb/Symbol/LineTable.h lldb/include/lldb/Utility/ArchSpec.h lldb/include/lldb/Utility/RangeMap.h lldb/source/Expression/DWARFExpression.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp 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/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 @@ -1463,3 +1463,26 @@ if (!environ_str.empty()) s << "-" << environ_str; } + +addr_t ArchSpec::GetOpcodeLoadAddress(addr_t opcode_addr, + AddressClass addr_class) const { + if (opcode_addr == LLDB_INVALID_ADDRESS) + return opcode_addr; + 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 @@ -174,6 +174,12 @@ return (*this)(seq_a->m_entries.front(), seq_b->m_entries.front()); } +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 @@ -24,6 +24,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" @@ -305,6 +306,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 @@ -1011,6 +1011,7 @@ std::unique_ptr<LineTable> line_table_up = std::make_unique<LineTable>(&comp_unit, std::move(sequences)); + 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 @@ -1115,6 +1116,11 @@ if (die.GetDIENamesAndRanges(name, mangled_name, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column, nullptr)) { + ArchSpec arch = GetArchSpec(); + for (size_t i = 0; i < ranges.GetSize(); i++) { + DWARFRangeList::Entry *entry = ranges.GetMutableEntryAtIndex(i); + entry->base = arch.GetOpcodeLoadAddress(entry->base); + } if (tag == DW_TAG_subprogram) { assert(subprogram_low_pc == LLDB_INVALID_ADDRESS); subprogram_low_pc = ranges.GetMinRangeBase(0); @@ -3143,9 +3149,10 @@ if (sc.function) { DWARFDIE function_die = GetDIE(sc.function->GetID()); - const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress( + dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress( DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (func_lo_pc != LLDB_INVALID_ADDRESS) { + func_lo_pc = GetArchSpec().GetOpcodeLoadAddress(func_lo_pc); const size_t num_variables = ParseVariables( sc, function_die.GetFirstChild(), func_lo_pc, true, true); @@ -3969,3 +3976,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 @@ -790,6 +790,7 @@ dwo_die->BuildFunctionAddressRangeTable(dwo_cu, m_func_aranges_up.get()); } + m_func_aranges_up->Finalize(m_dwarf.GetArchSpec()); const bool minimize = false; m_func_aranges_up->Sort(minimize); Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -62,6 +62,7 @@ if (cus_with_data.find(offset) == cus_with_data.end()) cu->BuildAddressRangeTable(m_cu_aranges_up.get()); } + m_cu_aranges_up->Finalize(m_dwarf.GetArchSpec()); const bool minimize = true; m_cu_aranges_up->Sort(minimize); 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/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -139,6 +139,14 @@ return DWARFDIE(); } +static bool FinalizeRanges(DWARFRangeList &ranges, const ArchSpec &arch) { + for (size_t i = 0; i < ranges.GetSize(); i++) { + DWARFRangeList::Entry *entry = ranges.GetMutableEntryAtIndex(i); + entry->base = arch.GetOpcodeLoadAddress(entry->base); + } + return true; +} + DWARFDIE DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const { if (!IsValid()) @@ -175,6 +183,7 @@ DWARFRangeList ranges; if (m_die->GetAttributeAddressRanges(m_cu, ranges, /*check_hi_lo_pc=*/true) && + FinalizeRanges(ranges, GetDWARF()->GetArchSpec()) && ranges.FindEntryThatContains(address)) { check_children = true; switch (Tag()) { Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2319,6 +2319,16 @@ if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column, &frame_base)) { + ArchSpec arch = die.GetCU()->GetSymbolFileDWARF().GetArchSpec(); + for (size_t i = 0; i < func_ranges.GetSize(); i++) { + DWARFRangeList::Entry *entry = func_ranges.GetMutableEntryAtIndex(i); + entry->base = arch.GetOpcodeLoadAddress(entry->base); + } + if (frame_base.IsLocationList()) { + std::pair<addr_t, addr_t> loclist = frame_base.GetLocationListAddresses(); + loclist.second = arch.GetOpcodeLoadAddress(loclist.second); + frame_base.SetLocationListAddresses(loclist.first, loclist.second); + } // Union of all ranges in the function DIE (if the function is // discontiguous) Index: lldb/source/Expression/DWARFExpression.cpp =================================================================== --- lldb/source/Expression/DWARFExpression.cpp +++ lldb/source/Expression/DWARFExpression.cpp @@ -99,6 +99,11 @@ m_loclist_addresses = LoclistAddresses{cu_file_addr, func_file_addr}; } +std::pair<addr_t, addr_t> DWARFExpression::GetLocationListAddresses() const { + return std::make_pair(m_loclist_addresses->cu_file_addr, + m_loclist_addresses->func_file_addr); +} + int DWARFExpression::GetRegisterKind() { return m_reg_kind; } void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) { Index: lldb/include/lldb/Utility/RangeMap.h =================================================================== --- lldb/include/lldb/Utility/RangeMap.h +++ lldb/include/lldb/Utility/RangeMap.h @@ -244,6 +244,10 @@ return ((i < m_entries.size()) ? &m_entries[i] : nullptr); } + Entry *GetMutableEntryAtIndex(size_t i) { + return ((i < m_entries.size()) ? &m_entries[i] : nullptr); + } + // Clients must ensure that "i" is a valid index prior to calling this // function const Entry &GetEntryRef(size_t i) const { return m_entries[i]; } Index: lldb/include/lldb/Utility/ArchSpec.h =================================================================== --- lldb/include/lldb/Utility/ArchSpec.h +++ lldb/include/lldb/Utility/ArchSpec.h @@ -504,6 +504,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 @@ -85,6 +85,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 Index: lldb/include/lldb/Expression/DWARFExpression.h =================================================================== --- lldb/include/lldb/Expression/DWARFExpression.h +++ lldb/include/lldb/Expression/DWARFExpression.h @@ -139,6 +139,8 @@ void SetLocationListAddresses(lldb::addr_t cu_file_addr, lldb::addr_t func_file_addr); + std::pair<lldb::addr_t, lldb::addr_t> GetLocationListAddresses() const; + /// Return the call-frame-info style register kind int GetRegisterKind();
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits