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