LLVM: lib/DebugInfo/DWARF/DWARFDebugLoc.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

21#include

22#include

23#include

24

25using namespace llvm;

27

28namespace llvm {

30}

31

32namespace {

33class DWARFLocationInterpreter {

34 std::optionalobject::SectionedAddress Base;

35 std::function<std::optionalobject::SectionedAddress(uint32_t)> LookupAddr;

36

37public:

38 DWARFLocationInterpreter(

39 std::optionalobject::SectionedAddress Base,

40 std::function<std::optionalobject::SectionedAddress(uint32_t)>

41 LookupAddr)

42 : Base(Base), LookupAddr(std::move(LookupAddr)) {}

43

44 Expected<std::optional>

45 Interpret(const DWARFLocationEntry &E);

46};

47}

48

52

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);

62 return std::nullopt;

63 }

64 case dwarf::DW_LLE_startx_endx: {

65 std::optional LowPC = LookupAddr(E.Value0);

66 if (!LowPC)

68 std::optional HighPC = LookupAddr(E.Value1);

69 if (!HighPC)

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 LowPC = LookupAddr(E.Value0);

77 if (!LowPC)

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: {

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};

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:

110 }

111}

112

115 unsigned AddressSize, DWARFUnit *U) {

117 std::optionaldwarf::DwarfFormat Format;

118 if (U)

119 Format = U->getFormat();

122}

123

127 unsigned Indent) const {

128 DWARFLocationInterpreter Interp(

129 BaseAddr, [U](uint32_t Index) -> std::optional {

130 if (U)

131 return U->getAddrOffsetSectionItem(Index);

132 return std::nullopt;

133 });

140 OS << "\n";

143 OS << " => ";

144

147 if (Loc.get()->Range)

148 Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, &Obj);

149 else

150 OS << "";

151 }

152 if (Loc)

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 << ": ";

160 Data.getAddressSize(), U);

161 }

162 return true;

163 });

164 if (E) {

166 return false;

167 }

168 return true;

169}

170

172 uint64_t Offset, std::optional BaseAddr,

173 std::function<std::optional(uint32_t)> LookupAddr,

175 DWARFLocationInterpreter Interp(BaseAddr, std::move(LookupAddr));

178 if (Loc)

179 return Callback(Loc.takeError());

180 if (*Loc)

181 return Callback(**Loc);

182 return true;

183 });

184}

185

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 {

197 bool CanContinue = true;

198 while (CanContinue && Data.isValidOffset(Offset)) {

199 OS << Separator;

200 Separator = "\n";

201

203 DumpOpts, Indent);

204 OS << '\n';

205 }

206 }

207}

208

213 while (true) {

216 uint64_t Value1 = Data.getRelocatedAddress(C, &SectionIndex);

217

219

220

221

222

223

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

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 }

247}

248

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:

267 }

268 OS << '\n';

270 OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", "

271 << format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')';

273}

274

277

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

296

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);

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:

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

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 }

340}

341

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";

355

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:

382 break;

383 default:

384 break;

385 }

386}

387

391 if (Data.isValidOffsetForDataOfSize(StartOffset, Size)) {

392 OS << "Invalid dump range\n";

393 return;

394 }

397 bool CanContinue = true;

398 while (CanContinue && Offset < StartOffset + Size) {

399 OS << Separator;

400 Separator = "\n";

401

403 nullptr, DumpOpts, 12);

404 OS << '\n';

405 }

406}

407

409 OS << format("unable to resolve indirect address %u for: %s", Index,

411}

412

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts, ArrayRef< uint8_t > Data, bool IsLittleEndian, unsigned AddressSize, DWARFUnit *U)

Definition DWARFDebugLoc.cpp:113

static Error createResolverError(uint32_t Index, unsigned Kind)

Definition DWARFDebugLoc.cpp:49

static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue, DWARFUnit *U, unsigned Indent, DIDumpOptions DumpOpts)

This file contains constants used for implementing Dwarf debug support.

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS, unsigned Indent, DIDumpOptions DumpOpts, const DWARFObject &Obj) const override

Definition DWARFDebugLoc.cpp:249

void dump(raw_ostream &OS, const DWARFObject &Obj, DIDumpOptions DumpOpts, std::optional< uint64_t > Offset) const

Print the location lists found within the debug_loc section.

Definition DWARFDebugLoc.cpp:186

Error visitLocationList(uint64_t *Offset, function_ref< bool(const DWARFLocationEntry &)> Callback) const override

Call the user-provided callback for each entry (including the end-of-list entry) in the location list...

Definition DWARFDebugLoc.cpp:209

void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS, const DWARFObject &Obj, DIDumpOptions DumpOpts)

Dump all location lists within the given range.

Definition DWARFDebugLoc.cpp:388

Error visitLocationList(uint64_t *Offset, function_ref< bool(const DWARFLocationEntry &)> Callback) const override

Call the user-provided callback for each entry (including the end-of-list entry) in the location list...

Definition DWARFDebugLoc.cpp:275

void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS, unsigned Indent, DIDumpOptions DumpOpts, const DWARFObject &Obj) const override

Definition DWARFDebugLoc.cpp:342

static LLVM_ABI void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, DIDumpOptions DumpOpts, uint64_t SectionIndex)

virtual void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS, unsigned Indent, DIDumpOptions DumpOpts, const DWARFObject &Obj) const =0

virtual Error visitLocationList(uint64_t *Offset, function_ref< bool(const DWARFLocationEntry &)> Callback) const =0

Call the user-provided callback for each entry (including the end-of-list entry) in the location list...

LLVM_ABI Error visitAbsoluteLocationList(uint64_t Offset, std::optional< object::SectionedAddress > BaseAddr, std::function< std::optional< object::SectionedAddress >(uint32_t)> LookupAddr, function_ref< bool(Expected< DWARFLocationExpression >)> Callback) const

Definition DWARFDebugLoc.cpp:171

LLVM_ABI bool dumpLocationList(uint64_t *Offset, raw_ostream &OS, std::optional< object::SectionedAddress > BaseAddr, const DWARFObject &Obj, DWARFUnit *U, DIDumpOptions DumpOpts, unsigned Indent) const

Dump the location list at the given Offset.

Definition DWARFDebugLoc.cpp:124

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

void log(raw_ostream &OS) const override

Print an error message to an output stream.

Definition DWARFDebugLoc.cpp:408

StringRef - Represent a constant reference to a string, i.e.

constexpr bool empty() const

empty - Check if the string is empty.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

An efficient, type-erasing, non-owning reference to a callable.

This class implements an extremely fast bulk output stream that can only output to a stream.

raw_ostream & indent(unsigned NumSpaces)

indent - Insert 'NumSpaces' spaces.

LLVM_ABI StringRef LocListEncodingString(unsigned Encoding)

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ C

The default llvm calling convention, compatible with C.

LoclistEntries

DWARF v5 loc list entry encoding values.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

LLVM_ABI void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U, bool IsEH=false)

Print a Dwarf expression/.

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)

format_hex - Output N as a fixed width hexadecimal.

format_object< Ts... > format(const char *Fmt, const Ts &... Vals)

These are helper functions used to produce formatted output.

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

void consumeError(Error Err)

Consume a Error without doing anything.

Container for dump options that control which debug information will be dumped.

std::function< void(Error)> RecoverableErrorHandler

A single location within a location list.

uint8_t Kind

The entry kind (DW_LLE_***).

static const uint64_t UndefSection

static const uint64_t UndefSection