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 
9 #include <string.h>
10 
11 #include <memory>
12 
13 #include "CPPLanguageRuntime.h"
14 
15 #include "llvm/ADT/StringRef.h"
16 
17 #include "lldb/Symbol/Block.h"
18 #include "lldb/Symbol/Variable.h"
19 #include "lldb/Symbol/VariableList.h"
20 
21 #include "lldb/Core/PluginManager.h"
22 #include "lldb/Core/UniqueCStringMap.h"
23 #include "lldb/Symbol/ClangASTContext.h"
24 #include "lldb/Target/ABI.h"
25 #include "lldb/Target/ExecutionContext.h"
26 #include "lldb/Target/RegisterContext.h"
27 #include "lldb/Target/SectionLoadList.h"
28 #include "lldb/Target/StackFrame.h"
29 #include "lldb/Target/ThreadPlanRunToAddress.h"
30 #include "lldb/Target/ThreadPlanStepInRange.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 static ConstString g_this = ConstString("this");
36 
37 char CPPLanguageRuntime::ID = 0;
38 
39 // Destructor
40 CPPLanguageRuntime::~CPPLanguageRuntime() {}
41 
42 CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
43     : LanguageRuntime(process) {}
44 
45 bool CPPLanguageRuntime::IsWhitelistedRuntimeValue(ConstString name) {
46   return name == g_this;
47 }
48 
49 bool CPPLanguageRuntime::GetObjectDescription(Stream &str,
50                                               ValueObject &object) {
51   // C++ has no generic way to do this.
52   return false;
53 }
54 
55 bool CPPLanguageRuntime::GetObjectDescription(
56     Stream &str, Value &value, ExecutionContextScope *exe_scope) {
57   // C++ has no generic way to do this.
58   return false;
59 }
60 
61 CPPLanguageRuntime::LibCppStdFunctionCallableInfo
62 CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
63     lldb::ValueObjectSP &valobj_sp) {
64   LibCppStdFunctionCallableInfo optional_info;
65 
66   if (!valobj_sp)
67     return optional_info;
68 
69   // Member __f_ has type __base*, the contents of which will hold:
70   // 1) a vtable entry which may hold type information needed to discover the
71   //    lambda being called
72   // 2) possibly hold a pointer to the callable object
73   // e.g.
74   //
75   // (lldb) frame var -R  f_display
76   // (std::__1::function<void (int)>) f_display = {
77   //  __buf_ = {
78   //  …
79   // }
80   //  __f_ = 0x00007ffeefbffa00
81   // }
82   // (lldb) memory read -fA 0x00007ffeefbffa00
83   // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
84   // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
85   //
86   // We will be handling five cases below, std::function is wrapping:
87   //
88   // 1) a lambda we know at compile time. We will obtain the name of the lambda
89   //    from the first template pameter from __func's vtable. We will look up
90   //    the lambda's operator()() and obtain the line table entry.
91   // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
92   //    will be stored after the vtable. We will obtain the lambdas name from
93   //    this entry and lookup operator()() and obtain the line table entry.
94   // 3) a callable object via operator()(). We will obtain the name of the
95   //    object from the first template parameter from __func's vtable. We will
96   //    look up the objectc operator()() and obtain the line table entry.
97   // 4) a member function. A pointer to the function will stored after the
98   //    we will obtain the name from this pointer.
99   // 5) a free function. A pointer to the function will stored after the vtable
100   //    we will obtain the name from this pointer.
101   ValueObjectSP member__f_(
102       valobj_sp->GetChildMemberWithName(ConstString("__f_"), true));
103 
104   if (member__f_) {
105     ValueObjectSP sub_member__f_(
106        member__f_->GetChildMemberWithName(ConstString("__f_"), true));
107 
108     if (sub_member__f_)
109         member__f_ = sub_member__f_;
110   }
111 
112   lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0);
113 
114   optional_info.member__f_pointer_value = member__f_pointer_value;
115 
116   ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
117   Process *process = exe_ctx.GetProcessPtr();
118 
119   if (process == nullptr)
120     return optional_info;
121 
122   uint32_t address_size = process->GetAddressByteSize();
123   Status status;
124 
125   // First item pointed to by __f_ should be the pointer to the vtable for
126   // a __base object.
127   lldb::addr_t vtable_address =
128       process->ReadPointerFromMemory(member__f_pointer_value, status);
129 
130   if (status.Fail())
131     return optional_info;
132 
133   lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
134   // As commened above we may not have a function pointer but if we do we will
135   // need it.
136   lldb::addr_t possible_function_address =
137       process->ReadPointerFromMemory(address_after_vtable, status);
138 
139   if (status.Fail())
140     return optional_info;
141 
142   Target &target = process->GetTarget();
143 
144   if (target.GetSectionLoadList().IsEmpty())
145     return optional_info;
146 
147   Address vtable_addr_resolved;
148   SymbolContext sc;
149   Symbol *symbol;
150 
151   if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
152                                                       vtable_addr_resolved))
153     return optional_info;
154 
155   target.GetImages().ResolveSymbolContextForAddress(
156       vtable_addr_resolved, eSymbolContextEverything, sc);
157   symbol = sc.symbol;
158 
159   if (symbol == nullptr)
160     return optional_info;
161 
162   llvm::StringRef vtable_name(symbol->GetName().GetCString());
163   bool found_expected_start_string =
164       vtable_name.startswith("vtable for std::__1::__function::__func<");
165 
166   if (!found_expected_start_string)
167     return optional_info;
168 
169   // Given case 1 or 3 we have a vtable name, we are want to extract the first
170   // template parameter
171   //
172   //  ... __func<main::$_0, std::__1::allocator<main::$_0> ...
173   //             ^^^^^^^^^
174   //
175   // We do this by find the first < and , and extracting in between.
176   //
177   // This covers the case of the lambda known at compile time.
178   size_t first_open_angle_bracket = vtable_name.find('<') + 1;
179   size_t first_comma = vtable_name.find(',');
180 
181   llvm::StringRef first_template_parameter =
182       vtable_name.slice(first_open_angle_bracket, first_comma);
183 
184   Address function_address_resolved;
185 
186   // Setup for cases 2, 4 and 5 we have a pointer to a function after the
187   // vtable. We will use a process of elimination to drop through each case
188   // and obtain the data we need.
189   if (target.GetSectionLoadList().ResolveLoadAddress(
190           possible_function_address, function_address_resolved)) {
191     target.GetImages().ResolveSymbolContextForAddress(
192         function_address_resolved, eSymbolContextEverything, sc);
193     symbol = sc.symbol;
194   }
195 
196     auto contains_lambda_identifier = []( llvm::StringRef & str_ref ) {
197         return str_ref.contains("$_") || str_ref.contains("'lambda'");
198     };
199 
200   // Case 4 or 5
201   // We eliminate these cases early because they don't need the potentially
202   // expensive lookup through the symbol table.
203   if (symbol && !symbol->GetName().GetStringRef().startswith("vtable for") &&
204       !contains_lambda_identifier(first_template_parameter) &&
205       !symbol->GetName().GetStringRef().contains("__invoke")) {
206     optional_info.callable_case =
207         LibCppStdFunctionCallableCase::FreeOrMemberFunction;
208     optional_info.callable_address = function_address_resolved;
209     optional_info.callable_symbol = *symbol;
210 
211     return optional_info;
212   }
213 
214   auto get_name = [&first_template_parameter, &symbol, contains_lambda_identifier]() {
215     // Given case 1:
216     //
217     //    main::$_0
218     //    Bar::add_num2(int)::'lambda'(int)
219     //
220     // we want to append ::operator()()
221     if (contains_lambda_identifier(first_template_parameter))
222       return llvm::Regex::escape(first_template_parameter.str()) +
223              R"(::operator\(\)\(.*\))";
224 
225     if (symbol != nullptr &&
226         symbol->GetName().GetStringRef().contains("__invoke")) {
227 
228       llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
229       size_t pos2 = symbol_name.find_last_of(':');
230 
231       // Given case 2:
232       //
233       //    main::$_1::__invoke(...)
234       //
235       // We want to slice off __invoke(...) and append operator()()
236       std::string lambda_operator =
237           llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
238           R"(operator\(\)\(.*\))";
239 
240       return lambda_operator;
241     }
242 
243     // Case 3
244     return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
245     ;
246   };
247 
248   std::string func_to_match = get_name();
249 
250   auto it = CallableLookupCache.find(func_to_match);
251   if (it != CallableLookupCache.end())
252     return it->second;
253 
254   SymbolContextList scl;
255 
256   target.GetImages().FindSymbolsMatchingRegExAndType(
257       RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl);
258 
259   // Case 1,2 or 3
260   if (scl.GetSize() >= 1) {
261     SymbolContext sc2 = scl[0];
262 
263     AddressRange range;
264     sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);
265 
266     Address address = range.GetBaseAddress();
267 
268     Address addr;
269     if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
270                                   addr)) {
271       LineEntry line_entry;
272       addr.CalculateSymbolContextLineEntry(line_entry);
273 
274       if (contains_lambda_identifier(first_template_parameter) ||
275           (symbol != nullptr &&
276            symbol->GetName().GetStringRef().contains("__invoke"))) {
277         // Case 1 and 2
278         optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
279       } else {
280         // Case 3
281         optional_info.callable_case =
282             LibCppStdFunctionCallableCase::CallableObject;
283       }
284 
285       optional_info.callable_symbol = *symbol;
286       optional_info.callable_line_entry = line_entry;
287       optional_info.callable_address = addr;
288     }
289   }
290 
291   CallableLookupCache[func_to_match] = optional_info;
292 
293   return optional_info;
294 }
295 
296 lldb::ThreadPlanSP
297 CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
298                                                  bool stop_others) {
299   ThreadPlanSP ret_plan_sp;
300 
301   lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
302 
303   TargetSP target_sp(thread.CalculateTarget());
304 
305   if (target_sp->GetSectionLoadList().IsEmpty())
306     return ret_plan_sp;
307 
308   Address pc_addr_resolved;
309   SymbolContext sc;
310   Symbol *symbol;
311 
312   if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc,
313                                                           pc_addr_resolved))
314     return ret_plan_sp;
315 
316   target_sp->GetImages().ResolveSymbolContextForAddress(
317       pc_addr_resolved, eSymbolContextEverything, sc);
318   symbol = sc.symbol;
319 
320   if (symbol == nullptr)
321     return ret_plan_sp;
322 
323   llvm::StringRef function_name(symbol->GetName().GetCString());
324 
325   // Handling the case where we are attempting to step into std::function.
326   // The behavior will be that we will attempt to obtain the wrapped
327   // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
328   // will return a ThreadPlanRunToAddress to the callable. Therefore we will
329   // step into the wrapped callable.
330   //
331   bool found_expected_start_string =
332       function_name.startswith("std::__1::function<");
333 
334   if (!found_expected_start_string)
335     return ret_plan_sp;
336 
337   AddressRange range_of_curr_func;
338   sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);
339 
340   StackFrameSP frame = thread.GetStackFrameAtIndex(0);
341 
342   if (frame) {
343     ValueObjectSP value_sp = frame->FindVariable(g_this);
344 
345     CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
346         FindLibCppStdFunctionCallableInfo(value_sp);
347 
348     if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
349         value_sp->GetValueIsValid()) {
350       // We found the std::function wrapped callable and we have its address.
351       // We now create a ThreadPlan to run to the callable.
352       ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
353           thread, callable_info.callable_address, stop_others);
354       return ret_plan_sp;
355     } else {
356       // We are in std::function but we could not obtain the callable.
357       // We create a ThreadPlan to keep stepping through using the address range
358       // of the current function.
359       ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
360           thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes,
361           eLazyBoolYes);
362       return ret_plan_sp;
363     }
364   }
365 
366   return ret_plan_sp;
367 }
368