forked from OSchip/llvm-project
[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
This commit is contained in:
parent
8b65f792a0
commit
00539d8b64
|
@ -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_strp)
|
||||
return context.getOrLoadStrData().PeekCStr(m_value.value.uval);
|
||||
|
||||
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) {
|
||||
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) {
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
dwo_cu->SetStrOffsetsBase(baseOffset);
|
||||
// Skip padding.
|
||||
baseOffset += 2;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -59,6 +59,9 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ private:
|
|||
void ClearDIEsRWLocked();
|
||||
|
||||
void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
|
||||
void SetDwoStrOffsetsBase();
|
||||
|
||||
void ComputeCompDirAndGuessPathStyle();
|
||||
void ComputeAbsolutePath();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue