1 //===-- AppleObjCTrampolineHandler.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 "AppleObjCTrampolineHandler.h" 10 #include "AppleThreadPlanStepThroughObjCTrampoline.h" 11 12 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 13 #include "lldb/Breakpoint/StoppointCallbackContext.h" 14 #include "lldb/Core/Debugger.h" 15 #include "lldb/Core/Module.h" 16 #include "lldb/Core/StreamFile.h" 17 #include "lldb/Core/Value.h" 18 #include "lldb/Expression/DiagnosticManager.h" 19 #include "lldb/Expression/FunctionCaller.h" 20 #include "lldb/Expression/UserExpression.h" 21 #include "lldb/Expression/UtilityFunction.h" 22 #include "lldb/Symbol/Symbol.h" 23 #include "lldb/Target/ABI.h" 24 #include "lldb/Target/ExecutionContext.h" 25 #include "lldb/Target/Process.h" 26 #include "lldb/Target/RegisterContext.h" 27 #include "lldb/Target/Target.h" 28 #include "lldb/Target/Thread.h" 29 #include "lldb/Target/ThreadPlanRunToAddress.h" 30 #include "lldb/Utility/ConstString.h" 31 #include "lldb/Utility/FileSpec.h" 32 #include "lldb/Utility/LLDBLog.h" 33 #include "lldb/Utility/Log.h" 34 35 #include "llvm/ADT/STLExtras.h" 36 #include "llvm/ADT/ScopeExit.h" 37 38 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" 39 40 #include <memory> 41 42 using namespace lldb; 43 using namespace lldb_private; 44 45 const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = 46 "__lldb_objc_find_implementation_for_selector"; 47 const char *AppleObjCTrampolineHandler:: 48 g_lookup_implementation_with_stret_function_code = 49 R"( 50 if (is_stret) { 51 return_struct.impl_addr = 52 class_getMethodImplementation_stret (return_struct.class_addr, 53 return_struct.sel_addr); 54 } else { 55 return_struct.impl_addr = 56 class_getMethodImplementation (return_struct.class_addr, 57 return_struct.sel_addr); 58 } 59 if (debug) 60 printf ("\n*** Returning implementation: %p.\n", 61 return_struct.impl_addr); 62 63 return return_struct.impl_addr; 64 } 65 )"; 66 const char * 67 AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code = 68 R"( 69 return_struct.impl_addr = 70 class_getMethodImplementation (return_struct.class_addr, 71 return_struct.sel_addr); 72 if (debug) 73 printf ("\n*** getMethodImpletation for addr: 0x%p sel: 0x%p result: 0x%p.\n", 74 return_struct.class_addr, return_struct.sel_addr, return_struct.impl_addr); 75 76 return return_struct.impl_addr; 77 } 78 )"; 79 80 const char 81 *AppleObjCTrampolineHandler::g_lookup_implementation_function_common_code = 82 R"( 83 extern "C" 84 { 85 extern void *class_getMethodImplementation(void *objc_class, void *sel); 86 extern void *class_getMethodImplementation_stret(void *objc_class, void *sel); 87 extern void * object_getClass (id object); 88 extern void * sel_getUid(char *name); 89 extern int printf(const char *format, ...); 90 } 91 extern "C" void * 92 __lldb_objc_find_implementation_for_selector (void *object, 93 void *sel, 94 int is_str_ptr, 95 int is_stret, 96 int is_super, 97 int is_super2, 98 int is_fixup, 99 int is_fixed, 100 int debug) 101 { 102 struct __lldb_imp_return_struct { 103 void *class_addr; 104 void *sel_addr; 105 void *impl_addr; 106 }; 107 108 struct __lldb_objc_class { 109 void *isa; 110 void *super_ptr; 111 }; 112 struct __lldb_objc_super { 113 void *receiver; 114 struct __lldb_objc_class *class_ptr; 115 }; 116 struct __lldb_msg_ref { 117 void *dont_know; 118 void *sel; 119 }; 120 121 struct __lldb_imp_return_struct return_struct; 122 123 if (debug) 124 printf ("\n*** Called with obj: %p sel: %p is_str_ptr: %d " 125 "is_stret: %d is_super: %d, " 126 "is_super2: %d, is_fixup: %d, is_fixed: %d\n", 127 object, sel, is_str_ptr, is_stret, 128 is_super, is_super2, is_fixup, is_fixed); 129 130 if (is_str_ptr) { 131 if (debug) 132 printf("*** Turning string: '%s'", sel); 133 sel = sel_getUid((char *)sel); 134 if (debug) 135 printf("*** into sel to %p", sel); 136 } 137 if (is_super) { 138 if (is_super2) { 139 return_struct.class_addr 140 = ((__lldb_objc_super *) object)->class_ptr->super_ptr; 141 } else { 142 return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; 143 } 144 if (debug) 145 printf("*** Super, class addr: %p\n", return_struct.class_addr); 146 } else { 147 // This code seems a little funny, but has its reasons... 148 // The call to [object class] is here because if this is a class, and has 149 // not been called into yet, we need to do something to force the class to 150 // initialize itself. 151 // Then the call to object_getClass will actually return the correct class, 152 // either the class if object is a class instance, or the meta-class if it 153 // is a class pointer. 154 void *class_ptr = (void *) [(id) object class]; 155 return_struct.class_addr = (id) object_getClass((id) object); 156 if (debug) { 157 if (class_ptr == object) { 158 printf ("Found a class object, need to return the meta class %p -> %p\n", 159 class_ptr, return_struct.class_addr); 160 } else { 161 printf ("[object class] returned: %p object_getClass: %p.\n", 162 class_ptr, return_struct.class_addr); 163 } 164 } 165 } 166 167 if (is_fixup) { 168 if (is_fixed) { 169 return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; 170 } else { 171 char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; 172 return_struct.sel_addr = sel_getUid (sel_name); 173 if (debug) 174 printf ("\n*** Got fixed up selector: %p for name %s.\n", 175 return_struct.sel_addr, sel_name); 176 } 177 } else { 178 return_struct.sel_addr = sel; 179 } 180 )"; 181 182 AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion( 183 AppleObjCVTables *owner, lldb::addr_t header_addr) 184 : m_valid(true), m_owner(owner), m_header_addr(header_addr) { 185 SetUpRegion(); 186 } 187 188 AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() = default; 189 190 void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() { 191 // The header looks like: 192 // 193 // uint16_t headerSize 194 // uint16_t descSize 195 // uint32_t descCount 196 // void * next 197 // 198 // First read in the header: 199 200 char memory_buffer[16]; 201 ProcessSP process_sp = m_owner->GetProcessSP(); 202 if (!process_sp) 203 return; 204 DataExtractor data(memory_buffer, sizeof(memory_buffer), 205 process_sp->GetByteOrder(), 206 process_sp->GetAddressByteSize()); 207 size_t actual_size = 8 + process_sp->GetAddressByteSize(); 208 Status error; 209 size_t bytes_read = 210 process_sp->ReadMemory(m_header_addr, memory_buffer, actual_size, error); 211 if (bytes_read != actual_size) { 212 m_valid = false; 213 return; 214 } 215 216 lldb::offset_t offset = 0; 217 const uint16_t header_size = data.GetU16(&offset); 218 const uint16_t descriptor_size = data.GetU16(&offset); 219 const size_t num_descriptors = data.GetU32(&offset); 220 221 m_next_region = data.GetAddress(&offset); 222 223 // If the header size is 0, that means we've come in too early before this 224 // data is set up. 225 // Set ourselves as not valid, and continue. 226 if (header_size == 0 || num_descriptors == 0) { 227 m_valid = false; 228 return; 229 } 230 231 // Now read in all the descriptors: 232 // The descriptor looks like: 233 // 234 // uint32_t offset 235 // uint32_t flags 236 // 237 // Where offset is either 0 - in which case it is unused, or it is 238 // the offset of the vtable code from the beginning of the 239 // descriptor record. Below, we'll convert that into an absolute 240 // code address, since I don't want to have to compute it over and 241 // over. 242 243 // Ingest the whole descriptor array: 244 const lldb::addr_t desc_ptr = m_header_addr + header_size; 245 const size_t desc_array_size = num_descriptors * descriptor_size; 246 WritableDataBufferSP data_sp(new DataBufferHeap(desc_array_size, '\0')); 247 uint8_t *dst = (uint8_t *)data_sp->GetBytes(); 248 249 DataExtractor desc_extractor(dst, desc_array_size, process_sp->GetByteOrder(), 250 process_sp->GetAddressByteSize()); 251 bytes_read = process_sp->ReadMemory(desc_ptr, dst, desc_array_size, error); 252 if (bytes_read != desc_array_size) { 253 m_valid = false; 254 return; 255 } 256 257 // The actual code for the vtables will be laid out consecutively, so I also 258 // compute the start and end of the whole code block. 259 260 offset = 0; 261 m_code_start_addr = 0; 262 m_code_end_addr = 0; 263 264 for (size_t i = 0; i < num_descriptors; i++) { 265 lldb::addr_t start_offset = offset; 266 uint32_t voffset = desc_extractor.GetU32(&offset); 267 uint32_t flags = desc_extractor.GetU32(&offset); 268 lldb::addr_t code_addr = desc_ptr + start_offset + voffset; 269 m_descriptors.push_back(VTableDescriptor(flags, code_addr)); 270 271 if (m_code_start_addr == 0 || code_addr < m_code_start_addr) 272 m_code_start_addr = code_addr; 273 if (code_addr > m_code_end_addr) 274 m_code_end_addr = code_addr; 275 276 offset = start_offset + descriptor_size; 277 } 278 // Finally, a little bird told me that all the vtable code blocks 279 // are the same size. Let's compute the blocks and if they are all 280 // the same add the size to the code end address: 281 lldb::addr_t code_size = 0; 282 bool all_the_same = true; 283 for (size_t i = 0; i < num_descriptors - 1; i++) { 284 lldb::addr_t this_size = 285 m_descriptors[i + 1].code_start - m_descriptors[i].code_start; 286 if (code_size == 0) 287 code_size = this_size; 288 else { 289 if (this_size != code_size) 290 all_the_same = false; 291 if (this_size > code_size) 292 code_size = this_size; 293 } 294 } 295 if (all_the_same) 296 m_code_end_addr += code_size; 297 } 298 299 bool AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion:: 300 AddressInRegion(lldb::addr_t addr, uint32_t &flags) { 301 if (!IsValid()) 302 return false; 303 304 if (addr < m_code_start_addr || addr > m_code_end_addr) 305 return false; 306 307 std::vector<VTableDescriptor>::iterator pos, end = m_descriptors.end(); 308 for (pos = m_descriptors.begin(); pos != end; pos++) { 309 if (addr <= (*pos).code_start) { 310 flags = (*pos).flags; 311 return true; 312 } 313 } 314 return false; 315 } 316 317 void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump( 318 Stream &s) { 319 s.Printf("Header addr: 0x%" PRIx64 " Code start: 0x%" PRIx64 320 " Code End: 0x%" PRIx64 " Next: 0x%" PRIx64 "\n", 321 m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region); 322 size_t num_elements = m_descriptors.size(); 323 for (size_t i = 0; i < num_elements; i++) { 324 s.Indent(); 325 s.Printf("Code start: 0x%" PRIx64 " Flags: %d\n", 326 m_descriptors[i].code_start, m_descriptors[i].flags); 327 } 328 } 329 330 AppleObjCTrampolineHandler::AppleObjCVTables::AppleObjCVTables( 331 const ProcessSP &process_sp, const ModuleSP &objc_module_sp) 332 : m_process_wp(), m_trampoline_header(LLDB_INVALID_ADDRESS), 333 m_trampolines_changed_bp_id(LLDB_INVALID_BREAK_ID), 334 m_objc_module_sp(objc_module_sp) { 335 if (process_sp) 336 m_process_wp = process_sp; 337 } 338 339 AppleObjCTrampolineHandler::AppleObjCVTables::~AppleObjCVTables() { 340 ProcessSP process_sp = GetProcessSP(); 341 if (process_sp) { 342 if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID) 343 process_sp->GetTarget().RemoveBreakpointByID(m_trampolines_changed_bp_id); 344 } 345 } 346 347 bool AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols() { 348 if (m_trampoline_header != LLDB_INVALID_ADDRESS) 349 return true; 350 351 ProcessSP process_sp = GetProcessSP(); 352 if (process_sp) { 353 Target &target = process_sp->GetTarget(); 354 355 if (!m_objc_module_sp) { 356 for (ModuleSP module_sp : target.GetImages().Modules()) { 357 if (ObjCLanguageRuntime::Get(*process_sp) 358 ->IsModuleObjCLibrary(module_sp)) { 359 m_objc_module_sp = module_sp; 360 break; 361 } 362 } 363 } 364 365 if (m_objc_module_sp) { 366 ConstString trampoline_name("gdb_objc_trampolines"); 367 const Symbol *trampoline_symbol = 368 m_objc_module_sp->FindFirstSymbolWithNameAndType(trampoline_name, 369 eSymbolTypeData); 370 if (trampoline_symbol != nullptr) { 371 m_trampoline_header = trampoline_symbol->GetLoadAddress(&target); 372 if (m_trampoline_header == LLDB_INVALID_ADDRESS) 373 return false; 374 375 // Next look up the "changed" symbol and set a breakpoint on that... 376 ConstString changed_name("gdb_objc_trampolines_changed"); 377 const Symbol *changed_symbol = 378 m_objc_module_sp->FindFirstSymbolWithNameAndType(changed_name, 379 eSymbolTypeCode); 380 if (changed_symbol != nullptr) { 381 const Address changed_symbol_addr = changed_symbol->GetAddress(); 382 if (!changed_symbol_addr.IsValid()) 383 return false; 384 385 lldb::addr_t changed_addr = 386 changed_symbol_addr.GetOpcodeLoadAddress(&target); 387 if (changed_addr != LLDB_INVALID_ADDRESS) { 388 BreakpointSP trampolines_changed_bp_sp = 389 target.CreateBreakpoint(changed_addr, true, false); 390 if (trampolines_changed_bp_sp) { 391 m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID(); 392 trampolines_changed_bp_sp->SetCallback(RefreshTrampolines, this, 393 true); 394 trampolines_changed_bp_sp->SetBreakpointKind( 395 "objc-trampolines-changed"); 396 return true; 397 } 398 } 399 } 400 } 401 } 402 } 403 return false; 404 } 405 406 bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines( 407 void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, 408 lldb::user_id_t break_loc_id) { 409 AppleObjCVTables *vtable_handler = (AppleObjCVTables *)baton; 410 if (vtable_handler->InitializeVTableSymbols()) { 411 // The Update function is called with the address of an added region. So we 412 // grab that address, and 413 // feed it into ReadRegions. Of course, our friend the ABI will get the 414 // values for us. 415 ExecutionContext exe_ctx(context->exe_ctx_ref); 416 Process *process = exe_ctx.GetProcessPtr(); 417 const ABI *abi = process->GetABI().get(); 418 419 TypeSystemClang *clang_ast_context = 420 ScratchTypeSystemClang::GetForTarget(process->GetTarget()); 421 if (!clang_ast_context) 422 return false; 423 424 ValueList argument_values; 425 Value input_value; 426 CompilerType clang_void_ptr_type = 427 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 428 429 input_value.SetValueType(Value::ValueType::Scalar); 430 // input_value.SetContext (Value::eContextTypeClangType, 431 // clang_void_ptr_type); 432 input_value.SetCompilerType(clang_void_ptr_type); 433 argument_values.PushValue(input_value); 434 435 bool success = 436 abi->GetArgumentValues(exe_ctx.GetThreadRef(), argument_values); 437 if (!success) 438 return false; 439 440 // Now get a pointer value from the zeroth argument. 441 Status error; 442 DataExtractor data; 443 error = argument_values.GetValueAtIndex(0)->GetValueAsData(&exe_ctx, data, 444 nullptr); 445 lldb::offset_t offset = 0; 446 lldb::addr_t region_addr = data.GetAddress(&offset); 447 448 if (region_addr != 0) 449 vtable_handler->ReadRegions(region_addr); 450 } 451 return false; 452 } 453 454 bool AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions() { 455 // The no argument version reads the start region from the value of 456 // the gdb_regions_header, and gets started from there. 457 458 m_regions.clear(); 459 if (!InitializeVTableSymbols()) 460 return false; 461 Status error; 462 ProcessSP process_sp = GetProcessSP(); 463 if (process_sp) { 464 lldb::addr_t region_addr = 465 process_sp->ReadPointerFromMemory(m_trampoline_header, error); 466 if (error.Success()) 467 return ReadRegions(region_addr); 468 } 469 return false; 470 } 471 472 bool AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions( 473 lldb::addr_t region_addr) { 474 ProcessSP process_sp = GetProcessSP(); 475 if (!process_sp) 476 return false; 477 478 Log *log = GetLog(LLDBLog::Step); 479 480 // We aren't starting at the trampoline symbol. 481 InitializeVTableSymbols(); 482 lldb::addr_t next_region = region_addr; 483 484 // Read in the sizes of the headers. 485 while (next_region != 0) { 486 m_regions.push_back(VTableRegion(this, next_region)); 487 if (!m_regions.back().IsValid()) { 488 m_regions.clear(); 489 return false; 490 } 491 if (log) { 492 StreamString s; 493 m_regions.back().Dump(s); 494 LLDB_LOGF(log, "Read vtable region: \n%s", s.GetData()); 495 } 496 497 next_region = m_regions.back().GetNextRegionAddr(); 498 } 499 500 return true; 501 } 502 503 bool AppleObjCTrampolineHandler::AppleObjCVTables::IsAddressInVTables( 504 lldb::addr_t addr, uint32_t &flags) { 505 region_collection::iterator pos, end = m_regions.end(); 506 for (pos = m_regions.begin(); pos != end; pos++) { 507 if ((*pos).AddressInRegion(addr, flags)) 508 return true; 509 } 510 return false; 511 } 512 513 const AppleObjCTrampolineHandler::DispatchFunction 514 AppleObjCTrampolineHandler::g_dispatch_functions[] = { 515 // NAME STRET SUPER SUPER2 FIXUP TYPE 516 {"objc_msgSend", false, false, false, DispatchFunction::eFixUpNone}, 517 {"objc_msgSend_fixup", false, false, false, 518 DispatchFunction::eFixUpToFix}, 519 {"objc_msgSend_fixedup", false, false, false, 520 DispatchFunction::eFixUpFixed}, 521 {"objc_msgSend_stret", true, false, false, 522 DispatchFunction::eFixUpNone}, 523 {"objc_msgSend_stret_fixup", true, false, false, 524 DispatchFunction::eFixUpToFix}, 525 {"objc_msgSend_stret_fixedup", true, false, false, 526 DispatchFunction::eFixUpFixed}, 527 {"objc_msgSend_fpret", false, false, false, 528 DispatchFunction::eFixUpNone}, 529 {"objc_msgSend_fpret_fixup", false, false, false, 530 DispatchFunction::eFixUpToFix}, 531 {"objc_msgSend_fpret_fixedup", false, false, false, 532 DispatchFunction::eFixUpFixed}, 533 {"objc_msgSend_fp2ret", false, false, true, 534 DispatchFunction::eFixUpNone}, 535 {"objc_msgSend_fp2ret_fixup", false, false, true, 536 DispatchFunction::eFixUpToFix}, 537 {"objc_msgSend_fp2ret_fixedup", false, false, true, 538 DispatchFunction::eFixUpFixed}, 539 {"objc_msgSendSuper", false, true, false, DispatchFunction::eFixUpNone}, 540 {"objc_msgSendSuper_stret", true, true, false, 541 DispatchFunction::eFixUpNone}, 542 {"objc_msgSendSuper2", false, true, true, DispatchFunction::eFixUpNone}, 543 {"objc_msgSendSuper2_fixup", false, true, true, 544 DispatchFunction::eFixUpToFix}, 545 {"objc_msgSendSuper2_fixedup", false, true, true, 546 DispatchFunction::eFixUpFixed}, 547 {"objc_msgSendSuper2_stret", true, true, true, 548 DispatchFunction::eFixUpNone}, 549 {"objc_msgSendSuper2_stret_fixup", true, true, true, 550 DispatchFunction::eFixUpToFix}, 551 {"objc_msgSendSuper2_stret_fixedup", true, true, true, 552 DispatchFunction::eFixUpFixed}, 553 }; 554 555 // This is the table of ObjC "accelerated dispatch" functions. They are a set 556 // of objc methods that are "seldom overridden" and so the compiler replaces the 557 // objc_msgSend with a call to one of the dispatch functions. That will check 558 // whether the method has been overridden, and directly call the Foundation 559 // implementation if not. 560 // This table is supposed to be complete. If ones get added in the future, we 561 // will have to add them to the table. 562 const char *AppleObjCTrampolineHandler::g_opt_dispatch_names[] = { 563 "objc_alloc", 564 "objc_autorelease", 565 "objc_release", 566 "objc_retain", 567 "objc_alloc_init", 568 "objc_allocWithZone", 569 "objc_opt_class", 570 "objc_opt_isKindOfClass", 571 "objc_opt_new", 572 "objc_opt_respondsToSelector", 573 "objc_opt_self", 574 }; 575 576 AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( 577 const ProcessSP &process_sp, const ModuleSP &objc_module_sp) 578 : m_process_wp(), m_objc_module_sp(objc_module_sp), 579 m_impl_fn_addr(LLDB_INVALID_ADDRESS), 580 m_impl_stret_fn_addr(LLDB_INVALID_ADDRESS), 581 m_msg_forward_addr(LLDB_INVALID_ADDRESS), 582 m_msg_forward_stret_addr(LLDB_INVALID_ADDRESS) { 583 if (process_sp) 584 m_process_wp = process_sp; 585 // Look up the known resolution functions: 586 587 ConstString get_impl_name("class_getMethodImplementation"); 588 ConstString get_impl_stret_name("class_getMethodImplementation_stret"); 589 ConstString msg_forward_name("_objc_msgForward"); 590 ConstString msg_forward_stret_name("_objc_msgForward_stret"); 591 592 Target *target = process_sp ? &process_sp->GetTarget() : nullptr; 593 const Symbol *class_getMethodImplementation = 594 m_objc_module_sp->FindFirstSymbolWithNameAndType(get_impl_name, 595 eSymbolTypeCode); 596 const Symbol *class_getMethodImplementation_stret = 597 m_objc_module_sp->FindFirstSymbolWithNameAndType(get_impl_stret_name, 598 eSymbolTypeCode); 599 const Symbol *msg_forward = m_objc_module_sp->FindFirstSymbolWithNameAndType( 600 msg_forward_name, eSymbolTypeCode); 601 const Symbol *msg_forward_stret = 602 m_objc_module_sp->FindFirstSymbolWithNameAndType(msg_forward_stret_name, 603 eSymbolTypeCode); 604 605 if (class_getMethodImplementation) 606 m_impl_fn_addr = 607 class_getMethodImplementation->GetAddress().GetOpcodeLoadAddress( 608 target); 609 if (class_getMethodImplementation_stret) 610 m_impl_stret_fn_addr = 611 class_getMethodImplementation_stret->GetAddress().GetOpcodeLoadAddress( 612 target); 613 if (msg_forward) 614 m_msg_forward_addr = msg_forward->GetAddress().GetOpcodeLoadAddress(target); 615 if (msg_forward_stret) 616 m_msg_forward_stret_addr = 617 msg_forward_stret->GetAddress().GetOpcodeLoadAddress(target); 618 619 // FIXME: Do some kind of logging here. 620 if (m_impl_fn_addr == LLDB_INVALID_ADDRESS) { 621 // If we can't even find the ordinary get method implementation function, 622 // then we aren't going to be able to 623 // step through any method dispatches. Warn to that effect and get out of 624 // here. 625 if (process_sp->CanJIT()) { 626 process_sp->GetTarget().GetDebugger().GetErrorStream().Printf( 627 "Could not find implementation lookup function \"%s\"" 628 " step in through ObjC method dispatch will not work.\n", 629 get_impl_name.AsCString()); 630 } 631 return; 632 } 633 634 // We will either set the implementation to the _stret or non_stret version, 635 // so either way it's safe to start filling the m_lookup_..._code here. 636 m_lookup_implementation_function_code.assign( 637 g_lookup_implementation_function_common_code); 638 639 if (m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS) { 640 // It there is no stret return lookup function, assume that it is the same 641 // as the straight lookup: 642 m_impl_stret_fn_addr = m_impl_fn_addr; 643 // Also we will use the version of the lookup code that doesn't rely on the 644 // stret version of the function. 645 m_lookup_implementation_function_code.append( 646 g_lookup_implementation_no_stret_function_code); 647 } else { 648 m_lookup_implementation_function_code.append( 649 g_lookup_implementation_with_stret_function_code); 650 } 651 652 // Look up the addresses for the objc dispatch functions and cache 653 // them. For now I'm inspecting the symbol names dynamically to 654 // figure out how to dispatch to them. If it becomes more 655 // complicated than this we can turn the g_dispatch_functions char * 656 // array into a template table, and populate the DispatchFunction 657 // map from there. 658 659 for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++) { 660 ConstString name_const_str(g_dispatch_functions[i].name); 661 const Symbol *msgSend_symbol = 662 m_objc_module_sp->FindFirstSymbolWithNameAndType(name_const_str, 663 eSymbolTypeCode); 664 if (msgSend_symbol && msgSend_symbol->ValueIsAddress()) { 665 // FIXME: Make g_dispatch_functions static table of 666 // DispatchFunctions, and have the map be address->index. 667 // Problem is we also need to lookup the dispatch function. For 668 // now we could have a side table of stret & non-stret dispatch 669 // functions. If that's as complex as it gets, we're fine. 670 671 lldb::addr_t sym_addr = 672 msgSend_symbol->GetAddressRef().GetOpcodeLoadAddress(target); 673 674 m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i)); 675 } 676 } 677 678 // Similarly, cache the addresses of the "optimized dispatch" function. 679 for (size_t i = 0; i != llvm::array_lengthof(g_opt_dispatch_names); i++) { 680 ConstString name_const_str(g_opt_dispatch_names[i]); 681 const Symbol *msgSend_symbol = 682 m_objc_module_sp->FindFirstSymbolWithNameAndType(name_const_str, 683 eSymbolTypeCode); 684 if (msgSend_symbol && msgSend_symbol->ValueIsAddress()) { 685 lldb::addr_t sym_addr = 686 msgSend_symbol->GetAddressRef().GetOpcodeLoadAddress(target); 687 688 m_opt_dispatch_map.emplace(sym_addr, i); 689 } 690 } 691 692 // Build our vtable dispatch handler here: 693 m_vtables_up = 694 std::make_unique<AppleObjCVTables>(process_sp, m_objc_module_sp); 695 if (m_vtables_up) 696 m_vtables_up->ReadRegions(); 697 } 698 699 lldb::addr_t 700 AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, 701 ValueList &dispatch_values) { 702 ThreadSP thread_sp(thread.shared_from_this()); 703 ExecutionContext exe_ctx(thread_sp); 704 Log *log = GetLog(LLDBLog::Step); 705 706 lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; 707 FunctionCaller *impl_function_caller = nullptr; 708 709 // Scope for mutex locker: 710 { 711 std::lock_guard<std::mutex> guard(m_impl_function_mutex); 712 713 // First stage is to make the ClangUtility to hold our injected function: 714 715 if (!m_impl_code) { 716 if (!m_lookup_implementation_function_code.empty()) { 717 auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction( 718 m_lookup_implementation_function_code, 719 g_lookup_implementation_function_name, eLanguageTypeC, exe_ctx); 720 if (!utility_fn_or_error) { 721 LLDB_LOG_ERROR( 722 log, utility_fn_or_error.takeError(), 723 "Failed to get Utility Function for implementation lookup: {0}."); 724 return args_addr; 725 } 726 m_impl_code = std::move(*utility_fn_or_error); 727 } else { 728 LLDB_LOGF(log, "No method lookup implementation code."); 729 return LLDB_INVALID_ADDRESS; 730 } 731 732 // Next make the runner function for our implementation utility function. 733 TypeSystemClang *clang_ast_context = ScratchTypeSystemClang::GetForTarget( 734 thread.GetProcess()->GetTarget()); 735 if (!clang_ast_context) 736 return LLDB_INVALID_ADDRESS; 737 738 CompilerType clang_void_ptr_type = 739 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 740 Status error; 741 742 impl_function_caller = m_impl_code->MakeFunctionCaller( 743 clang_void_ptr_type, dispatch_values, thread_sp, error); 744 if (error.Fail()) { 745 LLDB_LOGF(log, 746 "Error getting function caller for dispatch lookup: \"%s\".", 747 error.AsCString()); 748 return args_addr; 749 } 750 } else { 751 impl_function_caller = m_impl_code->GetFunctionCaller(); 752 } 753 } 754 755 // Now write down the argument values for this particular call. 756 // This looks like it might be a race condition if other threads 757 // were calling into here, but actually it isn't because we allocate 758 // a new args structure for this call by passing args_addr = 759 // LLDB_INVALID_ADDRESS... 760 761 DiagnosticManager diagnostics; 762 if (!impl_function_caller->WriteFunctionArguments( 763 exe_ctx, args_addr, dispatch_values, diagnostics)) { 764 if (log) { 765 LLDB_LOGF(log, "Error writing function arguments."); 766 diagnostics.Dump(log); 767 } 768 return args_addr; 769 } 770 771 return args_addr; 772 } 773 774 const AppleObjCTrampolineHandler::DispatchFunction * 775 AppleObjCTrampolineHandler::FindDispatchFunction(lldb::addr_t addr) { 776 MsgsendMap::iterator pos; 777 pos = m_msgSend_map.find(addr); 778 if (pos != m_msgSend_map.end()) { 779 return &g_dispatch_functions[(*pos).second]; 780 } 781 return nullptr; 782 } 783 784 void AppleObjCTrampolineHandler::ForEachDispatchFunction( 785 std::function<void(lldb::addr_t, const DispatchFunction &)> callback) { 786 for (auto elem : m_msgSend_map) { 787 callback(elem.first, g_dispatch_functions[elem.second]); 788 } 789 } 790 791 ThreadPlanSP 792 AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, 793 bool stop_others) { 794 ThreadPlanSP ret_plan_sp; 795 lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC(); 796 797 DispatchFunction vtable_dispatch = {"vtable", false, false, false, 798 DispatchFunction::eFixUpFixed}; 799 // The selector specific stubs are a wrapper for objc_msgSend. They don't get 800 // passed a SEL, but instead the selector string is encoded in the stub 801 // name, in the form: 802 // objc_msgSend$SelectorName 803 // and the stub figures out the uniqued selector. If we find ourselves in 804 // one of these stubs, we strip off the selector string and pass that to the 805 // implementation finder function, which looks up the SEL (you have to do this 806 // in process) and passes that to the runtime lookup function. 807 DispatchFunction sel_stub_dispatch = {"sel-specific-stub", false, false, 808 false, DispatchFunction::eFixUpNone}; 809 810 // First step is to see if we're in a selector-specific dispatch stub. 811 // Those are of the form _objc_msgSend$<SELECTOR>, so see if the current 812 // function has that name: 813 Address func_addr; 814 Target &target = thread.GetProcess()->GetTarget(); 815 llvm::StringRef sym_name; 816 const DispatchFunction *this_dispatch = nullptr; 817 818 if (target.ResolveLoadAddress(curr_pc, func_addr)) { 819 Symbol *curr_sym = func_addr.CalculateSymbolContextSymbol(); 820 if (curr_sym) 821 sym_name = curr_sym->GetName().GetStringRef(); 822 823 if (!sym_name.empty() && !sym_name.consume_front("objc_msgSend$")) 824 sym_name = {}; 825 else 826 this_dispatch = &sel_stub_dispatch; 827 } 828 bool in_selector_stub = !sym_name.empty(); 829 // Second step is to look and see if we are in one of the known ObjC 830 // dispatch functions. We've already compiled a table of same, so 831 // consult it. 832 833 if (!in_selector_stub) 834 this_dispatch = FindDispatchFunction(curr_pc); 835 836 // Next check to see if we are in a vtable region: 837 838 if (!this_dispatch && m_vtables_up) { 839 uint32_t flags; 840 if (m_vtables_up->IsAddressInVTables(curr_pc, flags)) { 841 vtable_dispatch.stret_return = 842 (flags & AppleObjCVTables::eOBJC_TRAMPOLINE_STRET) == 843 AppleObjCVTables::eOBJC_TRAMPOLINE_STRET; 844 this_dispatch = &vtable_dispatch; 845 } 846 } 847 848 // Since we set this_dispatch in both the vtable & sel specific stub cases 849 // this if will be used for all three of those cases. 850 if (this_dispatch) { 851 Log *log = GetLog(LLDBLog::Step); 852 853 // We are decoding a method dispatch. First job is to pull the 854 // arguments out. If we are in a regular stub, we get self & selector, 855 // but if we are in a selector-specific stub, we'll have to get that from 856 // the string sym_name. 857 858 lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); 859 860 const ABI *abi = nullptr; 861 ProcessSP process_sp(thread.CalculateProcess()); 862 if (process_sp) 863 abi = process_sp->GetABI().get(); 864 if (abi == nullptr) 865 return ret_plan_sp; 866 867 TargetSP target_sp(thread.CalculateTarget()); 868 869 TypeSystemClang *clang_ast_context = 870 ScratchTypeSystemClang::GetForTarget(*target_sp); 871 if (!clang_ast_context) 872 return ret_plan_sp; 873 874 ValueList argument_values; 875 Value void_ptr_value; 876 CompilerType clang_void_ptr_type = 877 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 878 void_ptr_value.SetValueType(Value::ValueType::Scalar); 879 // void_ptr_value.SetContext (Value::eContextTypeClangType, 880 // clang_void_ptr_type); 881 void_ptr_value.SetCompilerType(clang_void_ptr_type); 882 883 int obj_index; 884 int sel_index; 885 886 // If this is a selector-specific stub then just push one value, 'cause 887 // we only get the object. 888 // If this is a struct return dispatch, then the first argument is 889 // the return struct pointer, and the object is the second, and 890 // the selector is the third. 891 // Otherwise the object is the first and the selector the second. 892 if (in_selector_stub) { 893 obj_index = 0; 894 sel_index = 1; 895 argument_values.PushValue(void_ptr_value); 896 } else if (this_dispatch->stret_return) { 897 obj_index = 1; 898 sel_index = 2; 899 argument_values.PushValue(void_ptr_value); 900 argument_values.PushValue(void_ptr_value); 901 argument_values.PushValue(void_ptr_value); 902 } else { 903 obj_index = 0; 904 sel_index = 1; 905 argument_values.PushValue(void_ptr_value); 906 argument_values.PushValue(void_ptr_value); 907 } 908 909 bool success = abi->GetArgumentValues(thread, argument_values); 910 if (!success) 911 return ret_plan_sp; 912 913 lldb::addr_t obj_addr = 914 argument_values.GetValueAtIndex(obj_index)->GetScalar().ULongLong(); 915 if (obj_addr == 0x0) { 916 LLDB_LOGF( 917 log, 918 "Asked to step to dispatch to nil object, returning empty plan."); 919 return ret_plan_sp; 920 } 921 922 ExecutionContext exe_ctx(thread.shared_from_this()); 923 // isa_addr will store the class pointer that the method is being 924 // dispatched to - so either the class directly or the super class 925 // if this is one of the objc_msgSendSuper flavors. That's mostly 926 // used to look up the class/selector pair in our cache. 927 928 lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS; 929 lldb::addr_t sel_addr = LLDB_INVALID_ADDRESS; 930 // If we are not in a selector stub, get the sel address from the arguments. 931 if (!in_selector_stub) 932 sel_addr = 933 argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong(); 934 935 // Figure out the class this is being dispatched to and see if 936 // we've already cached this method call, If so we can push a 937 // run-to-address plan directly. Otherwise we have to figure out 938 // where the implementation lives. 939 940 if (this_dispatch->is_super) { 941 if (this_dispatch->is_super2) { 942 // In the objc_msgSendSuper2 case, we don't get the object 943 // directly, we get a structure containing the object and the 944 // class to which the super message is being sent. So we need 945 // to dig the super out of the class and use that. 946 947 Value super_value(*(argument_values.GetValueAtIndex(obj_index))); 948 super_value.GetScalar() += process_sp->GetAddressByteSize(); 949 super_value.ResolveValue(&exe_ctx); 950 951 if (super_value.GetScalar().IsValid()) { 952 953 // isa_value now holds the class pointer. The second word of the 954 // class pointer is the super-class pointer: 955 super_value.GetScalar() += process_sp->GetAddressByteSize(); 956 super_value.ResolveValue(&exe_ctx); 957 if (super_value.GetScalar().IsValid()) 958 isa_addr = super_value.GetScalar().ULongLong(); 959 else { 960 LLDB_LOGF(log, "Failed to extract the super class value from the " 961 "class in objc_super."); 962 } 963 } else { 964 LLDB_LOGF(log, "Failed to extract the class value from objc_super."); 965 } 966 } else { 967 // In the objc_msgSendSuper case, we don't get the object 968 // directly, we get a two element structure containing the 969 // object and the super class to which the super message is 970 // being sent. So the class we want is the second element of 971 // this structure. 972 973 Value super_value(*(argument_values.GetValueAtIndex(obj_index))); 974 super_value.GetScalar() += process_sp->GetAddressByteSize(); 975 super_value.ResolveValue(&exe_ctx); 976 977 if (super_value.GetScalar().IsValid()) { 978 isa_addr = super_value.GetScalar().ULongLong(); 979 } else { 980 LLDB_LOGF(log, "Failed to extract the class value from objc_super."); 981 } 982 } 983 } else { 984 // In the direct dispatch case, the object->isa is the class pointer we 985 // want. 986 987 // This is a little cheesy, but since object->isa is the first field, 988 // making the object value a load address value and resolving it will get 989 // the pointer sized data pointed to by that value... 990 991 // Note, it isn't a fatal error not to be able to get the 992 // address from the object, since this might be a "tagged 993 // pointer" which isn't a real object, but rather some word 994 // length encoded dingus. 995 996 Value isa_value(*(argument_values.GetValueAtIndex(obj_index))); 997 998 isa_value.SetValueType(Value::ValueType::LoadAddress); 999 isa_value.ResolveValue(&exe_ctx); 1000 if (isa_value.GetScalar().IsValid()) { 1001 isa_addr = isa_value.GetScalar().ULongLong(); 1002 } else { 1003 LLDB_LOGF(log, "Failed to extract the isa value from object."); 1004 } 1005 } 1006 1007 // Okay, we've got the address of the class for which we're resolving this, 1008 // let's see if it's in our cache: 1009 lldb::addr_t impl_addr = LLDB_INVALID_ADDRESS; 1010 // If this is a regular dispatch, look up the sel in our addr to sel cache: 1011 if (isa_addr != LLDB_INVALID_ADDRESS) { 1012 ObjCLanguageRuntime *objc_runtime = 1013 ObjCLanguageRuntime::Get(*thread.GetProcess()); 1014 assert(objc_runtime != nullptr); 1015 if (!in_selector_stub) { 1016 LLDB_LOG(log, "Resolving call for class - {0} and selector - {1}", 1017 isa_addr, sel_addr); 1018 impl_addr = objc_runtime->LookupInMethodCache(isa_addr, sel_addr); 1019 } else { 1020 LLDB_LOG(log, "Resolving call for class - {0} and selector - {1}", 1021 isa_addr, sym_name); 1022 impl_addr = objc_runtime->LookupInMethodCache(isa_addr, sym_name); 1023 } 1024 } 1025 // If it is a selector-specific stub dispatch, look in the string cache: 1026 1027 if (impl_addr != LLDB_INVALID_ADDRESS) { 1028 // Yup, it was in the cache, so we can run to that address directly. 1029 1030 LLDB_LOGF(log, "Found implementation address in cache: 0x%" PRIx64, 1031 impl_addr); 1032 1033 ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(thread, impl_addr, 1034 stop_others); 1035 } else { 1036 // We haven't seen this class/selector pair yet. Look it up. 1037 StreamString errors; 1038 Address impl_code_address; 1039 1040 ValueList dispatch_values; 1041 1042 // We've will inject a little function in the target that takes the 1043 // object, selector/selector string and some flags, 1044 // and figures out the implementation. Looks like: 1045 // void *__lldb_objc_find_implementation_for_selector (void *object, 1046 // void *sel, 1047 // int 1048 // is_str_ptr, 1049 // int is_stret, 1050 // int is_super, 1051 // int is_super2, 1052 // int is_fixup, 1053 // int is_fixed, 1054 // int debug) 1055 // If we don't have an actual SEL, but rather a string version of the 1056 // selector WE injected, set is_str_ptr to true, and sel to the address 1057 // of the string. 1058 // So set up the arguments for that call. 1059 1060 dispatch_values.PushValue(*(argument_values.GetValueAtIndex(obj_index))); 1061 lldb::addr_t sel_str_addr = LLDB_INVALID_ADDRESS; 1062 if (!in_selector_stub) { 1063 // If we don't have a selector string, push the selector from arguments. 1064 dispatch_values.PushValue( 1065 *(argument_values.GetValueAtIndex(sel_index))); 1066 } else { 1067 // Otherwise, inject the string into the target, and push that value for 1068 // the sel argument. 1069 Status error; 1070 sel_str_addr = process_sp->AllocateMemory( 1071 sym_name.size() + 1, ePermissionsReadable | ePermissionsWritable, 1072 error); 1073 if (sel_str_addr == LLDB_INVALID_ADDRESS || error.Fail()) { 1074 LLDB_LOG(log, 1075 "Could not allocate memory for selector string {0}: {1}", 1076 sym_name, error); 1077 return ret_plan_sp; 1078 } 1079 process_sp->WriteMemory(sel_str_addr, sym_name.str().c_str(), 1080 sym_name.size() + 1, error); 1081 if (error.Fail()) { 1082 LLDB_LOG(log, "Could not write string to address {0}", sel_str_addr); 1083 return ret_plan_sp; 1084 } 1085 Value sel_ptr_value(void_ptr_value); 1086 sel_ptr_value.GetScalar() = sel_str_addr; 1087 dispatch_values.PushValue(sel_ptr_value); 1088 } 1089 1090 Value flag_value; 1091 CompilerType clang_int_type = 1092 clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( 1093 lldb::eEncodingSint, 32); 1094 flag_value.SetValueType(Value::ValueType::Scalar); 1095 // flag_value.SetContext (Value::eContextTypeClangType, clang_int_type); 1096 flag_value.SetCompilerType(clang_int_type); 1097 1098 if (in_selector_stub) 1099 flag_value.GetScalar() = 1; 1100 else 1101 flag_value.GetScalar() = 0; 1102 dispatch_values.PushValue(flag_value); 1103 1104 if (this_dispatch->stret_return) 1105 flag_value.GetScalar() = 1; 1106 else 1107 flag_value.GetScalar() = 0; 1108 dispatch_values.PushValue(flag_value); 1109 1110 if (this_dispatch->is_super) 1111 flag_value.GetScalar() = 1; 1112 else 1113 flag_value.GetScalar() = 0; 1114 dispatch_values.PushValue(flag_value); 1115 1116 if (this_dispatch->is_super2) 1117 flag_value.GetScalar() = 1; 1118 else 1119 flag_value.GetScalar() = 0; 1120 dispatch_values.PushValue(flag_value); 1121 1122 switch (this_dispatch->fixedup) { 1123 case DispatchFunction::eFixUpNone: 1124 flag_value.GetScalar() = 0; 1125 dispatch_values.PushValue(flag_value); 1126 dispatch_values.PushValue(flag_value); 1127 break; 1128 case DispatchFunction::eFixUpFixed: 1129 flag_value.GetScalar() = 1; 1130 dispatch_values.PushValue(flag_value); 1131 flag_value.GetScalar() = 1; 1132 dispatch_values.PushValue(flag_value); 1133 break; 1134 case DispatchFunction::eFixUpToFix: 1135 flag_value.GetScalar() = 1; 1136 dispatch_values.PushValue(flag_value); 1137 flag_value.GetScalar() = 0; 1138 dispatch_values.PushValue(flag_value); 1139 break; 1140 } 1141 if (log && log->GetVerbose()) 1142 flag_value.GetScalar() = 1; 1143 else 1144 flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done. 1145 dispatch_values.PushValue(flag_value); 1146 1147 ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughObjCTrampoline>( 1148 thread, *this, dispatch_values, isa_addr, sel_addr, sel_str_addr, 1149 sym_name); 1150 if (log) { 1151 StreamString s; 1152 ret_plan_sp->GetDescription(&s, eDescriptionLevelFull); 1153 LLDB_LOGF(log, "Using ObjC step plan: %s.\n", s.GetData()); 1154 } 1155 } 1156 } 1157 1158 // Finally, check if we have hit an "optimized dispatch" function. This will 1159 // either directly call the base implementation or dispatch an objc_msgSend 1160 // if the method has been overridden. So we just do a "step in/step out", 1161 // setting a breakpoint on objc_msgSend, and if we hit the msgSend, we 1162 // will automatically step in again. That's the job of the 1163 // AppleThreadPlanStepThroughDirectDispatch. 1164 if (!this_dispatch && !ret_plan_sp) { 1165 MsgsendMap::iterator pos; 1166 pos = m_opt_dispatch_map.find(curr_pc); 1167 if (pos != m_opt_dispatch_map.end()) { 1168 const char *opt_name = g_opt_dispatch_names[(*pos).second]; 1169 ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughDirectDispatch>( 1170 thread, *this, opt_name); 1171 } 1172 } 1173 1174 return ret_plan_sp; 1175 } 1176 1177 FunctionCaller * 1178 AppleObjCTrampolineHandler::GetLookupImplementationFunctionCaller() { 1179 return m_impl_code->GetFunctionCaller(); 1180 } 1181