LCOV - code coverage report
Current view: top level - include/llvm/DebugInfo/DWARF - DWARFListTable.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 53 60 88.3 %
Date: 2018-10-20 13:21:21 Functions: 5 10 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DWARFListTable.h -----------------------------------------*- C++ -*-===//
       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             : #ifndef LLVM_DEBUGINFO_DWARFLISTTABLE_H
      11             : #define LLVM_DEBUGINFO_DWARFLISTTABLE_H
      12             : 
      13             : #include "llvm/BinaryFormat/Dwarf.h"
      14             : #include "llvm/DebugInfo/DIContext.h"
      15             : #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
      16             : #include "llvm/Support/Errc.h"
      17             : #include "llvm/Support/Error.h"
      18             : #include "llvm/Support/Format.h"
      19             : #include "llvm/Support/raw_ostream.h"
      20             : #include <cstdint>
      21             : #include <map>
      22             : #include <vector>
      23             : 
      24             : namespace llvm {
      25             : 
      26             : /// A base class for DWARF list entries, such as range or location list
      27             : /// entries.
      28             : struct DWARFListEntryBase {
      29             :   /// The offset at which the entry is located in the section.
      30             :   uint32_t Offset;
      31             :   /// The DWARF encoding (DW_RLE_* or DW_LLE_*).
      32             :   uint8_t EntryKind;
      33             :   /// The index of the section this entry belongs to.
      34             :   uint64_t SectionIndex;
      35             : };
      36             : 
      37             : /// A base class for lists of entries that are extracted from a particular
      38             : /// section, such as range lists or location lists.
      39          27 : template <typename ListEntryType> class DWARFListType {
      40             :   using EntryType = ListEntryType;
      41             :   using ListEntries = std::vector<EntryType>;
      42             : 
      43             : protected:
      44             :   ListEntries Entries;
      45             : 
      46             : public:
      47             :   const ListEntries &getEntries() const { return Entries; }
      48             :   bool empty() const { return Entries.empty(); }
      49             :   void clear() { Entries.clear(); }
      50             :   Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
      51             :                 uint32_t *OffsetPtr, StringRef SectionName,
      52             :                 StringRef ListStringName);
      53             : };
      54             : 
      55             : /// A class representing the header of a list table such as the range list
      56             : /// table in the .debug_rnglists section.
      57             : class DWARFListTableHeader {
      58          44 :   struct Header {
      59             :     /// The total length of the entries for this table, not including the length
      60             :     /// field itself.
      61             :     uint32_t Length = 0;
      62             :     /// The DWARF version number.
      63             :     uint16_t Version;
      64             :     /// The size in bytes of an address on the target architecture. For
      65             :     /// segmented addressing, this is the size of the offset portion of the
      66             :     /// address.
      67             :     uint8_t AddrSize;
      68             :     /// The size in bytes of a segment selector on the target architecture.
      69             :     /// If the target system uses a flat address space, this value is 0.
      70             :     uint8_t SegSize;
      71             :     /// The number of offsets that follow the header before the range lists.
      72             :     uint32_t OffsetEntryCount;
      73             :   };
      74             : 
      75             :   Header HeaderData;
      76             :   /// The offset table, which contains offsets to the individual list entries.
      77             :   /// It is used by forms such as DW_FORM_rnglistx.
      78             :   /// FIXME: Generate the table and use the appropriate forms.
      79             :   std::vector<uint32_t> Offsets;
      80             :   /// The table's format, either DWARF32 or DWARF64.
      81             :   dwarf::DwarfFormat Format;
      82             :   /// The offset at which the header (and hence the table) is located within
      83             :   /// its section.
      84             :   uint32_t HeaderOffset;
      85             :   /// The name of the section the list is located in.
      86             :   StringRef SectionName;
      87             :   /// A characterization of the list for dumping purposes, e.g. "range" or
      88             :   /// "location".
      89             :   StringRef ListTypeString;
      90             : 
      91             : public:
      92             :   DWARFListTableHeader(StringRef SectionName, StringRef ListTypeString)
      93          44 :       : SectionName(SectionName), ListTypeString(ListTypeString) {}
      94             : 
      95             :   void clear() {
      96          34 :     HeaderData = {};
      97             :     Offsets.clear();
      98             :   }
      99           0 :   uint32_t getHeaderOffset() const { return HeaderOffset; }
     100           0 :   uint8_t getAddrSize() const { return HeaderData.AddrSize; }
     101             :   uint32_t getLength() const { return HeaderData.Length; }
     102           0 :   StringRef getSectionName() const { return SectionName; }
     103           0 :   StringRef getListTypeString() const { return ListTypeString; }
     104           0 :   dwarf::DwarfFormat getFormat() const { return Format; }
     105             : 
     106             :   void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
     107             :   Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
     108          10 :     if (Index < Offsets.size())
     109             :       return Offsets[Index];
     110             :     return None;
     111             :   }
     112             : 
     113             :   /// Extract the table header and the array of offsets.
     114             :   Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
     115             : 
     116             :   /// Returns the length of the table, including the length field, or 0 if the
     117             :   /// length has not been determined (e.g. because the table has not yet been
     118             :   /// parsed, or there was a problem in parsing).
     119             :   uint32_t length() const;
     120             : };
     121             : 
     122             : /// A class representing a table of lists as specified in the DWARF v5
     123             : /// standard for location lists and range lists. The table consists of a header
     124             : /// followed by an array of offsets into a DWARF section, followed by zero or
     125             : /// more list entries. The list entries are kept in a map where the keys are
     126             : /// the lists' section offsets.
     127             : template <typename DWARFListType> class DWARFListTableBase {
     128             :   DWARFListTableHeader Header;
     129             :   /// A mapping between file offsets and lists. It is used to find a particular
     130             :   /// list based on an offset (obtained from DW_AT_ranges, for example).
     131             :   std::map<uint32_t, DWARFListType> ListMap;
     132             :   /// This string is displayed as a heading before the list is dumped
     133             :   /// (e.g. "ranges:").
     134             :   StringRef HeaderString;
     135             : 
     136             : protected:
     137          44 :   DWARFListTableBase(StringRef SectionName, StringRef HeaderString,
     138             :                      StringRef ListTypeString)
     139          44 :       : Header(SectionName, ListTypeString), HeaderString(HeaderString) {}
     140             : 
     141             : public:
     142          34 :   void clear() {
     143             :     Header.clear();
     144             :     ListMap.clear();
     145          34 :   }
     146             :   /// Extract the table header and the array of offsets.
     147             :   Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) {
     148          44 :     return Header.extract(Data, OffsetPtr);
     149             :   }
     150             :   /// Extract an entire table, including all list entries.
     151             :   Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
     152             :   /// Look up a list based on a given offset. Extract it and enter it into the
     153             :   /// list map if necessary.
     154             :   Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset);
     155             : 
     156          75 :   uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); }
     157          59 :   uint8_t getAddrSize() const { return Header.getAddrSize(); }
     158             : 
     159             :   void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
     160             : 
     161             :   /// Return the contents of the offset entry designated by a given index.
     162             :   Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
     163             :     return Header.getOffsetEntry(Index);
     164             :   }
     165             :   /// Return the size of the table header including the length but not including
     166             :   /// the offsets. This is dependent on the table format, which is unambiguously
     167             :   /// derived from parsing the table.
     168             :   uint8_t getHeaderSize() const {
     169           1 :     switch (Header.getFormat()) {
     170             :     case dwarf::DwarfFormat::DWARF32:
     171             :       return 12;
     172           0 :     case dwarf::DwarfFormat::DWARF64:
     173             :       return 20;
     174             :     }
     175           0 :     llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
     176             :   }
     177             : 
     178          19 :   uint32_t length() { return Header.length(); }
     179             : };
     180             : 
     181             : template <typename DWARFListType>
     182          34 : Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
     183             :                                                  uint32_t *OffsetPtr) {
     184          34 :   clear();
     185          43 :   if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
     186             :     return E;
     187             : 
     188          25 :   Data.setAddressSize(Header.getAddrSize());
     189          25 :   uint32_t End = getHeaderOffset() + Header.length();
     190          43 :   while (*OffsetPtr < End) {
     191             :     DWARFListType CurrentList;
     192          28 :     uint32_t Off = *OffsetPtr;
     193          56 :     if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr,
     194             :                                       Header.getSectionName(),
     195             :                                       Header.getListTypeString()))
     196             :       return E;
     197          18 :     ListMap[Off] = CurrentList;
     198             :   }
     199             : 
     200             :   assert(*OffsetPtr == End &&
     201             :          "mismatch between expected length of table and length "
     202             :          "of extracted data");
     203             :   return Error::success();
     204             : }
     205             : 
     206             : template <typename ListEntryType>
     207          39 : Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
     208             :                                             uint32_t HeaderOffset, uint32_t End,
     209             :                                             uint32_t *OffsetPtr,
     210             :                                             StringRef SectionName,
     211             :                                             StringRef ListTypeString) {
     212          39 :   if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
     213             :     return createStringError(errc::invalid_argument,
     214             :                        "invalid %s list offset 0x%" PRIx32,
     215           4 :                        ListTypeString.data(), *OffsetPtr);
     216          37 :   Entries.clear();
     217          88 :   while (*OffsetPtr < End) {
     218             :     ListEntryType Entry;
     219         174 :     if (Error E = Entry.extract(Data, End, OffsetPtr))
     220             :       return E;
     221          78 :     Entries.push_back(Entry);
     222          78 :     if (Entry.isSentinel())
     223             :       return Error::success();
     224             :   }
     225             :   return createStringError(errc::illegal_byte_sequence,
     226             :                      "no end of list marker detected at end of %s table "
     227             :                      "starting at offset 0x%" PRIx32,
     228           2 :                      SectionName.data(), HeaderOffset);
     229             : }
     230             : 
     231             : template <typename DWARFListType>
     232          15 : void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS,
     233             :                                              DIDumpOptions DumpOpts) const {
     234          15 :   Header.dump(OS, DumpOpts);
     235          15 :   OS << HeaderString << "\n";
     236             : 
     237             :   // Determine the length of the longest encoding string we have in the table,
     238             :   // so we can align the output properly. We only need this in verbose mode.
     239          15 :   size_t MaxEncodingStringLength = 0;
     240          15 :   if (DumpOpts.Verbose) {
     241          18 :     for (const auto &List : ListMap)
     242          39 :       for (const auto &Entry : List.second.getEntries())
     243          29 :         MaxEncodingStringLength =
     244          29 :             std::max(MaxEncodingStringLength,
     245          58 :                      dwarf::RangeListEncodingString(Entry.EntryKind).size());
     246             :   }
     247             : 
     248          15 :   uint64_t CurrentBase = 0;
     249          33 :   for (const auto &List : ListMap)
     250          66 :     for (const auto &Entry : List.second.getEntries())
     251          48 :       Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase,
     252             :                  DumpOpts);
     253          15 : }
     254             : 
     255             : template <typename DWARFListType>
     256             : Expected<DWARFListType>
     257          11 : DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
     258             :                                             uint32_t Offset) {
     259             :   auto Entry = ListMap.find(Offset);
     260          11 :   if (Entry != ListMap.end())
     261             :     return Entry->second;
     262             : 
     263             :   // Extract the list from the section and enter it into the list map.
     264             :   DWARFListType List;
     265          11 :   uint32_t End = getHeaderOffset() + Header.length();
     266          11 :   uint32_t StartingOffset = Offset;
     267          22 :   if (Error E =
     268             :           List.extract(Data, getHeaderOffset(), End, &Offset,
     269             :                        Header.getSectionName(), Header.getListTypeString()))
     270             :     return std::move(E);
     271           9 :   ListMap[StartingOffset] = List;
     272             :   return List;
     273             : }
     274             : 
     275             : } // end namespace llvm
     276             : 
     277             : #endif // LLVM_DEBUGINFO_DWARFLISTTABLE_H

Generated by: LCOV version 1.13