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 
11 #include "lldb/Symbol/Function.h"
13 #include "lldb/Target/StackFrame.h"
14 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
15 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 bool DWARFExpressionList::IsAlwaysValidSingleExpr() const {
21  return GetAlwaysValidExpr() != nullptr;
22 }
23 
24 const DWARFExpression * DWARFExpressionList::GetAlwaysValidExpr() const {
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 
33 bool DWARFExpressionList::AddExpression(addr_t base, addr_t end,
34  DWARFExpression expr) {
35  if (IsAlwaysValidSingleExpr() || base >= end)
36  return false;
37  m_exprs.Append({base, end - base, expr});
38  return true;
39 }
40 
41 bool DWARFExpressionList::GetExpressionData(DataExtractor &data,
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 
50 bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr,
51  lldb::addr_t addr) const {
52  if (IsAlwaysValidSingleExpr())
53  return true;
54  return GetExpressionAtAddress(func_load_addr, addr) != nullptr;
55 }
56 
57 const DWARFExpression *
58 DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr,
59  lldb::addr_t load_addr) const {
60  if (const DWARFExpression *expr = GetAlwaysValidExpr())
61  return expr;
62  if (func_load_addr == LLDB_INVALID_ADDRESS)
63  func_load_addr = m_func_file_addr;
64  addr_t addr = load_addr - func_load_addr + m_func_file_addr;
65  uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
66  if (index == UINT32_MAX)
67  return nullptr;
68  return &m_exprs.GetEntryAtIndex(index)->data;
69 }
70 
72 DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr,
73  lldb::addr_t load_addr) {
74  if (IsAlwaysValidSingleExpr())
75  return &m_exprs.GetMutableEntryAtIndex(0)->data;
76  if (func_load_addr == LLDB_INVALID_ADDRESS)
77  func_load_addr = m_func_file_addr;
78  addr_t addr = load_addr - func_load_addr + m_func_file_addr;
79  uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
80  if (index == UINT32_MAX)
81  return nullptr;
82  return &m_exprs.GetMutableEntryAtIndex(index)->data;
83 }
84 
85 bool DWARFExpressionList::ContainsThreadLocalStorage() const {
86  // We are assuming for now that any thread local variable will not have a
87  // location list. This has been true for all thread local variables we have
88  // seen so far produced by any compiler.
89  if (!IsAlwaysValidSingleExpr())
90  return false;
91 
92  const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
93  return expr.ContainsThreadLocalStorage(m_dwarf_cu);
94 }
95 
96 bool DWARFExpressionList::LinkThreadLocalStorage(
97  lldb::ModuleSP new_module_sp,
98  std::function<lldb::addr_t(lldb::addr_t file_addr)> const
99  &link_address_callback) {
100  // We are assuming for now that any thread local variable will not have a
101  // location list. This has been true for all thread local variables we have
102  // seen so far produced by any compiler.
103  if (!IsAlwaysValidSingleExpr())
104  return false;
105 
106  DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
107  // If we linked the TLS address correctly, update the module so that when the
108  // expression is evaluated it can resolve the file address to a load address
109  // and read the TLS data
110  if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback))
111  m_module_wp = new_module_sp;
112  return true;
113 }
114 
115 bool DWARFExpressionList::MatchesOperand(
116  StackFrame &frame, const Instruction::Operand &operand) const {
117  RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
118  if (!reg_ctx_sp) {
119  return false;
120  }
121  const DWARFExpression *expr = nullptr;
122  if (IsAlwaysValidSingleExpr())
123  expr = &m_exprs.GetEntryAtIndex(0)->data;
124  else {
125  SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
126  if (!sc.function)
127  return false;
128 
129  addr_t load_function_start =
131  if (load_function_start == LLDB_INVALID_ADDRESS)
132  return false;
133 
135  expr = GetExpressionAtAddress(LLDB_INVALID_ADDRESS, pc);
136  }
137  if (!expr)
138  return false;
139  return expr->MatchesOperand(frame, operand);
140 }
141 
142 bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level,
143  lldb::addr_t func_load_addr,
144  lldb::addr_t file_addr,
145  ABI *abi) const {
146  llvm::raw_ostream &os = s->AsRawOstream();
147  llvm::ListSeparator separator;
148  if (const DWARFExpression *expr = GetAlwaysValidExpr()) {
149  expr->DumpLocation(s, level, abi);
150  return true;
151  }
152  for (const Entry &entry : *this) {
153  addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr;
154  addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr;
155  if (file_addr != LLDB_INVALID_ADDRESS &&
156  (file_addr < load_base || file_addr >= load_end))
157  continue;
158  const auto &expr = entry.data;
159  DataExtractor data;
160  expr.GetExpressionData(data);
161  uint32_t addr_size = data.GetAddressByteSize();
162 
163  os << separator;
164  os << "[";
165  os << llvm::format_hex(load_base, 2 + 2 * addr_size);
166  os << ", ";
167  os << llvm::format_hex(load_end, 2 + 2 * addr_size);
168  os << ") -> ";
169  expr.DumpLocation(s, level, abi);
170  if (file_addr != LLDB_INVALID_ADDRESS)
171  break;
172  }
173  return true;
174 }
175 
176 void DWARFExpressionList::GetDescription(Stream *s,
178  ABI *abi) const {
179  llvm::raw_ostream &os = s->AsRawOstream();
180  if (IsAlwaysValidSingleExpr()) {
181  m_exprs.Back()->data.DumpLocation(s, level, abi);
182  return;
183  }
184  os << llvm::format("0x%8.8" PRIx64 ": ", 0);
185  for (const Entry &entry : *this) {
186  const auto &expr = entry.data;
187  DataExtractor data;
188  expr.GetExpressionData(data);
189  uint32_t addr_size = data.GetAddressByteSize();
190  os << "\n";
191  os.indent(s->GetIndentLevel() + 2);
192  os << "[";
193  llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase());
194  os << ", ";
195  llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd());
196  os << "): ";
197  expr.DumpLocation(s, level, abi);
198  }
199 }
200 
201 bool DWARFExpressionList::Evaluate(ExecutionContext *exe_ctx,
202  RegisterContext *reg_ctx,
203  lldb::addr_t func_load_addr,
204  const Value *initial_value_ptr,
205  const Value *object_address_ptr,
206  Value &result, Status *error_ptr) const {
207  ModuleSP module_sp = m_module_wp.lock();
208  DataExtractor data;
209  RegisterKind reg_kind;
210  DWARFExpression expr;
211  if (IsAlwaysValidSingleExpr()) {
212  expr = m_exprs.Back()->data;
213  } else {
214  Address pc;
215  StackFrame *frame = nullptr;
216  if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {
217  if (exe_ctx)
218  frame = exe_ctx->GetFramePtr();
219  if (!frame)
220  return false;
221  RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
222  if (!reg_ctx_sp)
223  return false;
224  reg_ctx_sp->GetPCForSymbolication(pc);
225  }
226 
227  if (!pc.IsValid()) {
228  if (error_ptr)
229  error_ptr->SetErrorString("Invalid PC in frame.");
230  return false;
231  }
232  addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr());
233  const DWARFExpression *entry =
234  GetExpressionAtAddress(func_load_addr, pc_load_addr);
235  if (!entry) {
236  if (error_ptr) {
237  error_ptr->SetErrorString("variable not available");
238  }
239  return false;
240  }
241  expr = *entry;
242  }
243  expr.GetExpressionData(data);
244  reg_kind = expr.GetRegisterKind();
245  return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data,
246  m_dwarf_cu, reg_kind, initial_value_ptr,
247  object_address_ptr, result, error_ptr);
248 }
lldb_private::AddressRange::GetBaseAddress
Address & GetBaseAddress()
Get accessor for the base address of the range.
Definition: AddressRange.h:209
lldb_private::Range::GetRangeBase
BaseType GetRangeBase() const
Definition: RangeMap.h:46
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::ABI
Definition: ABI.h:27
lldb_private::Function::GetAddressRange
const AddressRange & GetAddressRange()
Definition: Function.h:457
lldb_private::Value
Definition: Value.h:38
lldb_private::ExecutionContext::GetFramePtr
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
Definition: ExecutionContext.h:408
StackFrame.h
lldb_private::Stream
Definition: Stream.h:28
lldb_private::RangeData
Definition: RangeMap.h:415
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
pc
@ pc
Definition: CompactUnwindInfo.cpp:1251
lldb_private::RegisterContext::GetPCForSymbolication
bool GetPCForSymbolication(Address &address)
Get an address suitable for symbolication.
Definition: RegisterContext.cpp:127
lldb_private::SymbolContext
Definition: SymbolContext.h:33
lldb_private::DWARFExpression::ContainsThreadLocalStorage
bool ContainsThreadLocalStorage(const DWARFUnit *dwarf_cu) const
Definition: DWARFExpression.cpp:420
lldb_private::DWARFExpression::LinkThreadLocalStorage
bool LinkThreadLocalStorage(const DWARFUnit *dwarf_cu, std::function< lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback)
Definition: DWARFExpression.cpp:436
lldb_private::DataExtractor::GetAddressByteSize
uint32_t GetAddressByteSize() const
Get the current address size.
Definition: DataExtractor.h:264
lldb_private::DataExtractor
Definition: DataExtractor.h:48
lldb_private::SymbolContext::function
Function * function
The Function for a given query.
Definition: SymbolContext.h:320
lldb_private::Address::GetFileAddress
lldb::addr_t GetFileAddress() const
Get the file address.
Definition: Address.cpp:291
lldb_private::DWARFExpression
Definition: DWARFExpression.h:36
lldb_private::DWARFExpression::GetRegisterKind
lldb::RegisterKind GetRegisterKind() const
Return the call-frame-info style register kind.
Definition: DWARFExpression.cpp:77
lldb_private::Instruction::Operand
Definition: Disassembler.h:198
lldb_private::Stream::GetIndentLevel
unsigned GetIndentLevel() const
Get the current indentation level.
Definition: Stream.cpp:160
DWARFUnit.h
lldb_private::RegisterContext
Definition: RegisterContext.h:17
lldb_private::DWARFExpression::GetExpressionData
bool GetExpressionData(DataExtractor &data) const
Definition: DWARFExpression.h:149
lldb::RegisterKind
RegisterKind
Register numbering types.
Definition: lldb-enumerations.h:228
lldb_private::DWARFExpression::MatchesOperand
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const
Definition: DWARFExpression.cpp:2645
lldb_private::Status
Definition: Status.h:44
DWARFExpressionList.h
uint32_t
lldb_private::Address
Definition: Address.h:59
lldb_private::Status::SetErrorString
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
lldb_private::Stream::AsRawOstream
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition: Stream.h:357
UINT32_MAX
#define UINT32_MAX
Definition: lldb-defines.h:19
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
Function.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::StackFrame::GetRegisterContext
lldb::RegisterContextSP GetRegisterContext()
Get the RegisterContext for this frame, if possible.
Definition: StackFrame.cpp:1143
lldb_private::StackFrame::GetFrameCodeAddressForSymbolication
Address GetFrameCodeAddressForSymbolication()
Get the current code Address suitable for symbolication, may not be the same as GetFrameCodeAddress()...
Definition: StackFrame.cpp:222
lldb_private::RangeData::data
DataType data
Definition: RangeMap.h:418
lldb_private::StackFrame
Definition: StackFrame.h:40
lldb
Definition: SBAddress.h:15
RegisterContext.h
lldb_private::StackFrame::GetSymbolContext
const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
Definition: StackFrame.cpp:300
lldb_private::ExecutionContext::GetTargetPtr
Target * GetTargetPtr() const
Returns a pointer to the target object.
Definition: ExecutionContext.cpp:198
lldb::DescriptionLevel
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
Definition: lldb-enumerations.h:208
lldb_private::Range::GetRangeEnd
BaseType GetRangeEnd() const
Definition: RangeMap.h:78