]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Plugins / LanguageRuntime / CPlusPlus / CPPLanguageRuntime.cpp
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 get_name = [&first_template_parameter, &symbol]() {
197     // Given case 1:
198     //
199     //    main::$_0
200     //
201     // we want to append ::operator()()
202     if (first_template_parameter.contains("$_"))
203       return llvm::Regex::escape(first_template_parameter.str()) +
204              R"(::operator\(\)\(.*\))";
205
206     if (symbol != nullptr &&
207         symbol->GetName().GetStringRef().contains("__invoke")) {
208
209       llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
210       size_t pos2 = symbol_name.find_last_of(':');
211
212       // Given case 2:
213       //
214       //    main::$_1::__invoke(...)
215       //
216       // We want to slice off __invoke(...) and append operator()()
217       std::string lambda_operator =
218           llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
219           R"(operator\(\)\(.*\))";
220
221       return lambda_operator;
222     }
223
224     // Case 3
225     return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
226     ;
227   };
228
229   std::string func_to_match = get_name();
230
231   SymbolContextList scl;
232
233   target.GetImages().FindSymbolsMatchingRegExAndType(
234       RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl, true);
235
236   // Case 1,2 or 3
237   if (scl.GetSize() >= 1) {
238     SymbolContext sc2 = scl[0];
239
240     AddressRange range;
241     sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);
242
243     Address address = range.GetBaseAddress();
244
245     Address addr;
246     if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
247                                   addr)) {
248       LineEntry line_entry;
249       addr.CalculateSymbolContextLineEntry(line_entry);
250
251       if (first_template_parameter.contains("$_") ||
252           (symbol != nullptr &&
253            symbol->GetName().GetStringRef().contains("__invoke"))) {
254         // Case 1 and 2
255         optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
256       } else {
257         // Case 3
258         optional_info.callable_case =
259             LibCppStdFunctionCallableCase::CallableObject;
260       }
261
262       optional_info.callable_symbol = *symbol;
263       optional_info.callable_line_entry = line_entry;
264       optional_info.callable_address = addr;
265       return optional_info;
266     }
267   }
268
269   // Case 4 or 5
270   if (symbol && !symbol->GetName().GetStringRef().startswith("vtable for")) {
271     optional_info.callable_case =
272         LibCppStdFunctionCallableCase::FreeOrMemberFunction;
273     optional_info.callable_address = function_address_resolved;
274     optional_info.callable_symbol = *symbol;
275
276     return optional_info;
277   }
278
279   return optional_info;
280 }
281
282 lldb::ThreadPlanSP
283 CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
284                                                  bool stop_others) {
285   ThreadPlanSP ret_plan_sp;
286
287   lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
288
289   TargetSP target_sp(thread.CalculateTarget());
290
291   if (target_sp->GetSectionLoadList().IsEmpty())
292     return ret_plan_sp;
293
294   Address pc_addr_resolved;
295   SymbolContext sc;
296   Symbol *symbol;
297
298   if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc,
299                                                           pc_addr_resolved))
300     return ret_plan_sp;
301
302   target_sp->GetImages().ResolveSymbolContextForAddress(
303       pc_addr_resolved, eSymbolContextEverything, sc);
304   symbol = sc.symbol;
305
306   if (symbol == nullptr)
307     return ret_plan_sp;
308
309   llvm::StringRef function_name(symbol->GetName().GetCString());
310
311   // Handling the case where we are attempting to step into std::function.
312   // The behavior will be that we will attempt to obtain the wrapped
313   // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
314   // will return a ThreadPlanRunToAddress to the callable. Therefore we will
315   // step into the wrapped callable.
316   //
317   bool found_expected_start_string =
318       function_name.startswith("std::__1::function<");
319
320   if (!found_expected_start_string)
321     return ret_plan_sp;
322
323   AddressRange range_of_curr_func;
324   sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);
325
326   StackFrameSP frame = thread.GetStackFrameAtIndex(0);
327
328   if (frame) {
329     ValueObjectSP value_sp = frame->FindVariable(g_this);
330
331     CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
332         FindLibCppStdFunctionCallableInfo(value_sp);
333
334     if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
335         value_sp->GetValueIsValid()) {
336       // We found the std::function wrapped callable and we have its address.
337       // We now create a ThreadPlan to run to the callable.
338       ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
339           thread, callable_info.callable_address, stop_others);
340       return ret_plan_sp;
341     } else {
342       // We are in std::function but we could not obtain the callable.
343       // We create a ThreadPlan to keep stepping through using the address range
344       // of the current function.
345       ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
346           thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes,
347           eLazyBoolYes);
348       return ret_plan_sp;
349     }
350   }
351
352   return ret_plan_sp;
353 }