DebugInfo: Cleanup RLE dumping, using a length-constrained DataExtractor rather than carrying the end offset separately

This commit is contained in:
David Blaikie 2020-09-18 19:29:37 -07:00
parent 528a1f121c
commit ad68a8b952
6 changed files with 57 additions and 70 deletions

View File

@ -553,6 +553,7 @@ StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage);
StringRef IndexString(unsigned Idx);
StringRef FormatString(DwarfFormat Format);
StringRef FormatString(bool IsDWARF64);
StringRef RLEString(unsigned RLE);
/// @}
/// \defgroup DwarfConstantsParsing Dwarf constants parsing functions

View File

@ -34,7 +34,7 @@ struct RangeListEntry : public DWARFListEntryBase {
uint64_t Value0;
uint64_t Value1;
Error extract(DWARFDataExtractor Data, uint64_t End, uint64_t *OffsetPtr);
Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr);
void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
uint64_t &CurrentBase, DIDumpOptions DumpOpts,
llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>

View File

@ -46,7 +46,7 @@ public:
const ListEntries &getEntries() const { return Entries; }
bool empty() const { return Entries.empty(); }
void clear() { Entries.clear(); }
Error extract(DWARFDataExtractor Data, uint64_t HeaderOffset, uint64_t End,
Error extract(DWARFDataExtractor Data, uint64_t HeaderOffset,
uint64_t *OffsetPtr, StringRef SectionName,
StringRef ListStringName);
};
@ -197,18 +197,18 @@ Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
return E;
Data.setAddressSize(Header.getAddrSize());
uint64_t End = getHeaderOffset() + Header.length();
while (*OffsetPtr < End) {
Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length());
while (Data.isValidOffset(*OffsetPtr)) {
DWARFListType CurrentList;
uint64_t Off = *OffsetPtr;
if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr,
if (Error E = CurrentList.extract(Data, getHeaderOffset(), OffsetPtr,
Header.getSectionName(),
Header.getListTypeString()))
return E;
ListMap[Off] = CurrentList;
}
assert(*OffsetPtr == End &&
assert(*OffsetPtr == Data.size() &&
"mismatch between expected length of table and length "
"of extracted data");
return Error::success();
@ -216,18 +216,18 @@ Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
template <typename ListEntryType>
Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
uint64_t HeaderOffset, uint64_t End,
uint64_t HeaderOffset,
uint64_t *OffsetPtr,
StringRef SectionName,
StringRef ListTypeString) {
if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
if (*OffsetPtr < HeaderOffset || *OffsetPtr >= Data.size())
return createStringError(errc::invalid_argument,
"invalid %s list offset 0x%" PRIx64,
ListTypeString.data(), *OffsetPtr);
Entries.clear();
while (*OffsetPtr < End) {
while (Data.isValidOffset(*OffsetPtr)) {
ListEntryType Entry;
if (Error E = Entry.extract(Data, End, OffsetPtr))
if (Error E = Entry.extract(Data, OffsetPtr))
return E;
Entries.push_back(Entry);
if (Entry.isSentinel())
@ -272,9 +272,9 @@ DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
uint64_t Offset) {
// Extract the list from the section and enter it into the list map.
DWARFListType List;
uint64_t End = getHeaderOffset() + Header.length();
Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length());
if (Error E =
List.extract(Data, getHeaderOffset(), End, &Offset,
List.extract(Data, getHeaderOffset(), &Offset,
Header.getSectionName(), Header.getListTypeString()))
return std::move(E);
return List;

View File

@ -795,6 +795,17 @@ StringRef llvm::dwarf::FormatString(bool IsDWARF64) {
return FormatString(IsDWARF64 ? DWARF64 : DWARF32);
}
StringRef llvm::dwarf::RLEString(unsigned RLE) {
switch (RLE) {
default:
return StringRef();
#define HANDLE_DW_RLE(ID, NAME) \
case DW_RLE_##NAME: \
return "DW_RLE_" #NAME;
#include "llvm/BinaryFormat/Dwarf.def"
}
}
constexpr char llvm::dwarf::EnumTraits<Attribute>::Type[];
constexpr char llvm::dwarf::EnumTraits<Form>::Type[];
constexpr char llvm::dwarf::EnumTraits<Index>::Type[];

View File

@ -16,98 +16,73 @@
using namespace llvm;
Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t End,
uint64_t *OffsetPtr) {
Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) {
Offset = *OffsetPtr;
SectionIndex = -1ULL;
// The caller should guarantee that we have at least 1 byte available, so
// we just assert instead of revalidate.
assert(*OffsetPtr < End &&
assert(*OffsetPtr < Data.size() &&
"not enough space to extract a rangelist encoding");
uint8_t Encoding = Data.getU8(OffsetPtr);
DataExtractor::Cursor C(*OffsetPtr);
switch (Encoding) {
case dwarf::DW_RLE_end_of_list:
Value0 = Value1 = 0;
break;
// TODO: Support other encodings.
case dwarf::DW_RLE_base_addressx: {
uint64_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%" PRIx64,
PreviousOffset);
Value0 = Data.getULEB128(C);
break;
}
case dwarf::DW_RLE_startx_endx:
return createStringError(errc::not_supported,
"unsupported rnglists encoding DW_RLE_startx_endx at "
"offset 0x%" PRIx64,
*OffsetPtr - 1);
consumeError(C.takeError());
return createStringError(
errc::not_supported,
"unsupported rnglists encoding DW_RLE_startx_endx at "
"offset 0x%" PRIx64,
Offset);
case dwarf::DW_RLE_startx_length: {
uint64_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%" PRIx64,
PreviousOffset);
Value0 = Data.getULEB128(C);
Value1 = Data.getULEB128(C);
break;
}
case dwarf::DW_RLE_offset_pair: {
uint64_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_offset_pair encoding at offset 0x%" PRIx64,
PreviousOffset);
Value0 = Data.getULEB128(C);
Value1 = Data.getULEB128(C);
break;
}
case dwarf::DW_RLE_base_address: {
if ((End - *OffsetPtr) < Data.getAddressSize())
return createStringError(errc::invalid_argument,
"insufficient space remaining in table for "
"DW_RLE_base_address encoding at offset 0x%" PRIx64,
*OffsetPtr - 1);
Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
Value0 = Data.getRelocatedAddress(C, &SectionIndex);
break;
}
case dwarf::DW_RLE_start_end: {
if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
return createStringError(errc::invalid_argument,
"insufficient space remaining in table for "
"DW_RLE_start_end encoding "
"at offset 0x%" PRIx64,
*OffsetPtr - 1);
Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
Value1 = Data.getRelocatedAddress(OffsetPtr);
Value0 = Data.getRelocatedAddress(C, &SectionIndex);
Value1 = Data.getRelocatedAddress(C);
break;
}
case dwarf::DW_RLE_start_length: {
uint64_t PreviousOffset = *OffsetPtr - 1;
Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
Value1 = Data.getULEB128(OffsetPtr);
if (End < *OffsetPtr)
return createStringError(errc::invalid_argument,
"read past end of table when reading "
"DW_RLE_start_length encoding at offset 0x%" PRIx64,
PreviousOffset);
Value0 = Data.getRelocatedAddress(C, &SectionIndex);
Value1 = Data.getULEB128(C);
break;
}
default:
consumeError(C.takeError());
return createStringError(errc::not_supported,
"unknown rnglists encoding 0x%" PRIx32
" at offset 0x%" PRIx64,
uint32_t(Encoding), *OffsetPtr - 1);
"unknown rnglists encoding 0x%" PRIx32
" at offset 0x%" PRIx64,
uint32_t(Encoding), Offset);
}
if (!C) {
consumeError(C.takeError());
return createStringError(
errc::invalid_argument,
"read past end of table when reading %s encoding at offset 0x%" PRIx64,
dwarf::RLEString(Encoding).data(), Offset);
}
*OffsetPtr = C.tell();
EntryKind = Encoding;
return Error::success();
}

View File

@ -30,7 +30,7 @@
# CHECK-NEXT: error: .debug_rnglists table at offset 0x39 has unsupported address size 2
# CHECK-NEXT: error: .debug_rnglists table at offset 0x45 has unsupported segment selector size 4
# CHECK-NEXT: error: .debug_rnglists table at offset 0x51 has more offset entries (12345678) than there is space for
# CHECK-NEXT: error: insufficient space remaining in table for DW_RLE_start_end encoding at offset 0x69
# CHECK-NEXT: error: read past end of table when reading DW_RLE_start_end encoding at offset 0x69
# CHECK-NEXT: error: read past end of table when reading DW_RLE_start_length encoding at offset 0x82
# CHECK-NEXT: error: unknown rnglists encoding 0x2a at offset 0x98
# CHECK-NEXT: error: no end of list marker detected at end of .debug_rnglists table starting at offset 0xaa