LLDB  mainline
CPPLanguageRuntime.cpp
Go to the documentation of this file.
1 //===-- CPPLanguageRuntime.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 
12 #include <string.h>
13 
14 #include <memory>
15 
16 #include "llvm/ADT/StringRef.h"
17 
18 #include "lldb/Symbol/Block.h"
19 #include "lldb/Symbol/Variable.h"
21 
25 #include "lldb/Target/ABI.h"
29 #include "lldb/Target/StackFrame.h"
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 
36 static ConstString g_this = ConstString("this");
37 
38 // Destructor
39 CPPLanguageRuntime::~CPPLanguageRuntime() {}
40 
41 CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
42  : LanguageRuntime(process) {}
43 
45  // All runtime support values have to be marked as artificial by the
46  // compiler. But not all artificial variables should be hidden from
47  // the user.
48  if (!valobj.GetVariable())
49  return false;
50  if (!valobj.GetVariable()->IsArtificial())
51  return false;
52 
53  // Whitelist "this" and since there is no ObjC++ runtime, any ObjC names.
54  ConstString name = valobj.GetName();
55  if (name == g_this)
56  return false;
58 }
59 
61  ValueObject &object) {
62  // C++ has no generic way to do this.
63  return false;
64 }
65 
67  Stream &str, Value &value, ExecutionContextScope *exe_scope) {
68  // C++ has no generic way to do this.
69  return false;
70 }
71 
74  lldb::ValueObjectSP &valobj_sp) {
75  LibCppStdFunctionCallableInfo optional_info;
76 
77  if (!valobj_sp)
78  return optional_info;
79 
80  // Member __f_ has type __base*, the contents of which will hold:
81  // 1) a vtable entry which may hold type information needed to discover the
82  // lambda being called
83  // 2) possibly hold a pointer to the callable object
84  // e.g.
85  //
86  // (lldb) frame var -R f_display
87  // (std::__1::function<void (int)>) f_display = {
88  // __buf_ = {
89  // …
90  // }
91  // __f_ = 0x00007ffeefbffa00
92  // }
93  // (lldb) memory read -fA 0x00007ffeefbffa00
94  // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
95  // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
96  //
97  // We will be handling five cases below, std::function is wrapping:
98  //
99  // 1) a lambda we know at compile time. We will obtain the name of the lambda
100  // from the first template pameter from __func's vtable. We will look up
101  // the lambda's operator()() and obtain the line table entry.
102  // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
103  // will be stored after the vtable. We will obtain the lambdas name from
104  // this entry and lookup operator()() and obtain the line table entry.
105  // 3) a callable object via operator()(). We will obtain the name of the
106  // object from the first template parameter from __func's vtable. We will
107  // look up the objectc operator()() and obtain the line table entry.
108  // 4) a member function. A pointer to the function will stored after the
109  // we will obtain the name from this pointer.
110  // 5) a free function. A pointer to the function will stored after the vtable
111  // we will obtain the name from this pointer.
112  ValueObjectSP member__f_(
113  valobj_sp->GetChildMemberWithName(ConstString("__f_"), true));
114 
115  if (member__f_) {
116  ValueObjectSP sub_member__f_(
117  member__f_->GetChildMemberWithName(ConstString("__f_"), true));
118 
119  if (sub_member__f_)
120  member__f_ = sub_member__f_;
121  }
122 
123  lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0);
124 
125  optional_info.member__f_pointer_value = member__f_pointer_value;
126 
127  ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
128  Process *process = exe_ctx.GetProcessPtr();
129 
130  if (process == nullptr)
131  return optional_info;
132 
133  uint32_t address_size = process->GetAddressByteSize();
134  Status status;
135 
136  // First item pointed to by __f_ should be the pointer to the vtable for
137  // a __base object.
138  lldb::addr_t vtable_address =
139  process->ReadPointerFromMemory(member__f_pointer_value, status);
140 
141  if (status.Fail())
142  return optional_info;
143 
144  lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
145  // As commened above we may not have a function pointer but if we do we will
146  // need it.
147  lldb::addr_t possible_function_address =
148  process->ReadPointerFromMemory(address_after_vtable, status);
149 
150  if (status.Fail())
151  return optional_info;
152 
153  Target &target = process->GetTarget();
154 
155  if (target.GetSectionLoadList().IsEmpty())
156  return optional_info;
157 
158  Address vtable_addr_resolved;
159  SymbolContext sc;
160  Symbol *symbol;
161 
162  if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
163  vtable_addr_resolved))
164  return optional_info;
165 
167  vtable_addr_resolved, eSymbolContextEverything, sc);
168  symbol = sc.symbol;
169 
170  if (symbol == nullptr)
171  return optional_info;
172 
173  llvm::StringRef vtable_name(symbol->GetName().GetCString());
174  bool found_expected_start_string =
175  vtable_name.startswith("vtable for std::__1::__function::__func<");
176 
177  if (!found_expected_start_string)
178  return optional_info;
179 
180  // Given case 1 or 3 we have a vtable name, we are want to extract the first
181  // template parameter
182  //
183  // ... __func<main::$_0, std::__1::allocator<main::$_0> ...
184  // ^^^^^^^^^
185  //
186  // We do this by find the first < and , and extracting in between.
187  //
188  // This covers the case of the lambda known at compile time.
189  size_t first_open_angle_bracket = vtable_name.find('<') + 1;
190  size_t first_comma = vtable_name.find(',');
191 
192  llvm::StringRef first_template_parameter =
193  vtable_name.slice(first_open_angle_bracket, first_comma);
194 
195  Address function_address_resolved;
196 
197  // Setup for cases 2, 4 and 5 we have a pointer to a function after the
198  // vtable. We will use a process of elimination to drop through each case
199  // and obtain the data we need.
201  possible_function_address, function_address_resolved)) {
203  function_address_resolved, eSymbolContextEverything, sc);
204  symbol = sc.symbol;
205  }
206 
207  auto get_name = [&first_template_parameter, &symbol]() {
208  // Given case 1:
209  //
210  // main::$_0
211  //
212  // we want to append ::operator()()
213  if (first_template_parameter.contains("$_"))
214  return llvm::Regex::escape(first_template_parameter.str()) +
215  R"(::operator\(\)\(.*\))";
216 
217  if (symbol != NULL &&
218  symbol->GetName().GetStringRef().contains("__invoke")) {
219 
220  llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
221  size_t pos2 = symbol_name.find_last_of(':');
222 
223  // Given case 2:
224  //
225  // main::$_1::__invoke(...)
226  //
227  // We want to slice off __invoke(...) and append operator()()
228  std::string lambda_operator =
229  llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
230  R"(operator\(\)\(.*\))";
231 
232  return lambda_operator;
233  }
234 
235  // Case 3
236  return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
237  ;
238  };
239 
240  std::string func_to_match = get_name();
241 
242  SymbolContextList scl;
243 
244  target.GetImages().FindFunctions(RegularExpression{func_to_match}, true, true,
245  true, scl);
246 
247  // Case 1,2 or 3
248  if (scl.GetSize() >= 1) {
249  SymbolContext sc2 = scl[0];
250 
251  AddressRange range;
252  sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);
253 
254  Address address = range.GetBaseAddress();
255 
256  Address addr;
257  if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
258  addr)) {
259  LineEntry line_entry;
260  addr.CalculateSymbolContextLineEntry(line_entry);
261 
262  if (first_template_parameter.contains("$_") ||
263  (symbol != nullptr &&
264  symbol->GetName().GetStringRef().contains("__invoke"))) {
265  // Case 1 and 2
267  } else {
268  // Case 3
269  optional_info.callable_case =
271  }
272 
273  optional_info.callable_symbol = *symbol;
274  optional_info.callable_line_entry = line_entry;
275  optional_info.callable_address = addr;
276  return optional_info;
277  }
278  }
279 
280  // Case 4 or 5
281  if (!symbol->GetName().GetStringRef().startswith("vtable for")) {
282  optional_info.callable_case =
284  optional_info.callable_address = function_address_resolved;
285  optional_info.callable_symbol = *symbol;
286 
287  return optional_info;
288  }
289 
290  return optional_info;
291 }
292 
293 lldb::ThreadPlanSP
295  bool stop_others) {
296  ThreadPlanSP ret_plan_sp;
297 
298  lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
299 
300  TargetSP target_sp(thread.CalculateTarget());
301 
302  if (target_sp->GetSectionLoadList().IsEmpty())
303  return ret_plan_sp;
304 
305  Address pc_addr_resolved;
306  SymbolContext sc;
307  Symbol *symbol;
308 
309  if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc,
310  pc_addr_resolved))
311  return ret_plan_sp;
312 
313  target_sp->GetImages().ResolveSymbolContextForAddress(
314  pc_addr_resolved, eSymbolContextEverything, sc);
315  symbol = sc.symbol;
316 
317  if (symbol == nullptr)
318  return ret_plan_sp;
319 
320  llvm::StringRef function_name(symbol->GetName().GetCString());
321 
322  // Handling the case where we are attempting to step into std::function.
323  // The behavior will be that we will attempt to obtain the wrapped
324  // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
325  // will return a ThreadPlanRunToAddress to the callable. Therefore we will
326  // step into the wrapped callable.
327  //
328  bool found_expected_start_string =
329  function_name.startswith("std::__1::function<");
330 
331  if (!found_expected_start_string)
332  return ret_plan_sp;
333 
334  AddressRange range_of_curr_func;
335  sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);
336 
337  StackFrameSP frame = thread.GetStackFrameAtIndex(0);
338 
339  if (frame) {
340  ValueObjectSP value_sp = frame->FindVariable(g_this);
341 
344 
346  value_sp->GetValueIsValid()) {
347  // We found the std::function wrapped callable and we have its address.
348  // We now create a ThreadPlan to run to the callable.
349  ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
350  thread, callable_info.callable_address, stop_others);
351  return ret_plan_sp;
352  } else {
353  // We are in std::function but we could not obtain the callable.
354  // We create a ThreadPlan to keep stepping through using the address range
355  // of the current function.
356  ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
357  thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes,
358  eLazyBoolYes);
359  return ret_plan_sp;
360  }
361  }
362 
363  return ret_plan_sp;
364 }
lldb::addr_t GetCallableLoadAddress(Target *target, bool is_indirect=false) const
Get the load address as a callable code load address.
Definition: Address.cpp:317
A line table entry class.
Definition: LineEntry.h:20
Defines a list of symbol context objects.
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
static bool IsWhitelistedRuntimeValue(ConstString name)
Check whether the name is "self" or "_cmd" and should show up in "frame variable".
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
ConstString GetName() const
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop_others)
Obtain a ThreadPlan to get us into C++ constructs such as std::function.
"lldb/Utility/RegularExpression.h" A C++ wrapper class for regex.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Symbol * symbol
The Symbol for a given query.
uint32_t GetSize() const
Get accessor for a symbol context list size.
bool IsRuntimeSupportValue(ValueObject &valobj) override
Identify whether a value is a language implementation detaul that should be hidden from the user inte...
static ConstString g_this
virtual lldb::VariableSP GetVariable()
Definition: ValueObject.h:801
SectionLoadList & GetSectionLoadList()
Definition: Target.h:1012
lldb::TargetSP CalculateTarget() override
Definition: Thread.cpp:1584
virtual lldb::RegisterContextSP GetRegisterContext()=0
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, bool allow_section_end=false) const
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:233
LibCppStdFunctionCallableInfo FindLibCppStdFunctionCallableInfo(lldb::ValueObjectSP &valobj_sp)
A section + offset based address class.
Definition: Address.h:80
uint32_t ResolveSymbolContextForAddress(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) const
Resolve the symbol context for the given address. (const Address
Definition: ModuleList.cpp:662
bool CalculateSymbolContextLineEntry(LineEntry &line_entry) const
Definition: Address.cpp:864
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:899
uint64_t addr_t
Definition: lldb-types.h:83
A uniqued constant string class.
Definition: ConstString.h:38
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
Definition: SBAddress.h:15
ConstString GetName() const
Definition: Symbol.cpp:494
bool GetAddressRange(uint32_t scope, uint32_t range_idx, bool use_inline_block_range, AddressRange &range) const
Get the address range contained within a symbol context.
Address & GetBaseAddress()
Get accessor for the base address of the range.
Definition: AddressRange.h:220
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow)
Definition: Target.cpp:2746
size_t FindFunctions(ConstString name, lldb::FunctionNameType name_type_mask, bool include_symbols, bool include_inlines, bool append, SymbolContextList &sc_list) const
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:395
A section + offset based address range class.
Definition: AddressRange.h:32
bool GetObjectDescription(Stream &str, ValueObject &object) override
An error handling class.
Definition: Status.h:44