Author: Pavel Labath Date: 2020-02-18T11:02:34+01:00 New Revision: 00539d8b6425529240d970082c23e6ee1263669b
URL: https://github.com/llvm/llvm-project/commit/00539d8b6425529240d970082c23e6ee1263669b DIFF: https://github.com/llvm/llvm-project/commit/00539d8b6425529240d970082c23e6ee1263669b.diff LOG: [lldb/DWARF] Support the debug_str_offsets section in dwp files Summary: In dwp files a constant (from the debug_cu_index section) needs to be added to each reference into the debug_str_offsets section. I've tried to implement this to roughly match the llvm flow: I've changed the DWARFormValue to stop resolving the indirect string references directly -- instead, it calls into DWARFUnit, which resolves this for it (similar to how it already resolves indirect range and location list references). I've also done a small refactor of the string offset base computation code in DWARFUnit in order to make it easier to access the debug_cu_index base offset. Reviewers: JDevlieghere, aprantl, clayborg Subscribers: lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D74723 Added: Modified: lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h lldb/test/Shell/SymbolFile/DWARF/dwp.s Removed: ################################################################################ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index d1a27981f025..83cda24a27d2 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -454,40 +454,26 @@ void DWARFFormValue::Dump(Stream &s) const { } const char *DWARFFormValue::AsCString() const { - SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); + DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext(); - if (m_form == DW_FORM_string) { + if (m_form == DW_FORM_string) return m_value.value.cstr; - } else if (m_form == DW_FORM_strp) { - return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr( - m_value.value.uval); - } else if (m_form == DW_FORM_GNU_str_index) { - uint32_t index_size = 4; - lldb::offset_t offset = m_value.value.uval * index_size; - dw_offset_t str_offset = - symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( - &offset, index_size); - return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr( - str_offset); - } - - if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 || - m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 || - m_form == DW_FORM_strx4) { - - // The same code as above. - uint32_t indexSize = 4; - lldb::offset_t offset = - m_unit->GetStrOffsetsBase() + m_value.value.uval * indexSize; - dw_offset_t strOffset = - symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( - &offset, indexSize); - return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(strOffset); + if (m_form == DW_FORM_strp) + return context.getOrLoadStrData().PeekCStr(m_value.value.uval); + + if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx || + m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 || + m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) { + + llvm::Optional<uint64_t> offset = + m_unit->GetStringOffsetSectionItem(m_value.value.uval); + if (!offset) + return nullptr; + return context.getOrLoadStrData().PeekCStr(*offset); } if (m_form == DW_FORM_line_strp) - return symbol_file.GetDWARFContext().getOrLoadLineStrData().PeekCStr( - m_value.value.uval); + return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval); return nullptr; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 37e52331faca..6ff3601ab049 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -259,23 +259,32 @@ void DWARFUnit::ExtractDIEsRWLocked() { // .debug_str_offsets. At the same time, the corresponding split debug unit also // may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and // for that case, we should find the offset (skip the section header). -static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) { +void DWARFUnit::SetDwoStrOffsetsBase() { lldb::offset_t baseOffset = 0; - const DWARFDataExtractor &strOffsets = - dwo_cu->GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData(); - uint64_t length = strOffsets.GetU32(&baseOffset); - if (length == 0xffffffff) - length = strOffsets.GetU64(&baseOffset); + if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { + if (const auto *contribution = entry->getOffset(llvm::DW_SECT_STR_OFFSETS)) + baseOffset = contribution->Offset; + else + return; + } - // Check version. - if (strOffsets.GetU16(&baseOffset) < 5) - return; + if (GetVersion() >= 5) { + const DWARFDataExtractor &strOffsets = + GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData(); + uint64_t length = strOffsets.GetU32(&baseOffset); + if (length == 0xffffffff) + length = strOffsets.GetU64(&baseOffset); - // Skip padding. - baseOffset += 2; + // Check version. + if (strOffsets.GetU16(&baseOffset) < 5) + return; + + // Skip padding. + baseOffset += 2; + } - dwo_cu->SetStrOffsetsBase(baseOffset); + SetStrOffsetsBase(baseOffset); } // m_die_array_mutex must be already held as read/write. @@ -334,8 +343,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { } } - if (m_is_dwo) + if (m_is_dwo) { + SetDwoStrOffsetsBase(); return; + } std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file = m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die); @@ -377,10 +388,6 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32)); dwo_cu->SetBaseAddress(GetBaseAddress()); - for (size_t i = 0; i < dwo_symbol_file->DebugInfo()->GetNumUnits(); ++i) { - DWARFUnit *unit = dwo_symbol_file->DebugInfo()->GetUnitAtIndex(i); - SetDwoStrOffsetsBase(unit); - } m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu); } @@ -900,6 +907,12 @@ uint32_t DWARFUnit::GetHeaderByteSize() const { llvm_unreachable("invalid UnitType."); } +llvm::Optional<uint64_t> +DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { + offset_t offset = GetStrOffsetsBase() + index * 4; + return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); +} + llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { if (GetVersion() <= 4) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index f0f293f64a39..f15086d9504d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -59,6 +59,9 @@ class DWARFUnitHeader { dw_offset_t GetLength() const { return m_length; } dw_offset_t GetAbbrOffset() const { return m_abbr_offset; } uint8_t GetUnitType() const { return m_unit_type; } + const llvm::DWARFUnitIndex::Entry *GetIndexEntry() const { + return m_index_entry; + } uint64_t GetTypeHash() const { return m_type_hash; } dw_offset_t GetTypeOffset() const { return m_type_offset; } bool IsTypeUnit() const { @@ -215,6 +218,8 @@ class DWARFUnit : public lldb_private::UserID { uint8_t GetUnitType() const { return m_header.GetUnitType(); } bool IsTypeUnit() const { return m_header.IsTypeUnit(); } + llvm::Optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const; + /// Return a list of address ranges resulting from a (possibly encoded) /// range list starting at a given offset in the appropriate ranges section. llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset); @@ -331,6 +336,7 @@ class DWARFUnit : public lldb_private::UserID { void ClearDIEsRWLocked(); void AddUnitDIE(const DWARFDebugInfoEntry &cu_die); + void SetDwoStrOffsetsBase(); void ComputeCompDirAndGuessPathStyle(); void ComputeAbsolutePath(); diff --git a/lldb/test/Shell/SymbolFile/DWARF/dwp.s b/lldb/test/Shell/SymbolFile/DWARF/dwp.s index 47ac804efd2c..23fcde872947 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/dwp.s +++ b/lldb/test/Shell/SymbolFile/DWARF/dwp.s @@ -5,10 +5,10 @@ # RUN: %lldb %t -o "target variable A" -b | FileCheck %s # RUN: lldb-test symbols %t | FileCheck %s --check-prefix=SYMBOLS -# CHECK: (int) A = 0 -# CHECK: (int) A = 1 -# CHECK: (int) A = 2 -# CHECK: (int) A = 3 +# CHECK: (INT0) A = 0 +# CHECK: (INT1) A = 1 +# CHECK: (INT2) A = 2 +# CHECK: (INT3) A = 3 # SYMBOLS: Compile units: # SYMBOLS-NEXT: CompileUnit{0x00000000}, language = "unknown", file = '0.c' @@ -64,6 +64,15 @@ A\I: # This deliberately excludes compile unit 4 to check test the case of a missing # split unit. .irpc I,0123 + .section .debug_str.dwo,"e",@progbits +.Lstr\I: + .byte 'I', 'N', 'T', '0'+\I, 0 + + .section .debug_str_offsets.dwo,"e",@progbits +.Lstr_offsets\I: + .long .Lstr\I-.debug_str.dwo +.Lstr_offsets_end\I: + .section .debug_abbrev.dwo,"e",@progbits .Labbrev\I: .byte \I*10+1 # Abbreviation Code @@ -90,13 +99,22 @@ A\I: .byte 36 # DW_TAG_base_type .byte 0 # DW_CHILDREN_no .byte 3 # DW_AT_name - .byte 14 # DW_FORM_string + .byte 8 # DW_FORM_string .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 \I*10+4 # Abbreviation Code + .byte 22 # DW_TAG_typedef + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .uleb128 0x1f02 # DW_FORM_GNU_str_index + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) .byte 0 # EOM(3) .Labbrev_end\I: @@ -112,10 +130,14 @@ A\I: .byte '0'+\I, '.', 'c', 0 # DW_AT_name .byte \I*10+2 # Abbrev DW_TAG_variable .asciz "A" # DW_AT_name - .long .Ltype\I-.Lcu_begin\I # DW_AT_type + .long .Ltypedef\I-.Lcu_begin\I# DW_AT_type .byte 2 # DW_AT_location .byte 0xfb # DW_OP_GNU_addr_index .byte \I +.Ltypedef\I: + .byte \I*10+4 # Abbrev DW_TAG_typedef + .byte 0 # DW_AT_name + .long .Ltype\I-.Lcu_begin\I # DW_AT_type .Ltype\I: .byte \I*10+3 # Abbrev DW_TAG_base_type .asciz "int" # DW_AT_name @@ -128,22 +150,26 @@ A\I: .section .debug_cu_index,"e",@progbits .short 2 # DWARF version number .short 0 # Reserved - .long 2 # Section count + .long 3 # Section count .long 4 # Unit count .long 8 # Slot count .quad 0, 1, 2, 3, 0, 0, 0, 0 # Hash table .long 1, 2, 3, 4, 0, 0, 0, 0 # Index table - .long 1, 3 # DW_SECT_INFO, DW_SECT_ABBREV + .long 1 # DW_SECT_INFO + .long 3 # DW_SECT_ABBREV + .long 6 # DW_SECT_STR_OFFSETS .irpc I,0123 .long .Lcu_begin\I-.debug_info.dwo .long .Labbrev\I-.debug_abbrev.dwo + .long .Lstr_offsets\I-.debug_str_offsets.dwo .endr .irpc I,0123 .long .Ldebug_info_end\I-.Lcu_begin\I .long .Labbrev_end\I-.Labbrev\I + .long .Lstr_offsets_end\I-.Lstr_offsets\I .endr .endif _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits