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

          Line data    Source code
       1             : //===- DWARFDebugRnglists.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/DWARFDebugRnglists.h"
      11             : #include "llvm/BinaryFormat/Dwarf.h"
      12             : #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
      13             : #include "llvm/Support/Errc.h"
      14             : #include "llvm/Support/Error.h"
      15             : #include "llvm/Support/Format.h"
      16             : #include "llvm/Support/raw_ostream.h"
      17             : 
      18             : using namespace llvm;
      19             : 
      20          87 : Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
      21             :                               uint32_t *OffsetPtr) {
      22          87 :   Offset = *OffsetPtr;
      23          87 :   SectionIndex = -1ULL;
      24             :   // The caller should guarantee that we have at least 1 byte available, so
      25             :   // we just assert instead of revalidate.
      26             :   assert(*OffsetPtr < End &&
      27             :          "not enough space to extract a rangelist encoding");
      28          87 :   uint8_t Encoding = Data.getU8(OffsetPtr);
      29             : 
      30          87 :   switch (Encoding) {
      31          27 :   case dwarf::DW_RLE_end_of_list:
      32          27 :     Value0 = Value1 = 0;
      33          27 :     break;
      34             :   // TODO: Support other encodings.
      35           2 :   case dwarf::DW_RLE_base_addressx:
      36             :     return createStringError(errc::not_supported,
      37             :                        "unsupported rnglists encoding DW_RLE_base_addressx "
      38             :                        "at offset 0x%" PRIx32,
      39           4 :                        *OffsetPtr - 1);
      40           2 :   case dwarf::DW_RLE_startx_endx:
      41             :     return createStringError(errc::not_supported,
      42             :                        "unsupported rnglists encoding DW_RLE_startx_endx at "
      43             :                        "offset 0x%" PRIx32,
      44           4 :                        *OffsetPtr - 1);
      45           2 :   case dwarf::DW_RLE_startx_length:
      46             :     return createStringError(errc::not_supported,
      47             :                        "unsupported rnglists encoding DW_RLE_startx_length "
      48             :                        "at offset 0x%" PRIx32,
      49           4 :                        *OffsetPtr - 1);
      50          17 :   case dwarf::DW_RLE_offset_pair: {
      51          17 :     uint32_t PreviousOffset = *OffsetPtr - 1;
      52          17 :     Value0 = Data.getULEB128(OffsetPtr);
      53          17 :     Value1 = Data.getULEB128(OffsetPtr);
      54          17 :     if (End < *OffsetPtr)
      55             :       return createStringError(errc::invalid_argument,
      56             :                          "read past end of table when reading "
      57             :                          "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
      58           0 :                          PreviousOffset);
      59          17 :     break;
      60             :   }
      61           7 :   case dwarf::DW_RLE_base_address: {
      62           7 :     if ((End - *OffsetPtr) < Data.getAddressSize())
      63             :       return createStringError(errc::invalid_argument,
      64             :                          "insufficient space remaining in table for "
      65             :                          "DW_RLE_base_address encoding at offset 0x%" PRIx32,
      66           0 :                          *OffsetPtr - 1);
      67           7 :     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
      68           7 :     break;
      69             :   }
      70          14 :   case dwarf::DW_RLE_start_end: {
      71          14 :     if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
      72             :       return createStringError(errc::invalid_argument,
      73             :                          "insufficient space remaining in table for "
      74             :                          "DW_RLE_start_end encoding "
      75             :                          "at offset 0x%" PRIx32,
      76           2 :                          *OffsetPtr - 1);
      77          13 :     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
      78          13 :     Value1 = Data.getRelocatedAddress(OffsetPtr);
      79          13 :     break;
      80             :   }
      81          15 :   case dwarf::DW_RLE_start_length: {
      82          15 :     uint32_t PreviousOffset = *OffsetPtr - 1;
      83          15 :     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
      84          15 :     Value1 = Data.getULEB128(OffsetPtr);
      85          15 :     if (End < *OffsetPtr)
      86             :       return createStringError(errc::invalid_argument,
      87             :                          "read past end of table when reading "
      88             :                          "DW_RLE_start_length encoding at offset 0x%" PRIx32,
      89           1 :                          PreviousOffset);
      90          14 :     break;
      91             :   }
      92           1 :   default:
      93             :     return createStringError(errc::not_supported,
      94             :                        "unknown rnglists encoding 0x%" PRIx32
      95             :                        " at offset 0x%" PRIx32,
      96           2 :                        uint32_t(Encoding), *OffsetPtr - 1);
      97             :   }
      98             : 
      99          78 :   EntryKind = Encoding;
     100             :   return Error::success();
     101             : }
     102             : 
     103           9 : DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
     104             :     llvm::Optional<BaseAddress> BaseAddr) const {
     105             :   DWARFAddressRangesVector Res;
     106          29 :   for (const RangeListEntry &RLE : Entries) {
     107          29 :     if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
     108             :       break;
     109          20 :     if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
     110           4 :       BaseAddr = {RLE.Value0, RLE.SectionIndex};
     111           4 :       continue;
     112             :     }
     113             : 
     114             :     DWARFAddressRange E;
     115          16 :     E.SectionIndex = RLE.SectionIndex;
     116          16 :     if (BaseAddr && E.SectionIndex == -1ULL)
     117           8 :       E.SectionIndex = BaseAddr->SectionIndex;
     118             : 
     119          16 :     switch (RLE.EntryKind) {
     120           8 :     case dwarf::DW_RLE_offset_pair:
     121           8 :       E.LowPC = RLE.Value0;
     122           8 :       E.HighPC = RLE.Value1;
     123           8 :       if (BaseAddr) {
     124           8 :         E.LowPC += BaseAddr->Address;
     125           8 :         E.HighPC += BaseAddr->Address;
     126             :       }
     127             :       break;
     128           2 :     case dwarf::DW_RLE_start_end:
     129           2 :       E.LowPC = RLE.Value0;
     130           2 :       E.HighPC = RLE.Value1;
     131           2 :       break;
     132           6 :     case dwarf::DW_RLE_start_length:
     133           6 :       E.LowPC = RLE.Value0;
     134           6 :       E.HighPC = E.LowPC + RLE.Value1;
     135           6 :       break;
     136           0 :     default:
     137             :       // Unsupported encodings should have been reported during extraction,
     138             :       // so we should not run into any here.
     139           0 :       llvm_unreachable("Unsupported range list encoding");
     140             :     }
     141          16 :     Res.push_back(E);
     142             :   }
     143           9 :   return Res;
     144             : }
     145             : 
     146          48 : void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize,
     147             :                           uint8_t MaxEncodingStringLength,
     148             :                           uint64_t &CurrentBase, DIDumpOptions DumpOpts) const {
     149             :   auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
     150             :                           uint8_t AddrSize, DIDumpOptions DumpOpts) {
     151             :     if (DumpOpts.Verbose) {
     152             :       DumpOpts.DisplayRawContents = true;
     153             :       DWARFAddressRange(Entry.Value0, Entry.Value1)
     154             :           .dump(OS, AddrSize, DumpOpts);
     155             :       OS << " => ";
     156             :     }
     157             :   };
     158             : 
     159          48 :   if (DumpOpts.Verbose) {
     160             :     // Print the section offset in verbose mode.
     161          58 :     OS << format("0x%8.8" PRIx32 ":", Offset);
     162          29 :     auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
     163             :     // Unsupported encodings should have been reported during parsing.
     164             :     assert(!EncodingString.empty() && "Unknown range entry encoding");
     165          29 :     OS << format(" [%s%*c", EncodingString.data(),
     166          87 :                  MaxEncodingStringLength - EncodingString.size() + 1, ']');
     167          29 :     if (EntryKind != dwarf::DW_RLE_end_of_list)
     168          19 :       OS << ": ";
     169             :   }
     170             : 
     171          48 :   switch (EntryKind) {
     172          18 :   case dwarf::DW_RLE_end_of_list:
     173          26 :     OS << (DumpOpts.Verbose ? "" : "<End of list>");
     174          18 :     break;
     175           3 :   case dwarf::DW_RLE_base_address:
     176             :     // In non-verbose mode we do not print anything for this entry.
     177           3 :     CurrentBase = Value0;
     178           3 :     if (!DumpOpts.Verbose)
     179           1 :       return;
     180           4 :     OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
     181           2 :     break;
     182           8 :   case dwarf::DW_RLE_start_length:
     183           8 :     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
     184          16 :     DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
     185           8 :     break;
     186           9 :   case dwarf::DW_RLE_offset_pair:
     187           9 :     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
     188           9 :     DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
     189           9 :         .dump(OS, AddrSize, DumpOpts);
     190           9 :     break;
     191          10 :   case dwarf::DW_RLE_start_end:
     192          20 :     DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
     193          10 :     break;
     194           0 :   default:
     195           0 :     llvm_unreachable("Unsupported range list encoding");
     196             :   }
     197          47 :   OS << "\n";
     198             : }

Generated by: LCOV version 1.13