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