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 
17 namespace llvm {
18 class DWARFUnit;
19 class MCRegisterInfo;
20 class raw_ostream;
21 class DWARFObject;
22 struct DIDumpOptions;
23 struct DWARFLocationExpression;
24 namespace object {
25 struct 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.
30 struct 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).
49 class DWARFLocationTable {
50 public:
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 
80 protected:
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 
88 class DWARFDebugLoc final : public DWARFLocationTable {
89 public:
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 
99 private:
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 
106 public:
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 
118 protected:
119   void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
120                     unsigned Indent, DIDumpOptions DumpOpts,
121                     const DWARFObject &Obj) const override;
122 };
123 
124 class DWARFDebugLoclists final : public DWARFLocationTable {
125 public:
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 
137 protected:
138   void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
139                     unsigned Indent, DIDumpOptions DumpOpts,
140                     const DWARFObject &Obj) const override;
141 
142 private:
143   uint16_t Version;
144 };
145 
146 class ResolverError : public ErrorInfo<ResolverError> {
147 public:
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 
157 private:
158   uint32_t Index;
159   dwarf::LoclistEntries Kind;
160 };
161 
162 } // end namespace llvm
163 
164 #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
165