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#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16
17using namespace lldb;
18using namespace lldb_private;
19
21 return GetAlwaysValidExpr() != nullptr;
22}
23
25 if (m_exprs.GetSize() != 1)
26 return nullptr;
27 const auto *expr = m_exprs.GetEntryAtIndex(0);
28 if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS)
29 return &expr->data;
30 return nullptr;
31}
32
34 DWARFExpression expr) {
35 if (IsAlwaysValidSingleExpr() || base >= end)
36 return false;
37 m_exprs.Append({base, end - base, expr});
38 return true;
39}
40
42 lldb::addr_t func_load_addr,
43 lldb::addr_t file_addr) const {
44 if (const DWARFExpression *expr =
45 GetExpressionAtAddress(func_load_addr, file_addr))
46 return expr->GetExpressionData(data);
47 return false;
48}
49
51 lldb::addr_t addr) const {
53 return true;
54 return GetExpressionAtAddress(func_load_addr, addr) != nullptr;
55}
56
57std::optional<DWARFExpressionList::DWARFExpressionEntry>
59 lldb::addr_t load_addr) const {
60 if (const DWARFExpression *always = GetAlwaysValidExpr()) {
61 return DWARFExpressionEntry{std::nullopt, always};
62 }
63
64 if (func_load_addr == LLDB_INVALID_ADDRESS)
65 func_load_addr = m_func_file_addr;
66
67 // Guard against underflow when translating a load address back into file
68 // space.
69 if (load_addr < func_load_addr)
70 return std::nullopt;
71
72 // Guard against overflow.
73 lldb::addr_t delta = load_addr - func_load_addr;
74 if (delta > std::numeric_limits<lldb::addr_t>::max() - m_func_file_addr)
75 return std::nullopt;
76
77 lldb::addr_t file_pc = (load_addr - func_load_addr) + m_func_file_addr;
78
79 if (const auto *entry = m_exprs.FindEntryThatContains(file_pc)) {
80 AddressRange range_in_file(entry->GetRangeBase(),
81 entry->GetRangeEnd() - entry->GetRangeBase());
82 return DWARFExpressionEntry{range_in_file, &entry->data};
83 }
84
85 // No entry covers this PC:
86 return std::nullopt;
87}
88
89const DWARFExpression *
91 lldb::addr_t load_addr) const {
92 if (const DWARFExpression *expr = GetAlwaysValidExpr())
93 return expr;
94 if (func_load_addr == LLDB_INVALID_ADDRESS)
95 func_load_addr = m_func_file_addr;
96 addr_t addr = load_addr - func_load_addr + m_func_file_addr;
97 uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
98 if (index == UINT32_MAX)
99 return nullptr;
100 return &m_exprs.GetEntryAtIndex(index)->data;
101}
102
105 lldb::addr_t load_addr) {
107 return &m_exprs.GetMutableEntryAtIndex(0)->data;
108 if (func_load_addr == LLDB_INVALID_ADDRESS)
109 func_load_addr = m_func_file_addr;
110 addr_t addr = load_addr - func_load_addr + m_func_file_addr;
111 uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
112 if (index == UINT32_MAX)
113 return nullptr;
114 return &m_exprs.GetMutableEntryAtIndex(index)->data;
115}
116
118 // We are assuming for now that any thread local variable will not have a
119 // location list. This has been true for all thread local variables we have
120 // seen so far produced by any compiler.
122 return false;
123
124 const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
126}
127
129 lldb::ModuleSP new_module_sp,
130 std::function<lldb::addr_t(lldb::addr_t file_addr)> const
131 &link_address_callback) {
132 // We are assuming for now that any thread local variable will not have a
133 // location list. This has been true for all thread local variables we have
134 // seen so far produced by any compiler.
136 return false;
137
138 DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
139 // If we linked the TLS address correctly, update the module so that when the
140 // expression is evaluated it can resolve the file address to a load address
141 // and read the TLS data
142 if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback))
143 m_module_wp = new_module_sp;
144 return true;
145}
146
148 StackFrame &frame, const Instruction::Operand &operand) const {
149 RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
150 if (!reg_ctx_sp) {
151 return false;
152 }
153 const DWARFExpression *expr = nullptr;
155 expr = &m_exprs.GetEntryAtIndex(0)->data;
156 else {
157 SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
158 if (!sc.function)
159 return false;
160
161 addr_t load_function_start = sc.function->GetAddress().GetFileAddress();
162 if (load_function_start == LLDB_INVALID_ADDRESS)
163 return false;
164
167 }
168 if (!expr)
169 return false;
170 return expr->MatchesOperand(frame, operand);
171}
172
174 lldb::addr_t func_load_addr,
175 lldb::addr_t file_addr,
176 ABI *abi) const {
177 llvm::raw_ostream &os = s->AsRawOstream();
178 llvm::ListSeparator separator;
179 if (const DWARFExpression *expr = GetAlwaysValidExpr()) {
180 expr->DumpLocation(s, level, abi);
181 return true;
182 }
183 for (const Entry &entry : *this) {
184 addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr;
185 addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr;
186 if (file_addr != LLDB_INVALID_ADDRESS &&
187 (file_addr < load_base || file_addr >= load_end))
188 continue;
189 const auto &expr = entry.data;
190 DataExtractor data;
191 expr.GetExpressionData(data);
192 uint32_t addr_size = data.GetAddressByteSize();
193
194 os << separator;
195 os << "[";
196 os << llvm::format_hex(load_base, 2 + 2 * addr_size);
197 os << ", ";
198 os << llvm::format_hex(load_end, 2 + 2 * addr_size);
199 os << ") -> ";
200 expr.DumpLocation(s, level, abi);
201 if (file_addr != LLDB_INVALID_ADDRESS)
202 break;
203 }
204 return true;
205}
206
209 ABI *abi) const {
210 llvm::raw_ostream &os = s->AsRawOstream();
212 m_exprs.Back()->data.DumpLocation(s, level, abi);
213 return;
214 }
215 os << llvm::format("0x%8.8" PRIx64 ": ", 0);
216 for (const Entry &entry : *this) {
217 const auto &expr = entry.data;
218 DataExtractor data;
219 expr.GetExpressionData(data);
220 uint32_t addr_size = data.GetAddressByteSize();
221 os << "\n";
222 os.indent(s->GetIndentLevel() + 2);
223 os << "[";
224 llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase());
225 os << ", ";
226 llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd());
227 os << "): ";
228 expr.DumpLocation(s, level, abi);
229 }
230}
231
232llvm::Expected<Value> DWARFExpressionList::Evaluate(
233 ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
234 lldb::addr_t func_load_addr, const Value *initial_value_ptr,
235 const Value *object_address_ptr) const {
236 ModuleSP module_sp = m_module_wp.lock();
237 DataExtractor data;
238 RegisterKind reg_kind;
239 DWARFExpression expr;
241 expr = m_exprs.Back()->data;
242 } else {
243 Address pc;
244 StackFrame *frame = nullptr;
245 if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {
246 if (exe_ctx)
247 frame = exe_ctx->GetFramePtr();
248 if (!frame)
249 return llvm::createStringError("no frame");
250 RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
251 if (!reg_ctx_sp)
252 return llvm::createStringError("no register context");
253 reg_ctx_sp->GetPCForSymbolication(pc);
254 }
255
256 if (!pc.IsValid()) {
257 return llvm::createStringError("invalid PC in frame");
258 }
259 addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr());
260 const DWARFExpression *entry =
261 GetExpressionAtAddress(func_load_addr, pc_load_addr);
262 if (!entry)
263 return llvm::createStringError("variable not available");
264 expr = *entry;
265 }
266 expr.GetExpressionData(data);
267 reg_kind = expr.GetRegisterKind();
268 return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data,
269 m_dwarf_cu, reg_kind, initial_value_ptr,
270 object_address_ptr);
271}
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:281
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 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.
bool GetExpressionData(DataExtractor &data) const
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
lldb::RegisterKind GetRegisterKind() const
Return the call-frame-info style register kind.
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:453
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:406
unsigned GetIndentLevel() const
Get the current indentation level.
Definition Stream.cpp:187
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