LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFUnitIndex.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 95 102 93.1 %
Date: 2018-10-20 13:21:21 Functions: 10 10 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "llvm/ADT/STLExtras.h"
      12             : #include "llvm/ADT/StringRef.h"
      13             : #include "llvm/Support/ErrorHandling.h"
      14             : #include "llvm/Support/Format.h"
      15             : #include "llvm/Support/raw_ostream.h"
      16             : #include <cinttypes>
      17             : #include <cstdint>
      18             : 
      19             : using namespace llvm;
      20             : 
      21          87 : bool DWARFUnitIndex::Header::parse(DataExtractor IndexData,
      22             :                                    uint32_t *OffsetPtr) {
      23          87 :   if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
      24             :     return false;
      25          29 :   Version = IndexData.getU32(OffsetPtr);
      26          29 :   NumColumns = IndexData.getU32(OffsetPtr);
      27          29 :   NumUnits = IndexData.getU32(OffsetPtr);
      28          29 :   NumBuckets = IndexData.getU32(OffsetPtr);
      29          29 :   return Version <= 2;
      30             : }
      31             : 
      32          16 : void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
      33          32 :   OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
      34          16 : }
      35             : 
      36          87 : bool DWARFUnitIndex::parse(DataExtractor IndexData) {
      37          87 :   bool b = parseImpl(IndexData);
      38          87 :   if (!b) {
      39             :     // Make sure we don't try to dump anything
      40          58 :     Header.NumBuckets = 0;
      41             :     // Release any partially initialized data.
      42             :     ColumnKinds.reset();
      43             :     Rows.reset();
      44             :   }
      45          87 :   return b;
      46             : }
      47             : 
      48          87 : bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
      49          87 :   uint32_t Offset = 0;
      50          87 :   if (!Header.parse(IndexData, &Offset))
      51             :     return false;
      52             : 
      53          29 :   if (!IndexData.isValidOffsetForDataOfSize(
      54          29 :           Offset, Header.NumBuckets * (8 + 4) +
      55          29 :                       (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
      56             :     return false;
      57             : 
      58          29 :   Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
      59             :   auto Contribs =
      60          29 :       llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
      61          58 :   ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
      62             : 
      63             :   // Read Hash Table of Signatures
      64         172 :   for (unsigned i = 0; i != Header.NumBuckets; ++i)
      65         286 :     Rows[i].Signature = IndexData.getU64(&Offset);
      66             : 
      67             :   // Read Parallel Table of Indexes
      68         172 :   for (unsigned i = 0; i != Header.NumBuckets; ++i) {
      69         143 :     auto Index = IndexData.getU32(&Offset);
      70         143 :     if (!Index)
      71             :       continue;
      72          60 :     Rows[i].Index = this;
      73             :     Rows[i].Contributions =
      74         120 :         llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
      75         120 :     Contribs[Index - 1] = Rows[i].Contributions.get();
      76             :   }
      77             : 
      78             :   // Read the Column Headers
      79         141 :   for (unsigned i = 0; i != Header.NumColumns; ++i) {
      80         224 :     ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
      81         112 :     if (ColumnKinds[i] == InfoColumnKind) {
      82          29 :       if (InfoColumn != -1)
      83             :         return false;
      84          29 :       InfoColumn = i;
      85             :     }
      86             :   }
      87             : 
      88          29 :   if (InfoColumn == -1)
      89             :     return false;
      90             : 
      91             :   // Read Table of Section Offsets
      92          89 :   for (unsigned i = 0; i != Header.NumUnits; ++i) {
      93         120 :     auto *Contrib = Contribs[i];
      94         292 :     for (unsigned i = 0; i != Header.NumColumns; ++i)
      95         232 :       Contrib[i].Offset = IndexData.getU32(&Offset);
      96             :   }
      97             : 
      98             :   // Read Table of Section Sizes
      99          89 :   for (unsigned i = 0; i != Header.NumUnits; ++i) {
     100         120 :     auto *Contrib = Contribs[i];
     101         292 :     for (unsigned i = 0; i != Header.NumColumns; ++i)
     102         232 :       Contrib[i].Length = IndexData.getU32(&Offset);
     103             :   }
     104             : 
     105             :   return true;
     106             : }
     107             : 
     108          60 : StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
     109             : #define CASE(DS)                                                               \
     110             :   case DW_SECT_##DS:                                                           \
     111             :     return #DS;
     112          60 :   switch (DS) {
     113          10 :     CASE(INFO);
     114           6 :     CASE(TYPES);
     115          16 :     CASE(ABBREV);
     116          14 :     CASE(LINE);
     117           0 :     CASE(LOC);
     118          14 :     CASE(STR_OFFSETS);
     119           0 :     CASE(MACINFO);
     120           0 :     CASE(MACRO);
     121             :   }
     122           0 :   llvm_unreachable("unknown DWARFSectionKind");
     123             : }
     124             : 
     125          16 : void DWARFUnitIndex::dump(raw_ostream &OS) const {
     126          16 :   if (!*this)
     127             :     return;
     128             : 
     129          16 :   Header.dump(OS);
     130          16 :   OS << "Index Signature         ";
     131          76 :   for (unsigned i = 0; i != Header.NumColumns; ++i)
     132         120 :     OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24);
     133          16 :   OS << "\n----- ------------------";
     134          76 :   for (unsigned i = 0; i != Header.NumColumns; ++i)
     135          60 :     OS << " ------------------------";
     136             :   OS << '\n';
     137         113 :   for (unsigned i = 0; i != Header.NumBuckets; ++i) {
     138          97 :     auto &Row = Rows[i];
     139          97 :     if (auto *Contribs = Row.Contributions.get()) {
     140          74 :       OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
     141         177 :       for (unsigned i = 0; i != Header.NumColumns; ++i) {
     142         140 :         auto &Contrib = Contribs[i];
     143         140 :         OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
     144         280 :                      Contrib.Offset + Contrib.Length);
     145             :       }
     146             :       OS << '\n';
     147             :     }
     148             :   }
     149             : }
     150             : 
     151             : const DWARFUnitIndex::Entry::SectionContribution *
     152         168 : DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const {
     153             :   uint32_t i = 0;
     154         505 :   for (; i != Index->Header.NumColumns; ++i)
     155         998 :     if (Index->ColumnKinds[i] == Sec)
     156         162 :       return &Contributions[i];
     157             :   return nullptr;
     158             : }
     159             : 
     160             : const DWARFUnitIndex::Entry::SectionContribution *
     161          41 : DWARFUnitIndex::Entry::getOffset() const {
     162          82 :   return &Contributions[Index->InfoColumn];
     163             : }
     164             : 
     165             : const DWARFUnitIndex::Entry *
     166         116 : DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
     167         116 :   if (OffsetLookup.empty()) {
     168         208 :     for (uint32_t i = 0; i != Header.NumBuckets; ++i)
     169         226 :       if (Rows[i].Contributions)
     170          45 :         OffsetLookup.push_back(&Rows[i]);
     171             :     llvm::sort(OffsetLookup, [&](Entry *E1, Entry *E2) {
     172          50 :       return E1->Contributions[InfoColumn].Offset <
     173          51 :              E2->Contributions[InfoColumn].Offset;
     174             :     });
     175             :   }
     176             :   auto I =
     177             :       llvm::upper_bound(OffsetLookup, Offset, [&](uint32_t Offset, Entry *E2) {
     178         146 :         return Offset < E2->Contributions[InfoColumn].Offset;
     179         116 :       });
     180         116 :   if (I == OffsetLookup.begin())
     181             :     return nullptr;
     182             :   --I;
     183          41 :   const auto *E = *I;
     184          41 :   const auto &InfoContrib = E->Contributions[InfoColumn];
     185          41 :   if ((InfoContrib.Offset + InfoContrib.Length) <= Offset)
     186           0 :     return nullptr;
     187             :   return E;
     188             : }
     189             : 
     190           4 : const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const {
     191           4 :   uint64_t Mask = Header.NumBuckets - 1;
     192             : 
     193           4 :   auto H = S & Mask;
     194           4 :   auto HP = ((S >> 32) & Mask) | 1;
     195           4 :   while (Rows[H].getSignature() != S && Rows[H].getSignature() != 0)
     196           0 :     H = (H + HP) & Mask;
     197             : 
     198           4 :   if (Rows[H].getSignature() != S)
     199           0 :     return nullptr;
     200             : 
     201             :   return &Rows[H];
     202             : }

Generated by: LCOV version 1.13