mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-27 15:02:16 +00:00
[DWARFv5] Support DW_FORM_strp in the .debug_line.dwo header.
As a side effect, the .debug_line section will be dumped in physical order, rather than in the order that compile units refer to their associated portions of the .debug_line section. These are probably always the same order anyway, and no tests noticed the difference. Differential Revision: https://reviews.llvm.org/D39854 llvm-svn: 318839
This commit is contained in:
parent
bd81e5f80e
commit
76e4694e00
@ -204,6 +204,28 @@ static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We want to supply the Unit associated with a .debug_line[.dwo] table when
|
||||||
|
// we dump it, if possible, but still dump the table even if there isn't a Unit.
|
||||||
|
// Therefore, collect up handles on all the Units that point into the
|
||||||
|
// line-table section.
|
||||||
|
typedef std::map<uint64_t, DWARFUnit *> LineToUnitMap;
|
||||||
|
|
||||||
|
static LineToUnitMap
|
||||||
|
buildLineToUnitMap(DWARFContext::cu_iterator_range CUs,
|
||||||
|
DWARFContext::tu_section_iterator_range TUSections) {
|
||||||
|
LineToUnitMap LineToUnit;
|
||||||
|
for (const auto &CU : CUs)
|
||||||
|
if (auto CUDIE = CU->getUnitDIE())
|
||||||
|
if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list)))
|
||||||
|
LineToUnit.insert(std::make_pair(*StmtOffset, &*CU));
|
||||||
|
for (const auto &TUS : TUSections)
|
||||||
|
for (const auto &TU : TUS)
|
||||||
|
if (auto TUDIE = TU->getUnitDIE())
|
||||||
|
if (auto StmtOffset = toSectionOffset(TUDIE.find(DW_AT_stmt_list)))
|
||||||
|
LineToUnit.insert(std::make_pair(*StmtOffset, &*TU));
|
||||||
|
return LineToUnit;
|
||||||
|
}
|
||||||
|
|
||||||
void DWARFContext::dump(
|
void DWARFContext::dump(
|
||||||
raw_ostream &OS, DIDumpOptions DumpOpts,
|
raw_ostream &OS, DIDumpOptions DumpOpts,
|
||||||
std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
|
std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
|
||||||
@ -310,48 +332,57 @@ void DWARFContext::dump(
|
|||||||
set.dump(OS);
|
set.dump(OS);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t savedAddressByteSize = 0;
|
|
||||||
if (shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
|
if (shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
|
||||||
DObj->getLineSection().Data)) {
|
DObj->getLineSection().Data)) {
|
||||||
for (const auto &CU : compile_units()) {
|
LineToUnitMap LineToUnit =
|
||||||
savedAddressByteSize = CU->getAddressByteSize();
|
buildLineToUnitMap(compile_units(), type_unit_sections());
|
||||||
auto CUDIE = CU->getUnitDIE();
|
unsigned Offset = 0;
|
||||||
if (!CUDIE)
|
DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(),
|
||||||
|
0);
|
||||||
|
while (Offset < LineData.getData().size()) {
|
||||||
|
DWARFUnit *U = nullptr;
|
||||||
|
auto It = LineToUnit.find(Offset);
|
||||||
|
if (It != LineToUnit.end()) {
|
||||||
|
U = It->second;
|
||||||
|
LineData.setAddressSize(U->getAddressByteSize());
|
||||||
|
}
|
||||||
|
DWARFDebugLine::LineTable LineTable;
|
||||||
|
if (DumpOffset && Offset != *DumpOffset) {
|
||||||
|
// Find the size of this part of the line table section and skip it.
|
||||||
|
unsigned OldOffset = Offset;
|
||||||
|
LineTable.Prologue.parse(LineData, &Offset, U);
|
||||||
|
Offset = OldOffset + LineTable.Prologue.TotalLength +
|
||||||
|
LineTable.Prologue.sizeofTotalLength();
|
||||||
continue;
|
continue;
|
||||||
if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) {
|
}
|
||||||
if (DumpOffset && *StmtOffset != *DumpOffset)
|
// Verbose dumping is done during parsing and not on the intermediate
|
||||||
continue;
|
// representation.
|
||||||
DWARFDataExtractor lineData(*DObj, DObj->getLineSection(),
|
OS << "debug_line[" << format("0x%8.8x", Offset) << "]\n";
|
||||||
isLittleEndian(), savedAddressByteSize);
|
if (DumpOpts.Verbose) {
|
||||||
DWARFDebugLine::LineTable LineTable;
|
LineTable.parse(LineData, &Offset, U, &OS);
|
||||||
uint32_t Offset = *StmtOffset;
|
} else {
|
||||||
// Verbose dumping is done during parsing and not on the intermediate
|
LineTable.parse(LineData, &Offset, U);
|
||||||
// representation.
|
LineTable.dump(OS);
|
||||||
OS << "debug_line[" << format("0x%8.8x", Offset) << "]\n";
|
|
||||||
if (DumpOpts.Verbose) {
|
|
||||||
LineTable.parse(lineData, &Offset, &*CU, &OS);
|
|
||||||
} else {
|
|
||||||
LineTable.parse(lineData, &Offset, &*CU);
|
|
||||||
LineTable.dump(OS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This seems sketchy.
|
|
||||||
for (const auto &CU : compile_units()) {
|
|
||||||
savedAddressByteSize = CU->getAddressByteSize();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
|
if (shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
|
||||||
DObj->getLineDWOSection().Data)) {
|
DObj->getLineDWOSection().Data)) {
|
||||||
unsigned stmtOffset = 0;
|
LineToUnitMap LineToUnit =
|
||||||
DWARFDataExtractor lineData(*DObj, DObj->getLineDWOSection(),
|
buildLineToUnitMap(dwo_compile_units(), dwo_type_unit_sections());
|
||||||
isLittleEndian(), savedAddressByteSize);
|
unsigned Offset = 0;
|
||||||
DWARFDebugLine::LineTable LineTable;
|
DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(),
|
||||||
while (LineTable.Prologue.parse(lineData, &stmtOffset, nullptr)) {
|
isLittleEndian(), 0);
|
||||||
|
while (Offset < LineData.getData().size()) {
|
||||||
|
DWARFUnit *U = nullptr;
|
||||||
|
auto It = LineToUnit.find(Offset);
|
||||||
|
if (It != LineToUnit.end())
|
||||||
|
U = It->second;
|
||||||
|
DWARFDebugLine::LineTable LineTable;
|
||||||
|
if (!LineTable.Prologue.parse(LineData, &Offset, U))
|
||||||
|
break;
|
||||||
LineTable.dump(OS);
|
LineTable.dump(OS);
|
||||||
LineTable.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,6 +424,11 @@ void DWARFContext::dump(
|
|||||||
// last compile unit (there is no easy and fast way to associate address
|
// last compile unit (there is no easy and fast way to associate address
|
||||||
// range list and the compile unit it describes).
|
// range list and the compile unit it describes).
|
||||||
// FIXME: savedAddressByteSize seems sketchy.
|
// FIXME: savedAddressByteSize seems sketchy.
|
||||||
|
uint8_t savedAddressByteSize = 0;
|
||||||
|
for (const auto &CU : compile_units()) {
|
||||||
|
savedAddressByteSize = CU->getAddressByteSize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(),
|
DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(),
|
||||||
isLittleEndian(), savedAddressByteSize);
|
isLittleEndian(), savedAddressByteSize);
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
@ -230,7 +230,8 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
|
|||||||
|
|
||||||
if (getVersion() >= 5) {
|
if (getVersion() >= 5) {
|
||||||
FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
|
FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
|
||||||
assert(getAddressSize() == DebugLineData.getAddressSize() &&
|
assert((DebugLineData.getAddressSize() == 0 ||
|
||||||
|
DebugLineData.getAddressSize() == getAddressSize()) &&
|
||||||
"Line table header and data extractor disagree");
|
"Line table header and data extractor disagree");
|
||||||
SegSelectorSize = DebugLineData.getU8(OffsetPtr);
|
SegSelectorSize = DebugLineData.getU8(OffsetPtr);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@ str_LT_5b:
|
|||||||
.section .debug_str.dwo,"MS",@progbits,1
|
.section .debug_str.dwo,"MS",@progbits,1
|
||||||
dwo_TU_5:
|
dwo_TU_5:
|
||||||
.asciz "V5_split_type_unit"
|
.asciz "V5_split_type_unit"
|
||||||
|
dwo_producer:
|
||||||
|
.asciz "Handmade DWO producer"
|
||||||
|
dwo_CU_5:
|
||||||
|
.asciz "V5_dwo_compile_unit"
|
||||||
|
dwo_LT_5a:
|
||||||
|
.asciz "DWODirectory5a"
|
||||||
|
dwo_LT_5b:
|
||||||
|
.asciz "DWODirectory5b"
|
||||||
|
|
||||||
# All CUs/TUs use the same abbrev section for simplicity.
|
# All CUs/TUs use the same abbrev section for simplicity.
|
||||||
.section .debug_abbrev,"",@progbits
|
.section .debug_abbrev,"",@progbits
|
||||||
@ -61,6 +69,8 @@ dwo_TU_5:
|
|||||||
.byte 0x0e # DW_FORM_strp
|
.byte 0x0e # DW_FORM_strp
|
||||||
.byte 0x03 # DW_AT_name
|
.byte 0x03 # DW_AT_name
|
||||||
.byte 0x0e # DW_FORM_strp
|
.byte 0x0e # DW_FORM_strp
|
||||||
|
.byte 0x10 # DW_AT_stmt_list
|
||||||
|
.byte 0x17 # DW_FORM_sec_offset
|
||||||
.byte 0x00 # EOM(1)
|
.byte 0x00 # EOM(1)
|
||||||
.byte 0x00 # EOM(2)
|
.byte 0x00 # EOM(2)
|
||||||
.byte 0x02 # Abbrev code
|
.byte 0x02 # Abbrev code
|
||||||
@ -117,6 +127,29 @@ CU_5_end:
|
|||||||
# CHECK: 0x00000019: Compile Unit: length = 0x00000016 version = 0x0005 unit_type = DW_UT_compile abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000033)
|
# CHECK: 0x00000019: Compile Unit: length = 0x00000016 version = 0x0005 unit_type = DW_UT_compile abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000033)
|
||||||
# CHECK: 0x00000025: DW_TAG_compile_unit
|
# CHECK: 0x00000025: DW_TAG_compile_unit
|
||||||
|
|
||||||
|
.section .debug_info.dwo,"",@progbits
|
||||||
|
# CHECK-LABEL: .debug_info.dwo
|
||||||
|
|
||||||
|
# DWARF v5 split CU header.
|
||||||
|
.long CU_split_5_end-CU_split_5_version # Length of Unit
|
||||||
|
CU_split_5_version:
|
||||||
|
.short 5 # DWARF version number
|
||||||
|
.byte 5 # DWARF Unit Type
|
||||||
|
.byte 8 # Address Size (in bytes)
|
||||||
|
.long .debug_abbrev.dwo # Offset Into Abbrev. Section
|
||||||
|
# The split compile-unit DIE, with DW_AT_producer, DW_AT_name, DW_AT_stmt_list.
|
||||||
|
.byte 1
|
||||||
|
.long dwo_producer
|
||||||
|
.long dwo_CU_5
|
||||||
|
.long dwo_LH_5_start
|
||||||
|
.byte 0 # NULL
|
||||||
|
CU_split_5_end:
|
||||||
|
|
||||||
|
# CHECK: 0x00000000: Compile Unit: length = 0x00000016 version = 0x0005 unit_type = DW_UT_split_compile abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x0000001a)
|
||||||
|
# CHECK: 0x0000000c: DW_TAG_compile_unit
|
||||||
|
# CHECK-NEXT: DW_AT_producer {{.*}} "Handmade DWO producer"
|
||||||
|
# CHECK-NEXT: DW_AT_name {{.*}} "V5_dwo_compile_unit"
|
||||||
|
|
||||||
.section .debug_types,"",@progbits
|
.section .debug_types,"",@progbits
|
||||||
# CHECK-LABEL: .debug_types contents:
|
# CHECK-LABEL: .debug_types contents:
|
||||||
|
|
||||||
@ -298,4 +331,78 @@ LH_5_end:
|
|||||||
# CHECK-NOT: include_directories
|
# CHECK-NOT: include_directories
|
||||||
# CHECK: file_names[ 1] 1 0x00000051 0x00000052 File5a{{$}}
|
# CHECK: file_names[ 1] 1 0x00000051 0x00000052 File5a{{$}}
|
||||||
# CHECK: file_names[ 2] 2 0x00000053 0x00000054 File5b{{$}}
|
# CHECK: file_names[ 2] 2 0x00000053 0x00000054 File5b{{$}}
|
||||||
|
# CHECK-NOT: file_names
|
||||||
|
|
||||||
|
.section .debug_line.dwo,"",@progbits
|
||||||
|
# CHECK-LABEL: .debug_line.dwo
|
||||||
|
|
||||||
|
# DWARF v5 DWO line-table header.
|
||||||
|
dwo_LH_5_start:
|
||||||
|
.long dwo_LH_5_end-dwo_LH_5_version # Length of Unit
|
||||||
|
dwo_LH_5_version:
|
||||||
|
.short 5 # DWARF version number
|
||||||
|
.byte 8 # Address Size
|
||||||
|
.byte 0 # Segment Selector Size
|
||||||
|
.long dwo_LH_5_header_end-dwo_LH_5_params # Length of Prologue
|
||||||
|
dwo_LH_5_params:
|
||||||
|
.byte 1 # Minimum Instruction Length
|
||||||
|
.byte 1 # Maximum Operations per Instruction
|
||||||
|
.byte 1 # Default is_stmt
|
||||||
|
.byte -5 # Line Base
|
||||||
|
.byte 14 # Line Range
|
||||||
|
.byte 13 # Opcode Base
|
||||||
|
.byte 0 # Standard Opcode Lengths
|
||||||
|
.byte 1
|
||||||
|
.byte 1
|
||||||
|
.byte 1
|
||||||
|
.byte 1
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.byte 1
|
||||||
|
.byte 0
|
||||||
|
.byte 0
|
||||||
|
.byte 1
|
||||||
|
# Directory table format
|
||||||
|
.byte 1 # One element per directory entry
|
||||||
|
.byte 1 # DW_LNCT_path
|
||||||
|
.byte 0x0e # DW_FORM_strp (-> .debug_str.dwo)
|
||||||
|
# Directory table entries
|
||||||
|
.byte 2 # Two directories
|
||||||
|
.long dwo_LT_5a
|
||||||
|
.long dwo_LT_5b
|
||||||
|
# File table format
|
||||||
|
.byte 4 # Four elements per file entry
|
||||||
|
.byte 1 # DW_LNCT_path
|
||||||
|
.byte 0x08 # DW_FORM_string
|
||||||
|
.byte 2 # DW_LNCT_directory_index
|
||||||
|
.byte 0x0b # DW_FORM_data1
|
||||||
|
.byte 3 # DW_LNCT_timestamp
|
||||||
|
.byte 0x0f # DW_FORM_udata
|
||||||
|
.byte 4 # DW_LNCT_size
|
||||||
|
.byte 0x0f # DW_FORM_udata
|
||||||
|
# File table entries
|
||||||
|
.byte 2 # Two files
|
||||||
|
.asciz "DWOFile5a"
|
||||||
|
.byte 1
|
||||||
|
.byte 0x15
|
||||||
|
.byte 0x25
|
||||||
|
.asciz "DWOFile5b"
|
||||||
|
.byte 2
|
||||||
|
.byte 0x35
|
||||||
|
.byte 0x45
|
||||||
|
dwo_LH_5_header_end:
|
||||||
|
# Line number program, which is empty.
|
||||||
|
dwo_LH_5_end:
|
||||||
|
|
||||||
|
# CHECK: Line table prologue:
|
||||||
|
# CHECK: version: 5
|
||||||
|
# CHECK: address_size: 8
|
||||||
|
# CHECK: seg_select_size: 0
|
||||||
|
# CHECK: max_ops_per_inst: 1
|
||||||
|
# CHECK: include_directories[ 1] = 'DWODirectory5a'
|
||||||
|
# CHECK: include_directories[ 2] = 'DWODirectory5b'
|
||||||
|
# CHECK-NOT: include_directories
|
||||||
|
# CHECK: file_names[ 1] 1 0x00000015 0x00000025 DWOFile5a{{$}}
|
||||||
|
# CHECK: file_names[ 2] 2 0x00000035 0x00000045 DWOFile5b{{$}}
|
||||||
# CHECK-NOT: file_names
|
# CHECK-NOT: file_names
|
||||||
|
Loading…
x
Reference in New Issue
Block a user