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 IsLittleEndian, AddressSize); 36 DWARFExpression(Extractor, AddressSize, dwarf::DWARF_VERSION).print(OS, MRI); 37 } 38 39 void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, 40 unsigned AddressSize, 41 const MCRegisterInfo *MRI, 42 unsigned Indent) const { 43 for (const Entry &E : Entries) { 44 OS << '\n'; 45 OS.indent(Indent); 46 OS << format("0x%016" PRIx64, E.Begin) << " - " 47 << format("0x%016" PRIx64, E.End) << ": "; 48 49 dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI); 50 } 51 } 52 53 DWARFDebugLoc::LocationList const * 54 DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { 55 auto It = std::lower_bound( 56 Locations.begin(), Locations.end(), Offset, 57 [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; }); 58 if (It != Locations.end() && It->Offset == Offset) 59 return &(*It); 60 return nullptr; 61 } 62 63 void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, 64 Optional<uint64_t> Offset) const { 65 auto DumpLocationList = [&](const LocationList &L) { 66 OS << format("0x%8.8x: ", L.Offset); 67 L.dump(OS, IsLittleEndian, AddressSize, MRI, 12); 68 OS << "\n\n"; 69 }; 70 71 if (Offset) { 72 if (auto *L = getLocationListAtOffset(*Offset)) 73 DumpLocationList(*L); 74 return; 75 } 76 77 for (const LocationList &L : Locations) { 78 DumpLocationList(L); 79 } 80 } 81 82 Optional<DWARFDebugLoc::LocationList> 83 DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) { 84 LocationList LL; 85 LL.Offset = *Offset; 86 87 // 2.6.2 Location Lists 88 // A location list entry consists of: 89 while (true) { 90 Entry E; 91 if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) { 92 llvm::errs() << "Location list overflows the debug_loc section.\n"; 93 return None; 94 } 95 96 // 1. A beginning address offset. ... 97 E.Begin = Data.getRelocatedAddress(Offset); 98 99 // 2. An ending address offset. ... 100 E.End = Data.getRelocatedAddress(Offset); 101 102 // The end of any given location list is marked by an end of list entry, 103 // which consists of a 0 for the beginning address offset and a 0 for the 104 // ending address offset. 105 if (E.Begin == 0 && E.End == 0) 106 return LL; 107 108 if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) { 109 llvm::errs() << "Location list overflows the debug_loc section.\n"; 110 return None; 111 } 112 113 unsigned Bytes = Data.getU16(Offset); 114 if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) { 115 llvm::errs() << "Location list overflows the debug_loc section.\n"; 116 return None; 117 } 118 // A single location description describing the location of the object... 119 StringRef str = Data.getData().substr(*Offset, Bytes); 120 *Offset += Bytes; 121 E.Loc.reserve(str.size()); 122 std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); 123 LL.Entries.push_back(std::move(E)); 124 } 125 } 126 127 void DWARFDebugLoc::parse(const DWARFDataExtractor &data) { 128 IsLittleEndian = data.isLittleEndian(); 129 AddressSize = data.getAddressSize(); 130 131 uint32_t Offset = 0; 132 while (data.isValidOffset(Offset + data.getAddressSize() - 1)) { 133 if (auto LL = parseOneLocationList(data, &Offset)) 134 Locations.push_back(std::move(*LL)); 135 else 136 break; 137 } 138 if (data.isValidOffset(Offset)) 139 errs() << "error: failed to consume entire .debug_loc section\n"; 140 } 141 142 Optional<DWARFDebugLocDWO::LocationList> 143 DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) { 144 LocationList LL; 145 LL.Offset = *Offset; 146 147 // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list. 148 while (auto Kind = 149 static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) { 150 if (Kind != dwarf::DW_LLE_startx_length) { 151 llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind 152 << " not implemented\n"; 153 return None; 154 } 155 156 Entry E; 157 E.Start = Data.getULEB128(Offset); 158 E.Length = Data.getU32(Offset); 159 160 unsigned Bytes = Data.getU16(Offset); 161 // A single location description describing the location of the object... 162 StringRef str = Data.getData().substr(*Offset, Bytes); 163 *Offset += Bytes; 164 E.Loc.resize(str.size()); 165 std::copy(str.begin(), str.end(), E.Loc.begin()); 166 167 LL.Entries.push_back(std::move(E)); 168 } 169 return LL; 170 } 171 172 void DWARFDebugLocDWO::parse(DataExtractor data) { 173 IsLittleEndian = data.isLittleEndian(); 174 AddressSize = data.getAddressSize(); 175 176 uint32_t Offset = 0; 177 while (data.isValidOffset(Offset)) { 178 if (auto LL = parseOneLocationList(data, &Offset)) 179 Locations.push_back(std::move(*LL)); 180 else 181 return; 182 } 183 } 184 185 DWARFDebugLocDWO::LocationList const * 186 DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const { 187 auto It = std::lower_bound( 188 Locations.begin(), Locations.end(), Offset, 189 [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; }); 190 if (It != Locations.end() && It->Offset == Offset) 191 return &(*It); 192 return nullptr; 193 } 194 195 void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, 196 unsigned AddressSize, 197 const MCRegisterInfo *MRI, 198 unsigned Indent) const { 199 for (const Entry &E : Entries) { 200 OS << '\n'; 201 OS.indent(Indent); 202 OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): "; 203 dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI); 204 } 205 } 206 207 void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI, 208 Optional<uint64_t> Offset) const { 209 auto DumpLocationList = [&](const LocationList &L) { 210 OS << format("0x%8.8x: ", L.Offset); 211 L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12); 212 OS << "\n\n"; 213 }; 214 215 if (Offset) { 216 if (auto *L = getLocationListAtOffset(*Offset)) 217 DumpLocationList(*L); 218 return; 219 } 220 221 for (const LocationList &L : Locations) { 222 DumpLocationList(L); 223 } 224 } 225