blob: eb76a25356f8627c4e1b4de310751b6459e6641c [file] [log] [blame]
Kate Stoneb9c1b512016-09-06 20:57:50 +00001//===-- CPPLanguageRuntime.cpp
2//-------------------------------------------------*- C++ -*-===//
Jim Ingham22777012010-09-23 02:01:19 +00003//
4// The LLVM Compiler Infrastructure
5//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#include "lldb/Target/CPPLanguageRuntime.h"
Enrico Granata1d261d12012-02-03 01:41:25 +000012
Greg Clayton6ecb2322013-05-18 00:11:21 +000013#include <string.h>
14
Jim Inghamfa39bb42014-10-25 00:33:55 +000015#include "llvm/ADT/StringRef.h"
16
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000017#include "lldb/Symbol/Block.h"
18#include "lldb/Symbol/VariableList.h"
19
Jim Ingham22777012010-09-23 02:01:19 +000020#include "lldb/Core/PluginManager.h"
Enrico Granata1d261d12012-02-03 01:41:25 +000021#include "lldb/Core/UniqueCStringMap.h"
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000022#include "lldb/Symbol/ClangASTContext.h"
23#include "lldb/Target/ABI.h"
Jim Ingham5a369122010-09-28 01:25:32 +000024#include "lldb/Target/ExecutionContext.h"
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000025#include "lldb/Target/RegisterContext.h"
26#include "lldb/Target/SectionLoadList.h"
27#include "lldb/Target/StackFrame.h"
28#include "lldb/Target/ThreadPlanRunToAddress.h"
Jim Ingham22777012010-09-23 02:01:19 +000029
30using namespace lldb;
31using namespace lldb_private;
32
33//----------------------------------------------------------------------
34// Destructor
35//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000036CPPLanguageRuntime::~CPPLanguageRuntime() {}
37
38CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
39 : LanguageRuntime(process) {}
40
41bool CPPLanguageRuntime::GetObjectDescription(Stream &str,
42 ValueObject &object) {
43 // C++ has no generic way to do this.
44 return false;
Jim Ingham22777012010-09-23 02:01:19 +000045}
46
Kate Stoneb9c1b512016-09-06 20:57:50 +000047bool CPPLanguageRuntime::GetObjectDescription(
48 Stream &str, Value &value, ExecutionContextScope *exe_scope) {
49 // C++ has no generic way to do this.
50 return false;
Jim Ingham6c68fb42010-09-30 00:54:27 +000051}
Shafik Yaghmour443e20b2018-09-11 20:58:28 +000052
53CPPLanguageRuntime::LibCppStdFunctionCallableInfo
54CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
55 lldb::ValueObjectSP &valobj_sp) {
56 LibCppStdFunctionCallableInfo optional_info;
57
58 if (!valobj_sp)
59 return optional_info;
60
61 // Member __f_ has type __base*, the contents of which will hold:
62 // 1) a vtable entry which may hold type information needed to discover the
63 // lambda being called
64 // 2) possibly hold a pointer to the callable object
65 // e.g.
66 //
67 // (lldb) frame var -R f_display
68 // (std::__1::function<void (int)>) f_display = {
69 // __buf_ = {
70 // …
71 // }
72 // __f_ = 0x00007ffeefbffa00
73 // }
74 // (lldb) memory read -fA 0x00007ffeefbffa00
75 // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
76 // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
77 //
78 // We will be handling five cases below, std::function is wrapping:
79 //
80 // 1) a lambda we know at compile time. We will obtain the name of the lambda
81 // from the first template pameter from __func's vtable. We will look up
82 // the lambda's operator()() and obtain the line table entry.
83 // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
84 // will be stored after the vtable. We will obtain the lambdas name from
85 // this entry and lookup operator()() and obtain the line table entry.
86 // 3) a callable object via operator()(). We will obtain the name of the
87 // object from the first template parameter from __func's vtable. We will
88 // look up the objectc operator()() and obtain the line table entry.
89 // 4) a member function. A pointer to the function will stored after the
90 // we will obtain the name from this pointer.
91 // 5) a free function. A pointer to the function will stored after the vtable
92 // we will obtain the name from this pointer.
93 ValueObjectSP member__f_(
94 valobj_sp->GetChildMemberWithName(ConstString("__f_"), true));
95 lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0);
96
97 optional_info.member__f_pointer_value = member__f_pointer_value;
98
99 ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
100 Process *process = exe_ctx.GetProcessPtr();
101
102 if (process == nullptr)
103 return optional_info;
104
105 uint32_t address_size = process->GetAddressByteSize();
106 Status status;
107
108 // First item pointed to by __f_ should be the pointer to the vtable for
109 // a __base object.
110 lldb::addr_t vtable_address =
111 process->ReadPointerFromMemory(member__f_pointer_value, status);
112
113 if (status.Fail())
114 return optional_info;
115
116 lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
117 // As commened above we may not have a function pointer but if we do we will
118 // need it.
119 lldb::addr_t possible_function_address =
120 process->ReadPointerFromMemory(address_after_vtable, status);
121
122 if (status.Fail())
123 return optional_info;
124
125 Target &target = process->GetTarget();
126
127 if (target.GetSectionLoadList().IsEmpty())
128 return optional_info;
129
130 Address vtable_addr_resolved;
131 SymbolContext sc;
132 Symbol *symbol;
133
134 if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
135 vtable_addr_resolved))
136 return optional_info;
137
138 target.GetImages().ResolveSymbolContextForAddress(
139 vtable_addr_resolved, eSymbolContextEverything, sc);
140 symbol = sc.symbol;
141
142 if (symbol == nullptr)
143 return optional_info;
144
145 llvm::StringRef vtable_name(symbol->GetName().GetCString());
146 bool found_expected_start_string =
147 vtable_name.startswith("vtable for std::__1::__function::__func<");
148
149 if (!found_expected_start_string)
150 return optional_info;
151
152 // Given case 1 or 3 we have a vtable name, we are want to extract the first
153 // template parameter
154 //
155 // ... __func<main::$_0, std::__1::allocator<main::$_0> ...
156 // ^^^^^^^^^
157 //
158 // We do this by find the first < and , and extracting in between.
159 //
160 // This covers the case of the lambda known at compile time.
161 //
162 size_t first_open_angle_bracket = vtable_name.find('<') + 1;
163 size_t first_comma = vtable_name.find_first_of(',');
164
165 llvm::StringRef first_template_parameter =
166 vtable_name.slice(first_open_angle_bracket, first_comma);
167
168 Address function_address_resolved;
169
170 // Setup for cases 2, 4 and 5 we have a pointer to a function after the
171 // vtable. We will use a process of elimination to drop through each case
172 // and obtain the data we need.
173 if (target.GetSectionLoadList().ResolveLoadAddress(
174 possible_function_address, function_address_resolved)) {
175 target.GetImages().ResolveSymbolContextForAddress(
176 function_address_resolved, eSymbolContextEverything, sc);
177 symbol = sc.symbol;
178 }
179
180 auto get_name = [&first_template_parameter, &symbol]() {
181 // Given case 1:
182 //
183 // main::$_0
184 //
185 // we want to append ::operator()()
186 if (first_template_parameter.contains("$_"))
187 return llvm::Regex::escape(first_template_parameter.str()) +
188 R"(::operator\(\)\(.*\))";
189
190 if (symbol != NULL &&
191 symbol->GetName().GetStringRef().contains("__invoke")) {
192
193 llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
194 size_t pos2 = symbol_name.find_last_of(':');
195
196 // Given case 2:
197 //
198 // main::$_1::__invoke(...)
199 //
200 // We want to slice off __invoke(...) and append operator()()
201 std::string lambda_operator =
202 llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
203 R"(operator\(\)\(.*\))";
204
205 return lambda_operator;
206 }
207
208 // Case 3
209 return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
210 ;
211 };
212
213 std::string func_to_match = get_name();
214
215 SymbolContextList scl;
216
217 target.GetImages().FindFunctions(RegularExpression{func_to_match}, true, true,
218 true, scl);
219
220 // Case 1,2 or 3
221 if (scl.GetSize() >= 1) {
222 SymbolContext sc2 = scl[0];
223
224 AddressRange range;
225 sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);
226
227 Address address = range.GetBaseAddress();
228
229 Address addr;
230 if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
231 addr)) {
232 LineEntry line_entry;
233 addr.CalculateSymbolContextLineEntry(line_entry);
234
235 if (first_template_parameter.contains("$_") ||
236 (symbol != nullptr &&
237 symbol->GetName().GetStringRef().contains("__invoke"))) {
238 // Case 1 and 2
239 optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
240 } else {
241 // Case 3
242 optional_info.callable_case =
243 LibCppStdFunctionCallableCase::CallableObject;
244 }
245
246 optional_info.callable_symbol = *symbol;
247 optional_info.callable_line_entry = line_entry;
248 optional_info.callable_address = addr;
249 return optional_info;
250 }
251 }
252
253 // Case 4 or 5
254 if (!symbol->GetName().GetStringRef().startswith("vtable for")) {
255 optional_info.callable_case =
256 LibCppStdFunctionCallableCase::FreeOrMemberFunction;
257 optional_info.callable_address = function_address_resolved;
258 optional_info.callable_symbol = *symbol;
259
260 return optional_info;
261 }
262
263 return optional_info;
264}