1//===- DWARFDebugLoc.h ------------------------------------------*- C++ -*-===//
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#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
10#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
11
12#include "llvm/ADT/SmallVector.h"
13#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
14#include "llvm/Support/Errc.h"
15#include <cstdint>
16
17namespace llvm {
18class DWARFUnit;
19class MCRegisterInfo;
20class raw_ostream;
21class DWARFObject;
22struct DIDumpOptions;
23struct DWARFLocationExpression;
24namespace object {
25struct SectionedAddress;
26}
27
28/// A single location within a location list. Entries are stored in the DWARF5
29/// form even if they originally come from a DWARF<=4 location list.
30struct DWARFLocationEntry {
31 /// The entry kind (DW_LLE_***).
32 uint8_t Kind;
33
34 /// The first value of the location entry (if applicable).
35 uint64_t Value0;
36
37 /// The second value of the location entry (if applicable).
38 uint64_t Value1;
39
40 /// The index of the section this entry is relative to (if applicable).
41 uint64_t SectionIndex;
42
43 /// The location expression itself (if applicable).
44 SmallVector<uint8_t, 4> Loc;
45};
46
47/// An abstract base class for various kinds of location tables (.debug_loc,
48/// .debug_loclists, and their dwo variants).
49class DWARFLocationTable {
50public:
51 DWARFLocationTable(DWARFDataExtractor Data) : Data(std::move(Data)) {}
52 virtual ~DWARFLocationTable() = default;
53
54 /// Call the user-provided callback for each entry (including the end-of-list
55 /// entry) in the location list starting at \p Offset. The callback can return
56 /// false to terminate the iteration early. Returns an error if it was unable
57 /// to parse the entire location list correctly. Upon successful termination
58 /// \p Offset will be updated point past the end of the list.
59 virtual Error visitLocationList(
60 uint64_t *Offset,
61 function_ref<bool(const DWARFLocationEntry &)> Callback) const = 0;
62
63 /// Dump the location list at the given \p Offset. The function returns true
64 /// iff it has successfully reched the end of the list. This means that one
65 /// can attempt to parse another list after the current one (\p Offset will be
66 /// updated to point past the end of the current list).
67 bool dumpLocationList(uint64_t *Offset, raw_ostream &OS,
68 std::optional<object::SectionedAddress> BaseAddr,
69 const DWARFObject &Obj, DWARFUnit *U,
70 DIDumpOptions DumpOpts, unsigned Indent) const;
71
72 Error visitAbsoluteLocationList(
73 uint64_t Offset, std::optional<object::SectionedAddress> BaseAddr,
74 std::function<std::optional<object::SectionedAddress>(uint32_t)>
75 LookupAddr,
76 function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const;
77
78 const DWARFDataExtractor &getData() { return Data; }
79
80protected:
81 DWARFDataExtractor Data;
82
83 virtual void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
84 unsigned Indent, DIDumpOptions DumpOpts,
85 const DWARFObject &Obj) const = 0;
86};
87
88class DWARFDebugLoc final : public DWARFLocationTable {
89public:
90 /// A list of locations that contain one variable.
91 struct LocationList {
92 /// The beginning offset where this location list is stored in the debug_loc
93 /// section.
94 uint64_t Offset;
95 /// All the locations in which the variable is stored.
96 SmallVector<DWARFLocationEntry, 2> Entries;
97 };
98
99private:
100 using LocationLists = SmallVector<LocationList, 4>;
101
102 /// A list of all the variables in the debug_loc section, each one describing
103 /// the locations in which the variable is stored.
104 LocationLists Locations;
105
106public:
107 DWARFDebugLoc(DWARFDataExtractor Data)
108 : DWARFLocationTable(std::move(Data)) {}
109
110 /// Print the location lists found within the debug_loc section.
111 void dump(raw_ostream &OS, const DWARFObject &Obj, DIDumpOptions DumpOpts,
112 std::optional<uint64_t> Offset) const;
113
114 Error visitLocationList(
115 uint64_t *Offset,
116 function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
117
118protected:
119 void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
120 unsigned Indent, DIDumpOptions DumpOpts,
121 const DWARFObject &Obj) const override;
122};
123
124class DWARFDebugLoclists final : public DWARFLocationTable {
125public:
126 DWARFDebugLoclists(DWARFDataExtractor Data, uint16_t Version)
127 : DWARFLocationTable(std::move(Data)), Version(Version) {}
128
129 Error visitLocationList(
130 uint64_t *Offset,
131 function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
132
133 /// Dump all location lists within the given range.
134 void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS,
135 const DWARFObject &Obj, DIDumpOptions DumpOpts);
136
137protected:
138 void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
139 unsigned Indent, DIDumpOptions DumpOpts,
140 const DWARFObject &Obj) const override;
141
142private:
143 uint16_t Version;
144};
145
146class ResolverError : public ErrorInfo<ResolverError> {
147public:
148 static char ID;
149
150 ResolverError(uint32_t Index, dwarf::LoclistEntries Kind) : Index(Index), Kind(Kind) {}
151
152 void log(raw_ostream &OS) const override;
153 std::error_code convertToErrorCode() const override {
154 return llvm::errc::invalid_argument;
155 }
156
157private:
158 uint32_t Index;
159 dwarf::LoclistEntries Kind;
160};
161
162} // end namespace llvm
163
164#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
165