aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-20 14:16:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-20 14:16:56 +0000
commit2cab237b5dbfe1b3e9c7aa7a3c02d2b98fcf7462 (patch)
tree524fe828571f81358bba62fdb6d04c6e5e96a2a4 /contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
parent6c7828a2807ea5e50c79ca42dbedf2b589ce63b2 (diff)
parent044eb2f6afba375a914ac9d8024f8f5142bb912e (diff)
Merge llvm trunk r321017 to contrib/llvm.
Notes
Notes: svn path=/projects/clang600-import/; revision=327023
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp')
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp104
1 files changed, 93 insertions, 11 deletions
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 9ae7c9a07f76..17f29737bf93 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -11,8 +11,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
@@ -23,12 +21,13 @@
using namespace llvm;
-bool DWARFAcceleratorTable::extract() {
+llvm::Error DWARFAcceleratorTable::extract() {
uint32_t Offset = 0;
// Check that we can at least read the header.
if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength)+4))
- return false;
+ return make_error<StringError>("Section too small: cannot read header.",
+ inconvertibleErrorCode());
Hdr.Magic = AccelSection.getU32(&Offset);
Hdr.Version = AccelSection.getU16(&Offset);
@@ -39,9 +38,13 @@ bool DWARFAcceleratorTable::extract() {
// Check that we can read all the hashes and offsets from the
// section (see SourceLevelDebugging.rst for the structure of the index).
+ // We need to substract one because we're checking for an *offset* which is
+ // equal to the size for an empty table and hence pointer after the section.
if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength +
- Hdr.NumBuckets*4 + Hdr.NumHashes*8))
- return false;
+ Hdr.NumBuckets * 4 + Hdr.NumHashes * 8 - 1))
+ return make_error<StringError>(
+ "Section too small: cannot read buckets and hashes.",
+ inconvertibleErrorCode());
HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
uint32_t NumAtoms = AccelSection.getU32(&Offset);
@@ -52,7 +55,8 @@ bool DWARFAcceleratorTable::extract() {
HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
}
- return true;
+ IsValid = true;
+ return Error::success();
}
uint32_t DWARFAcceleratorTable::getNumBuckets() { return Hdr.NumBuckets; }
@@ -73,6 +77,8 @@ bool DWARFAcceleratorTable::validateForms() {
DWARFFormValue FormValue(Atom.second);
switch (Atom.first) {
case dwarf::DW_ATOM_die_offset:
+ case dwarf::DW_ATOM_die_tag:
+ case dwarf::DW_ATOM_type_flags:
if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) &&
!FormValue.isFormClass(DWARFFormValue::FC_Flag)) ||
FormValue.getForm() == dwarf::DW_FORM_sdata)
@@ -84,24 +90,33 @@ bool DWARFAcceleratorTable::validateForms() {
return true;
}
-uint32_t DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
+std::pair<uint32_t, dwarf::Tag>
+DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
uint32_t DieOffset = dwarf::DW_INVALID_OFFSET;
+ dwarf::Tag DieTag = dwarf::DW_TAG_null;
+ DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
for (auto Atom : getAtomsDesc()) {
DWARFFormValue FormValue(Atom.second);
- FormValue.extractValue(AccelSection, &HashDataOffset, NULL);
+ FormValue.extractValue(AccelSection, &HashDataOffset, FormParams);
switch (Atom.first) {
case dwarf::DW_ATOM_die_offset:
DieOffset = *FormValue.getAsUnsignedConstant();
break;
+ case dwarf::DW_ATOM_die_tag:
+ DieTag = (dwarf::Tag)*FormValue.getAsUnsignedConstant();
+ break;
default:
break;
}
}
- return DieOffset;
+ return {DieOffset, DieTag};
}
LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
+ if (!IsValid)
+ return;
+
// Dump the header.
OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n'
<< "Version = " << format("0x%04x", Hdr.Version) << '\n'
@@ -135,6 +150,7 @@ LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
unsigned HashesBase = Offset + Hdr.NumBuckets * 4;
unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4;
+ DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) {
unsigned Index = AccelSection.getU32(&Offset);
@@ -171,7 +187,7 @@ LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
unsigned i = 0;
for (auto &Atom : AtomForms) {
OS << format("{Atom[%d]: ", i++);
- if (Atom.extractValue(AccelSection, &DataOffset, nullptr))
+ if (Atom.extractValue(AccelSection, &DataOffset, FormParams))
Atom.dump(OS);
else
OS << "Error extracting the value";
@@ -183,3 +199,69 @@ LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
}
}
}
+
+DWARFAcceleratorTable::ValueIterator::ValueIterator(
+ const DWARFAcceleratorTable &AccelTable, unsigned Offset)
+ : AccelTable(&AccelTable), DataOffset(Offset) {
+ if (!AccelTable.AccelSection.isValidOffsetForDataOfSize(DataOffset, 4))
+ return;
+
+ for (const auto &Atom : AccelTable.HdrData.Atoms)
+ AtomForms.push_back(DWARFFormValue(Atom.second));
+
+ // Read the first entry.
+ NumData = AccelTable.AccelSection.getU32(&DataOffset);
+ Next();
+}
+
+void DWARFAcceleratorTable::ValueIterator::Next() {
+ assert(NumData > 0 && "attempted to increment iterator past the end");
+ auto &AccelSection = AccelTable->AccelSection;
+ if (Data >= NumData ||
+ !AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) {
+ NumData = 0;
+ return;
+ }
+ DWARFFormParams FormParams = {AccelTable->Hdr.Version, 0,
+ dwarf::DwarfFormat::DWARF32};
+ for (auto &Atom : AtomForms)
+ Atom.extractValue(AccelSection, &DataOffset, FormParams);
+ ++Data;
+}
+
+iterator_range<DWARFAcceleratorTable::ValueIterator>
+DWARFAcceleratorTable::equal_range(StringRef Key) const {
+ if (!IsValid)
+ return make_range(ValueIterator(), ValueIterator());
+
+ // Find the bucket.
+ unsigned HashValue = dwarf::djbHash(Key);
+ unsigned Bucket = HashValue % Hdr.NumBuckets;
+ unsigned BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength;
+ unsigned HashesBase = BucketBase + Hdr.NumBuckets * 4;
+ unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4;
+
+ unsigned BucketOffset = BucketBase + Bucket * 4;
+ unsigned Index = AccelSection.getU32(&BucketOffset);
+
+ // Search through all hashes in the bucket.
+ for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) {
+ unsigned HashOffset = HashesBase + HashIdx * 4;
+ unsigned OffsetsOffset = OffsetsBase + HashIdx * 4;
+ uint32_t Hash = AccelSection.getU32(&HashOffset);
+
+ if (Hash % Hdr.NumBuckets != Bucket)
+ // We are already in the next bucket.
+ break;
+
+ unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
+ unsigned StringOffset = AccelSection.getRelocatedValue(4, &DataOffset);
+ if (!StringOffset)
+ break;
+
+ // Finally, compare the key.
+ if (Key == StringSection.getCStr(&StringOffset))
+ return make_range({*this, DataOffset}, ValueIterator());
+ }
+ return make_range(ValueIterator(), ValueIterator());
+}