1 //===-- DWARFExpression.h ---------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef liblldb_DWARFExpression_h_
10 #define liblldb_DWARFExpression_h_
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"
22 namespace lldb_private {
24 /// \class DWARFExpression DWARFExpression.h
25 /// "lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location
26 /// expression and interprets it.
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 {
37 enum LocationListFormat : uint8_t {
38 NonLocationList, // Not a location list
39 RegularLocationList, // Location list format used in non-split dwarf files
40 SplitDwarfLocationList, // Location list format used in pre-DWARF v5 split
41 // dwarf files (.debug_loc.dwo)
42 LocLists, // Location list format used in DWARF v5
43 // (.debug_loclists/.debug_loclists.dwo).
51 /// A data extractor configured to read the DWARF location expression's
54 /// \param[in] data_offset
55 /// The offset of the location expression in the extractor.
57 /// \param[in] data_length
58 /// The byte length of the location expression.
59 DWARFExpression(lldb::ModuleSP module, const DataExtractor &data,
60 const DWARFUnit *dwarf_cu, lldb::offset_t data_offset,
61 lldb::offset_t data_length);
64 virtual ~DWARFExpression();
66 /// Print the description of the expression to a stream
69 /// The stream to print to.
72 /// The level of verbosity to use.
74 /// \param[in] location_list_base_addr
75 /// If this is a location list based expression, this is the
76 /// address of the object that owns it. NOTE: this value is
77 /// different from the DWARF version of the location list base
78 /// address which is compile unit relative. This base address
79 /// is the address of the object that owns the location list.
82 /// An optional ABI plug-in that can be used to resolve register
84 void GetDescription(Stream *s, lldb::DescriptionLevel level,
85 lldb::addr_t location_list_base_addr, ABI *abi) const;
87 /// Return true if the location expression contains data
90 /// Return true if a location list was provided
91 bool IsLocationList() const;
93 /// Search for a load address in the location list
95 /// \param[in] process
96 /// The process to use when resolving the load address
99 /// The address to resolve
102 /// True if IsLocationList() is true and the address was found;
105 // LocationListContainsLoadAddress (Process* process, const Address &addr)
108 bool LocationListContainsAddress(lldb::addr_t loclist_base_addr,
109 lldb::addr_t addr) const;
111 /// If a location is not a location list, return true if the location
112 /// contains a DW_OP_addr () opcode in the stream that matches \a file_addr.
113 /// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true
114 /// if the variable there is any DW_OP_addr in a location that (yet still is
115 /// NOT a location list). This helps us detect if a variable is a global or
116 /// static variable since there is no other indication from DWARF debug
119 /// \param[in] op_addr_idx
120 /// The DW_OP_addr index to retrieve in case there is more than
121 /// one DW_OP_addr opcode in the location byte stream.
123 /// \param[out] error
124 /// If the location stream contains unknown DW_OP opcodes or the
125 /// data is missing, \a error will be set to \b true.
128 /// LLDB_INVALID_ADDRESS if the location doesn't contain a
129 /// DW_OP_addr for \a op_addr_idx, otherwise a valid file address
130 lldb::addr_t GetLocation_DW_OP_addr(uint32_t op_addr_idx, bool &error) const;
132 bool Update_DW_OP_addr(lldb::addr_t file_addr);
134 void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size,
135 uint8_t addr_byte_size);
137 void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; }
139 bool ContainsThreadLocalStorage() const;
141 bool LinkThreadLocalStorage(
142 lldb::ModuleSP new_module_sp,
143 std::function<lldb::addr_t(lldb::addr_t file_addr)> const
144 &link_address_callback);
146 /// Tells the expression that it refers to a location list.
149 /// This value should be a slide that is applied to any values
150 /// in the location list data so the values become zero based
151 /// offsets into the object that owns the location list. We need
152 /// to make location lists relative to the objects that own them
153 /// so we can relink addresses on the fly.
154 void SetLocationListSlide(lldb::addr_t slide);
156 /// Return the call-frame-info style register kind
157 int GetRegisterKind();
159 /// Set the call-frame-info style register kind
161 /// \param[in] reg_kind
162 /// The register kind.
163 void SetRegisterKind(lldb::RegisterKind reg_kind);
165 /// Wrapper for the static evaluate function that accepts an
166 /// ExecutionContextScope instead of an ExecutionContext and uses member
167 /// variables to populate many operands
168 bool Evaluate(ExecutionContextScope *exe_scope,
169 lldb::addr_t loclist_base_load_addr,
170 const Value *initial_value_ptr, const Value *object_address_ptr,
171 Value &result, Status *error_ptr) const;
173 /// Wrapper for the static evaluate function that uses member variables to
174 /// populate many operands
175 bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
176 lldb::addr_t loclist_base_load_addr,
177 const Value *initial_value_ptr, const Value *object_address_ptr,
178 Value &result, Status *error_ptr) const;
180 /// Evaluate a DWARF location expression in a particular context
182 /// \param[in] exe_ctx
183 /// The execution context in which to evaluate the location
184 /// expression. The location expression may access the target's
185 /// memory, especially if it comes from the expression parser.
187 /// \param[in] opcode_ctx
188 /// The module which defined the expression.
190 /// \param[in] opcodes
191 /// This is a static method so the opcodes need to be provided
194 /// \param[in] expr_locals
195 /// If the location expression was produced by the expression parser,
196 /// the list of local variables referenced by the DWARF expression.
197 /// This list should already have been populated during parsing;
198 /// the DWARF expression refers to variables by index. Can be NULL if
199 /// the location expression uses no locals.
201 /// \param[in] decl_map
202 /// If the location expression was produced by the expression parser,
203 /// the list of external variables referenced by the location
204 /// expression. Can be NULL if the location expression uses no
205 /// external variables.
207 /// \param[in] reg_ctx
208 /// An optional parameter which provides a RegisterContext for use
209 /// when evaluating the expression (i.e. for fetching register values).
210 /// Normally this will come from the ExecutionContext's StackFrame but
211 /// in the case where an expression needs to be evaluated while building
212 /// the stack frame list, this short-cut is available.
214 /// \param[in] offset
215 /// The offset of the location expression in the data extractor.
217 /// \param[in] length
218 /// The length in bytes of the location expression.
220 /// \param[in] reg_set
221 /// The call-frame-info style register kind.
223 /// \param[in] initial_value_ptr
224 /// A value to put on top of the interpreter stack before evaluating
225 /// the expression, if the expression is parametrized. Can be NULL.
227 /// \param[in] result
228 /// A value into which the result of evaluating the expression is
231 /// \param[in] error_ptr
232 /// If non-NULL, used to report errors in expression evaluation.
235 /// True on success; false otherwise. If error_ptr is non-NULL,
236 /// details of the failure are provided through it.
237 static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
238 lldb::ModuleSP opcode_ctx, const DataExtractor &opcodes,
239 const DWARFUnit *dwarf_cu, const lldb::offset_t offset,
240 const lldb::offset_t length,
241 const lldb::RegisterKind reg_set,
242 const Value *initial_value_ptr,
243 const Value *object_address_ptr, Value &result,
246 bool GetExpressionData(DataExtractor &data) const {
248 return data.GetByteSize() > 0;
251 bool DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level,
252 lldb::addr_t loclist_base_load_addr,
253 lldb::addr_t address, ABI *abi);
255 static size_t LocationListSize(const DWARFUnit *dwarf_cu,
256 const DataExtractor &debug_loc_data,
257 lldb::offset_t offset);
259 static bool PrintDWARFExpression(Stream &s, const DataExtractor &data,
260 int address_size, int dwarf_ref_size,
261 bool location_expression);
263 static void PrintDWARFLocationList(Stream &s, const DWARFUnit *cu,
264 const DataExtractor &debug_loc_data,
265 lldb::offset_t offset);
267 bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op);
270 /// Pretty-prints the location expression to a stream
272 /// \param[in] stream
273 /// The stream to use for pretty-printing.
275 /// \param[in] offset
276 /// The offset into the data buffer of the opcodes to be printed.
278 /// \param[in] length
279 /// The length in bytes of the opcodes to be printed.
282 /// The level of detail to use in pretty-printing.
285 /// An optional ABI plug-in that can be used to resolve register
287 void DumpLocation(Stream *s, lldb::offset_t offset, lldb::offset_t length,
288 lldb::DescriptionLevel level, ABI *abi) const;
290 bool GetLocation(lldb::addr_t base_addr, lldb::addr_t pc,
291 lldb::offset_t &offset, lldb::offset_t &len);
293 static bool AddressRangeForLocationListEntry(
294 const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data,
295 lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc);
297 bool GetOpAndEndOffsets(StackFrame &frame, lldb::offset_t &op_offset,
298 lldb::offset_t &end_offset);
300 /// Module which defined this expression.
301 lldb::ModuleWP m_module_wp;
303 /// A data extractor capable of reading opcode bytes
304 DataExtractor m_data;
306 /// The DWARF compile unit this expression belongs to. It is used to evaluate
307 /// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index,
308 /// DW_OP_GNU_const_index)
309 const DWARFUnit *m_dwarf_cu;
311 /// One of the defines that starts with LLDB_REGKIND_
312 lldb::RegisterKind m_reg_kind;
314 /// A value used to slide the location list offsets so that m_c they are
315 /// relative to the object that owns the location list (the function for
316 /// frame base and variable location lists)
317 lldb::addr_t m_loclist_slide;
320 } // namespace lldb_private
322 #endif // liblldb_DWARFExpression_h_