LLDB mainline
DWARFExpressionList.cpp
Go to the documentation of this file.
1//===-- DWARFExpressionList.cpp -------------------------------------------===//
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
14#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
15
16using namespace lldb;
17using namespace lldb_private;
18
19/// Format \p addr as a zero-padded hex address of \p addr_size bytes.
20static llvm::FormattedNumber FormatAddress(uint64_t addr, uint32_t addr_size) {
21 // The width passed to format_hex includes the "0x" prefix, followed by two
22 // hex digits per byte.
23 return llvm::format_hex(addr, 2 + 2 * addr_size);
24}
25
27 return GetAlwaysValidExpr() != nullptr;
28}
29
31 if (m_exprs.GetSize() != 1)
32 return nullptr;
33 const auto *expr = m_exprs.GetEntryAtIndex(0);
34 if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS)
35 return &expr->data;
36 return nullptr;
37}
38
40 DWARFExpression expr) {
41 if (IsAlwaysValidSingleExpr() || base >= end)
42 return false;
43 m_exprs.Append({base, end - base, expr});
44 return true;
45}
46
48 lldb::addr_t func_load_addr,
49 lldb::addr_t file_addr) const {
50 if (const DWARFExpression *expr =
51 GetExpressionAtAddress(func_load_addr, file_addr))
52 return expr->GetExpressionData(data);
53 return false;
54}
55
57 lldb::addr_t addr) const {
59 return true;
60 return GetExpressionAtAddress(func_load_addr, addr) != nullptr;
61}
62
63std::optional<DWARFExpressionList::DWARFExpressionEntry>
65 lldb::addr_t load_addr) const {
66 if (const DWARFExpression *always = GetAlwaysValidExpr()) {
67 return DWARFExpressionEntry{std::nullopt, always};
68 }
69
70 if (func_load_addr == LLDB_INVALID_ADDRESS)
71 func_load_addr = m_func_file_addr;
72
73 // Guard against underflow when translating a load address back into file
74 // space.
75 if (load_addr < func_load_addr)
76 return std::nullopt;
77
78 // Guard against overflow.
79 lldb::addr_t delta = load_addr - func_load_addr;
80 if (delta > std::numeric_limits<lldb::addr_t>::max() - m_func_file_addr)
81 return std::nullopt;
82
83 lldb::addr_t file_pc = (load_addr - func_load_addr) + m_func_file_addr;
84
85 if (const auto *entry = m_exprs.FindEntryThatContains(file_pc)) {
86 AddressRange range_in_file(entry->GetRangeBase(),
87 entry->GetRangeEnd() - entry->GetRangeBase());
88 return DWARFExpressionEntry{range_in_file, &entry->data};
89 }
90
91 // No entry covers this PC:
92 return std::nullopt;
93}
94
95const DWARFExpression *
97 lldb::addr_t load_addr) const {
98 if (const DWARFExpression *expr = GetAlwaysValidExpr())
99 return expr;
100 if (func_load_addr == LLDB_INVALID_ADDRESS)
101 func_load_addr = m_func_file_addr;
102 addr_t addr = load_addr - func_load_addr + m_func_file_addr;
103 uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
104 if (index == UINT32_MAX)
105 return nullptr;
106 return &m_exprs.GetEntryAtIndex(index)->data;
107}
108
111 lldb::addr_t load_addr) {
113 return &m_exprs.GetMutableEntryAtIndex(0)->data;
114 if (func_load_addr == LLDB_INVALID_ADDRESS)
115 func_load_addr = m_func_file_addr;
116 addr_t addr = load_addr - func_load_addr + m_func_file_addr;
117 uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
118 if (index == UINT32_MAX)
119 return nullptr;
120 return &m_exprs.GetMutableEntryAtIndex(index)->data;
121}
122
124 // We are assuming for now that any thread local variable will not have a
125 // location list. This has been true for all thread local variables we have
126 // seen so far produced by any compiler.
128 return false;
129
130 const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
132}
133
135 lldb::ModuleSP new_module_sp,
136 std::function<lldb::addr_t(lldb::addr_t file_addr)> const
137 &link_address_callback) {
138 // We are assuming for now that any thread local variable will not have a
139 // location list. This has been true for all thread local variables we have
140 // seen so far produced by any compiler.
142 return false;
143
144 DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
145 // If we linked the TLS address correctly, update the module so that when the
146 // expression is evaluated it can resolve the file address to a load address
147 // and read the TLS data
148 if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback))
149 m_module_wp = new_module_sp;
150 return true;
151}
152
154 StackFrame &frame, const Instruction::Operand &operand) const {
155 RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
156 if (!reg_ctx_sp) {
157 return false;
158 }
159 const DWARFExpression *expr = nullptr;
161 expr = &m_exprs.GetEntryAtIndex(0)->data;
162 else {
163 SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
164 if (!sc.function)
165 return false;
166
167 addr_t load_function_start = sc.function->GetAddress().GetFileAddress();
168 if (load_function_start == LLDB_INVALID_ADDRESS)
169 return false;
170
173 }
174 if (!expr)
175 return false;
176 return expr->MatchesOperand(frame, operand);
177}
178
180 lldb::addr_t func_load_addr,
181 lldb::addr_t file_addr,
182 ABI *abi) const {
183 llvm::raw_ostream &os = s->AsRawOstream();
184 llvm::ListSeparator separator;
185 if (const DWARFExpression *expr = GetAlwaysValidExpr()) {
186 expr->DumpLocation(s, level, abi);
187 return true;
188 }
189 for (const Entry &entry : *this) {
190 addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr;
191 addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr;
192 if (file_addr != LLDB_INVALID_ADDRESS &&
193 (file_addr < load_base || file_addr >= load_end))
194 continue;
195 const auto &expr = entry.data;
196 DataExtractor data;
197 expr.GetExpressionData(data);
198 uint32_t addr_size = data.GetAddressByteSize();
199
200 os << separator;
201 os << "[";
202 os << FormatAddress(load_base, addr_size);
203 os << ", ";
204 os << FormatAddress(load_end, addr_size);
205 os << ") -> ";
206 expr.DumpLocation(s, level, abi);
207 if (file_addr != LLDB_INVALID_ADDRESS)
208 break;
209 }
210 return true;
211}
212
215 ABI *abi) const {
216 llvm::raw_ostream &os = s->AsRawOstream();
218 m_exprs.Back()->data.DumpLocation(s, level, abi);
219 return;
220 }
221 os << llvm::format("0x%8.8" PRIx64 ": ", 0);
222 for (const Entry &entry : *this) {
223 const auto &expr = entry.data;
224 DataExtractor data;
225 expr.GetExpressionData(data);
226 uint32_t addr_size = data.GetAddressByteSize();
227 os << "\n";
228 os.indent(s->GetIndentLevel() + 2);
229 os << "[";
230 os << FormatAddress(entry.GetRangeBase(), addr_size);
231 os << ", ";
232 os << FormatAddress(entry.GetRangeEnd(), addr_size);
233 os << "): ";
234 expr.DumpLocation(s, level, abi);
235 }
236}
237
238llvm::Expected<const DWARFExpression *>
240 RegisterContext *reg_ctx,
241 lldb::addr_t func_load_addr) const {
242 if (const DWARFExpression *always = GetAlwaysValidExpr())
243 return always;
244
245 Address pc;
246 StackFrame *frame = nullptr;
247 if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {
248 if (exe_ctx)
249 frame = exe_ctx->GetFramePtr();
250 if (!frame)
251 return llvm::createStringError("no frame");
252 RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
253 if (!reg_ctx_sp)
254 return llvm::createStringError("no register context");
255 reg_ctx_sp->GetPCForSymbolication(pc);
256 }
257
258 if (!pc.IsValid())
259 return llvm::createStringError("invalid PC in frame");
260
261 addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr());
262 const DWARFExpression *entry =
263 GetExpressionAtAddress(func_load_addr, pc_load_addr);
264 if (!entry)
265 return llvm::createStringError("variable not available");
266 return entry;
267}
268
269llvm::Expected<Value> DWARFExpressionList::Evaluate(
270 ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
271 lldb::addr_t func_load_addr, const Value *initial_value_ptr,
272 const Value *object_address_ptr) const {
273 llvm::Expected<const DWARFExpression *> expr =
274 GetExpressionAtPC(exe_ctx, reg_ctx, func_load_addr);
275 if (!expr)
276 return expr.takeError();
277
278 ModuleSP module_sp = m_module_wp.lock();
279 DataExtractor data;
280 (*expr)->GetExpressionData(data);
281 RegisterKind reg_kind = (*expr)->GetRegisterKind();
282 return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data,
283 m_dwarf_cu, reg_kind, initial_value_ptr,
284 object_address_ptr);
285}
286
288 RegisterContext *reg_ctx,
289 lldb::addr_t func_load_addr) const {
290 llvm::Expected<const DWARFExpression *> expr =
291 GetExpressionAtPC(exe_ctx, reg_ctx, func_load_addr);
292 if (!expr) {
293 // No location in scope, so nothing to write back to.
294 llvm::consumeError(expr.takeError());
295 return true;
296 }
297 return (*expr)->IsImplicit(m_dwarf_cu);
298}
static llvm::FormattedNumber FormatAddress(uint64_t addr, uint32_t addr_size)
Format addr as a zero-padded hex address of addr_size bytes.
A section + offset based address range class.
A section + offset based address class.
Definition Address.h:62
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:283
llvm::Expected< const DWARFExpression * > GetExpressionAtPC(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::addr_t func_load_addr) const
Return the expression in scope at the current PC, or an error if no location is in scope.
bool AddExpression(lldb::addr_t base, lldb::addr_t end, DWARFExpression expr)
const DWARFExpression * GetExpressionAtAddress(lldb::addr_t func_load_addr, lldb::addr_t load_addr) const
const DWARFExpression::Delegate * m_dwarf_cu
The DWARF compile unit this expression belongs to.
void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const
Dump all locaitons with each separated by new line.
bool IsImplicit(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::addr_t func_load_addr) const
Return true if the expression in scope at the current PC produces an implicit location,...
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &operand) const
llvm::Expected< Value > Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::addr_t func_load_addr, const Value *initial_value_ptr, const Value *object_address_ptr) const
const DWARFExpression * GetAlwaysValidExpr() const
lldb::ModuleWP m_module_wp
Module which defined this expression.
bool GetExpressionData(DataExtractor &data, lldb::addr_t func_load_addr=LLDB_INVALID_ADDRESS, lldb::addr_t file_addr=0) const
Get the expression data at the file address.
std::optional< DWARFExpressionEntry > GetExpressionEntryAtAddress(lldb::addr_t func_load_addr, lldb::addr_t load_addr) const
Returns a DWARFExpressionEntry whose file_range contains the given load‐address.
bool DumpLocations(Stream *s, lldb::DescriptionLevel level, lldb::addr_t func_load_addr, lldb::addr_t file_addr, ABI *abi) const
Dump locations that contains file_addr if it's valid.
bool LinkThreadLocalStorage(lldb::ModuleSP new_module_sp, std::function< lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback)
bool ContainsAddress(lldb::addr_t func_load_addr, lldb::addr_t addr) const
Search for a load address in the dwarf location list.
DWARFExpression * GetMutableExpressionAtAddress(lldb::addr_t func_load_addr=LLDB_INVALID_ADDRESS, lldb::addr_t load_addr=0)
"lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location expression and interprets it.
static llvm::Expected< Value > Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::ModuleSP module_sp, const DataExtractor &opcodes, const Delegate *dwarf_cu, const lldb::RegisterKind reg_set, const Value *initial_value_ptr, const Value *object_address_ptr)
Evaluate a DWARF location expression in a particular context.
bool ContainsThreadLocalStorage(const Delegate *dwarf_cu) const
bool LinkThreadLocalStorage(const Delegate *dwarf_cu, std::function< lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback)
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const
An data extractor class.
uint32_t GetAddressByteSize() const
Get the current address size.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
Target * GetTargetPtr() const
Returns a pointer to the target object.
const Address & GetAddress() const
Return the address of the function (its entry point).
Definition Function.h:439
bool GetPCForSymbolication(Address &address)
Get an address suitable for symbolication.
This base class provides an interface to stack frames.
Definition StackFrame.h:44
virtual lldb::RegisterContextSP GetRegisterContext()
Get the RegisterContext for this frame, if possible.
virtual Address GetFrameCodeAddressForSymbolication()
Get the current code Address suitable for symbolication, may not be the same as GetFrameCodeAddress()...
virtual const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
A stream class that can stream formatted output to a file.
Definition Stream.h:28
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition Stream.h:405
unsigned GetIndentLevel() const
Get the current indentation level.
Definition Stream.cpp:193
Defines a symbol context baton that can be handed other debug core functions.
Function * function
The Function for a given query.
#define LLDB_INVALID_ADDRESS
#define UINT32_MAX
A class that represents a running process on the host machine.
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
std::shared_ptr< lldb_private::Module > ModuleSP
RegisterKind
Register numbering types.
Represents an entry in the DWARFExpressionList with all needed metadata.
BaseType GetRangeBase() const
Definition RangeMap.h:45
BaseType GetRangeEnd() const
Definition RangeMap.h:78