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