summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo
diff options
context:
space:
mode:
authorSpyridoula Gravani <sgravani@apple.com>2017-06-29 20:13:05 +0000
committerSpyridoula Gravani <sgravani@apple.com>2017-06-29 20:13:05 +0000
commit837c110cb114a105fa0fe186fbb1ba542cc07601 (patch)
tree08b9cbd593afd619f85bfa155c3fd67260aac9c8 /llvm/lib/DebugInfo
parent3f984ecb45d694727d1fb3522bf362e95028e231 (diff)
downloadbcm5719-llvm-837c110cb114a105fa0fe186fbb1ba542cc07601.tar.gz
bcm5719-llvm-837c110cb114a105fa0fe186fbb1ba542cc07601.zip
[DWARF] Added verification checks for the .apple_names section.
This patch verifies the number of atoms, the validity of the form for each atom, as well as the validity of the hashdata. For hashdata, we're verifying that the hashdata offset is correct and that the offset in the .debug_info for each DIE in the hashdata is also valid. llvm-svn: 306735
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp39
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp66
2 files changed, 102 insertions, 3 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 5c2254cb476..9ae7c9a07f7 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -62,6 +62,45 @@ uint32_t DWARFAcceleratorTable::getHeaderDataLength() {
return Hdr.HeaderDataLength;
}
+ArrayRef<std::pair<DWARFAcceleratorTable::HeaderData::AtomType,
+ DWARFAcceleratorTable::HeaderData::Form>>
+DWARFAcceleratorTable::getAtomsDesc() {
+ return HdrData.Atoms;
+}
+
+bool DWARFAcceleratorTable::validateForms() {
+ for (auto Atom : getAtomsDesc()) {
+ DWARFFormValue FormValue(Atom.second);
+ switch (Atom.first) {
+ case dwarf::DW_ATOM_die_offset:
+ if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) &&
+ !FormValue.isFormClass(DWARFFormValue::FC_Flag)) ||
+ FormValue.getForm() == dwarf::DW_FORM_sdata)
+ return false;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+uint32_t DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
+ uint32_t DieOffset = dwarf::DW_INVALID_OFFSET;
+
+ for (auto Atom : getAtomsDesc()) {
+ DWARFFormValue FormValue(Atom.second);
+ FormValue.extractValue(AccelSection, &HashDataOffset, NULL);
+ switch (Atom.first) {
+ case dwarf::DW_ATOM_die_offset:
+ DieOffset = *FormValue.getAsUnsignedConstant();
+ break;
+ default:
+ break;
+ }
+ }
+ return DieOffset;
+}
+
LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
// Dump the header.
OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n'
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 488649ced13..0a10e6b7891 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -291,20 +291,80 @@ bool DWARFVerifier::handleAppleNames() {
OS << "Verifying .apple_names...\n";
- // Verify that all buckets have a valid hash index or are empty
+ // Verify that all buckets have a valid hash index or are empty.
uint32_t NumBuckets = AppleNames.getNumBuckets();
uint32_t NumHashes = AppleNames.getNumHashes();
uint32_t BucketsOffset =
AppleNames.getSizeHdr() + AppleNames.getHeaderDataLength();
+ uint32_t HashesBase = BucketsOffset + NumBuckets * 4;
+ uint32_t OffsetsBase = HashesBase + NumHashes * 4;
for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
uint32_t HashIdx = AppleNamesSection.getU32(&BucketsOffset);
if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
- OS << format("error: Bucket[%d] has invalid hash index: [%d]\n",
- BucketIdx, HashIdx);
+ OS << format("error: Bucket[%d] has invalid hash index: %u\n", BucketIdx,
+ HashIdx);
++NumAppleNamesErrors;
}
}
+
+ uint32_t NumAtoms = AppleNames.getAtomsDesc().size();
+ if (NumAtoms == 0) {
+ OS << "error: no atoms; failed to read HashData\n";
+ ++NumAppleNamesErrors;
+ return false;
+ }
+
+ if (!AppleNames.validateForms()) {
+ OS << "error: unsupported form; failed to read HashData\n";
+ ++NumAppleNamesErrors;
+ return false;
+ }
+
+ for (uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
+ uint32_t HashOffset = HashesBase + 4 * HashIdx;
+ uint32_t DataOffset = OffsetsBase + 4 * HashIdx;
+ uint32_t Hash = AppleNamesSection.getU32(&HashOffset);
+ uint32_t HashDataOffset = AppleNamesSection.getU32(&DataOffset);
+ if (!AppleNamesSection.isValidOffsetForDataOfSize(HashDataOffset,
+ sizeof(uint64_t))) {
+ OS << format("error: Hash[%d] has invalid HashData offset: 0x%08x\n",
+ HashIdx, HashDataOffset);
+ ++NumAppleNamesErrors;
+ }
+
+ uint32_t StrpOffset;
+ uint32_t StringOffset;
+ uint32_t StringCount = 0;
+ uint32_t DieOffset = dwarf::DW_INVALID_OFFSET;
+
+ while ((StrpOffset = AppleNamesSection.getU32(&HashDataOffset)) != 0) {
+ const uint32_t NumHashDataObjects =
+ AppleNamesSection.getU32(&HashDataOffset);
+ for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
+ ++HashDataIdx) {
+ DieOffset = AppleNames.readAtoms(HashDataOffset);
+ if (!DCtx.getDIEForOffset(DieOffset)) {
+ const uint32_t BucketIdx =
+ NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
+ StringOffset = StrpOffset;
+ const char *Name = StrData.getCStr(&StringOffset);
+ if (!Name)
+ Name = "<NULL>";
+
+ OS << format(
+ "error: .apple_names Bucket[%d] Hash[%d] = 0x%08x "
+ "Str[%u] = 0x%08x "
+ "DIE[%d] = 0x%08x is not a valid DIE offset for \"%s\".\n",
+ BucketIdx, HashIdx, Hash, StringCount, StrpOffset, HashDataIdx,
+ DieOffset, Name);
+
+ ++NumAppleNamesErrors;
+ }
+ }
+ ++StringCount;
+ }
+ }
return NumAppleNamesErrors == 0;
}
OpenPOWER on IntegriCloud