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 {
|
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;
|
return m_value.value.cstr;
|
||||||
} else if (m_form == DW_FORM_strp) {
|
if (m_form == DW_FORM_strp)
|
||||||
return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(
|
return context.getOrLoadStrData().PeekCStr(m_value.value.uval);
|
||||||
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 ||
|
if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx ||
|
||||||
m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 ||
|
m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 ||
|
||||||
m_form == DW_FORM_strx4) {
|
m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) {
|
||||||
|
|
||||||
// The same code as above.
|
llvm::Optional<uint64_t> offset =
|
||||||
uint32_t indexSize = 4;
|
m_unit->GetStringOffsetSectionItem(m_value.value.uval);
|
||||||
lldb::offset_t offset =
|
if (!offset)
|
||||||
m_unit->GetStrOffsetsBase() + m_value.value.uval * indexSize;
|
return nullptr;
|
||||||
dw_offset_t strOffset =
|
return context.getOrLoadStrData().PeekCStr(*offset);
|
||||||
symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64(
|
|
||||||
&offset, indexSize);
|
|
||||||
return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(strOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_form == DW_FORM_line_strp)
|
if (m_form == DW_FORM_line_strp)
|
||||||
return symbol_file.GetDWARFContext().getOrLoadLineStrData().PeekCStr(
|
return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval);
|
||||||
m_value.value.uval);
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,11 +259,19 @@ void DWARFUnit::ExtractDIEsRWLocked() {
|
||||||
// .debug_str_offsets. At the same time, the corresponding split debug unit also
|
// .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
|
// 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).
|
// 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;
|
lldb::offset_t baseOffset = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetVersion() >= 5) {
|
||||||
const DWARFDataExtractor &strOffsets =
|
const DWARFDataExtractor &strOffsets =
|
||||||
dwo_cu->GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData();
|
GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData();
|
||||||
uint64_t length = strOffsets.GetU32(&baseOffset);
|
uint64_t length = strOffsets.GetU32(&baseOffset);
|
||||||
if (length == 0xffffffff)
|
if (length == 0xffffffff)
|
||||||
length = strOffsets.GetU64(&baseOffset);
|
length = strOffsets.GetU64(&baseOffset);
|
||||||
|
@ -274,8 +282,9 @@ static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) {
|
||||||
|
|
||||||
// Skip padding.
|
// Skip padding.
|
||||||
baseOffset += 2;
|
baseOffset += 2;
|
||||||
|
}
|
||||||
|
|
||||||
dwo_cu->SetStrOffsetsBase(baseOffset);
|
SetStrOffsetsBase(baseOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_die_array_mutex must be already held as read/write.
|
// 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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
|
std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
|
||||||
m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die);
|
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->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
|
||||||
dwo_cu->SetBaseAddress(GetBaseAddress());
|
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);
|
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_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>
|
llvm::Expected<DWARFRangeList>
|
||||||
DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
|
DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
|
||||||
if (GetVersion() <= 4) {
|
if (GetVersion() <= 4) {
|
||||||
|
|
|
@ -59,6 +59,9 @@ public:
|
||||||
dw_offset_t GetLength() const { return m_length; }
|
dw_offset_t GetLength() const { return m_length; }
|
||||||
dw_offset_t GetAbbrOffset() const { return m_abbr_offset; }
|
dw_offset_t GetAbbrOffset() const { return m_abbr_offset; }
|
||||||
uint8_t GetUnitType() const { return m_unit_type; }
|
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; }
|
uint64_t GetTypeHash() const { return m_type_hash; }
|
||||||
dw_offset_t GetTypeOffset() const { return m_type_offset; }
|
dw_offset_t GetTypeOffset() const { return m_type_offset; }
|
||||||
bool IsTypeUnit() const {
|
bool IsTypeUnit() const {
|
||||||
|
@ -215,6 +218,8 @@ public:
|
||||||
uint8_t GetUnitType() const { return m_header.GetUnitType(); }
|
uint8_t GetUnitType() const { return m_header.GetUnitType(); }
|
||||||
bool IsTypeUnit() const { return m_header.IsTypeUnit(); }
|
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)
|
/// Return a list of address ranges resulting from a (possibly encoded)
|
||||||
/// range list starting at a given offset in the appropriate ranges section.
|
/// range list starting at a given offset in the appropriate ranges section.
|
||||||
llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset);
|
llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset);
|
||||||
|
@ -331,6 +336,7 @@ private:
|
||||||
void ClearDIEsRWLocked();
|
void ClearDIEsRWLocked();
|
||||||
|
|
||||||
void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
|
void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
|
||||||
|
void SetDwoStrOffsetsBase();
|
||||||
|
|
||||||
void ComputeCompDirAndGuessPathStyle();
|
void ComputeCompDirAndGuessPathStyle();
|
||||||
void ComputeAbsolutePath();
|
void ComputeAbsolutePath();
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
# RUN: %lldb %t -o "target variable A" -b | FileCheck %s
|
# RUN: %lldb %t -o "target variable A" -b | FileCheck %s
|
||||||
# RUN: lldb-test symbols %t | FileCheck %s --check-prefix=SYMBOLS
|
# RUN: lldb-test symbols %t | FileCheck %s --check-prefix=SYMBOLS
|
||||||
|
|
||||||
# CHECK: (int) A = 0
|
# CHECK: (INT0) A = 0
|
||||||
# CHECK: (int) A = 1
|
# CHECK: (INT1) A = 1
|
||||||
# CHECK: (int) A = 2
|
# CHECK: (INT2) A = 2
|
||||||
# CHECK: (int) A = 3
|
# CHECK: (INT3) A = 3
|
||||||
|
|
||||||
# SYMBOLS: Compile units:
|
# SYMBOLS: Compile units:
|
||||||
# SYMBOLS-NEXT: CompileUnit{0x00000000}, language = "unknown", file = '0.c'
|
# 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
|
# This deliberately excludes compile unit 4 to check test the case of a missing
|
||||||
# split unit.
|
# split unit.
|
||||||
.irpc I,0123
|
.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
|
.section .debug_abbrev.dwo,"e",@progbits
|
||||||
.Labbrev\I:
|
.Labbrev\I:
|
||||||
.byte \I*10+1 # Abbreviation Code
|
.byte \I*10+1 # Abbreviation Code
|
||||||
|
@ -90,13 +99,22 @@ A\I:
|
||||||
.byte 36 # DW_TAG_base_type
|
.byte 36 # DW_TAG_base_type
|
||||||
.byte 0 # DW_CHILDREN_no
|
.byte 0 # DW_CHILDREN_no
|
||||||
.byte 3 # DW_AT_name
|
.byte 3 # DW_AT_name
|
||||||
.byte 14 # DW_FORM_string
|
.byte 8 # DW_FORM_string
|
||||||
.byte 62 # DW_AT_encoding
|
.byte 62 # DW_AT_encoding
|
||||||
.byte 11 # DW_FORM_data1
|
.byte 11 # DW_FORM_data1
|
||||||
.byte 11 # DW_AT_byte_size
|
.byte 11 # DW_AT_byte_size
|
||||||
.byte 11 # DW_FORM_data1
|
.byte 11 # DW_FORM_data1
|
||||||
.byte 0 # EOM(1)
|
.byte 0 # EOM(1)
|
||||||
.byte 0 # EOM(2)
|
.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)
|
.byte 0 # EOM(3)
|
||||||
.Labbrev_end\I:
|
.Labbrev_end\I:
|
||||||
|
|
||||||
|
@ -112,10 +130,14 @@ A\I:
|
||||||
.byte '0'+\I, '.', 'c', 0 # DW_AT_name
|
.byte '0'+\I, '.', 'c', 0 # DW_AT_name
|
||||||
.byte \I*10+2 # Abbrev DW_TAG_variable
|
.byte \I*10+2 # Abbrev DW_TAG_variable
|
||||||
.asciz "A" # DW_AT_name
|
.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 2 # DW_AT_location
|
||||||
.byte 0xfb # DW_OP_GNU_addr_index
|
.byte 0xfb # DW_OP_GNU_addr_index
|
||||||
.byte \I
|
.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:
|
.Ltype\I:
|
||||||
.byte \I*10+3 # Abbrev DW_TAG_base_type
|
.byte \I*10+3 # Abbrev DW_TAG_base_type
|
||||||
.asciz "int" # DW_AT_name
|
.asciz "int" # DW_AT_name
|
||||||
|
@ -128,22 +150,26 @@ A\I:
|
||||||
.section .debug_cu_index,"e",@progbits
|
.section .debug_cu_index,"e",@progbits
|
||||||
.short 2 # DWARF version number
|
.short 2 # DWARF version number
|
||||||
.short 0 # Reserved
|
.short 0 # Reserved
|
||||||
.long 2 # Section count
|
.long 3 # Section count
|
||||||
.long 4 # Unit count
|
.long 4 # Unit count
|
||||||
.long 8 # Slot count
|
.long 8 # Slot count
|
||||||
|
|
||||||
.quad 0, 1, 2, 3, 0, 0, 0, 0 # Hash table
|
.quad 0, 1, 2, 3, 0, 0, 0, 0 # Hash table
|
||||||
.long 1, 2, 3, 4, 0, 0, 0, 0 # Index 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
|
.irpc I,0123
|
||||||
.long .Lcu_begin\I-.debug_info.dwo
|
.long .Lcu_begin\I-.debug_info.dwo
|
||||||
.long .Labbrev\I-.debug_abbrev.dwo
|
.long .Labbrev\I-.debug_abbrev.dwo
|
||||||
|
.long .Lstr_offsets\I-.debug_str_offsets.dwo
|
||||||
.endr
|
.endr
|
||||||
.irpc I,0123
|
.irpc I,0123
|
||||||
.long .Ldebug_info_end\I-.Lcu_begin\I
|
.long .Ldebug_info_end\I-.Lcu_begin\I
|
||||||
.long .Labbrev_end\I-.Labbrev\I
|
.long .Labbrev_end\I-.Labbrev\I
|
||||||
|
.long .Lstr_offsets_end\I-.Lstr_offsets\I
|
||||||
.endr
|
.endr
|
||||||
|
|
||||||
.endif
|
.endif
|
||||||
|
|
Loading…
Reference in New Issue