forked from OSchip/llvm-project
[DebugInfo] Do not hang when parsing a malformed .debug_pub* section.
The parsing method did not check reading errors and might easily fall into an infinite loop on an invalid input because of that. Differential Revision: https://reviews.llvm.org/D83049
This commit is contained in:
parent
a86ce06faf
commit
68f5a8b204
|
@ -56,11 +56,11 @@ public:
|
|||
return addrSection;
|
||||
}
|
||||
|
||||
const llvm::DWARFSection &getGnuPubnamesSection() const override {
|
||||
const LLDDWARFSection &getGnuPubnamesSection() const override {
|
||||
return gnuPubnamesSection;
|
||||
}
|
||||
|
||||
const llvm::DWARFSection &getGnuPubtypesSection() const override {
|
||||
const LLDDWARFSection &getGnuPubtypesSection() const override {
|
||||
return gnuPubtypesSection;
|
||||
}
|
||||
|
||||
|
|
|
@ -2705,12 +2705,15 @@ template <class ELFT>
|
|||
static std::vector<GdbIndexSection::NameAttrEntry>
|
||||
readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
|
||||
const std::vector<GdbIndexSection::CuEntry> &cus) {
|
||||
const DWARFSection &pubNames = obj.getGnuPubnamesSection();
|
||||
const DWARFSection &pubTypes = obj.getGnuPubtypesSection();
|
||||
const LLDDWARFSection &pubNames = obj.getGnuPubnamesSection();
|
||||
const LLDDWARFSection &pubTypes = obj.getGnuPubtypesSection();
|
||||
|
||||
std::vector<GdbIndexSection::NameAttrEntry> ret;
|
||||
for (const DWARFSection *pub : {&pubNames, &pubTypes}) {
|
||||
DWARFDebugPubTable table(obj, *pub, config->isLE, true);
|
||||
for (const LLDDWARFSection *pub : {&pubNames, &pubTypes}) {
|
||||
DWARFDataExtractor data(obj, *pub, config->isLE, config->wordsize);
|
||||
DWARFDebugPubTable table;
|
||||
if (Error e = table.extract(data, /*GnuStyle=*/true))
|
||||
warn(toString(pub->sec) + ": " + toString(std::move(e)));
|
||||
for (const DWARFDebugPubTable::Set &set : table.getData()) {
|
||||
// The value written into the constant pool is kind << 24 | cuIndex. As we
|
||||
// don't know how many compilation units precede this object to compute
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t
|
||||
# RUN: ld.lld --gdb-index %t -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: warning: {{.*}}(.debug_gnu_pubnames): unexpected end of data at offset 0x1 while reading [0x0, 0x4)
|
||||
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.byte 1 # Abbreviation Code
|
||||
.byte 17 # DW_TAG_compile_unit
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 0 # EOM(3)
|
||||
|
||||
.section .debug_info,"",@progbits
|
||||
.LCUBegin:
|
||||
.long .LUnitEnd-.LUnitBegin # Length of Unit
|
||||
.LUnitBegin:
|
||||
.short 4 # DWARF version number
|
||||
.long .debug_abbrev # Offset Into Abbrev. Section
|
||||
.byte 8 # Address Size (in bytes)
|
||||
.byte 1 # Abbrev [1] DW_TAG_compile_unit
|
||||
.LUnitEnd:
|
||||
|
||||
.section .debug_gnu_pubnames,"",@progbits
|
||||
.byte 0
|
|
@ -12,6 +12,7 @@
|
|||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
@ -67,11 +68,12 @@ private:
|
|||
|
||||
/// gnu styled tables contains additional information.
|
||||
/// This flag determines whether or not section we parse is debug_gnu* table.
|
||||
bool GnuStyle;
|
||||
bool GnuStyle = false;
|
||||
|
||||
public:
|
||||
DWARFDebugPubTable(const DWARFObject &Obj, const DWARFSection &Sec,
|
||||
bool LittleEndian, bool GnuStyle);
|
||||
DWARFDebugPubTable() = default;
|
||||
|
||||
Error extract(DWARFDataExtractor Data, bool GnuStyle);
|
||||
|
||||
void dump(raw_ostream &OS) const;
|
||||
|
||||
|
|
|
@ -336,6 +336,14 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
|
|||
}
|
||||
}
|
||||
|
||||
static void dumpPubTableSection(raw_ostream &OS, DIDumpOptions DumpOpts,
|
||||
DWARFDataExtractor Data, bool GnuStyle) {
|
||||
DWARFDebugPubTable Table;
|
||||
if (Error E = Table.extract(Data, GnuStyle))
|
||||
DumpOpts.RecoverableErrorHandler(std::move(E));
|
||||
Table.dump(OS);
|
||||
}
|
||||
|
||||
void DWARFContext::dump(
|
||||
raw_ostream &OS, DIDumpOptions DumpOpts,
|
||||
std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
|
||||
|
@ -626,26 +634,32 @@ void DWARFContext::dump(
|
|||
}
|
||||
|
||||
if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
|
||||
DObj->getPubnamesSection().Data))
|
||||
DWARFDebugPubTable(*DObj, DObj->getPubnamesSection(), isLittleEndian(), false)
|
||||
.dump(OS);
|
||||
DObj->getPubnamesSection().Data)) {
|
||||
DWARFDataExtractor PubTableData(*DObj, DObj->getPubnamesSection(),
|
||||
isLittleEndian(), 0);
|
||||
dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
|
||||
}
|
||||
|
||||
if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,
|
||||
DObj->getPubtypesSection().Data))
|
||||
DWARFDebugPubTable(*DObj, DObj->getPubtypesSection(), isLittleEndian(), false)
|
||||
.dump(OS);
|
||||
DObj->getPubtypesSection().Data)) {
|
||||
DWARFDataExtractor PubTableData(*DObj, DObj->getPubtypesSection(),
|
||||
isLittleEndian(), 0);
|
||||
dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
|
||||
}
|
||||
|
||||
if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,
|
||||
DObj->getGnuPubnamesSection().Data))
|
||||
DWARFDebugPubTable(*DObj, DObj->getGnuPubnamesSection(), isLittleEndian(),
|
||||
true /* GnuStyle */)
|
||||
.dump(OS);
|
||||
DObj->getGnuPubnamesSection().Data)) {
|
||||
DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubnamesSection(),
|
||||
isLittleEndian(), 0);
|
||||
dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
|
||||
}
|
||||
|
||||
if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,
|
||||
DObj->getGnuPubtypesSection().Data))
|
||||
DWARFDebugPubTable(*DObj, DObj->getGnuPubtypesSection(), isLittleEndian(),
|
||||
true /* GnuStyle */)
|
||||
.dump(OS);
|
||||
DObj->getGnuPubtypesSection().Data)) {
|
||||
DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubtypesSection(),
|
||||
isLittleEndian(), 0);
|
||||
dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
|
||||
}
|
||||
|
||||
if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
|
||||
DObj->getStrOffsetsSection().Data))
|
||||
|
|
|
@ -18,34 +18,32 @@
|
|||
using namespace llvm;
|
||||
using namespace dwarf;
|
||||
|
||||
DWARFDebugPubTable::DWARFDebugPubTable(const DWARFObject &Obj,
|
||||
const DWARFSection &Sec,
|
||||
bool LittleEndian, bool GnuStyle)
|
||||
: GnuStyle(GnuStyle) {
|
||||
DWARFDataExtractor PubNames(Obj, Sec, LittleEndian, 0);
|
||||
uint64_t Offset = 0;
|
||||
while (PubNames.isValidOffset(Offset)) {
|
||||
Error DWARFDebugPubTable::extract(DWARFDataExtractor Data, bool GnuStyle) {
|
||||
this->GnuStyle = GnuStyle;
|
||||
Sets.clear();
|
||||
DataExtractor::Cursor C(0);
|
||||
while (C && Data.isValidOffset(C.tell())) {
|
||||
Sets.push_back({});
|
||||
Set &SetData = Sets.back();
|
||||
|
||||
std::tie(SetData.Length, SetData.Format) =
|
||||
PubNames.getInitialLength(&Offset);
|
||||
std::tie(SetData.Length, SetData.Format) = Data.getInitialLength(C);
|
||||
const unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(SetData.Format);
|
||||
|
||||
SetData.Version = PubNames.getU16(&Offset);
|
||||
SetData.Offset = PubNames.getRelocatedValue(OffsetSize, &Offset);
|
||||
SetData.Size = PubNames.getUnsigned(&Offset, OffsetSize);
|
||||
SetData.Version = Data.getU16(C);
|
||||
SetData.Offset = Data.getRelocatedValue(C, OffsetSize);
|
||||
SetData.Size = Data.getUnsigned(C, OffsetSize);
|
||||
|
||||
while (Offset < Sec.Data.size()) {
|
||||
uint64_t DieRef = PubNames.getUnsigned(&Offset, OffsetSize);
|
||||
while (C) {
|
||||
uint64_t DieRef = Data.getUnsigned(C, OffsetSize);
|
||||
if (DieRef == 0)
|
||||
break;
|
||||
uint8_t IndexEntryValue = GnuStyle ? PubNames.getU8(&Offset) : 0;
|
||||
StringRef Name = PubNames.getCStrRef(&Offset);
|
||||
uint8_t IndexEntryValue = GnuStyle ? Data.getU8(C) : 0;
|
||||
StringRef Name = Data.getCStrRef(C);
|
||||
SetData.Entries.push_back(
|
||||
{DieRef, PubIndexEntryDescriptor(IndexEntryValue), Name});
|
||||
}
|
||||
}
|
||||
return C.takeError();
|
||||
}
|
||||
|
||||
void DWARFDebugPubTable::dump(raw_ostream &OS) const {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o %t
|
||||
# RUN: not llvm-dwarfdump -v %t 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: .debug_pubnames contents:
|
||||
# CHECK-NEXT: error: unexpected end of data at offset 0x1 while reading [0x0, 0x4)
|
||||
|
||||
# CHECK: .debug_pubtypes contents:
|
||||
# CHECK-NEXT: error: unexpected end of data at offset 0x1 while reading [0x0, 0x4)
|
||||
|
||||
# CHECK: .debug_gnu_pubnames contents:
|
||||
# CHECK-NEXT: error: unexpected end of data at offset 0x1 while reading [0x0, 0x4)
|
||||
|
||||
# CHECK: .debug_gnu_pubtypes contents:
|
||||
# CHECK-NEXT: error: unexpected end of data at offset 0x1 while reading [0x0, 0x4)
|
||||
|
||||
.section .debug_pubnames,"",@progbits
|
||||
.byte 0
|
||||
|
||||
.section .debug_pubtypes,"",@progbits
|
||||
.byte 0
|
||||
|
||||
.section .debug_gnu_pubnames,"",@progbits
|
||||
.byte 0
|
||||
|
||||
.section .debug_gnu_pubtypes,"",@progbits
|
||||
.byte 0
|
Loading…
Reference in New Issue