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
20class DWARFUnit;
21
22namespace 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.
35class DWARFExpression {
36public:
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
230private:
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