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   const DWARFDataExtractor &getData() { return Data; }
76 
77 protected:
78   DWARFDataExtractor Data;
79 
80   virtual void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
81                             unsigned Indent, DIDumpOptions DumpOpts,
82                             const DWARFObject &Obj) const = 0;
83 };
84 
85 class DWARFDebugLoc final : public DWARFLocationTable {
86 public:
87   /// A list of locations that contain one variable.
88   struct LocationList {
89     /// The beginning offset where this location list is stored in the debug_loc
90     /// section.
91     uint64_t Offset;
92     /// All the locations in which the variable is stored.
93     SmallVector<DWARFLocationEntry, 2> Entries;
94   };
95 
96 private:
97   using LocationLists = SmallVector<LocationList, 4>;
98 
99   /// A list of all the variables in the debug_loc section, each one describing
100   /// the locations in which the variable is stored.
101   LocationLists Locations;
102 
103 public:
104   DWARFDebugLoc(DWARFDataExtractor Data)
105       : DWARFLocationTable(std::move(Data)) {}
106 
107   /// Print the location lists found within the debug_loc section.
108   void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo,
109             const DWARFObject &Obj, DIDumpOptions DumpOpts,
110             Optional<uint64_t> Offset) const;
111 
112   Error visitLocationList(
113       uint64_t *Offset,
114       function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
115 
116 protected:
117   void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
118                     unsigned Indent, DIDumpOptions DumpOpts,
119                     const DWARFObject &Obj) const override;
120 };
121 
122 class DWARFDebugLoclists final : public DWARFLocationTable {
123 public:
124   DWARFDebugLoclists(DWARFDataExtractor Data, uint16_t Version)
125       : DWARFLocationTable(std::move(Data)), Version(Version) {}
126 
127   Error visitLocationList(
128       uint64_t *Offset,
129       function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
130 
131   /// Dump all location lists within the given range.
132   void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS,
133                  const MCRegisterInfo *MRI, const DWARFObject &Obj,
134                  DIDumpOptions DumpOpts);
135 
136 protected:
137   void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
138                     unsigned Indent, DIDumpOptions DumpOpts,
139                     const DWARFObject &Obj) const override;
140 
141 private:
142   uint16_t Version;
143 };
144 
145 } // end namespace llvm
146 
147 #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
148