blob: 70e5aee3e45b1f290fa700108e13d64319c53fdf [file] [log] [blame]
Kate Stoneb9c1b512016-09-06 20:57:50 +00001//===-- CPPLanguageRuntime.cpp
Jim Ingham22777012010-09-23 02:01:19 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Jim Ingham22777012010-09-23 02:01:19 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Target/CPPLanguageRuntime.h"
Adrian Prantl1db0f0c2019-05-02 23:07:23 +000010#include "lldb/Target/ObjCLanguageRuntime.h"
Enrico Granata1d261d12012-02-03 01:41:25 +000011
Greg Clayton6ecb2322013-05-18 00:11:21 +000012#include <string.h>
13
Jonas Devlieghere796ac802019-02-11 23:13:08 +000014#include <memory>
15
Jim Inghamfa39bb42014-10-25 00:33:55 +000016#include "llvm/ADT/StringRef.h"
17
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000018#include "lldb/Symbol/Block.h"
Adrian Prantl1db0f0c2019-05-02 23:07:23 +000019#include "lldb/Symbol/Variable.h"
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000020#include "lldb/Symbol/VariableList.h"
21
Jim Ingham22777012010-09-23 02:01:19 +000022#include "lldb/Core/PluginManager.h"
Enrico Granata1d261d12012-02-03 01:41:25 +000023#include "lldb/Core/UniqueCStringMap.h"
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000024#include "lldb/Symbol/ClangASTContext.h"
25#include "lldb/Target/ABI.h"
Jim Ingham5a369122010-09-28 01:25:32 +000026#include "lldb/Target/ExecutionContext.h"
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000027#include "lldb/Target/RegisterContext.h"
28#include "lldb/Target/SectionLoadList.h"
29#include "lldb/Target/StackFrame.h"
30#include "lldb/Target/ThreadPlanRunToAddress.h"
Shafik Yaghmouraa302682018-10-12 17:20:39 +000031#include "lldb/Target/ThreadPlanStepInRange.h"
Jim Ingham22777012010-09-23 02:01:19 +000032
33using namespace lldb;
34using namespace lldb_private;
35
Adrian Prantl1db0f0c2019-05-02 23:07:23 +000036static ConstString g_this = ConstString("this");
37
Jim Ingham22777012010-09-23 02:01:19 +000038// Destructor
Kate Stoneb9c1b512016-09-06 20:57:50 +000039CPPLanguageRuntime::~CPPLanguageRuntime() {}
40
41CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
42 : LanguageRuntime(process) {}
43
Adrian Prantl1db0f0c2019-05-02 23:07:23 +000044bool CPPLanguageRuntime::IsRuntimeSupportValue(ValueObject &valobj) {
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;
57 return !ObjCLanguageRuntime::IsWhitelistedRuntimeValue(name);
58}
59
Kate Stoneb9c1b512016-09-06 20:57:50 +000060bool CPPLanguageRuntime::GetObjectDescription(Stream &str,
61 ValueObject &object) {
62 // C++ has no generic way to do this.
63 return false;
Jim Ingham22777012010-09-23 02:01:19 +000064}
65
Kate Stoneb9c1b512016-09-06 20:57:50 +000066bool CPPLanguageRuntime::GetObjectDescription(
67 Stream &str, Value &value, ExecutionContextScope *exe_scope) {
68 // C++ has no generic way to do this.
69 return false;
Jim Ingham6c68fb42010-09-30 00:54:27 +000070}
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000071
72CPPLanguageRuntime::LibCppStdFunctionCallableInfo
73CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
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));
Shafik Yaghmour99bc2b22018-12-10 23:26:38 +0000114
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
Shafik Yaghmour443e20b2018-09-11 20:58:28 +0000123 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
166 target.GetImages().ResolveSymbolContextForAddress(
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.
Shafik Yaghmour443e20b2018-09-11 20:58:28 +0000189 size_t first_open_angle_bracket = vtable_name.find('<') + 1;
Jonas Devliegherec712bac2019-03-28 18:10:14 +0000190 size_t first_comma = vtable_name.find(',');
Shafik Yaghmour443e20b2018-09-11 20:58:28 +0000191
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.
200 if (target.GetSectionLoadList().ResolveLoadAddress(
201 possible_function_address, function_address_resolved)) {
202 target.GetImages().ResolveSymbolContextForAddress(
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
Konrad Kleine248a1302019-05-23 11:14:47 +0000217 if (symbol != nullptr &&
Shafik Yaghmour443e20b2018-09-11 20:58:28 +0000218 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
Shafik Yaghmour9acaceb2019-05-13 16:48:06 +0000244 target.GetImages().FindSymbolsMatchingRegExAndType(
245 RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl, true);
Shafik Yaghmour443e20b2018-09-11 20:58:28 +0000246
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
266 optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
267 } else {
268 // Case 3
269 optional_info.callable_case =
270 LibCppStdFunctionCallableCase::CallableObject;
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 =
283 LibCppStdFunctionCallableCase::FreeOrMemberFunction;
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}
Shafik Yaghmouraa302682018-10-12 17:20:39 +0000292
293lldb::ThreadPlanSP
294CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
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) {
Adrian Prantl1db0f0c2019-05-02 23:07:23 +0000340 ValueObjectSP value_sp = frame->FindVariable(g_this);
Shafik Yaghmouraa302682018-10-12 17:20:39 +0000341
342 CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
343 FindLibCppStdFunctionCallableInfo(value_sp);
344
345 if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
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.
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000349 ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
350 thread, callable_info.callable_address, stop_others);
Shafik Yaghmouraa302682018-10-12 17:20:39 +0000351 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.
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000356 ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
357 thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes,
358 eLazyBoolYes);
Shafik Yaghmouraa302682018-10-12 17:20:39 +0000359 return ret_plan_sp;
360 }
361 }
362
363 return ret_plan_sp;
364}