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