1 //===- DWARFDebugLoc.cpp --------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 10 #include "llvm/ADT/StringRef.h" 11 #include "llvm/BinaryFormat/Dwarf.h" 12 #include "llvm/DebugInfo/DIContext.h" 13 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" 14 #include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" 15 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 16 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" 17 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 18 #include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" 19 #include "llvm/Support/Format.h" 20 #include "llvm/Support/raw_ostream.h" 21 #include <algorithm> 22 #include <cinttypes> 23 #include <cstdint> 24 25 using namespace llvm; 26 using object::SectionedAddress; 27 28 namespace llvm { 29 class DWARFObject; 30 } 31 32 namespace { 33 class DWARFLocationInterpreter { 34 std::optional<object::SectionedAddress> Base; 35 std::function<std::optional<object::SectionedAddress>(uint32_t)> LookupAddr; 36 37 public: 38 DWARFLocationInterpreter( 39 std::optional<object::SectionedAddress> Base, 40 std::function<std::optional<object::SectionedAddress>(uint32_t)> 41 LookupAddr) 42 : Base(Base), LookupAddr(std::move(LookupAddr)) {} 43 44 Expected<std::optional<DWARFLocationExpression>> 45 Interpret(const DWARFLocationEntry &E); 46 }; 47 } // namespace 48 49 static Error createResolverError(uint32_t Index, unsigned Kind) { 50 return make_error<ResolverError>(Index, (dwarf::LoclistEntries)Kind); 51 } 52 53 Expected<std::optional<DWARFLocationExpression>> 54 DWARFLocationInterpreter::Interpret(const DWARFLocationEntry &E) { 55 switch (E.Kind) { 56 case dwarf::DW_LLE_end_of_list: 57 return std::nullopt; 58 case dwarf::DW_LLE_base_addressx: { 59 Base = LookupAddr(E.Value0); 60 if (!Base) 61 return createResolverError(E.Value0, E.Kind); 62 return std::nullopt; 63 } 64 case dwarf::DW_LLE_startx_endx: { 65 std::optional<SectionedAddress> LowPC = LookupAddr(E.Value0); 66 if (!LowPC) 67 return createResolverError(E.Value0, E.Kind); 68 std::optional<SectionedAddress> HighPC = LookupAddr(E.Value1); 69 if (!HighPC) 70 return createResolverError(E.Value1, E.Kind); 71 return DWARFLocationExpression{ 72 DWARFAddressRange{LowPC->Address, HighPC->Address, LowPC->SectionIndex}, 73 E.Loc}; 74 } 75 case dwarf::DW_LLE_startx_length: { 76 std::optional<SectionedAddress> LowPC = LookupAddr(E.Value0); 77 if (!LowPC) 78 return createResolverError(E.Value0, E.Kind); 79 return DWARFLocationExpression{DWARFAddressRange{LowPC->Address, 80 LowPC->Address + E.Value1, 81 LowPC->SectionIndex}, 82 E.Loc}; 83 } 84 case dwarf::DW_LLE_offset_pair: { 85 if (!Base) { 86 return createStringError(inconvertibleErrorCode(), 87 "Unable to resolve location list offset pair: " 88 "Base address not defined"); 89 } 90 DWARFAddressRange Range{Base->Address + E.Value0, Base->Address + E.Value1, 91 Base->SectionIndex}; 92 if (Range.SectionIndex == SectionedAddress::UndefSection) 93 Range.SectionIndex = E.SectionIndex; 94 return DWARFLocationExpression{Range, E.Loc}; 95 } 96 case dwarf::DW_LLE_default_location: 97 return DWARFLocationExpression{std::nullopt, E.Loc}; 98 case dwarf::DW_LLE_base_address: 99 Base = SectionedAddress{E.Value0, E.SectionIndex}; 100 return std::nullopt; 101 case dwarf::DW_LLE_start_end: 102 return DWARFLocationExpression{ 103 DWARFAddressRange{E.Value0, E.Value1, E.SectionIndex}, E.Loc}; 104 case dwarf::DW_LLE_start_length: 105 return DWARFLocationExpression{ 106 DWARFAddressRange{E.Value0, E.Value0 + E.Value1, E.SectionIndex}, 107 E.Loc}; 108 default: 109 llvm_unreachable("unreachable locations list kind"); 110 } 111 } 112 113 static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts, 114 ArrayRef<uint8_t> Data, bool IsLittleEndian, 115 unsigned AddressSize, DWARFUnit *U) { 116 DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize); 117 std::optional<dwarf::DwarfFormat> Format; 118 if (U) 119 Format = U->getFormat(); 120 DWARFExpression E(Extractor, AddressSize, Format); 121 printDwarfExpression(&E, OS, DumpOpts, U); 122 } 123 124 bool DWARFLocationTable::dumpLocationList( 125 uint64_t *Offset, raw_ostream &OS, std::optional<SectionedAddress> BaseAddr, 126 const DWARFObject &Obj, DWARFUnit *U, DIDumpOptions DumpOpts, 127 unsigned Indent) const { 128 DWARFLocationInterpreter Interp( 129 BaseAddr, [U](uint32_t Index) -> std::optional<SectionedAddress> { 130 if (U) 131 return U->getAddrOffsetSectionItem(Index); 132 return std::nullopt; 133 }); 134 OS << format("0x%8.8" PRIx64 ": ", *Offset); 135 Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) { 136 Expected<std::optional<DWARFLocationExpression>> Loc = Interp.Interpret(E); 137 if (!Loc || DumpOpts.DisplayRawContents) 138 dumpRawEntry(E, OS, Indent, DumpOpts, Obj); 139 if (Loc && *Loc) { 140 OS << "\n"; 141 OS.indent(Indent); 142 if (DumpOpts.DisplayRawContents) 143 OS << " => "; 144 145 DIDumpOptions RangeDumpOpts(DumpOpts); 146 RangeDumpOpts.DisplayRawContents = false; 147 if (Loc.get()->Range) 148 Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, &Obj); 149 else 150 OS << "<default>"; 151 } 152 if (!Loc) 153 consumeError(Loc.takeError()); 154 155 if (E.Kind != dwarf::DW_LLE_base_address && 156 E.Kind != dwarf::DW_LLE_base_addressx && 157 E.Kind != dwarf::DW_LLE_end_of_list) { 158 OS << ": "; 159 dumpExpression(OS, DumpOpts, E.Loc, Data.isLittleEndian(), 160 Data.getAddressSize(), U); 161 } 162 return true; 163 }); 164 if (E) { 165 DumpOpts.RecoverableErrorHandler(std::move(E)); 166 return false; 167 } 168 return true; 169 } 170 171 Error DWARFLocationTable::visitAbsoluteLocationList( 172 uint64_t Offset, std::optional<SectionedAddress> BaseAddr, 173 std::function<std::optional<SectionedAddress>(uint32_t)> LookupAddr, 174 function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const { 175 DWARFLocationInterpreter Interp(BaseAddr, std::move(LookupAddr)); 176 return visitLocationList(&Offset, [&](const DWARFLocationEntry &E) { 177 Expected<std::optional<DWARFLocationExpression>> Loc = Interp.Interpret(E); 178 if (!Loc) 179 return Callback(Loc.takeError()); 180 if (*Loc) 181 return Callback(**Loc); 182 return true; 183 }); 184 } 185 186 void DWARFDebugLoc::dump(raw_ostream &OS, const DWARFObject &Obj, 187 DIDumpOptions DumpOpts, 188 std::optional<uint64_t> DumpOffset) const { 189 auto BaseAddr = std::nullopt; 190 unsigned Indent = 12; 191 if (DumpOffset) { 192 dumpLocationList(&*DumpOffset, OS, BaseAddr, Obj, nullptr, DumpOpts, 193 Indent); 194 } else { 195 uint64_t Offset = 0; 196 StringRef Separator; 197 bool CanContinue = true; 198 while (CanContinue && Data.isValidOffset(Offset)) { 199 OS << Separator; 200 Separator = "\n"; 201 202 CanContinue = dumpLocationList(&Offset, OS, BaseAddr, Obj, nullptr, 203 DumpOpts, Indent); 204 OS << '\n'; 205 } 206 } 207 } 208 209 Error DWARFDebugLoc::visitLocationList( 210 uint64_t *Offset, 211 function_ref<bool(const DWARFLocationEntry &)> Callback) const { 212 DataExtractor::Cursor C(*Offset); 213 while (true) { 214 uint64_t SectionIndex; 215 uint64_t Value0 = Data.getRelocatedAddress(C); 216 uint64_t Value1 = Data.getRelocatedAddress(C, &SectionIndex); 217 218 DWARFLocationEntry E; 219 220 // The end of any given location list is marked by an end of list entry, 221 // which consists of a 0 for the beginning address offset and a 0 for the 222 // ending address offset. A beginning offset of 0xff...f marks the base 223 // address selection entry. 224 if (Value0 == 0 && Value1 == 0) { 225 E.Kind = dwarf::DW_LLE_end_of_list; 226 } else if (Value0 == (Data.getAddressSize() == 4 ? -1U : -1ULL)) { 227 E.Kind = dwarf::DW_LLE_base_address; 228 E.Value0 = Value1; 229 E.SectionIndex = SectionIndex; 230 } else { 231 E.Kind = dwarf::DW_LLE_offset_pair; 232 E.Value0 = Value0; 233 E.Value1 = Value1; 234 E.SectionIndex = SectionIndex; 235 unsigned Bytes = Data.getU16(C); 236 // A single location description describing the location of the object... 237 Data.getU8(C, E.Loc, Bytes); 238 } 239 240 if (!C) 241 return C.takeError(); 242 if (!Callback(E) || E.Kind == dwarf::DW_LLE_end_of_list) 243 break; 244 } 245 *Offset = C.tell(); 246 return Error::success(); 247 } 248 249 void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry, 250 raw_ostream &OS, unsigned Indent, 251 DIDumpOptions DumpOpts, 252 const DWARFObject &Obj) const { 253 uint64_t Value0, Value1; 254 switch (Entry.Kind) { 255 case dwarf::DW_LLE_base_address: 256 Value0 = Data.getAddressSize() == 4 ? -1U : -1ULL; 257 Value1 = Entry.Value0; 258 break; 259 case dwarf::DW_LLE_offset_pair: 260 Value0 = Entry.Value0; 261 Value1 = Entry.Value1; 262 break; 263 case dwarf::DW_LLE_end_of_list: 264 return; 265 default: 266 llvm_unreachable("Not possible in DWARF4!"); 267 } 268 OS << '\n'; 269 OS.indent(Indent); 270 OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", " 271 << format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')'; 272 DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex); 273 } 274 275 Error DWARFDebugLoclists::visitLocationList( 276 uint64_t *Offset, function_ref<bool(const DWARFLocationEntry &)> F) const { 277 278 DataExtractor::Cursor C(*Offset); 279 bool Continue = true; 280 while (Continue) { 281 DWARFLocationEntry E; 282 E.Kind = Data.getU8(C); 283 switch (E.Kind) { 284 case dwarf::DW_LLE_end_of_list: 285 break; 286 case dwarf::DW_LLE_base_addressx: 287 E.Value0 = Data.getULEB128(C); 288 break; 289 case dwarf::DW_LLE_startx_endx: 290 E.Value0 = Data.getULEB128(C); 291 E.Value1 = Data.getULEB128(C); 292 break; 293 case dwarf::DW_LLE_startx_length: 294 E.Value0 = Data.getULEB128(C); 295 // Pre-DWARF 5 has different interpretation of the length field. We have 296 // to support both pre- and standartized styles for the compatibility. 297 if (Version < 5) 298 E.Value1 = Data.getU32(C); 299 else 300 E.Value1 = Data.getULEB128(C); 301 break; 302 case dwarf::DW_LLE_offset_pair: 303 E.Value0 = Data.getULEB128(C); 304 E.Value1 = Data.getULEB128(C); 305 E.SectionIndex = SectionedAddress::UndefSection; 306 break; 307 case dwarf::DW_LLE_default_location: 308 break; 309 case dwarf::DW_LLE_base_address: 310 E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex); 311 break; 312 case dwarf::DW_LLE_start_end: 313 E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex); 314 E.Value1 = Data.getRelocatedAddress(C); 315 break; 316 case dwarf::DW_LLE_start_length: 317 E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex); 318 E.Value1 = Data.getULEB128(C); 319 break; 320 default: 321 cantFail(C.takeError()); 322 return createStringError(errc::illegal_byte_sequence, 323 "LLE of kind %x not supported", (int)E.Kind); 324 } 325 326 if (E.Kind != dwarf::DW_LLE_base_address && 327 E.Kind != dwarf::DW_LLE_base_addressx && 328 E.Kind != dwarf::DW_LLE_end_of_list) { 329 unsigned Bytes = Version >= 5 ? Data.getULEB128(C) : Data.getU16(C); 330 // A single location description describing the location of the object... 331 Data.getU8(C, E.Loc, Bytes); 332 } 333 334 if (!C) 335 return C.takeError(); 336 Continue = F(E) && E.Kind != dwarf::DW_LLE_end_of_list; 337 } 338 *Offset = C.tell(); 339 return Error::success(); 340 } 341 342 void DWARFDebugLoclists::dumpRawEntry(const DWARFLocationEntry &Entry, 343 raw_ostream &OS, unsigned Indent, 344 DIDumpOptions DumpOpts, 345 const DWARFObject &Obj) const { 346 size_t MaxEncodingStringLength = 0; 347 #define HANDLE_DW_LLE(ID, NAME) \ 348 MaxEncodingStringLength = std::max(MaxEncodingStringLength, \ 349 dwarf::LocListEncodingString(ID).size()); 350 #include "llvm/BinaryFormat/Dwarf.def" 351 352 OS << "\n"; 353 OS.indent(Indent); 354 StringRef EncodingString = dwarf::LocListEncodingString(Entry.Kind); 355 // Unsupported encodings should have been reported during parsing. 356 assert(!EncodingString.empty() && "Unknown loclist entry encoding"); 357 OS << format("%-*s(", MaxEncodingStringLength, EncodingString.data()); 358 unsigned FieldSize = 2 + 2 * Data.getAddressSize(); 359 switch (Entry.Kind) { 360 case dwarf::DW_LLE_end_of_list: 361 case dwarf::DW_LLE_default_location: 362 break; 363 case dwarf::DW_LLE_startx_endx: 364 case dwarf::DW_LLE_startx_length: 365 case dwarf::DW_LLE_offset_pair: 366 case dwarf::DW_LLE_start_end: 367 case dwarf::DW_LLE_start_length: 368 OS << format_hex(Entry.Value0, FieldSize) << ", " 369 << format_hex(Entry.Value1, FieldSize); 370 break; 371 case dwarf::DW_LLE_base_addressx: 372 case dwarf::DW_LLE_base_address: 373 OS << format_hex(Entry.Value0, FieldSize); 374 break; 375 } 376 OS << ')'; 377 switch (Entry.Kind) { 378 case dwarf::DW_LLE_base_address: 379 case dwarf::DW_LLE_start_end: 380 case dwarf::DW_LLE_start_length: 381 DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex); 382 break; 383 default: 384 break; 385 } 386 } 387 388 void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size, 389 raw_ostream &OS, const DWARFObject &Obj, 390 DIDumpOptions DumpOpts) { 391 if (!Data.isValidOffsetForDataOfSize(StartOffset, Size)) { 392 OS << "Invalid dump range\n"; 393 return; 394 } 395 uint64_t Offset = StartOffset; 396 StringRef Separator; 397 bool CanContinue = true; 398 while (CanContinue && Offset < StartOffset + Size) { 399 OS << Separator; 400 Separator = "\n"; 401 402 CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj, 403 nullptr, DumpOpts, /*Indent=*/12); 404 OS << '\n'; 405 } 406 } 407 408 void llvm::ResolverError::log(raw_ostream &OS) const { 409 OS << format("unable to resolve indirect address %u for: %s", Index, 410 dwarf::LocListEncodingString(Kind).data()); 411 } 412 413 char llvm::ResolverError::ID; 414