414 lines · cpp
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-exception6//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 25using namespace llvm;26using object::SectionedAddress;27 28namespace llvm {29class DWARFObject;30}31 32namespace {33class DWARFLocationInterpreter {34 std::optional<object::SectionedAddress> Base;35 std::function<std::optional<object::SectionedAddress>(uint32_t)> LookupAddr;36 37public: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} // namespace48 49static Error createResolverError(uint32_t Index, unsigned Kind) {50 return make_error<ResolverError>(Index, (dwarf::LoclistEntries)Kind);51}52 53Expected<std::optional<DWARFLocationExpression>>54DWARFLocationInterpreter::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 113static 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 124bool 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 else150 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 171Error 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 186void 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 209Error 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 the222 // ending address offset. A beginning offset of 0xff...f marks the base223 // 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 249void 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 275Error 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 have296 // to support both pre- and standartized styles for the compatibility.297 if (Version < 5)298 E.Value1 = Data.getU32(C);299 else300 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 342void 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 388void 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 408void 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 413char llvm::ResolverError::ID;414