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 #include <iostream> 11 12 #include <memory> 13 14 #include "CPPLanguageRuntime.h" 15 16 #include "llvm/ADT/StringRef.h" 17 18 #include "lldb/Symbol/Block.h" 19 #include "lldb/Symbol/Variable.h" 20 #include "lldb/Symbol/VariableList.h" 21 22 #include "lldb/Core/PluginManager.h" 23 #include "lldb/Core/UniqueCStringMap.h" 24 #include "lldb/Symbol/CompileUnit.h" 25 #include "lldb/Target/ABI.h" 26 #include "lldb/Target/ExecutionContext.h" 27 #include "lldb/Target/RegisterContext.h" 28 #include "lldb/Target/SectionLoadList.h" 29 #include "lldb/Target/StackFrame.h" 30 #include "lldb/Target/StackFrameRecognizer.h" 31 #include "lldb/Target/ThreadPlanRunToAddress.h" 32 #include "lldb/Target/ThreadPlanStepInRange.h" 33 #include "lldb/Utility/Timer.h" 34 35 using namespace lldb; 36 using namespace lldb_private; 37 38 static ConstString g_this = ConstString("this"); 39 // Artificial coroutine-related variables emitted by clang. 40 static ConstString g_promise = ConstString("__promise"); 41 static ConstString g_coro_frame = ConstString("__coro_frame"); 42 43 char CPPLanguageRuntime::ID = 0; 44 45 /// A frame recognizer that is installed to hide libc++ implementation 46 /// details from the backtrace. 47 class LibCXXFrameRecognizer : public StackFrameRecognizer { 48 std::array<RegularExpression, 2> m_hidden_regex; 49 RecognizedStackFrameSP m_hidden_frame; 50 51 struct LibCXXHiddenFrame : public RecognizedStackFrame { 52 bool ShouldHide() override { return true; } 53 }; 54 55 public: 56 LibCXXFrameRecognizer() 57 : m_hidden_regex{ 58 // internal implementation details in the `std::` namespace 59 // std::__1::__function::__alloc_func<void (*)(), std::__1::allocator<void (*)()>, void ()>::operator()[abi:ne200000] 60 // std::__1::__function::__func<void (*)(), std::__1::allocator<void (*)()>, void ()>::operator() 61 // std::__1::__function::__value_func<void ()>::operator()[abi:ne200000]() const 62 // std::__2::__function::__policy_invoker<void (int, int)>::__call_impl[abi:ne200000]<std::__2::__function::__default_alloc_func<int (*)(int, int), int (int, int)>> 63 // std::__1::__invoke[abi:ne200000]<void (*&)()> 64 // std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ne200000]<void (*&)()> 65 RegularExpression{R"(^std::__[^:]*::__)"}, 66 // internal implementation details in the `std::ranges` namespace 67 // std::__1::ranges::__sort::__sort_fn_impl[abi:ne200000]<std::__1::__wrap_iter<int*>, std::__1::__wrap_iter<int*>, bool (*)(int, int), std::__1::identity> 68 RegularExpression{R"(^std::__[^:]*::ranges::__)"}, 69 }, 70 m_hidden_frame(new LibCXXHiddenFrame()) {} 71 72 std::string GetName() override { return "libc++ frame recognizer"; } 73 74 lldb::RecognizedStackFrameSP 75 RecognizeFrame(lldb::StackFrameSP frame_sp) override { 76 if (!frame_sp) 77 return {}; 78 const auto &sc = frame_sp->GetSymbolContext(lldb::eSymbolContextFunction); 79 if (!sc.function) 80 return {}; 81 82 // Check if we have a regex match 83 for (RegularExpression &r : m_hidden_regex) { 84 if (!r.Execute(sc.function->GetNameNoArguments())) 85 continue; 86 87 // Only hide this frame if the immediate caller is also within libc++. 88 lldb::ThreadSP thread_sp = frame_sp->GetThread(); 89 if (!thread_sp) 90 return {}; 91 lldb::StackFrameSP parent_frame_sp = 92 thread_sp->GetStackFrameAtIndex(frame_sp->GetFrameIndex() + 1); 93 if (!parent_frame_sp) 94 return {}; 95 const auto &parent_sc = 96 parent_frame_sp->GetSymbolContext(lldb::eSymbolContextFunction); 97 if (!parent_sc.function) 98 return {}; 99 if (parent_sc.function->GetNameNoArguments().GetStringRef().starts_with( 100 "std::")) 101 return m_hidden_frame; 102 } 103 104 return {}; 105 } 106 }; 107 108 CPPLanguageRuntime::CPPLanguageRuntime(Process *process) 109 : LanguageRuntime(process) { 110 if (process) 111 process->GetTarget().GetFrameRecognizerManager().AddRecognizer( 112 StackFrameRecognizerSP(new LibCXXFrameRecognizer()), {}, 113 std::make_shared<RegularExpression>("^std::__[^:]*::"), 114 /*mangling_preference=*/Mangled::ePreferDemangledWithoutArguments, 115 /*first_instruction_only=*/false); 116 } 117 118 bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) { 119 return name == g_this || name == g_promise || name == g_coro_frame; 120 } 121 122 llvm::Error CPPLanguageRuntime::GetObjectDescription(Stream &str, 123 ValueObject &object) { 124 // C++ has no generic way to do this. 125 return llvm::createStringError("C++ does not support object descriptions"); 126 } 127 128 llvm::Error 129 CPPLanguageRuntime::GetObjectDescription(Stream &str, Value &value, 130 ExecutionContextScope *exe_scope) { 131 // C++ has no generic way to do this. 132 return llvm::createStringError("C++ does not support object descriptions"); 133 } 134 135 bool contains_lambda_identifier(llvm::StringRef &str_ref) { 136 return str_ref.contains("$_") || str_ref.contains("'lambda'"); 137 } 138 139 CPPLanguageRuntime::LibCppStdFunctionCallableInfo 140 line_entry_helper(Target &target, const SymbolContext &sc, Symbol *symbol, 141 llvm::StringRef first_template_param_sref, bool has_invoke) { 142 143 CPPLanguageRuntime::LibCppStdFunctionCallableInfo optional_info; 144 145 AddressRange range; 146 sc.GetAddressRange(eSymbolContextEverything, 0, false, range); 147 148 Address address = range.GetBaseAddress(); 149 150 Address addr; 151 if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target), 152 addr)) { 153 LineEntry line_entry; 154 addr.CalculateSymbolContextLineEntry(line_entry); 155 156 if (contains_lambda_identifier(first_template_param_sref) || has_invoke) { 157 // Case 1 and 2 158 optional_info.callable_case = lldb_private::CPPLanguageRuntime:: 159 LibCppStdFunctionCallableCase::Lambda; 160 } else { 161 // Case 3 162 optional_info.callable_case = lldb_private::CPPLanguageRuntime:: 163 LibCppStdFunctionCallableCase::CallableObject; 164 } 165 166 optional_info.callable_symbol = *symbol; 167 optional_info.callable_line_entry = line_entry; 168 optional_info.callable_address = addr; 169 } 170 171 return optional_info; 172 } 173 174 CPPLanguageRuntime::LibCppStdFunctionCallableInfo 175 CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( 176 lldb::ValueObjectSP &valobj_sp) { 177 LLDB_SCOPED_TIMER(); 178 179 LibCppStdFunctionCallableInfo optional_info; 180 181 if (!valobj_sp) 182 return optional_info; 183 184 // Member __f_ has type __base*, the contents of which will hold: 185 // 1) a vtable entry which may hold type information needed to discover the 186 // lambda being called 187 // 2) possibly hold a pointer to the callable object 188 // e.g. 189 // 190 // (lldb) frame var -R f_display 191 // (std::__1::function<void (int)>) f_display = { 192 // __buf_ = { 193 // … 194 // } 195 // __f_ = 0x00007ffeefbffa00 196 // } 197 // (lldb) memory read -fA 0x00007ffeefbffa00 198 // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ... 199 // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ... 200 // 201 // We will be handling five cases below, std::function is wrapping: 202 // 203 // 1) a lambda we know at compile time. We will obtain the name of the lambda 204 // from the first template pameter from __func's vtable. We will look up 205 // the lambda's operator()() and obtain the line table entry. 206 // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method 207 // will be stored after the vtable. We will obtain the lambdas name from 208 // this entry and lookup operator()() and obtain the line table entry. 209 // 3) a callable object via operator()(). We will obtain the name of the 210 // object from the first template parameter from __func's vtable. We will 211 // look up the objects operator()() and obtain the line table entry. 212 // 4) a member function. A pointer to the function will stored after the 213 // we will obtain the name from this pointer. 214 // 5) a free function. A pointer to the function will stored after the vtable 215 // we will obtain the name from this pointer. 216 ValueObjectSP member_f_(valobj_sp->GetChildMemberWithName("__f_")); 217 218 if (member_f_) { 219 ValueObjectSP sub_member_f_(member_f_->GetChildMemberWithName("__f_")); 220 221 if (sub_member_f_) 222 member_f_ = sub_member_f_; 223 } 224 225 if (!member_f_) 226 return optional_info; 227 228 lldb::addr_t member_f_pointer_value = member_f_->GetValueAsUnsigned(0); 229 230 optional_info.member_f_pointer_value = member_f_pointer_value; 231 232 if (!member_f_pointer_value) 233 return optional_info; 234 235 ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef()); 236 Process *process = exe_ctx.GetProcessPtr(); 237 238 if (process == nullptr) 239 return optional_info; 240 241 uint32_t address_size = process->GetAddressByteSize(); 242 Status status; 243 244 // First item pointed to by __f_ should be the pointer to the vtable for 245 // a __base object. 246 lldb::addr_t vtable_address = 247 process->ReadPointerFromMemory(member_f_pointer_value, status); 248 249 if (status.Fail()) 250 return optional_info; 251 252 lldb::addr_t vtable_address_first_entry = 253 process->ReadPointerFromMemory(vtable_address + address_size, status); 254 255 if (status.Fail()) 256 return optional_info; 257 258 lldb::addr_t address_after_vtable = member_f_pointer_value + address_size; 259 // As commented above we may not have a function pointer but if we do we will 260 // need it. 261 lldb::addr_t possible_function_address = 262 process->ReadPointerFromMemory(address_after_vtable, status); 263 264 if (status.Fail()) 265 return optional_info; 266 267 Target &target = process->GetTarget(); 268 269 if (!target.HasLoadedSections()) 270 return optional_info; 271 272 Address vtable_first_entry_resolved; 273 274 if (!target.ResolveLoadAddress(vtable_address_first_entry, 275 vtable_first_entry_resolved)) 276 return optional_info; 277 278 Address vtable_addr_resolved; 279 SymbolContext sc; 280 Symbol *symbol = nullptr; 281 282 if (!target.ResolveLoadAddress(vtable_address, vtable_addr_resolved)) 283 return optional_info; 284 285 target.GetImages().ResolveSymbolContextForAddress( 286 vtable_addr_resolved, eSymbolContextEverything, sc); 287 symbol = sc.symbol; 288 289 if (symbol == nullptr) 290 return optional_info; 291 292 llvm::StringRef vtable_name(symbol->GetName().GetStringRef()); 293 bool found_expected_start_string = 294 vtable_name.starts_with("vtable for std::__1::__function::__func<"); 295 296 if (!found_expected_start_string) 297 return optional_info; 298 299 // Given case 1 or 3 we have a vtable name, we are want to extract the first 300 // template parameter 301 // 302 // ... __func<main::$_0, std::__1::allocator<main::$_0> ... 303 // ^^^^^^^^^ 304 // 305 // We could see names such as: 306 // main::$_0 307 // Bar::add_num2(int)::'lambda'(int) 308 // Bar 309 // 310 // We do this by find the first < and , and extracting in between. 311 // 312 // This covers the case of the lambda known at compile time. 313 size_t first_open_angle_bracket = vtable_name.find('<') + 1; 314 size_t first_comma = vtable_name.find(','); 315 316 llvm::StringRef first_template_parameter = 317 vtable_name.slice(first_open_angle_bracket, first_comma); 318 319 Address function_address_resolved; 320 321 // Setup for cases 2, 4 and 5 we have a pointer to a function after the 322 // vtable. We will use a process of elimination to drop through each case 323 // and obtain the data we need. 324 if (target.ResolveLoadAddress(possible_function_address, 325 function_address_resolved)) { 326 target.GetImages().ResolveSymbolContextForAddress( 327 function_address_resolved, eSymbolContextEverything, sc); 328 symbol = sc.symbol; 329 } 330 331 // These conditions are used several times to simplify statements later on. 332 bool has_invoke = 333 (symbol ? symbol->GetName().GetStringRef().contains("__invoke") : false); 334 auto calculate_symbol_context_helper = [](auto &t, 335 SymbolContextList &sc_list) { 336 SymbolContext sc; 337 t->CalculateSymbolContext(&sc); 338 sc_list.Append(sc); 339 }; 340 341 // Case 2 342 if (has_invoke) { 343 SymbolContextList scl; 344 calculate_symbol_context_helper(symbol, scl); 345 346 return line_entry_helper(target, scl[0], symbol, first_template_parameter, 347 has_invoke); 348 } 349 350 // Case 4 or 5 351 if (symbol && !symbol->GetName().GetStringRef().starts_with("vtable for") && 352 !contains_lambda_identifier(first_template_parameter) && !has_invoke) { 353 optional_info.callable_case = 354 LibCppStdFunctionCallableCase::FreeOrMemberFunction; 355 optional_info.callable_address = function_address_resolved; 356 optional_info.callable_symbol = *symbol; 357 358 return optional_info; 359 } 360 361 std::string func_to_match = first_template_parameter.str(); 362 363 auto it = CallableLookupCache.find(func_to_match); 364 if (it != CallableLookupCache.end()) 365 return it->second; 366 367 SymbolContextList scl; 368 369 CompileUnit *vtable_cu = 370 vtable_first_entry_resolved.CalculateSymbolContextCompileUnit(); 371 llvm::StringRef name_to_use = func_to_match; 372 373 // Case 3, we have a callable object instead of a lambda 374 // 375 // TODO 376 // We currently don't support this case a callable object may have multiple 377 // operator()() varying on const/non-const and number of arguments and we 378 // don't have a way to currently distinguish them so we will bail out now. 379 if (!contains_lambda_identifier(name_to_use)) 380 return optional_info; 381 382 if (vtable_cu && !has_invoke) { 383 lldb::FunctionSP func_sp = 384 vtable_cu->FindFunction([name_to_use](const FunctionSP &f) { 385 auto name = f->GetName().GetStringRef(); 386 if (name.starts_with(name_to_use) && name.contains("operator")) 387 return true; 388 389 return false; 390 }); 391 392 if (func_sp) { 393 calculate_symbol_context_helper(func_sp, scl); 394 } 395 } 396 397 if (symbol == nullptr) 398 return optional_info; 399 400 // Case 1 or 3 401 if (scl.GetSize() >= 1) { 402 optional_info = line_entry_helper(target, scl[0], symbol, 403 first_template_parameter, has_invoke); 404 } 405 406 CallableLookupCache[func_to_match] = optional_info; 407 408 return optional_info; 409 } 410 411 lldb::ThreadPlanSP 412 CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, 413 bool stop_others) { 414 ThreadPlanSP ret_plan_sp; 415 416 lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC(); 417 418 TargetSP target_sp(thread.CalculateTarget()); 419 420 if (!target_sp->HasLoadedSections()) 421 return ret_plan_sp; 422 423 Address pc_addr_resolved; 424 SymbolContext sc; 425 Symbol *symbol; 426 427 if (!target_sp->ResolveLoadAddress(curr_pc, pc_addr_resolved)) 428 return ret_plan_sp; 429 430 target_sp->GetImages().ResolveSymbolContextForAddress( 431 pc_addr_resolved, eSymbolContextEverything, sc); 432 symbol = sc.symbol; 433 434 if (symbol == nullptr) 435 return ret_plan_sp; 436 437 llvm::StringRef function_name(symbol->GetName().GetCString()); 438 439 // Handling the case where we are attempting to step into std::function. 440 // The behavior will be that we will attempt to obtain the wrapped 441 // callable via FindLibCppStdFunctionCallableInfo() and if we find it we 442 // will return a ThreadPlanRunToAddress to the callable. Therefore we will 443 // step into the wrapped callable. 444 // 445 bool found_expected_start_string = 446 function_name.starts_with("std::__1::function<"); 447 448 if (!found_expected_start_string) 449 return ret_plan_sp; 450 451 AddressRange range_of_curr_func; 452 sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func); 453 454 StackFrameSP frame = thread.GetStackFrameAtIndex(0); 455 456 if (frame) { 457 ValueObjectSP value_sp = frame->FindVariable(g_this); 458 459 CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info = 460 FindLibCppStdFunctionCallableInfo(value_sp); 461 462 if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid && 463 value_sp->GetValueIsValid()) { 464 // We found the std::function wrapped callable and we have its address. 465 // We now create a ThreadPlan to run to the callable. 466 ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>( 467 thread, callable_info.callable_address, stop_others); 468 return ret_plan_sp; 469 } else { 470 // We are in std::function but we could not obtain the callable. 471 // We create a ThreadPlan to keep stepping through using the address range 472 // of the current function. 473 ret_plan_sp = std::make_shared<ThreadPlanStepInRange>( 474 thread, range_of_curr_func, sc, nullptr, eOnlyThisThread, 475 eLazyBoolYes, eLazyBoolYes); 476 return ret_plan_sp; 477 } 478 } 479 480 return ret_plan_sp; 481 } 482