LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFDebugLoc.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 73 87 83.9 %
Date: 2018-10-20 13:21:21 Functions: 9 10 90.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/WithColor.h"
      20             : #include "llvm/Support/raw_ostream.h"
      21             : #include <algorithm>
      22             : #include <cinttypes>
      23             : #include <cstdint>
      24             : 
      25             : using namespace llvm;
      26             : 
      27             : // When directly dumping the .debug_loc without a compile unit, we have to guess
      28             : // at the DWARF version. This only affects DW_OP_call_ref, which is a rare
      29             : // expression that LLVM doesn't produce. Guessing the wrong version means we
      30             : // won't be able to pretty print expressions in DWARF2 binaries produced by
      31             : // non-LLVM tools.
      32             : static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data,
      33             :                            bool IsLittleEndian, unsigned AddressSize,
      34             :                            const MCRegisterInfo *MRI) {
      35             :   DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()),
      36         419 :                                IsLittleEndian, AddressSize);
      37         419 :   DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI);
      38             : }
      39             : 
      40         255 : void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
      41             :                                        unsigned AddressSize,
      42             :                                        const MCRegisterInfo *MRI,
      43             :                                        uint64_t BaseAddress,
      44             :                                        unsigned Indent) const {
      45         659 :   for (const Entry &E : Entries) {
      46             :     OS << '\n';
      47         404 :     OS.indent(Indent);
      48         808 :     OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2,
      49         808 :                  BaseAddress + E.Begin);
      50         404 :     OS << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2,
      51         808 :                  BaseAddress + E.End);
      52         404 :     OS << ": ";
      53             : 
      54             :     dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
      55             :   }
      56         255 : }
      57             : 
      58             : DWARFDebugLoc::LocationList const *
      59          15 : DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const {
      60             :   auto It = std::lower_bound(
      61             :       Locations.begin(), Locations.end(), Offset,
      62          27 :       [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
      63          15 :   if (It != Locations.end() && It->Offset == Offset)
      64          15 :     return &(*It);
      65             :   return nullptr;
      66             : }
      67             : 
      68          50 : void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
      69             :                          Optional<uint64_t> Offset) const {
      70             :   auto DumpLocationList = [&](const LocationList &L) {
      71             :     OS << format("0x%8.8x: ", L.Offset);
      72             :     L.dump(OS, IsLittleEndian, AddressSize, MRI, 0, 12);
      73             :     OS << "\n\n";
      74          50 :   };
      75             : 
      76          50 :   if (Offset) {
      77           2 :     if (auto *L = getLocationListAtOffset(*Offset))
      78           2 :       DumpLocationList(*L);
      79           2 :     return;
      80             :   }
      81             : 
      82         135 :   for (const LocationList &L : Locations) {
      83          87 :     DumpLocationList(L);
      84             :   }
      85             : }
      86             : 
      87             : Optional<DWARFDebugLoc::LocationList>
      88         269 : DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) {
      89             :   LocationList LL;
      90         269 :   LL.Offset = *Offset;
      91             : 
      92             :   // 2.6.2 Location Lists
      93             :   // A location list entry consists of:
      94             :   while (true) {
      95             :     Entry E;
      96         695 :     if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) {
      97           0 :       WithColor::error() << "location list overflows the debug_loc section.\n";
      98             :       return None;
      99             :     }
     100             : 
     101             :     // 1. A beginning address offset. ...
     102         695 :     E.Begin = Data.getRelocatedAddress(Offset);
     103             : 
     104             :     // 2. An ending address offset. ...
     105         695 :     E.End = Data.getRelocatedAddress(Offset);
     106             : 
     107             :     // The end of any given location list is marked by an end of list entry,
     108             :     // which consists of a 0 for the beginning address offset and a 0 for the
     109             :     // ending address offset.
     110         695 :     if (E.Begin == 0 && E.End == 0)
     111             :       return LL;
     112             : 
     113         426 :     if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) {
     114           0 :       WithColor::error() << "location list overflows the debug_loc section.\n";
     115             :       return None;
     116             :     }
     117             : 
     118         426 :     unsigned Bytes = Data.getU16(Offset);
     119         426 :     if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) {
     120           0 :       WithColor::error() << "location list overflows the debug_loc section.\n";
     121             :       return None;
     122             :     }
     123             :     // A single location description describing the location of the object...
     124         426 :     StringRef str = Data.getData().substr(*Offset, Bytes);
     125         426 :     *Offset += Bytes;
     126             :     E.Loc.reserve(str.size());
     127             :     std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
     128         426 :     LL.Entries.push_back(std::move(E));
     129             :   }
     130             : }
     131             : 
     132          56 : void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
     133          56 :   IsLittleEndian = data.isLittleEndian();
     134          56 :   AddressSize = data.getAddressSize();
     135             : 
     136          56 :   uint32_t Offset = 0;
     137         318 :   while (data.isValidOffset(Offset + data.getAddressSize() - 1)) {
     138         103 :     if (auto LL = parseOneLocationList(data, &Offset))
     139         103 :       Locations.push_back(std::move(*LL));
     140             :     else
     141             :       break;
     142             :   }
     143         112 :   if (data.isValidOffset(Offset))
     144           0 :     WithColor::error() << "failed to consume entire .debug_loc section\n";
     145          56 : }
     146             : 
     147             : Optional<DWARFDebugLocDWO::LocationList>
     148          11 : DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
     149             :   LocationList LL;
     150          11 :   LL.Offset = *Offset;
     151             : 
     152             :   // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
     153             :   while (auto Kind =
     154          26 :              static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
     155          15 :     if (Kind != dwarf::DW_LLE_startx_length) {
     156           0 :       WithColor::error() << "dumping support for LLE of kind " << (int)Kind
     157           0 :                          << " not implemented\n";
     158           0 :       return None;
     159             :     }
     160             : 
     161             :     Entry E;
     162          15 :     E.Start = Data.getULEB128(Offset);
     163          15 :     E.Length = Data.getU32(Offset);
     164             : 
     165          15 :     unsigned Bytes = Data.getU16(Offset);
     166             :     // A single location description describing the location of the object...
     167          15 :     StringRef str = Data.getData().substr(*Offset, Bytes);
     168          15 :     *Offset += Bytes;
     169          15 :     E.Loc.resize(str.size());
     170             :     std::copy(str.begin(), str.end(), E.Loc.begin());
     171             : 
     172          15 :     LL.Entries.push_back(std::move(E));
     173          15 :   }
     174             :   return LL;
     175             : }
     176             : 
     177           3 : void DWARFDebugLocDWO::parse(DataExtractor data) {
     178           3 :   IsLittleEndian = data.isLittleEndian();
     179           3 :   AddressSize = data.getAddressSize();
     180             : 
     181           3 :   uint32_t Offset = 0;
     182          18 :   while (data.isValidOffset(Offset)) {
     183           6 :     if (auto LL = parseOneLocationList(data, &Offset))
     184           6 :       Locations.push_back(std::move(*LL));
     185             :     else
     186             :       return;
     187             :   }
     188             : }
     189             : 
     190             : DWARFDebugLocDWO::LocationList const *
     191           0 : DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const {
     192             :   auto It = std::lower_bound(
     193             :       Locations.begin(), Locations.end(), Offset,
     194           0 :       [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
     195           0 :   if (It != Locations.end() && It->Offset == Offset)
     196           0 :     return &(*It);
     197             :   return nullptr;
     198             : }
     199             : 
     200          11 : void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
     201             :                                           unsigned AddressSize,
     202             :                                           const MCRegisterInfo *MRI,
     203             :                                           unsigned Indent) const {
     204          26 :   for (const Entry &E : Entries) {
     205             :     OS << '\n';
     206          15 :     OS.indent(Indent);
     207          15 :     OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): ";
     208             :     dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
     209             :   }
     210          11 : }
     211             : 
     212           3 : void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
     213             :                             Optional<uint64_t> Offset) const {
     214             :   auto DumpLocationList = [&](const LocationList &L) {
     215             :     OS << format("0x%8.8x: ", L.Offset);
     216             :     L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
     217             :     OS << "\n\n";
     218           3 :   };
     219             : 
     220           3 :   if (Offset) {
     221           0 :     if (auto *L = getLocationListAtOffset(*Offset))
     222           0 :       DumpLocationList(*L);
     223           0 :     return;
     224             :   }
     225             : 
     226           9 :   for (const LocationList &L : Locations) {
     227           6 :     DumpLocationList(L);
     228             :   }
     229             : }

Generated by: LCOV version 1.13