mstorsjo created this revision. mstorsjo added reviewers: labath, amccarth. Herald added subscribers: kristof.beyls, aprantl. Herald added a reviewer: jdoerfert. Herald added a project: LLDB.
Windows on ARM is always thumb, and contrary to ELF, there's no per-symbol flag to indicate arm vs thumb mode. Therefore, the linkers both Microsoft's link.exe and lld) sets the thumb bit in all relocations pointing to code sections. In ELF, the thumb bit is only set for symbols marked as %function, that is, it isn't set in local labels used when constructing the dwarf debug info and line tables. As the windows linkers sets the thumb bit in all code addresses, we'd have to cope with this and strip out the lowest bit from all code addresses if the architecture is ARM/Thumb. The testcase uses a prelinked .yaml source instead of an assembly source file, to avoid needing to run a linker as part of the test. There's already predecent for this in DWARFCallFrameInfo::GetFDEIndex, this extends the same concept to DWARF debug info and line tables. I'm not sure if I managed to get all spots covered here, but I tried to look for all cases of DW_AT_low_pc/DW_AT_high_pc and find the best place to handle it, where it would have to be handled in as few places as possible. This is admittedly not very pretty, improvement suggestions are welcome. Finally, this makes sure to propagate the correct address byte size to DataExtractors that are taken from e.g. ObjectFile::ReadSectionData. Previously, the DataExtractor got the host address size set, which later tripped up DWARFDebugLine::LineTable::parse as the address size of the line table (4) mismatched the one set in the DWARFDataExtractor (which was propagated from ObjectFile's internal m_data, which never got anything else set than the default from the host's sizeof(void*)). This caused line tables to end up missing if inspecting a foreign object file (like in the testcase). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D70840 Files: lldb/include/lldb/Symbol/LineTable.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/DWARFDebugInfoEntry.h lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h lldb/source/Symbol/LineTable.cpp lldb/source/Symbol/ObjectFile.cpp lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg lldb/test/Shell/SymbolFile/DWARF/thumb-windows.yaml
Index: lldb/test/Shell/SymbolFile/DWARF/thumb-windows.yaml =================================================================== --- /dev/null +++ lldb/test/Shell/SymbolFile/DWARF/thumb-windows.yaml @@ -0,0 +1,125 @@ +# 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. + +# RUN: yaml2obj %s > %t.exe +# 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 + +--- !COFF +OptionalHeader: + AddressOfEntryPoint: 4097 + ImageBase: 4194304 + SectionAlignment: 4096 + FileAlignment: 512 + MajorOperatingSystemVersion: 6 + MinorOperatingSystemVersion: 0 + MajorImageVersion: 0 + MinorImageVersion: 0 + MajorSubsystemVersion: 6 + MinorSubsystemVersion: 0 + Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI + DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ] + SizeOfStackReserve: 1048576 + SizeOfStackCommit: 4096 + SizeOfHeapReserve: 1048576 + SizeOfHeapCommit: 4096 + ExportTable: + RelativeVirtualAddress: 0 + Size: 0 + ImportTable: + RelativeVirtualAddress: 0 + Size: 0 + ResourceTable: + RelativeVirtualAddress: 0 + Size: 0 + ExceptionTable: + RelativeVirtualAddress: 0 + Size: 0 + CertificateTable: + RelativeVirtualAddress: 0 + Size: 0 + BaseRelocationTable: + RelativeVirtualAddress: 0 + Size: 0 + Debug: + RelativeVirtualAddress: 8192 + Size: 28 + Architecture: + RelativeVirtualAddress: 0 + Size: 0 + GlobalPtr: + RelativeVirtualAddress: 0 + Size: 0 + TlsTable: + RelativeVirtualAddress: 0 + Size: 0 + LoadConfigTable: + RelativeVirtualAddress: 0 + Size: 0 + BoundImport: + RelativeVirtualAddress: 0 + Size: 0 + IAT: + RelativeVirtualAddress: 0 + Size: 0 + DelayImportDescriptor: + RelativeVirtualAddress: 0 + Size: 0 + ClrRuntimeHeader: + RelativeVirtualAddress: 0 + Size: 0 +header: + Machine: IMAGE_FILE_MACHINE_ARMNT + Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_32BIT_MACHINE ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 4096 + VirtualSize: 12 + SectionData: 014600F000B801EB41007047 + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 8192 + VirtualSize: 53 + SectionData: 00000000D7D2DF5D0000000002000000190000001C2000001C06000000000000000000000000000000000000000000000000000000 + - Name: .debug_abbrev + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 12288 + VirtualSize: 46 + SectionData: 01110125251305030E10171B0E110112060000062E01110112064018974219030E3A0B3B0B271949133F19000000 + - Name: .debug_frame + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 16384 + VirtualSize: 52 + SectionData: 10000000FFFFFFFF04000400017C0E0C0D0000000C0000000000000001104000060000000C000000000000000710400006000000 + - Name: .debug_info + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 20480 + VirtualSize: 79 + SectionData: 4B0000000400000000000401000C0000000000000000000E000000011040000C000000060110400006000000015B2100000001023C00000000060710400006000000015B1B00000001063C00000000 + - Name: .debug_line + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 24576 + VirtualSize: 75 + SectionData: 47000000040025000000010101FB0E0D0001010101000000010000010064776172662D7468756D622E630000000000000502011040001305090A14050068050C0A130502064A0202000101 + - Name: .debug_loc + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 28672 + VirtualSize: 30 + SectionData: '000000000200000001005002000000060000000100510000000000000000' + - Name: .debug_str + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 32768 + VirtualSize: 39 + SectionData: 64776172662D7468756D622E63002F706174682F746F2F737263006F7468657200656E74727900 +symbols: +... Index: lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg =================================================================== --- lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg +++ lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg @@ -1 +1 @@ -config.suffixes = ['.cpp', '.m', '.s', '.test', '.ll'] +config.suffixes = ['.cpp', '.m', '.s', '.test', '.ll', '.yaml'] Index: lldb/source/Symbol/ObjectFile.cpp =================================================================== --- lldb/source/Symbol/ObjectFile.cpp +++ lldb/source/Symbol/ObjectFile.cpp @@ -477,7 +477,13 @@ DataExtractor &data) const { // The entire file has already been mmap'ed into m_data, so just copy from // there as the back mmap buffer will be shared with shared pointers. - return data.SetData(m_data, offset, length); + size_t ret = data.SetData(m_data, offset, length); + // DataExtractor::SetData copies the address byte size from m_data, but + // m_data's address byte size is only set from sizeof(void*), and we can't + // access subclasses GetAddressByteSize() when setting up m_data in the + // constructor. + data.SetAddressByteSize(GetAddressByteSize()); + return ret; } size_t ObjectFile::CopyData(lldb::offset_t offset, size_t length, Index: lldb/source/Symbol/LineTable.cpp =================================================================== --- lldb/source/Symbol/LineTable.cpp +++ lldb/source/Symbol/LineTable.cpp @@ -19,7 +19,13 @@ // LineTable constructor LineTable::LineTable(CompileUnit *comp_unit) - : m_comp_unit(comp_unit), m_entries() {} + : m_comp_unit(comp_unit), m_entries() { + if (ArchSpec arch = m_comp_unit->GetModule()->GetArchitecture()) { + if (arch.GetTriple().getArch() == llvm::Triple::arm || + arch.GetTriple().getArch() == llvm::Triple::thumb) + m_clear_address_zeroth_bit = true; + } +} // Destructor LineTable::~LineTable() {} @@ -30,6 +36,8 @@ bool is_start_of_basic_block, bool is_prologue_end, bool is_epilogue_begin, bool is_terminal_entry) { + if (m_clear_address_zeroth_bit) + file_addr &= ~1ull; Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); @@ -63,6 +71,8 @@ bool is_terminal_entry) { assert(sequence != nullptr); LineSequenceImpl *seq = reinterpret_cast<LineSequenceImpl *>(sequence); + if (m_clear_address_zeroth_bit) + file_addr &= ~1ull; Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -318,6 +318,8 @@ lldb_private::FileSpec GetFile(DWARFUnit &unit, size_t file_idx); + dw_addr_t GetAddressMask() 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 @@ -4003,3 +4003,12 @@ }); return m_dwp_symfile.get(); } + +dw_addr_t SymbolFileDWARF::GetAddressMask() const { + if (ArchSpec arch = m_objfile_sp->GetArchitecture()) { + if (arch.GetTriple().getArch() == llvm::Triple::arm || + arch.GetTriple().getArch() == llvm::Triple::thumb) + return ~1ull; + } + return ~0ull; +} Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -59,6 +59,7 @@ // We are in our compile unit, parse starting at the offset we were told to // parse + m_first_die.SetAddrMask(m_dwarf.GetAddressMask()); const DWARFDataExtractor &data = GetData(); if (offset < GetNextUnitOffset() && m_first_die.Extract(data, this, &offset)) { @@ -155,6 +156,7 @@ lldb::offset_t next_cu_offset = GetNextUnitOffset(); DWARFDebugInfoEntry die; + die.SetAddrMask(m_dwarf.GetAddressMask()); uint32_t depth = 0; // We are in our compile unit, parse starting at the offset we were told to @@ -721,7 +723,7 @@ const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { if (m_func_aranges_up == nullptr) { - m_func_aranges_up.reset(new DWARFDebugAranges()); + m_func_aranges_up.reset(new DWARFDebugAranges(m_dwarf.GetAddressMask())); const DWARFDebugInfoEntry *die = DIEPtr(); if (die) die->BuildFunctionAddressRangeTable(this, m_func_aranges_up.get()); Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -41,6 +41,8 @@ bool operator==(const DWARFDebugInfoEntry &rhs) const; bool operator!=(const DWARFDebugInfoEntry &rhs) const; + void SetAddrMask(dw_addr_t addr_mask) { m_addr_mask = addr_mask; } + void BuildAddressRangeTable(const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const; @@ -185,6 +187,7 @@ /// A copy of the DW_TAG value so we don't have to go through the compile /// unit abbrev table dw_tag_t m_tag = llvm::dwarf::DW_TAG_null; + dw_addr_t m_addr_mask = ~0ull; }; #endif // SymbolFileDWARF_DWARFDebugInfoEntry_h_ Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -255,7 +255,7 @@ if (form_value.ExtractValue(data, &offset)) { switch (attr) { case DW_AT_low_pc: - lo_pc = form_value.Address(); + lo_pc = form_value.Address() & m_addr_mask; if (do_offset) hi_pc += lo_pc; @@ -270,7 +270,7 @@ if (form_value.Form() == DW_FORM_addr || form_value.Form() == DW_FORM_addrx || form_value.Form() == DW_FORM_GNU_addr_index) { - hi_pc = form_value.Address(); + hi_pc = form_value.Address() & m_addr_mask; } else { hi_pc = form_value.Unsigned(); if (lo_pc == LLDB_INVALID_ADDRESS) @@ -735,7 +735,7 @@ 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 form_value.Address() & m_addr_mask; // DWARF4 can specify the hi_pc as an <offset-from-lowpc> return lo_pc + form_value.Unsigned(); @@ -755,6 +755,7 @@ lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value, check_specification_or_abstract_origin); if (lo_pc != fail_value) { + lo_pc &= m_addr_mask; hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value, check_specification_or_abstract_origin); if (hi_pc != fail_value) @@ -1125,8 +1126,10 @@ dw_addr_t lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (lo_pc != LLDB_INVALID_ADDRESS) { + lo_pc &= m_addr_mask; dw_addr_t hi_pc = GetAttributeHighPC(cu, lo_pc, LLDB_INVALID_ADDRESS); if (hi_pc != LLDB_INVALID_ADDRESS) { + hi_pc &= m_addr_mask; // 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 @@ -38,7 +38,8 @@ if (m_cu_aranges_up) return *m_cu_aranges_up; - m_cu_aranges_up = std::make_unique<DWARFDebugAranges>(); + m_cu_aranges_up = + std::make_unique<DWARFDebugAranges>(m_dwarf.GetAddressMask()); const DWARFDataExtractor &debug_aranges_data = m_context.getOrLoadArangesData(); if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data)) Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h @@ -22,7 +22,7 @@ typedef RangeToDIE::Entry Range; typedef std::vector<RangeToDIE::Entry> RangeColl; - DWARFDebugAranges(); + DWARFDebugAranges(dw_addr_t addr_mask); void Clear() { m_aranges.Clear(); } @@ -50,6 +50,7 @@ protected: RangeToDIE m_aranges; + dw_addr_t m_addr_mask; }; #endif // SymbolFileDWARF_DWARFDebugAranges_h_ Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -16,7 +16,8 @@ using namespace lldb_private; // Constructor -DWARFDebugAranges::DWARFDebugAranges() : m_aranges() {} +DWARFDebugAranges::DWARFDebugAranges(dw_addr_t addr_mask) + : m_aranges(), m_addr_mask(addr_mask) {} // CountArangeDescriptors class CountArangeDescriptors { @@ -74,7 +75,8 @@ void DWARFDebugAranges::AppendRange(dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc) { if (high_pc > low_pc) - m_aranges.Append(RangeToDIE::Entry(low_pc, high_pc - low_pc, offset)); + m_aranges.Append( + RangeToDIE::Entry(low_pc & m_addr_mask, high_pc - low_pc, offset)); } void DWARFDebugAranges::Sort(bool minimize) { Index: lldb/include/lldb/Symbol/LineTable.h =================================================================== --- lldb/include/lldb/Symbol/LineTable.h +++ lldb/include/lldb/Symbol/LineTable.h @@ -329,6 +329,8 @@ private: DISALLOW_COPY_AND_ASSIGN(LineTable); + + bool m_clear_address_zeroth_bit = false; }; } // namespace lldb_private
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits