LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFDebugLoc.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 77 85 90.6 %
Date: 2017-09-14 15:23:50 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DWARFDebugLoc.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/DWARFDebugLoc.h"
      11             : #include "llvm/ADT/StringRef.h"
      12             : #include "llvm/BinaryFormat/Dwarf.h"
      13             : #include "llvm/DebugInfo/DWARF/DWARFContext.h"
      14             : #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
      15             : #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
      16             : #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
      17             : #include "llvm/Support/Compiler.h"
      18             : #include "llvm/Support/Format.h"
      19             : #include "llvm/Support/raw_ostream.h"
      20             : #include <algorithm>
      21             : #include <cinttypes>
      22             : #include <cstdint>
      23             : 
      24             : using namespace llvm;
      25             : 
      26             : // When directly dumping the .debug_loc without a compile unit, we have to guess
      27             : // at the DWARF version. This only affects DW_OP_call_ref, which is a rare
      28             : // expression that LLVM doesn't produce. Guessing the wrong version means we
      29             : // won't be able to pretty print expressions in DWARF2 binaries produced by
      30             : // non-LLVM tools.
      31             : static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data,
      32             :                            bool IsLittleEndian, unsigned AddressSize,
      33             :                            const MCRegisterInfo *MRI) {
      34             :   DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()),
      35         373 :                                IsLittleEndian, AddressSize);
      36         746 :   DWARFExpression(Extractor, AddressSize, dwarf::DWARF_VERSION).print(OS, MRI);
      37             : }
      38             : 
      39         220 : void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
      40             :                                        unsigned AddressSize,
      41             :                                        const MCRegisterInfo *MRI,
      42             :                                        unsigned Indent) const {
      43        1019 :   for (const Entry &E : Entries) {
      44         359 :     OS << '\n';
      45         359 :     OS.indent(Indent);
      46        1077 :     OS << format("0x%016" PRIx64, E.Begin) << " - "
      47         718 :        << format("0x%016" PRIx64, E.End) << ": ";
      48             : 
      49        1077 :     dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
      50             :   }
      51         220 : }
      52             : 
      53         174 : void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI) const {
      54         600 :   for (const LocationList &L : Locations) {
      55         156 :     OS << format("0x%8.8x: ", L.Offset);
      56          78 :     L.dump(OS, IsLittleEndian, AddressSize, MRI, 12);
      57          78 :     OS << "\n\n";
      58             :   }
      59         174 : }
      60             : 
      61             : Optional<DWARFDebugLoc::LocationList>
      62         220 : DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) {
      63         440 :   LocationList LL;
      64         220 :   LL.Offset = *Offset;
      65             : 
      66             :   // 2.6.2 Location Lists
      67             :   // A location list entry consists of:
      68             :   while (true) {
      69         938 :     Entry E;
      70        1158 :     if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) {
      71           0 :       llvm::errs() << "Location list overflows the debug_loc section.\n";
      72         220 :       return None;
      73             :     }
      74             : 
      75             :     // 1. A beginning address offset. ...
      76         579 :     E.Begin = Data.getRelocatedAddress(Offset);
      77             : 
      78             :     // 2. An ending address offset. ...
      79         579 :     E.End = Data.getRelocatedAddress(Offset);
      80             : 
      81             :     // The end of any given location list is marked by an end of list entry,
      82             :     // which consists of a 0 for the beginning address offset and a 0 for the
      83             :     // ending address offset.
      84         896 :     if (E.Begin == 0 && E.End == 0)
      85             :       return LL;
      86             : 
      87         718 :     if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) {
      88           0 :       llvm::errs() << "Location list overflows the debug_loc section.\n";
      89             :       return None;
      90             :     }
      91             : 
      92         359 :     unsigned Bytes = Data.getU16(Offset);
      93         718 :     if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) {
      94           0 :       llvm::errs() << "Location list overflows the debug_loc section.\n";
      95             :       return None;
      96             :     }
      97             :     // A single location description describing the location of the object...
      98         718 :     StringRef str = Data.getData().substr(*Offset, Bytes);
      99         359 :     *Offset += Bytes;
     100         718 :     E.Loc.reserve(str.size());
     101        1077 :     std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
     102         359 :     LL.Entries.push_back(std::move(E));
     103             :   }
     104             : }
     105             : 
     106         157 : void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
     107         314 :   IsLittleEndian = data.isLittleEndian();
     108         157 :   AddressSize = data.getAddressSize();
     109             : 
     110         157 :   uint32_t Offset = 0;
     111         470 :   while (data.isValidOffset(Offset + data.getAddressSize() - 1)) {
     112         156 :     if (auto LL = parseOneLocationList(data, &Offset))
     113         156 :       Locations.push_back(std::move(*LL));
     114             :     else
     115             :       break;
     116             :   }
     117         314 :   if (data.isValidOffset(Offset))
     118           0 :     errs() << "error: failed to consume entire .debug_loc section\n";
     119         157 : }
     120             : 
     121             : Optional<DWARFDebugLocDWO::LocationList>
     122          10 : DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
     123          20 :   LocationList LL;
     124          10 :   LL.Offset = *Offset;
     125             : 
     126             :   // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
     127             :   while (auto Kind =
     128          24 :              static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
     129          14 :     if (Kind != dwarf::DW_LLE_startx_length) {
     130           0 :       llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
     131           0 :                    << " not implemented\n";
     132           0 :       return None;
     133             :     }
     134             : 
     135          28 :     Entry E;
     136          14 :     E.Start = Data.getULEB128(Offset);
     137          14 :     E.Length = Data.getU32(Offset);
     138             : 
     139          14 :     unsigned Bytes = Data.getU16(Offset);
     140             :     // A single location description describing the location of the object...
     141          28 :     StringRef str = Data.getData().substr(*Offset, Bytes);
     142          14 :     *Offset += Bytes;
     143          14 :     E.Loc.resize(str.size());
     144          42 :     std::copy(str.begin(), str.end(), E.Loc.begin());
     145             : 
     146          14 :     LL.Entries.push_back(std::move(E));
     147          14 :   }
     148             :   return LL;
     149             : }
     150             : 
     151         166 : void DWARFDebugLocDWO::parse(DataExtractor data) {
     152         332 :   IsLittleEndian = data.isLittleEndian();
     153         166 :   AddressSize = data.getAddressSize();
     154             : 
     155         166 :   uint32_t Offset = 0;
     156         342 :   while (data.isValidOffset(Offset)) {
     157          10 :     if (auto LL = parseOneLocationList(data, &Offset))
     158          10 :       Locations.push_back(std::move(*LL));
     159             :     else
     160           0 :       return;
     161             :   }
     162             : }
     163             : 
     164          10 : void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
     165             :                                           unsigned AddressSize,
     166             :                                           const MCRegisterInfo *MRI,
     167             :                                           unsigned Indent) const {
     168          44 :   for (const Entry &E : Entries) {
     169          14 :     OS << '\n';
     170          14 :     OS.indent(Indent);
     171          28 :     OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): ";
     172          42 :     dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
     173             :   }
     174          10 : }
     175             : 
     176         166 : void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI) const {
     177         503 :   for (const LocationList &L : Locations) {
     178          10 :     OS << format("0x%8.8x: ", L.Offset);
     179           5 :     L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
     180           5 :     OS << "\n\n";
     181             :   }
     182         166 : }

Generated by: LCOV version 1.13