2017-03-01 09:14:23 +08:00
|
|
|
//===- DWARFUnitIndex.cpp -------------------------------------------------===//
|
2015-11-12 03:28:21 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-03-01 09:14:23 +08:00
|
|
|
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
2015-11-12 09:41:52 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2017-03-01 09:14:23 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <cinttypes>
|
|
|
|
#include <cstdint>
|
2015-11-12 09:41:52 +08:00
|
|
|
|
2017-03-01 09:14:23 +08:00
|
|
|
using namespace llvm;
|
2015-11-12 03:28:21 +08:00
|
|
|
|
2015-11-12 03:30:47 +08:00
|
|
|
bool DWARFUnitIndex::Header::parse(DataExtractor IndexData,
|
|
|
|
uint32_t *OffsetPtr) {
|
2015-11-12 09:41:59 +08:00
|
|
|
if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
|
|
|
|
return false;
|
2015-11-12 03:28:21 +08:00
|
|
|
Version = IndexData.getU32(OffsetPtr);
|
|
|
|
NumColumns = IndexData.getU32(OffsetPtr);
|
|
|
|
NumUnits = IndexData.getU32(OffsetPtr);
|
|
|
|
NumBuckets = IndexData.getU32(OffsetPtr);
|
|
|
|
return Version <= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
|
2015-11-14 03:18:49 +08:00
|
|
|
OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
|
2015-11-12 03:28:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DWARFUnitIndex::parse(DataExtractor IndexData) {
|
2015-12-02 14:21:34 +08:00
|
|
|
bool b = parseImpl(IndexData);
|
2015-12-02 15:09:26 +08:00
|
|
|
if (!b) {
|
|
|
|
// Make sure we don't try to dump anything
|
|
|
|
Header.NumBuckets = 0;
|
|
|
|
// Release any partially initialized data.
|
|
|
|
ColumnKinds.reset();
|
|
|
|
Rows.reset();
|
|
|
|
}
|
2015-12-02 14:21:34 +08:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
|
2015-11-12 03:28:21 +08:00
|
|
|
uint32_t Offset = 0;
|
|
|
|
if (!Header.parse(IndexData, &Offset))
|
|
|
|
return false;
|
|
|
|
|
2015-11-12 09:41:59 +08:00
|
|
|
if (!IndexData.isValidOffsetForDataOfSize(
|
|
|
|
Offset, Header.NumBuckets * (8 + 4) +
|
|
|
|
(2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
|
|
|
|
return false;
|
|
|
|
|
2015-11-17 08:39:55 +08:00
|
|
|
Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
|
2015-11-14 03:18:49 +08:00
|
|
|
auto Contribs =
|
2015-11-17 08:39:55 +08:00
|
|
|
llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
|
|
|
|
ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
|
2015-11-14 03:18:49 +08:00
|
|
|
|
|
|
|
// Read Hash Table of Signatures
|
|
|
|
for (unsigned i = 0; i != Header.NumBuckets; ++i)
|
|
|
|
Rows[i].Signature = IndexData.getU64(&Offset);
|
|
|
|
|
|
|
|
// Read Parallel Table of Indexes
|
|
|
|
for (unsigned i = 0; i != Header.NumBuckets; ++i) {
|
|
|
|
auto Index = IndexData.getU32(&Offset);
|
|
|
|
if (!Index)
|
|
|
|
continue;
|
2015-11-17 08:39:55 +08:00
|
|
|
Rows[i].Index = this;
|
2015-11-14 03:18:49 +08:00
|
|
|
Rows[i].Contributions =
|
2015-11-17 08:39:55 +08:00
|
|
|
llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
|
2015-11-14 03:18:49 +08:00
|
|
|
Contribs[Index - 1] = Rows[i].Contributions.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the Column Headers
|
2015-11-17 08:39:55 +08:00
|
|
|
for (unsigned i = 0; i != Header.NumColumns; ++i) {
|
|
|
|
ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
|
2015-12-02 14:21:34 +08:00
|
|
|
if (ColumnKinds[i] == InfoColumnKind) {
|
2015-11-17 08:39:55 +08:00
|
|
|
if (InfoColumn != -1)
|
|
|
|
return false;
|
|
|
|
InfoColumn = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (InfoColumn == -1)
|
|
|
|
return false;
|
2015-11-14 03:18:49 +08:00
|
|
|
|
|
|
|
// Read Table of Section Offsets
|
|
|
|
for (unsigned i = 0; i != Header.NumUnits; ++i) {
|
|
|
|
auto *Contrib = Contribs[i];
|
2015-11-17 08:39:55 +08:00
|
|
|
for (unsigned i = 0; i != Header.NumColumns; ++i)
|
2015-11-14 03:18:49 +08:00
|
|
|
Contrib[i].Offset = IndexData.getU32(&Offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read Table of Section Sizes
|
|
|
|
for (unsigned i = 0; i != Header.NumUnits; ++i) {
|
|
|
|
auto *Contrib = Contribs[i];
|
2015-11-17 08:39:55 +08:00
|
|
|
for (unsigned i = 0; i != Header.NumColumns; ++i)
|
|
|
|
Contrib[i].Length = IndexData.getU32(&Offset);
|
2015-11-14 03:18:49 +08:00
|
|
|
}
|
|
|
|
|
2015-11-12 03:28:21 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-17 08:39:55 +08:00
|
|
|
StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
|
2015-11-12 09:41:52 +08:00
|
|
|
#define CASE(DS) \
|
|
|
|
case DW_SECT_##DS: \
|
|
|
|
return #DS;
|
|
|
|
switch (DS) {
|
|
|
|
CASE(INFO);
|
|
|
|
CASE(TYPES);
|
|
|
|
CASE(ABBREV);
|
|
|
|
CASE(LINE);
|
|
|
|
CASE(LOC);
|
|
|
|
CASE(STR_OFFSETS);
|
|
|
|
CASE(MACINFO);
|
|
|
|
CASE(MACRO);
|
|
|
|
}
|
2015-11-17 08:39:55 +08:00
|
|
|
llvm_unreachable("unknown DWARFSectionKind");
|
2015-11-12 09:41:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DWARFUnitIndex::dump(raw_ostream &OS) const {
|
2017-07-30 16:12:07 +08:00
|
|
|
if (!*this)
|
2015-12-02 14:21:34 +08:00
|
|
|
return;
|
|
|
|
|
2015-11-12 09:41:52 +08:00
|
|
|
Header.dump(OS);
|
2015-11-14 03:18:49 +08:00
|
|
|
OS << "Index Signature ";
|
|
|
|
for (unsigned i = 0; i != Header.NumColumns; ++i)
|
|
|
|
OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24);
|
|
|
|
OS << "\n----- ------------------";
|
|
|
|
for (unsigned i = 0; i != Header.NumColumns; ++i)
|
|
|
|
OS << " ------------------------";
|
|
|
|
OS << '\n';
|
|
|
|
for (unsigned i = 0; i != Header.NumBuckets; ++i) {
|
|
|
|
auto &Row = Rows[i];
|
|
|
|
if (auto *Contribs = Row.Contributions.get()) {
|
2015-12-04 02:41:59 +08:00
|
|
|
OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
|
2015-11-14 03:18:49 +08:00
|
|
|
for (unsigned i = 0; i != Header.NumColumns; ++i) {
|
|
|
|
auto &Contrib = Contribs[i];
|
2015-11-17 08:39:55 +08:00
|
|
|
OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
|
|
|
|
Contrib.Offset + Contrib.Length);
|
2015-11-14 03:18:49 +08:00
|
|
|
}
|
|
|
|
OS << '\n';
|
|
|
|
}
|
|
|
|
}
|
2015-11-12 09:41:52 +08:00
|
|
|
}
|
2015-11-17 08:39:55 +08:00
|
|
|
|
|
|
|
const DWARFUnitIndex::Entry::SectionContribution *
|
|
|
|
DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const {
|
|
|
|
uint32_t i = 0;
|
|
|
|
for (; i != Index->Header.NumColumns; ++i)
|
|
|
|
if (Index->ColumnKinds[i] == Sec)
|
|
|
|
return &Contributions[i];
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-03-01 09:14:23 +08:00
|
|
|
|
2015-11-17 08:39:55 +08:00
|
|
|
const DWARFUnitIndex::Entry::SectionContribution *
|
|
|
|
DWARFUnitIndex::Entry::getOffset() const {
|
|
|
|
return &Contributions[Index->InfoColumn];
|
|
|
|
}
|
|
|
|
|
|
|
|
const DWARFUnitIndex::Entry *
|
|
|
|
DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
|
2018-09-13 07:39:51 +08:00
|
|
|
if (OffsetLookup.empty()) {
|
|
|
|
for (uint32_t i = 0; i != Header.NumBuckets; ++i)
|
2018-09-13 18:54:23 +08:00
|
|
|
if (Rows[i].Contributions)
|
2018-09-13 07:39:51 +08:00
|
|
|
OffsetLookup.push_back(&Rows[i]);
|
|
|
|
llvm::sort(OffsetLookup, [&](Entry *E1, Entry *E2) {
|
|
|
|
return E1->Contributions[InfoColumn].Offset <
|
|
|
|
E2->Contributions[InfoColumn].Offset;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
auto I =
|
|
|
|
llvm::upper_bound(OffsetLookup, Offset, [&](uint32_t Offset, Entry *E2) {
|
|
|
|
return Offset < E2->Contributions[InfoColumn].Offset;
|
|
|
|
});
|
|
|
|
if (I == OffsetLookup.begin())
|
|
|
|
return nullptr;
|
|
|
|
--I;
|
|
|
|
const auto *E = *I;
|
|
|
|
const auto &InfoContrib = E->Contributions[InfoColumn];
|
|
|
|
if ((InfoContrib.Offset + InfoContrib.Length) <= Offset)
|
|
|
|
return nullptr;
|
|
|
|
return E;
|
2015-11-17 08:39:55 +08:00
|
|
|
}
|
2017-07-30 16:12:07 +08:00
|
|
|
|
|
|
|
const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const {
|
|
|
|
uint64_t Mask = Header.NumBuckets - 1;
|
|
|
|
|
|
|
|
auto H = S & Mask;
|
|
|
|
auto HP = ((S >> 32) & Mask) | 1;
|
|
|
|
while (Rows[H].getSignature() != S && Rows[H].getSignature() != 0)
|
|
|
|
H = (H + HP) & Mask;
|
|
|
|
|
|
|
|
if (Rows[H].getSignature() != S)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return &Rows[H];
|
|
|
|
}
|