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