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