mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
llvm-dwarfdump: Support RLE_addressx and RLE_startx_length in .debug_rnglists
llvm-svn: 344835
This commit is contained in:
parent
1acbf3bdd4
commit
a79c8f8708
@ -10,6 +10,7 @@
|
||||
#ifndef LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
|
||||
#define LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H
|
||||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
||||
@ -23,6 +24,7 @@ namespace llvm {
|
||||
|
||||
class Error;
|
||||
class raw_ostream;
|
||||
class DWARFUnit;
|
||||
|
||||
/// A class representing a single range list entry.
|
||||
struct RangeListEntry : public DWARFListEntryBase {
|
||||
@ -35,7 +37,9 @@ struct RangeListEntry : public DWARFListEntryBase {
|
||||
|
||||
Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr);
|
||||
void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
|
||||
uint64_t &CurrentBase, DIDumpOptions DumpOpts) const;
|
||||
uint64_t &CurrentBase, DIDumpOptions DumpOpts,
|
||||
llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
|
||||
LookupPooledAddress) const;
|
||||
bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; }
|
||||
};
|
||||
|
||||
@ -44,7 +48,8 @@ class DWARFDebugRnglist : public DWARFListType<RangeListEntry> {
|
||||
public:
|
||||
/// Build a DWARFAddressRangesVector from a rangelist.
|
||||
DWARFAddressRangesVector
|
||||
getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr) const;
|
||||
getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr,
|
||||
DWARFUnit &U) const;
|
||||
};
|
||||
|
||||
class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> {
|
||||
|
@ -156,7 +156,10 @@ public:
|
||||
uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); }
|
||||
uint8_t getAddrSize() const { return Header.getAddrSize(); }
|
||||
|
||||
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
|
||||
void dump(raw_ostream &OS,
|
||||
llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
|
||||
LookupPooledAddress,
|
||||
DIDumpOptions DumpOpts = {}) const;
|
||||
|
||||
/// Return the contents of the offset entry designated by a given index.
|
||||
Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
|
||||
@ -229,7 +232,10 @@ Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
|
||||
}
|
||||
|
||||
template <typename DWARFListType>
|
||||
void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS,
|
||||
void DWARFListTableBase<DWARFListType>::dump(
|
||||
raw_ostream &OS,
|
||||
llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
|
||||
LookupPooledAddress,
|
||||
DIDumpOptions DumpOpts) const {
|
||||
Header.dump(OS, DumpOpts);
|
||||
OS << HeaderString << "\n";
|
||||
@ -249,7 +255,7 @@ void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS,
|
||||
for (const auto &List : ListMap)
|
||||
for (const auto &Entry : List.second.getEntries())
|
||||
Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase,
|
||||
DumpOpts);
|
||||
DumpOpts, LookupPooledAddress);
|
||||
}
|
||||
|
||||
template <typename DWARFListType>
|
||||
|
@ -269,8 +269,10 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
|
||||
}
|
||||
|
||||
// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
|
||||
static void dumpRnglistsSection(raw_ostream &OS,
|
||||
DWARFDataExtractor &rnglistData,
|
||||
static void
|
||||
dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData,
|
||||
llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
|
||||
LookupPooledAddress,
|
||||
DIDumpOptions DumpOpts) {
|
||||
uint32_t Offset = 0;
|
||||
while (rnglistData.isValidOffset(Offset)) {
|
||||
@ -285,7 +287,7 @@ static void dumpRnglistsSection(raw_ostream &OS,
|
||||
break;
|
||||
Offset = TableOffset + Length;
|
||||
} else {
|
||||
Rnglists.dump(OS, DumpOpts);
|
||||
Rnglists.dump(OS, LookupPooledAddress, DumpOpts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -495,18 +497,26 @@ void DWARFContext::dump(
|
||||
}
|
||||
}
|
||||
|
||||
auto LookupPooledAddress = [&](uint32_t Index) -> Optional<SectionedAddress> {
|
||||
const auto &CUs = compile_units();
|
||||
auto I = CUs.begin();
|
||||
if (I == CUs.end())
|
||||
return None;
|
||||
return (*I)->getAddrOffsetSectionItem(Index);
|
||||
};
|
||||
|
||||
if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
|
||||
DObj->getRnglistsSection().Data)) {
|
||||
DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
|
||||
isLittleEndian(), 0);
|
||||
dumpRnglistsSection(OS, RnglistData, DumpOpts);
|
||||
dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
|
||||
}
|
||||
|
||||
if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
|
||||
DObj->getRnglistsDWOSection().Data)) {
|
||||
DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
|
||||
isLittleEndian(), 0);
|
||||
dumpRnglistsSection(OS, RnglistData, DumpOpts);
|
||||
dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
|
||||
}
|
||||
|
||||
if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
|
||||
|
@ -32,21 +32,34 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
|
||||
Value0 = Value1 = 0;
|
||||
break;
|
||||
// TODO: Support other encodings.
|
||||
case dwarf::DW_RLE_base_addressx:
|
||||
return createStringError(errc::not_supported,
|
||||
"unsupported rnglists encoding DW_RLE_base_addressx "
|
||||
"at offset 0x%" PRIx32,
|
||||
*OffsetPtr - 1);
|
||||
case dwarf::DW_RLE_base_addressx: {
|
||||
uint32_t PreviousOffset = *OffsetPtr - 1;
|
||||
Value0 = Data.getULEB128(OffsetPtr);
|
||||
if (End < *OffsetPtr)
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"read past end of table when reading "
|
||||
"DW_RLE_base_addressx encoding at offset 0x%" PRIx32,
|
||||
PreviousOffset);
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_RLE_startx_endx:
|
||||
return createStringError(errc::not_supported,
|
||||
"unsupported rnglists encoding DW_RLE_startx_endx at "
|
||||
"offset 0x%" PRIx32,
|
||||
*OffsetPtr - 1);
|
||||
case dwarf::DW_RLE_startx_length:
|
||||
return createStringError(errc::not_supported,
|
||||
"unsupported rnglists encoding DW_RLE_startx_length "
|
||||
"at offset 0x%" PRIx32,
|
||||
*OffsetPtr - 1);
|
||||
case dwarf::DW_RLE_startx_length: {
|
||||
uint32_t PreviousOffset = *OffsetPtr - 1;
|
||||
Value0 = Data.getULEB128(OffsetPtr);
|
||||
Value1 = Data.getULEB128(OffsetPtr);
|
||||
if (End < *OffsetPtr)
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"read past end of table when reading "
|
||||
"DW_RLE_startx_length encoding at offset 0x%" PRIx32,
|
||||
PreviousOffset);
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_RLE_offset_pair: {
|
||||
uint32_t PreviousOffset = *OffsetPtr - 1;
|
||||
Value0 = Data.getULEB128(OffsetPtr);
|
||||
@ -100,12 +113,19 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
|
||||
llvm::Optional<SectionedAddress> BaseAddr) const {
|
||||
DWARFAddressRangesVector
|
||||
DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr,
|
||||
DWARFUnit &U) const {
|
||||
DWARFAddressRangesVector Res;
|
||||
for (const RangeListEntry &RLE : Entries) {
|
||||
if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
|
||||
break;
|
||||
if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
|
||||
BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0);
|
||||
if (!BaseAddr)
|
||||
BaseAddr = {RLE.Value0, 0};
|
||||
continue;
|
||||
}
|
||||
if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
|
||||
BaseAddr = {RLE.Value0, RLE.SectionIndex};
|
||||
continue;
|
||||
@ -133,6 +153,15 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
|
||||
E.LowPC = RLE.Value0;
|
||||
E.HighPC = E.LowPC + RLE.Value1;
|
||||
break;
|
||||
case dwarf::DW_RLE_startx_length: {
|
||||
auto Start = U.getAddrOffsetSectionItem(RLE.Value0);
|
||||
if (!Start)
|
||||
Start = {0, 0};
|
||||
E.SectionIndex = Start->SectionIndex;
|
||||
E.LowPC = Start->Address;
|
||||
E.HighPC = E.LowPC + RLE.Value1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Unsupported encodings should have been reported during extraction,
|
||||
// so we should not run into any here.
|
||||
@ -143,9 +172,11 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
|
||||
return Res;
|
||||
}
|
||||
|
||||
void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize,
|
||||
uint8_t MaxEncodingStringLength,
|
||||
uint64_t &CurrentBase, DIDumpOptions DumpOpts) const {
|
||||
void RangeListEntry::dump(
|
||||
raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
|
||||
uint64_t &CurrentBase, DIDumpOptions DumpOpts,
|
||||
llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
|
||||
LookupPooledAddress) const {
|
||||
auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
|
||||
uint8_t AddrSize, DIDumpOptions DumpOpts) {
|
||||
if (DumpOpts.Verbose) {
|
||||
@ -172,6 +203,17 @@ void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize,
|
||||
case dwarf::DW_RLE_end_of_list:
|
||||
OS << (DumpOpts.Verbose ? "" : "<End of list>");
|
||||
break;
|
||||
// case dwarf::DW_RLE_base_addressx:
|
||||
case dwarf::DW_RLE_base_addressx: {
|
||||
if (auto SA = LookupPooledAddress(Value0))
|
||||
CurrentBase = SA->Address;
|
||||
else
|
||||
CurrentBase = Value0;
|
||||
if (!DumpOpts.Verbose)
|
||||
return;
|
||||
OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_RLE_base_address:
|
||||
// In non-verbose mode we do not print anything for this entry.
|
||||
CurrentBase = Value0;
|
||||
@ -191,6 +233,14 @@ void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize,
|
||||
case dwarf::DW_RLE_start_end:
|
||||
DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
|
||||
break;
|
||||
case dwarf::DW_RLE_startx_length: {
|
||||
PrintRawEntry(OS, *this, AddrSize, DumpOpts);
|
||||
uint64_t Start = 0;
|
||||
if (auto SA = LookupPooledAddress(Value0))
|
||||
Start = SA->Address;
|
||||
DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
llvm_unreachable("Unsupported range list encoding");
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ DWARFUnit::findRnglistFromOffset(uint32_t Offset) {
|
||||
isLittleEndian, RngListTable->getAddrSize());
|
||||
auto RangeListOrError = RngListTable->findList(RangesData, Offset);
|
||||
if (RangeListOrError)
|
||||
return RangeListOrError.get().getAbsoluteRanges(getBaseAddress());
|
||||
return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this);
|
||||
return RangeListOrError.takeError();
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,29 @@
|
||||
# BOTH: ranges:
|
||||
# BOTH-NOT: [
|
||||
|
||||
# TERSE-NEXT: range list header: length = 0x0000000b, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
|
||||
|
||||
# VERBOSE-NEXT: 0x{{[0-9a-f]*}}:
|
||||
# VERBOSE-SAME: range list header: length = 0x0000000b, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
|
||||
|
||||
# BOTH-NEXT: ranges:
|
||||
# TERSE-NEXT: <End of list>
|
||||
|
||||
# VERBOSE-NEXT: 0x00000082: [DW_RLE_base_addressx]: 0x0000000000000000
|
||||
# VERBOSE-NEXT: 0x00000084: [DW_RLE_end_of_list ]
|
||||
|
||||
# TERSE-NEXT: range list header: length = 0x0000000c, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
|
||||
|
||||
# VERBOSE-NEXT: 0x{{[0-9a-f]*}}:
|
||||
# VERBOSE-SAME: range list header: length = 0x0000000c, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
|
||||
|
||||
# BOTH-NEXT: ranges:
|
||||
# TERSE-NEXT: [0x0000000000000000, 0x000000000000002a)
|
||||
# TERSE-NEXT: <End of list>
|
||||
|
||||
# VERBOSE-NEXT: 0x000000a1: [DW_RLE_startx_length]: 0x0000000000000002, 0x000000000000002a => [0x0000000000000000, 0x000000000000002a)
|
||||
# VERBOSE-NEXT: 0x000000a4: [DW_RLE_end_of_list ]
|
||||
|
||||
# TERSE-NEXT: range list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
|
||||
|
||||
# VERBOSE-NEXT: 0x{{[0-9a-f]*}}:
|
||||
@ -87,9 +110,7 @@
|
||||
# BOTH-NOT: range list header:
|
||||
|
||||
# ERR-NOT: error:
|
||||
# ERR: error: unsupported rnglists encoding DW_RLE_base_addressx at offset 0x82
|
||||
# ERR-NEXT: error: unsupported rnglists encoding DW_RLE_startx_endx at offset 0x91
|
||||
# ERR-NEXT: error: unsupported rnglists encoding DW_RLE_startx_length at offset 0xa1
|
||||
# ERR: error: unsupported rnglists encoding DW_RLE_startx_endx at offset 0x91
|
||||
# ERR-NOT: error:
|
||||
|
||||
.section .debug_rnglists,"",@progbits
|
||||
|
Loading…
Reference in New Issue
Block a user