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
9#include "lldb/Expression/DWARFExpressionList.h"
10#include "lldb/Symbol/Function.h"
11#include "lldb/Target/RegisterContext.h"
12#include "lldb/Target/StackFrame.h"
13#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
14#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
15
16using namespace lldb;
17using namespace lldb_private;
18
19bool DWARFExpressionList::IsAlwaysValidSingleExpr() const {
20 return GetAlwaysValidExpr() != nullptr;
21}
22
23const DWARFExpression * DWARFExpressionList::GetAlwaysValidExpr() const {
24 if (m_exprs.GetSize() != 1)
25 return nullptr;
26 const auto *expr = m_exprs.GetEntryAtIndex(i: 0);
27 if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS)
28 return &expr->data;
29 return nullptr;
30}
31
32bool DWARFExpressionList::AddExpression(addr_t base, addr_t end,
33 DWARFExpression expr) {
34 if (IsAlwaysValidSingleExpr() || base >= end)
35 return false;
36 m_exprs.Append(entry: {base, end - base, expr});
37 return true;
38}
39
40bool DWARFExpressionList::GetExpressionData(DataExtractor &data,
41 lldb::addr_t func_load_addr,
42 lldb::addr_t file_addr) const {
43 if (const DWARFExpression *expr =
44 GetExpressionAtAddress(func_load_addr, load_addr: file_addr))
45 return expr->GetExpressionData(data);
46 return false;
47}
48
49bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr,
50 lldb::addr_t addr) const {
51 if (IsAlwaysValidSingleExpr())
52 return true;
53 return GetExpressionAtAddress(func_load_addr, load_addr: addr) != nullptr;
54}
55
56const DWARFExpression *
57DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr,
58 lldb::addr_t load_addr) const {
59 if (const DWARFExpression *expr = GetAlwaysValidExpr())
60 return expr;
61 if (func_load_addr == LLDB_INVALID_ADDRESS)
62 func_load_addr = m_func_file_addr;
63 addr_t addr = load_addr - func_load_addr + m_func_file_addr;
64 uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
65 if (index == UINT32_MAX)
66 return nullptr;
67 return &m_exprs.GetEntryAtIndex(i: index)->data;
68}
69
70DWARFExpression *
71DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr,
72 lldb::addr_t load_addr) {
73 if (IsAlwaysValidSingleExpr())
74 return &m_exprs.GetMutableEntryAtIndex(i: 0)->data;
75 if (func_load_addr == LLDB_INVALID_ADDRESS)
76 func_load_addr = m_func_file_addr;
77 addr_t addr = load_addr - func_load_addr + m_func_file_addr;
78 uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
79 if (index == UINT32_MAX)
80 return nullptr;
81 return &m_exprs.GetMutableEntryAtIndex(i: index)->data;
82}
83
84bool DWARFExpressionList::ContainsThreadLocalStorage() const {
85 // We are assuming for now that any thread local variable will not have a
86 // location list. This has been true for all thread local variables we have
87 // seen so far produced by any compiler.
88 if (!IsAlwaysValidSingleExpr())
89 return false;
90
91 const DWARFExpression &expr = m_exprs.GetEntryRef(i: 0).data;
92 return expr.ContainsThreadLocalStorage(dwarf_cu: m_dwarf_cu);
93}
94
95bool DWARFExpressionList::LinkThreadLocalStorage(
96 lldb::ModuleSP new_module_sp,
97 std::function<lldb::addr_t(lldb::addr_t file_addr)> const
98 &link_address_callback) {
99 // We are assuming for now that any thread local variable will not have a
100 // location list. This has been true for all thread local variables we have
101 // seen so far produced by any compiler.
102 if (!IsAlwaysValidSingleExpr())
103 return false;
104
105 DWARFExpression &expr = m_exprs.GetEntryRef(i: 0).data;
106 // If we linked the TLS address correctly, update the module so that when the
107 // expression is evaluated it can resolve the file address to a load address
108 // and read the TLS data
109 if (expr.LinkThreadLocalStorage(dwarf_cu: m_dwarf_cu, link_address_callback))
110 m_module_wp = new_module_sp;
111 return true;
112}
113
114bool DWARFExpressionList::MatchesOperand(
115 StackFrame &frame, const Instruction::Operand &operand) const {
116 RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
117 if (!reg_ctx_sp) {
118 return false;
119 }
120 const DWARFExpression *expr = nullptr;
121 if (IsAlwaysValidSingleExpr())
122 expr = &m_exprs.GetEntryAtIndex(i: 0)->data;
123 else {
124 SymbolContext sc = frame.GetSymbolContext(resolve_scope: eSymbolContextFunction);
125 if (!sc.function)
126 return false;
127
128 addr_t load_function_start = sc.function->GetAddress().GetFileAddress();
129 if (load_function_start == LLDB_INVALID_ADDRESS)
130 return false;
131
132 addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress();
133 expr = GetExpressionAtAddress(LLDB_INVALID_ADDRESS, load_addr: pc);
134 }
135 if (!expr)
136 return false;
137 return expr->MatchesOperand(frame, op: operand);
138}
139
140bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level,
141 lldb::addr_t func_load_addr,
142 lldb::addr_t file_addr,
143 ABI *abi) const {
144 llvm::raw_ostream &os = s->AsRawOstream();
145 llvm::ListSeparator separator;
146 if (const DWARFExpression *expr = GetAlwaysValidExpr()) {
147 expr->DumpLocation(s, level, abi);
148 return true;
149 }
150 for (const Entry &entry : *this) {
151 addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr;
152 addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr;
153 if (file_addr != LLDB_INVALID_ADDRESS &&
154 (file_addr < load_base || file_addr >= load_end))
155 continue;
156 const auto &expr = entry.data;
157 DataExtractor data;
158 expr.GetExpressionData(data);
159 uint32_t addr_size = data.GetAddressByteSize();
160
161 os << separator;
162 os << "[";
163 os << llvm::format_hex(N: load_base, Width: 2 + 2 * addr_size);
164 os << ", ";
165 os << llvm::format_hex(N: load_end, Width: 2 + 2 * addr_size);
166 os << ") -> ";
167 expr.DumpLocation(s, level, abi);
168 if (file_addr != LLDB_INVALID_ADDRESS)
169 break;
170 }
171 return true;
172}
173
174void DWARFExpressionList::GetDescription(Stream *s,
175 lldb::DescriptionLevel level,
176 ABI *abi) const {
177 llvm::raw_ostream &os = s->AsRawOstream();
178 if (IsAlwaysValidSingleExpr()) {
179 m_exprs.Back()->data.DumpLocation(s, level, abi);
180 return;
181 }
182 os << llvm::format(Fmt: "0x%8.8" PRIx64 ": ", Vals: 0);
183 for (const Entry &entry : *this) {
184 const auto &expr = entry.data;
185 DataExtractor data;
186 expr.GetExpressionData(data);
187 uint32_t addr_size = data.GetAddressByteSize();
188 os << "\n";
189 os.indent(NumSpaces: s->GetIndentLevel() + 2);
190 os << "[";
191 llvm::DWARFFormValue::dumpAddress(OS&: os, AddressSize: addr_size, Address: entry.GetRangeBase());
192 os << ", ";
193 llvm::DWARFFormValue::dumpAddress(OS&: os, AddressSize: addr_size, Address: entry.GetRangeEnd());
194 os << "): ";
195 expr.DumpLocation(s, level, abi);
196 }
197}
198
199llvm::Expected<Value> DWARFExpressionList::Evaluate(
200 ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
201 lldb::addr_t func_load_addr, const Value *initial_value_ptr,
202 const Value *object_address_ptr) const {
203 ModuleSP module_sp = m_module_wp.lock();
204 DataExtractor data;
205 RegisterKind reg_kind;
206 DWARFExpression expr;
207 if (IsAlwaysValidSingleExpr()) {
208 expr = m_exprs.Back()->data;
209 } else {
210 Address pc;
211 StackFrame *frame = nullptr;
212 if (!reg_ctx || !reg_ctx->GetPCForSymbolication(address&: pc)) {
213 if (exe_ctx)
214 frame = exe_ctx->GetFramePtr();
215 if (!frame)
216 return llvm::createStringError(Fmt: "no frame");
217 RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
218 if (!reg_ctx_sp)
219 return llvm::createStringError(Fmt: "no register context");
220 reg_ctx_sp->GetPCForSymbolication(address&: pc);
221 }
222
223 if (!pc.IsValid()) {
224 return llvm::createStringError(Fmt: "Invalid PC in frame.");
225 }
226 addr_t pc_load_addr = pc.GetLoadAddress(target: exe_ctx->GetTargetPtr());
227 const DWARFExpression *entry =
228 GetExpressionAtAddress(func_load_addr, load_addr: pc_load_addr);
229 if (!entry)
230 return llvm::createStringError(Fmt: "variable not available");
231 expr = *entry;
232 }
233 expr.GetExpressionData(data);
234 reg_kind = expr.GetRegisterKind();
235 return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, opcodes: data,
236 dwarf_cu: m_dwarf_cu, reg_set: reg_kind, initial_value_ptr,
237 object_address_ptr);
238}
239

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of lldb/source/Expression/DWARFExpressionList.cpp