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