1 //===-- DWARFExpression.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 liblldb_DWARFExpression_h_
10 #define liblldb_DWARFExpression_h_
11 
12 #include "lldb/Core/Address.h"
13 #include "lldb/Core/Disassembler.h"
14 #include "lldb/Utility/DataExtractor.h"
15 #include "lldb/Utility/Scalar.h"
16 #include "lldb/Utility/Status.h"
17 #include "lldb/lldb-private.h"
18 #include <functional>
19 
20 class DWARFUnit;
21 
22 namespace lldb_private {
23 
24 /// \class DWARFExpression DWARFExpression.h
25 /// "lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location
26 /// expression and interprets it.
27 ///
28 /// DWARF location expressions are used in two ways by LLDB.  The first
29 /// use is to find entities specified in the debug information, since their
30 /// locations are specified in precisely this language.  The second is to
31 /// interpret expressions without having to run the target in cases where the
32 /// overhead from copying JIT-compiled code into the target is too high or
33 /// where the target cannot be run.  This class encapsulates a single DWARF
34 /// location expression or a location list and interprets it.
35 class DWARFExpression {
36 public:
37   DWARFExpression();
38 
39   /// Constructor
40   ///
41   /// \param[in] data
42   ///     A data extractor configured to read the DWARF location expression's
43   ///     bytecode.
44   DWARFExpression(lldb::ModuleSP module, const DataExtractor &data,
45                   const DWARFUnit *dwarf_cu);
46 
47   /// Destructor
48   virtual ~DWARFExpression();
49 
50   /// Print the description of the expression to a stream
51   ///
52   /// \param[in] s
53   ///     The stream to print to.
54   ///
55   /// \param[in] level
56   ///     The level of verbosity to use.
57   ///
58   /// \param[in] location_list_base_addr
59   ///     If this is a location list based expression, this is the
60   ///     address of the object that owns it. NOTE: this value is
61   ///     different from the DWARF version of the location list base
62   ///     address which is compile unit relative. This base address
63   ///     is the address of the object that owns the location list.
64   ///
65   /// \param[in] abi
66   ///     An optional ABI plug-in that can be used to resolve register
67   ///     names.
68   void GetDescription(Stream *s, lldb::DescriptionLevel level,
69                       lldb::addr_t location_list_base_addr, ABI *abi) const;
70 
71   /// Return true if the location expression contains data
72   bool IsValid() const;
73 
74   /// Return true if a location list was provided
75   bool IsLocationList() const;
76 
77   /// Search for a load address in the location list
78   ///
79   /// \param[in] func_load_addr
80   ///     The actual address of the function containing this location list.
81   ///
82   /// \param[in] addr
83   ///     The address to resolve
84   ///
85   /// \return
86   ///     True if IsLocationList() is true and the address was found;
87   ///     false otherwise.
88   //    bool
89   //    LocationListContainsLoadAddress (Process* process, const Address &addr)
90   //    const;
91   //
92   bool LocationListContainsAddress(lldb::addr_t func_load_addr,
93                                    lldb::addr_t addr) const;
94 
95   /// If a location is not a location list, return true if the location
96   /// contains a DW_OP_addr () opcode in the stream that matches \a file_addr.
97   /// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true
98   /// if the variable there is any DW_OP_addr in a location that (yet still is
99   /// NOT a location list). This helps us detect if a variable is a global or
100   /// static variable since there is no other indication from DWARF debug
101   /// info.
102   ///
103   /// \param[in] op_addr_idx
104   ///     The DW_OP_addr index to retrieve in case there is more than
105   ///     one DW_OP_addr opcode in the location byte stream.
106   ///
107   /// \param[out] error
108   ///     If the location stream contains unknown DW_OP opcodes or the
109   ///     data is missing, \a error will be set to \b true.
110   ///
111   /// \return
112   ///     LLDB_INVALID_ADDRESS if the location doesn't contain a
113   ///     DW_OP_addr for \a op_addr_idx, otherwise a valid file address
114   lldb::addr_t GetLocation_DW_OP_addr(uint32_t op_addr_idx, bool &error) const;
115 
116   bool Update_DW_OP_addr(lldb::addr_t file_addr);
117 
118   void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size,
119                    uint8_t addr_byte_size);
120 
121   void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; }
122 
123   bool ContainsThreadLocalStorage() const;
124 
125   bool LinkThreadLocalStorage(
126       lldb::ModuleSP new_module_sp,
127       std::function<lldb::addr_t(lldb::addr_t file_addr)> const
128           &link_address_callback);
129 
130   /// Tells the expression that it refers to a location list.
131   ///
132   /// \param[in] cu_file_addr
133   ///     The base address to use for interpreting relative location list
134   ///     entries.
135   /// \param[in] func_file_addr
136   ///     The file address of the function containing this location list. This
137   ///     address will be used to relocate the location list on the fly (in
138   ///     conjuction with the func_load_addr arguments).
139   void SetLocationListAddresses(lldb::addr_t cu_file_addr,
140                                 lldb::addr_t func_file_addr);
141 
142   /// Return the call-frame-info style register kind
143   int GetRegisterKind();
144 
145   /// Set the call-frame-info style register kind
146   ///
147   /// \param[in] reg_kind
148   ///     The register kind.
149   void SetRegisterKind(lldb::RegisterKind reg_kind);
150 
151   /// Wrapper for the static evaluate function that accepts an
152   /// ExecutionContextScope instead of an ExecutionContext and uses member
153   /// variables to populate many operands
154   bool Evaluate(ExecutionContextScope *exe_scope, lldb::addr_t func_load_addr,
155                 const Value *initial_value_ptr, const Value *object_address_ptr,
156                 Value &result, Status *error_ptr) const;
157 
158   /// Wrapper for the static evaluate function that uses member variables to
159   /// populate many operands
160   bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
161                 lldb::addr_t loclist_base_load_addr,
162                 const Value *initial_value_ptr, const Value *object_address_ptr,
163                 Value &result, Status *error_ptr) const;
164 
165   /// Evaluate a DWARF location expression in a particular context
166   ///
167   /// \param[in] exe_ctx
168   ///     The execution context in which to evaluate the location
169   ///     expression.  The location expression may access the target's
170   ///     memory, especially if it comes from the expression parser.
171   ///
172   /// \param[in] opcode_ctx
173   ///     The module which defined the expression.
174   ///
175   /// \param[in] opcodes
176   ///     This is a static method so the opcodes need to be provided
177   ///     explicitly.
178   ///
179   ///  \param[in] reg_ctx
180   ///     An optional parameter which provides a RegisterContext for use
181   ///     when evaluating the expression (i.e. for fetching register values).
182   ///     Normally this will come from the ExecutionContext's StackFrame but
183   ///     in the case where an expression needs to be evaluated while building
184   ///     the stack frame list, this short-cut is available.
185   ///
186   /// \param[in] reg_set
187   ///     The call-frame-info style register kind.
188   ///
189   /// \param[in] initial_value_ptr
190   ///     A value to put on top of the interpreter stack before evaluating
191   ///     the expression, if the expression is parametrized.  Can be NULL.
192   ///
193   /// \param[in] result
194   ///     A value into which the result of evaluating the expression is
195   ///     to be placed.
196   ///
197   /// \param[in] error_ptr
198   ///     If non-NULL, used to report errors in expression evaluation.
199   ///
200   /// \return
201   ///     True on success; false otherwise.  If error_ptr is non-NULL,
202   ///     details of the failure are provided through it.
203   static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
204                        lldb::ModuleSP opcode_ctx, const DataExtractor &opcodes,
205                        const DWARFUnit *dwarf_cu,
206                        const lldb::RegisterKind reg_set,
207                        const Value *initial_value_ptr,
208                        const Value *object_address_ptr, Value &result,
209                        Status *error_ptr);
210 
211   bool GetExpressionData(DataExtractor &data) const {
212     data = m_data;
213     return data.GetByteSize() > 0;
214   }
215 
216   bool DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level,
217                               lldb::addr_t func_load_addr, lldb::addr_t address,
218                               ABI *abi);
219 
220   static bool PrintDWARFExpression(Stream &s, const DataExtractor &data,
221                                    int address_size, int dwarf_ref_size,
222                                    bool location_expression);
223 
224   static void PrintDWARFLocationList(Stream &s, const DWARFUnit *cu,
225                                      const DataExtractor &debug_loc_data,
226                                      lldb::offset_t offset);
227 
228   bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op);
229 
230 private:
231   /// Pretty-prints the location expression to a stream
232   ///
233   /// \param[in] s
234   ///     The stream to use for pretty-printing.
235   ///
236   /// \param[in] offset
237   ///     The offset into the data buffer of the opcodes to be printed.
238   ///
239   /// \param[in] length
240   ///     The length in bytes of the opcodes to be printed.
241   ///
242   /// \param[in] level
243   ///     The level of detail to use in pretty-printing.
244   ///
245   /// \param[in] abi
246   ///     An optional ABI plug-in that can be used to resolve register
247   ///     names.
248   void DumpLocation(Stream *s, const DataExtractor &data,
249                     lldb::DescriptionLevel level, ABI *abi) const;
250 
251   llvm::Optional<DataExtractor>
252   GetLocationExpression(lldb::addr_t load_function_start,
253                         lldb::addr_t addr) const;
254 
255   /// Module which defined this expression.
256   lldb::ModuleWP m_module_wp;
257 
258   /// A data extractor capable of reading opcode bytes
259   DataExtractor m_data;
260 
261   /// The DWARF compile unit this expression belongs to. It is used to evaluate
262   /// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index,
263   /// DW_OP_GNU_const_index)
264   const DWARFUnit *m_dwarf_cu;
265 
266   /// One of the defines that starts with LLDB_REGKIND_
267   lldb::RegisterKind m_reg_kind;
268 
269   struct LoclistAddresses {
270     lldb::addr_t cu_file_addr;
271     lldb::addr_t func_file_addr;
272   };
273   llvm::Optional<LoclistAddresses> m_loclist_addresses;
274 };
275 
276 } // namespace lldb_private
277 
278 #endif // liblldb_DWARFExpression_h_
279