Home | History | Annotate | Download | only in DWARF
      1 //===-- DWARFUnitIndex.cpp ------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
     11 
     12 #include "llvm/ADT/StringRef.h"
     13 #include "llvm/Support/ErrorHandling.h"
     14 
     15 namespace llvm {
     16 
     17 bool DWARFUnitIndex::Header::parse(DataExtractor IndexData,
     18                                    uint32_t *OffsetPtr) {
     19   if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
     20     return false;
     21   Version = IndexData.getU32(OffsetPtr);
     22   NumColumns = IndexData.getU32(OffsetPtr);
     23   NumUnits = IndexData.getU32(OffsetPtr);
     24   NumBuckets = IndexData.getU32(OffsetPtr);
     25   return Version <= 2;
     26 }
     27 
     28 void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
     29   OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
     30 }
     31 
     32 bool DWARFUnitIndex::parse(DataExtractor IndexData) {
     33   bool b = parseImpl(IndexData);
     34   if (!b) {
     35     // Make sure we don't try to dump anything
     36     Header.NumBuckets = 0;
     37     // Release any partially initialized data.
     38     ColumnKinds.reset();
     39     Rows.reset();
     40   }
     41   return b;
     42 }
     43 
     44 bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
     45   uint32_t Offset = 0;
     46   if (!Header.parse(IndexData, &Offset))
     47     return false;
     48 
     49   if (!IndexData.isValidOffsetForDataOfSize(
     50           Offset, Header.NumBuckets * (8 + 4) +
     51                       (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
     52     return false;
     53 
     54   Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
     55   auto Contribs =
     56       llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
     57   ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
     58 
     59   // Read Hash Table of Signatures
     60   for (unsigned i = 0; i != Header.NumBuckets; ++i)
     61     Rows[i].Signature = IndexData.getU64(&Offset);
     62 
     63   // Read Parallel Table of Indexes
     64   for (unsigned i = 0; i != Header.NumBuckets; ++i) {
     65     auto Index = IndexData.getU32(&Offset);
     66     if (!Index)
     67       continue;
     68     Rows[i].Index = this;
     69     Rows[i].Contributions =
     70         llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
     71     Contribs[Index - 1] = Rows[i].Contributions.get();
     72   }
     73 
     74   // Read the Column Headers
     75   for (unsigned i = 0; i != Header.NumColumns; ++i) {
     76     ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
     77     if (ColumnKinds[i] == InfoColumnKind) {
     78       if (InfoColumn != -1)
     79         return false;
     80       InfoColumn = i;
     81     }
     82   }
     83 
     84   if (InfoColumn == -1)
     85     return false;
     86 
     87   // Read Table of Section Offsets
     88   for (unsigned i = 0; i != Header.NumUnits; ++i) {
     89     auto *Contrib = Contribs[i];
     90     for (unsigned i = 0; i != Header.NumColumns; ++i)
     91       Contrib[i].Offset = IndexData.getU32(&Offset);
     92   }
     93 
     94   // Read Table of Section Sizes
     95   for (unsigned i = 0; i != Header.NumUnits; ++i) {
     96     auto *Contrib = Contribs[i];
     97     for (unsigned i = 0; i != Header.NumColumns; ++i)
     98       Contrib[i].Length = IndexData.getU32(&Offset);
     99   }
    100 
    101   return true;
    102 }
    103 
    104 StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
    105 #define CASE(DS)                                                               \
    106   case DW_SECT_##DS:                                                           \
    107     return #DS;
    108   switch (DS) {
    109     CASE(INFO);
    110     CASE(TYPES);
    111     CASE(ABBREV);
    112     CASE(LINE);
    113     CASE(LOC);
    114     CASE(STR_OFFSETS);
    115     CASE(MACINFO);
    116     CASE(MACRO);
    117   }
    118   llvm_unreachable("unknown DWARFSectionKind");
    119 }
    120 
    121 void DWARFUnitIndex::dump(raw_ostream &OS) const {
    122   if (!Header.NumBuckets)
    123     return;
    124 
    125   Header.dump(OS);
    126   OS << "Index Signature         ";
    127   for (unsigned i = 0; i != Header.NumColumns; ++i)
    128     OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24);
    129   OS << "\n----- ------------------";
    130   for (unsigned i = 0; i != Header.NumColumns; ++i)
    131     OS << " ------------------------";
    132   OS << '\n';
    133   for (unsigned i = 0; i != Header.NumBuckets; ++i) {
    134     auto &Row = Rows[i];
    135     if (auto *Contribs = Row.Contributions.get()) {
    136       OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
    137       for (unsigned i = 0; i != Header.NumColumns; ++i) {
    138         auto &Contrib = Contribs[i];
    139         OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
    140                      Contrib.Offset + Contrib.Length);
    141       }
    142       OS << '\n';
    143     }
    144   }
    145 }
    146 
    147 const DWARFUnitIndex::Entry::SectionContribution *
    148 DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const {
    149   uint32_t i = 0;
    150   for (; i != Index->Header.NumColumns; ++i)
    151     if (Index->ColumnKinds[i] == Sec)
    152       return &Contributions[i];
    153   return nullptr;
    154 }
    155 const DWARFUnitIndex::Entry::SectionContribution *
    156 DWARFUnitIndex::Entry::getOffset() const {
    157   return &Contributions[Index->InfoColumn];
    158 }
    159 
    160 const DWARFUnitIndex::Entry *
    161 DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
    162   for (uint32_t i = 0; i != Header.NumBuckets; ++i)
    163     if (const auto &Contribs = Rows[i].Contributions)
    164       if (Contribs[InfoColumn].Offset == Offset)
    165         return &Rows[i];
    166   return nullptr;
    167 }
    168 }
    169