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