diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -454,40 +454,26 @@ } 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 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.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -59,6 +59,9 @@ 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 @@ uint8_t GetUnitType() const { return m_header.GetUnitType(); } bool IsTypeUnit() const { return m_header.IsTypeUnit(); } + llvm::Optional 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 FindRnglistFromOffset(dw_offset_t offset); @@ -331,6 +336,7 @@ void ClearDIEsRWLocked(); void AddUnitDIE(const DWARFDebugInfoEntry &cu_die); + void SetDwoStrOffsetsBase(); void ComputeCompDirAndGuessPathStyle(); void ComputeAbsolutePath(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -259,23 +259,32 @@ // .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 @@ } } - if (m_is_dwo) + if (m_is_dwo) { + SetDwoStrOffsetsBase(); return; + } std::shared_ptr dwo_symbol_file = m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die); @@ -377,10 +388,6 @@ 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(std::move(dwo_symbol_file), dwo_cu); } @@ -900,6 +907,12 @@ llvm_unreachable("invalid UnitType."); } +llvm::Optional +DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { + offset_t offset = GetStrOffsetsBase() + index * 4; + return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); +} + llvm::Expected DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { if (GetVersion() <= 4) { diff --git a/lldb/test/Shell/SymbolFile/DWARF/dwp.s b/lldb/test/Shell/SymbolFile/DWARF/dwp.s --- 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 @@ # 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 @@ .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 @@ .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 @@ .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