1 //===-- DynamicLoaderMacOSXDYLD.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 "lldb/Breakpoint/StoppointCallbackContext.h" 11 #include "lldb/Core/DataBuffer.h" 12 #include "lldb/Core/DataBufferHeap.h" 13 #include "lldb/Core/Log.h" 14 #include "lldb/Core/Module.h" 15 #include "lldb/Core/PluginManager.h" 16 #include "lldb/Core/State.h" 17 #include "lldb/Symbol/ObjectFile.h" 18 #include "lldb/Target/RegisterContext.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Target/Thread.h" 21 #include "lldb/Target/ThreadPlanRunToAddress.h" 22 #include "lldb/Target/StackFrame.h" 23 24 #include "DynamicLoaderMacOSXDYLD.h" 25 #include "DynamicLoaderMacOSXDYLDLog.h" 26 27 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN 28 #ifdef ENABLE_DEBUG_PRINTF 29 #include <stdio.h> 30 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) 31 #else 32 #define DEBUG_PRINTF(fmt, ...) 33 #endif 34 35 using namespace lldb; 36 using namespace lldb_private; 37 38 39 /// FIXME - The ObjC Runtime trampoline handler doesn't really belong here. 40 /// I am putting it here so I can invoke it in the Trampoline code here, but 41 /// it should be moved to the ObjC Runtime support when it is set up. 42 43 //---------------------------------------------------------------------- 44 // Create an instance of this class. This function is filled into 45 // the plugin info class that gets handed out by the plugin factory and 46 // allows the lldb to instantiate an instance of this class. 47 //---------------------------------------------------------------------- 48 DynamicLoader * 49 DynamicLoaderMacOSXDYLD::CreateInstance (Process* process) 50 { 51 return new DynamicLoaderMacOSXDYLD (process); 52 } 53 54 //---------------------------------------------------------------------- 55 // Constructor 56 //---------------------------------------------------------------------- 57 DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) : 58 DynamicLoader(process), 59 m_dyld(), 60 m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS), 61 m_dyld_all_image_infos(), 62 m_break_id(LLDB_INVALID_BREAK_ID), 63 m_dyld_image_infos(), 64 m_mutex(Mutex::eMutexTypeRecursive), 65 m_objc_trampoline_handler_ap(NULL) 66 { 67 } 68 69 //---------------------------------------------------------------------- 70 // Destructor 71 //---------------------------------------------------------------------- 72 DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD() 73 { 74 Clear(true); 75 } 76 77 //------------------------------------------------------------------ 78 /// Called after attaching a process. 79 /// 80 /// Allow DynamicLoader plug-ins to execute some code after 81 /// attaching to a process. 82 //------------------------------------------------------------------ 83 void 84 DynamicLoaderMacOSXDYLD::DidAttach () 85 { 86 PrivateInitialize(m_process); 87 if (NeedToLocateDYLD ()) 88 LocateDYLD (); 89 SetNotificationBreakpoint (); 90 UpdateAllImageInfos(); 91 } 92 93 //------------------------------------------------------------------ 94 /// Called after attaching a process. 95 /// 96 /// Allow DynamicLoader plug-ins to execute some code after 97 /// attaching to a process. 98 //------------------------------------------------------------------ 99 void 100 DynamicLoaderMacOSXDYLD::DidLaunch () 101 { 102 PrivateInitialize(m_process); 103 if (NeedToLocateDYLD ()) 104 LocateDYLD (); 105 SetNotificationBreakpoint (); 106 UpdateAllImageInfos(); 107 } 108 109 110 //---------------------------------------------------------------------- 111 // Clear out the state of this class. 112 //---------------------------------------------------------------------- 113 void 114 DynamicLoaderMacOSXDYLD::Clear (bool clear_process) 115 { 116 Mutex::Locker locker(m_mutex); 117 118 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) 119 m_process->ClearBreakpointSiteByID(m_break_id); 120 121 if (clear_process) 122 m_process = NULL; 123 m_dyld.Clear(false); 124 m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS; 125 m_dyld_all_image_infos.Clear(); 126 m_break_id = LLDB_INVALID_BREAK_ID; 127 m_dyld_image_infos.clear(); 128 } 129 130 //---------------------------------------------------------------------- 131 // Check if we have found DYLD yet 132 //---------------------------------------------------------------------- 133 bool 134 DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const 135 { 136 return LLDB_BREAK_ID_IS_VALID (m_break_id); 137 } 138 139 //---------------------------------------------------------------------- 140 // Try and figure out where dyld is by first asking the Process 141 // if it knows (which currently calls down in the the lldb::Process 142 // to get the DYLD info (available on SnowLeopard only). If that fails, 143 // then check in the default addresses. 144 //---------------------------------------------------------------------- 145 bool 146 DynamicLoaderMacOSXDYLD::LocateDYLD() 147 { 148 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) 149 m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress (); 150 151 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) 152 { 153 if (ReadAllImageInfosStructure ()) 154 { 155 if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS) 156 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress); 157 else 158 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull); 159 } 160 } 161 162 // Check some default values 163 Module *executable = m_process->GetTarget().GetExecutableModule().get(); 164 165 if (executable) 166 { 167 if (executable->GetArchitecture().GetAddressByteSize() == 8) 168 { 169 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull); 170 } 171 #if defined (__arm__) 172 else 173 { 174 ArchSpec arm_arch("arm"); 175 if (arm_arch == executable->Arch()) 176 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000); 177 } 178 #endif 179 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000); 180 } 181 return false; 182 } 183 184 //---------------------------------------------------------------------- 185 // Assume that dyld is in memory at ADDR and try to parse it's load 186 // commands 187 //---------------------------------------------------------------------- 188 bool 189 DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr) 190 { 191 DataExtractor data; // Load command data 192 if (ReadMachHeader (addr, &m_dyld.header, &data)) 193 { 194 if (m_dyld.header.filetype == MH_DYLINKER) 195 { 196 m_dyld.address = addr; 197 ModuleSP dyld_module_sp; 198 if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec)) 199 { 200 if (m_dyld.file_spec) 201 { 202 ArchSpec dyld_arch(m_dyld.header.cputype, m_dyld.header.cpusubtype); 203 dyld_module_sp = m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld.file_spec); 204 205 if (dyld_module_sp.get() == NULL || dyld_module_sp->GetArchitecture() != dyld_arch) 206 { 207 dyld_module_sp = m_process->GetTarget().GetSharedModule (m_dyld.file_spec, 208 dyld_arch, 209 &m_dyld.uuid); 210 } 211 212 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld); 213 } 214 } 215 216 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get()) 217 { 218 static ConstString g_dyld_all_image_infos ("dyld_all_image_infos"); 219 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData); 220 if (symbol) 221 m_dyld_all_image_infos_addr = symbol->GetValue().GetLoadAddress(m_process); 222 } 223 224 // Update all image infos 225 UpdateAllImageInfos(); 226 227 // If we didn't have an executable before, but now we do, then the 228 // dyld module shared pointer might be unique and we may need to add 229 // it again (since Target::SetExecutableModule() will clear the 230 // images). So append the dyld module back to the list if it is 231 /// unique! 232 if (m_process->GetTarget().GetImages().AppendInNeeded (dyld_module_sp)) 233 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld); 234 235 return true; 236 } 237 } 238 return false; 239 } 240 241 bool 242 DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const 243 { 244 return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS; 245 } 246 247 bool 248 DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module) 249 { 250 bool changed = false; 251 if (module) 252 { 253 ObjectFile *image_object_file = module->GetObjectFile(); 254 if (image_object_file) 255 { 256 SectionList *section_list = image_object_file->GetSectionList (); 257 if (section_list) 258 { 259 uint32_t num_sections = section_list->GetSize(); 260 for (uint32_t i=0; i<num_sections; ++i) 261 { 262 Section* section = section_list->GetSectionAtIndex (i).get(); 263 if (section) 264 { 265 const addr_t new_section_load_addr = section->GetFileAddress (); 266 const addr_t old_section_load_addr = m_process->GetSectionLoadAddress (section); 267 if (old_section_load_addr == LLDB_INVALID_ADDRESS || 268 old_section_load_addr != new_section_load_addr) 269 { 270 if (m_process->SectionLoaded (section, section->GetFileAddress ())) 271 changed = true; 272 } 273 } 274 } 275 } 276 } 277 } 278 return changed; 279 } 280 281 //---------------------------------------------------------------------- 282 // Update the load addresses for all segments in MODULE using the 283 // updated INFO that is passed in. 284 //---------------------------------------------------------------------- 285 bool 286 DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, struct DYLDImageInfo& info) 287 { 288 bool changed = false; 289 if (module) 290 { 291 ObjectFile *image_object_file = module->GetObjectFile(); 292 if (image_object_file) 293 { 294 SectionList *section_list = image_object_file->GetSectionList (); 295 if (section_list) 296 { 297 // All sections listed in the dyld image info structure will all 298 // either be fixed up already, or they will all be off by a single 299 // slide amount that is determined by finding the first segment 300 // that is at file offset zero which also has bytes (a file size 301 // that is greater than zero) in the object file. 302 303 // Determine the slide amount (if any) 304 info.slide = 0; 305 const size_t num_sections = section_list->GetSize(); 306 size_t sect_idx = 0; 307 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) 308 { 309 // Iterate through the object file sections to find the 310 // first section that starts of file offset zero and that 311 // has bytes in the file... 312 Section *section = section_list->GetSectionAtIndex (sect_idx).get(); 313 if (section) 314 { 315 // Find the first section that begins at file offset zero 316 // a file size (skip page zero). 317 if (section->GetFileOffset() == 0 && section->GetFileSize() > 0) 318 { 319 // We have now found the section, lets match it up 320 // with the section in the dyld image info structure. 321 const Segment *dyld_segment = info.FindSegment (section->GetName()); 322 if (dyld_segment) 323 info.slide = info.address - dyld_segment->addr; 324 // We have found the slide amount, so we can exit 325 // this for loop. 326 break; 327 } 328 } 329 } 330 331 // We now know the slide amount, so go through all sections 332 // and update the load addresses with the correct values. 333 uint32_t num_segments = info.segments.size(); 334 for (uint32_t i=0; i<num_segments; ++i) 335 { 336 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); 337 assert (section_sp.get() != NULL); 338 const addr_t new_section_load_addr = info.segments[i].addr + info.slide; 339 const addr_t old_section_load_addr = m_process->GetSectionLoadAddress (section_sp.get()); 340 if (old_section_load_addr == LLDB_INVALID_ADDRESS || 341 old_section_load_addr != new_section_load_addr) 342 { 343 if (m_process->SectionLoaded (section_sp.get(), new_section_load_addr)) 344 changed = true; 345 } 346 } 347 } 348 } 349 } 350 return changed; 351 } 352 353 //---------------------------------------------------------------------- 354 // Update the load addresses for all segments in MODULE using the 355 // updated INFO that is passed in. 356 //---------------------------------------------------------------------- 357 bool 358 DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, struct DYLDImageInfo& info) 359 { 360 bool changed = false; 361 if (module) 362 { 363 ObjectFile *image_object_file = module->GetObjectFile(); 364 if (image_object_file) 365 { 366 SectionList *section_list = image_object_file->GetSectionList (); 367 if (section_list) 368 { 369 uint32_t num_segments = info.segments.size(); 370 for (uint32_t i=0; i<num_segments; ++i) 371 { 372 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); 373 assert (section_sp.get() != NULL); 374 const addr_t old_section_load_addr = info.segments[i].addr + info.slide; 375 if (m_process->SectionUnloaded (section_sp.get(), old_section_load_addr)) 376 changed = true; 377 } 378 } 379 } 380 } 381 return changed; 382 } 383 384 385 //---------------------------------------------------------------------- 386 // Static callback function that gets called when our DYLD notification 387 // breakpoint gets hit. We update all of our image infos and then 388 // let our super class DynamicLoader class decide if we should stop 389 // or not (based on global preference). 390 //---------------------------------------------------------------------- 391 bool 392 DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id) 393 { 394 // Let the event know that the images have changed 395 DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton; 396 dyld_instance->UpdateAllImageInfos(); 397 // Return true to stop the target, false to just let the target run 398 return dyld_instance->GetStopWhenImagesChange(); 399 } 400 401 bool 402 DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () 403 { 404 Mutex::Locker locker(m_mutex); 405 m_dyld_all_image_infos.Clear(); 406 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) 407 { 408 const ByteOrder endian = m_process->GetByteOrder(); 409 const uint32_t addr_size = m_process->GetAddressByteSize(); 410 uint8_t buf[256]; 411 const size_t count = 2 * sizeof(uint32_t) + // version + dylib_info_count 412 addr_size * 2 + // dylib_info_addr + notification 413 2 + addr_size - 2 + // processDetachedFromSharedRegion + libSystemInitialized + pad 414 addr_size; // dyldImageLoadAddress 415 Error error; 416 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error); 417 if (bytes_read == count) 418 { 419 DataExtractor data(buf, count, endian, addr_size); 420 uint32_t offset = 0; 421 m_dyld_all_image_infos.version = data.GetU32(&offset); 422 m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset); 423 m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset); 424 m_dyld_all_image_infos.notification = data.GetPointer(&offset); 425 m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset); 426 if (m_dyld_all_image_infos.version >= 2) 427 { 428 m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset); 429 // Adjust for padding. 430 offset += addr_size - 2; 431 m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset); 432 } 433 return true; 434 } 435 } 436 return false; 437 } 438 439 //---------------------------------------------------------------------- 440 // If we have found where the "_dyld_all_image_infos" lives in memory, 441 // read the current info from it, and then update all image load 442 // addresses (or lack thereof). 443 //---------------------------------------------------------------------- 444 uint32_t 445 DynamicLoaderMacOSXDYLD::UpdateAllImageInfos() 446 { 447 if (ReadAllImageInfosStructure ()) 448 { 449 Mutex::Locker locker(m_mutex); 450 uint32_t idx; 451 Error error; 452 uint32_t i = 0; 453 DYLDImageInfo::collection old_dyld_all_image_infos; 454 old_dyld_all_image_infos.swap(m_dyld_image_infos); 455 456 // If we made it here, we are assuming that the all dylib info data should 457 // be valid, lets read the info array. 458 const ByteOrder endian = m_process->GetByteOrder(); 459 const uint32_t addr_size = m_process->GetAddressByteSize(); 460 461 if (m_dyld_all_image_infos.dylib_info_count > 0) 462 { 463 if (m_dyld_all_image_infos.dylib_info_addr == 0) 464 { 465 // DYLD is updating the images right now... 466 } 467 else 468 { 469 m_dyld_image_infos.resize(m_dyld_all_image_infos.dylib_info_count); 470 const size_t count = m_dyld_image_infos.size() * 3 * addr_size; 471 DataBufferHeap info_data(count, 0); 472 Error error; 473 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos.dylib_info_addr, 474 info_data.GetBytes(), 475 info_data.GetByteSize(), 476 error); 477 if (bytes_read == count) 478 { 479 uint32_t info_data_offset = 0; 480 DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size); 481 for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++) 482 { 483 assert (i < m_dyld_image_infos.size()); 484 m_dyld_image_infos[i].address = info_data_ref.GetPointer(&info_data_offset); 485 lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset); 486 m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset); 487 488 char raw_path[PATH_MAX]; 489 m_process->ReadMemory (path_addr, raw_path, sizeof(raw_path), error); 490 m_dyld_image_infos[i].file_spec.SetFile(raw_path); 491 } 492 assert(i == m_dyld_all_image_infos.dylib_info_count); 493 494 UpdateAllImageInfosHeaderAndLoadCommands(); 495 } 496 else 497 { 498 DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); 499 m_dyld_image_infos.clear(); 500 } 501 } 502 } 503 else 504 { 505 m_dyld_image_infos.clear(); 506 } 507 508 // If our new list is smaller than our old list, we have unloaded 509 // some shared libraries 510 if (m_dyld_image_infos.size() < old_dyld_all_image_infos.size()) 511 { 512 ModuleList unloaded_module_list; 513 for (idx = m_dyld_image_infos.size(); idx < old_dyld_all_image_infos.size(); ++idx) 514 { 515 ModuleSP unload_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (old_dyld_all_image_infos[idx].file_spec)); 516 if (unload_image_module_sp.get()) 517 { 518 if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[idx])) 519 unloaded_module_list.AppendInNeeded (unload_image_module_sp); 520 } 521 } 522 if (unloaded_module_list.GetSize() > 0) 523 m_process->GetTarget().ModulesDidUnload (unloaded_module_list); 524 } 525 } 526 else 527 { 528 m_dyld_image_infos.clear(); 529 } 530 531 const uint32_t num_dylibs = m_dyld_image_infos.size(); 532 if (num_dylibs > 0) 533 { 534 ModuleList loaded_module_list; 535 for (uint32_t idx = 0; idx<num_dylibs; ++idx) 536 { 537 ArchSpec arch_spec(m_dyld_image_infos[idx].header.cputype, m_dyld_image_infos[idx].header.cpusubtype); 538 ModuleSP image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld_image_infos[idx].file_spec)); 539 if (image_module_sp.get() == NULL || image_module_sp->GetArchitecture() != arch_spec) 540 { 541 image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec, 542 arch_spec, 543 &m_dyld_image_infos[idx].uuid); 544 } 545 546 if (image_module_sp) 547 { 548 ObjectFile *objfile = image_module_sp->GetObjectFile (); 549 if (objfile) 550 { 551 SectionList *sections = objfile->GetSectionList(); 552 if (sections) 553 { 554 ConstString commpage_dbstr("__commpage"); 555 Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get(); 556 if (commpage_section) 557 { 558 FileSpec objfile_file_spec(objfile->GetFileSpec()); 559 ModuleSP commpage_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (objfile_file_spec, &commpage_dbstr)); 560 if (commpage_image_module_sp.get() == NULL) 561 { 562 commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec, 563 arch_spec, 564 &m_dyld_image_infos[idx].uuid, 565 &commpage_dbstr, 566 objfile->GetOffset() + commpage_section->GetOffset()); 567 UpdateCommPageLoadAddress(commpage_image_module_sp.get()); 568 } 569 } 570 } 571 } 572 573 // UpdateImageLoadAddress will return true if any segments 574 // change load address. We need to check this so we don't 575 // mention that all loaded shared libraries are newly loaded 576 // each time we hit out dyld breakpoint since dyld will list all 577 // shared libraries each time. 578 if (UpdateImageLoadAddress (image_module_sp.get(), m_dyld_image_infos[idx])) 579 { 580 loaded_module_list.AppendInNeeded (image_module_sp); 581 } 582 } 583 } 584 PutToLog(DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1)); 585 if (loaded_module_list.GetSize() > 0) 586 { 587 // FIXME: This should really be in the Runtime handlers class, which should get 588 // called by the target's ModulesDidLoad, but we're doing it all locally for now 589 // to save time. 590 // Also, I'm assuming there can be only one libobjc dylib loaded... 591 592 if (m_objc_trampoline_handler_ap.get() == NULL) 593 { 594 size_t num_modules = loaded_module_list.GetSize(); 595 for (int i = 0; i < num_modules; i++) 596 { 597 if (ObjCTrampolineHandler::ModuleIsObjCLibrary (loaded_module_list.GetModuleAtIndex (i))) 598 { 599 m_objc_trampoline_handler_ap.reset (new ObjCTrampolineHandler(m_process->GetSP(), loaded_module_list.GetModuleAtIndex (i))); 600 break; 601 } 602 } 603 } 604 m_process->GetTarget().ModulesDidLoad (loaded_module_list); 605 } 606 } 607 return m_dyld_image_infos.size(); 608 } 609 610 //---------------------------------------------------------------------- 611 // Read a mach_header at ADDR into HEADER, and also fill in the load 612 // command data into LOAD_COMMAND_DATA if it is non-NULL. 613 // 614 // Returns true if we succeed, false if we fail for any reason. 615 //---------------------------------------------------------------------- 616 bool 617 DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, struct mach_header *header, DataExtractor *load_command_data) 618 { 619 DataBufferHeap header_bytes(sizeof(struct mach_header), 0); 620 Error error; 621 size_t bytes_read = m_process->ReadMemory (addr, 622 header_bytes.GetBytes(), 623 header_bytes.GetByteSize(), 624 error); 625 if (bytes_read == sizeof(struct mach_header)) 626 { 627 uint32_t offset = 0; 628 ::memset (header, 0, sizeof(header)); 629 630 // Get the magic byte unswapped so we can figure out what we are dealing with 631 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), eByteOrderHost, 4); 632 header->magic = data.GetU32(&offset); 633 lldb::addr_t load_cmd_addr = addr; 634 data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic)); 635 switch (header->magic) 636 { 637 case MH_MAGIC: 638 case MH_CIGAM: 639 data.SetAddressByteSize(4); 640 load_cmd_addr += sizeof(struct mach_header); 641 break; 642 643 case MH_MAGIC_64: 644 case MH_CIGAM_64: 645 data.SetAddressByteSize(8); 646 load_cmd_addr += sizeof(struct mach_header_64); 647 break; 648 649 default: 650 return false; 651 } 652 653 // Read the rest of dyld's mach header 654 if (data.GetU32(&offset, &header->cputype, (sizeof(struct mach_header)/sizeof(uint32_t)) - 1)) 655 { 656 if (load_command_data == NULL) 657 return true; // We were able to read the mach_header and weren't asked to read the load command bytes 658 659 DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0)); 660 661 size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr, 662 load_cmd_data_sp->GetBytes(), 663 load_cmd_data_sp->GetByteSize(), 664 error); 665 666 if (load_cmd_bytes_read == header->sizeofcmds) 667 { 668 // Set the load command data and also set the correct endian 669 // swap settings and the correct address size 670 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds); 671 load_command_data->SetByteOrder(data.GetByteOrder()); 672 load_command_data->SetAddressByteSize(data.GetAddressByteSize()); 673 return true; // We successfully read the mach_header and the load command data 674 } 675 676 return false; // We weren't able to read the load command data 677 } 678 } 679 return false; // We failed the read the mach_header 680 } 681 682 683 //---------------------------------------------------------------------- 684 // Parse the load commands for an image 685 //---------------------------------------------------------------------- 686 uint32_t 687 DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker) 688 { 689 uint32_t offset = 0; 690 uint32_t cmd_idx; 691 Segment segment; 692 dylib_info.Clear (true); 693 694 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) 695 { 696 // Clear out any load command specific data from DYLIB_INFO since 697 // we are about to read it. 698 699 if (data.ValidOffsetForDataOfSize (offset, sizeof(struct load_command))) 700 { 701 struct load_command load_cmd; 702 uint32_t load_cmd_offset = offset; 703 load_cmd.cmd = data.GetU32 (&offset); 704 load_cmd.cmdsize = data.GetU32 (&offset); 705 switch (load_cmd.cmd) 706 { 707 case LC_SEGMENT: 708 { 709 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); 710 segment.addr = data.GetU32 (&offset); 711 segment.size = data.GetU32 (&offset); 712 dylib_info.segments.push_back (segment); 713 } 714 break; 715 716 case LC_SEGMENT_64: 717 { 718 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); 719 segment.addr = data.GetU64 (&offset); 720 segment.size = data.GetU64 (&offset); 721 dylib_info.segments.push_back (segment); 722 } 723 break; 724 725 case LC_ID_DYLINKER: 726 if (lc_id_dylinker) 727 { 728 uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset); 729 const char *path = data.PeekCStr (name_offset); 730 lc_id_dylinker->SetFile (path); 731 } 732 break; 733 734 case LC_UUID: 735 dylib_info.uuid.SetBytes(data.GetData (&offset, 16)); 736 break; 737 738 default: 739 break; 740 } 741 // Set offset to be the beginning of the next load command. 742 offset = load_cmd_offset + load_cmd.cmdsize; 743 } 744 } 745 return cmd_idx; 746 } 747 748 //---------------------------------------------------------------------- 749 // Read the mach_header and load commands for each image that the 750 // _dyld_all_image_infos structure points to and cache the results. 751 //---------------------------------------------------------------------- 752 void 753 DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands() 754 { 755 uint32_t exe_idx = UINT32_MAX; 756 // Read any UUID values that we can get 757 for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++) 758 { 759 if (!m_dyld_image_infos[i].UUIDValid()) 760 { 761 DataExtractor data; // Load command data 762 if (!ReadMachHeader (m_dyld_image_infos[i].address, &m_dyld_image_infos[i].header, &data)) 763 continue; 764 765 ParseLoadCommands (data, m_dyld_image_infos[i], NULL); 766 767 if (m_dyld_image_infos[i].header.filetype == MH_EXECUTE) 768 exe_idx = i; 769 } 770 } 771 772 if (exe_idx < m_dyld_image_infos.size()) 773 { 774 bool set_executable = false; 775 ArchSpec dyld_exe_arch_spec(m_dyld_image_infos[exe_idx].header.cputype, m_dyld_image_infos[exe_idx].header.cpusubtype); 776 ModuleSP exe_module_sp(m_process->GetTarget().GetExecutableModule()); 777 if (exe_module_sp.get()) 778 { 779 if (exe_module_sp->GetFileSpec() != m_dyld_image_infos[exe_idx].file_spec || 780 exe_module_sp->GetArchitecture() != dyld_exe_arch_spec) 781 set_executable = true; 782 } 783 else 784 set_executable = true; 785 786 if (set_executable) 787 { 788 exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec, 789 dyld_exe_arch_spec, 790 &m_dyld_image_infos[exe_idx].uuid); 791 if (exe_module_sp.get()) 792 { 793 // If we found the file where it purported to be, then it should 794 // be safe to load dependent images. 795 bool get_dependent_images = exe_module_sp->GetFileSpec() == m_dyld_image_infos[exe_idx].file_spec; 796 797 m_process->GetTarget().SetExecutableModule (exe_module_sp, get_dependent_images); 798 } 799 } 800 } 801 } 802 803 //---------------------------------------------------------------------- 804 // Dump a Segment to the file handle provided. 805 //---------------------------------------------------------------------- 806 void 807 DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const 808 { 809 if (log) 810 log->Printf("\t\t%16s [0x%16.16llx - 0x%16.16llx)", name.AsCString(""), addr + slide, addr + slide + size); 811 } 812 813 const DynamicLoaderMacOSXDYLD::Segment * 814 DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const 815 { 816 const size_t num_segments = segments.size(); 817 for (size_t i=0; i<num_segments; ++i) 818 { 819 if (segments[i].name == name) 820 return &segments[i]; 821 } 822 return NULL; 823 } 824 825 826 //---------------------------------------------------------------------- 827 // Dump an image info structure to the file handle provided. 828 //---------------------------------------------------------------------- 829 void 830 DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const 831 { 832 if (log == NULL) 833 return; 834 uint8_t *u = (uint8_t *)uuid.GetBytes(); 835 836 if (address == LLDB_INVALID_ADDRESS) 837 { 838 if (u) 839 { 840 log->Printf("\t modtime=0x%8.8llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s/%s' (UNLOADED)", 841 mod_date, 842 u[ 0], u[ 1], u[ 2], u[ 3], 843 u[ 4], u[ 5], u[ 6], u[ 7], 844 u[ 8], u[ 9], u[10], u[11], 845 u[12], u[13], u[14], u[15], 846 file_spec.GetDirectory().AsCString(), 847 file_spec.GetFilename().AsCString()); 848 } 849 else 850 log->Printf("\t modtime=0x%8.8llx path='%s/%s' (UNLOADED)", 851 mod_date, 852 file_spec.GetDirectory().AsCString(), 853 file_spec.GetFilename().AsCString()); 854 } 855 else 856 { 857 if (u) 858 { 859 log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s/%s'", 860 address, 861 mod_date, 862 u[ 0], u[ 1], u[ 2], u[ 3], 863 u[ 4], u[ 5], u[ 6], u[ 7], 864 u[ 8], u[ 9], u[10], u[11], 865 u[12], u[13], u[14], u[15], 866 file_spec.GetDirectory().AsCString(), 867 file_spec.GetFilename().AsCString()); 868 } 869 else 870 { 871 log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'", 872 address, 873 mod_date, 874 file_spec.GetDirectory().AsCString(), 875 file_spec.GetFilename().AsCString()); 876 877 } 878 for (uint32_t i=0; i<segments.size(); ++i) 879 segments[i].PutToLog(log, slide); 880 } 881 } 882 883 //---------------------------------------------------------------------- 884 // Dump the _dyld_all_image_infos members and all current image infos 885 // that we have parsed to the file handle provided. 886 //---------------------------------------------------------------------- 887 void 888 DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const 889 { 890 if (log == NULL) 891 return; 892 893 Mutex::Locker locker(m_mutex); 894 log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }", 895 m_dyld_all_image_infos.version, 896 m_dyld_all_image_infos.dylib_info_count, 897 (uint64_t)m_dyld_all_image_infos.dylib_info_addr, 898 (uint64_t)m_dyld_all_image_infos.notification); 899 size_t i; 900 const size_t count = m_dyld_image_infos.size(); 901 if (count > 0) 902 { 903 log->Printf("\tdyld_image_infos"); 904 for (i = 0; i<count; i++) 905 m_dyld_image_infos[i].PutToLog(log); 906 } 907 } 908 909 //---------------------------------------------------------------------- 910 // Static callback function that gets called when the process state 911 // changes. 912 //---------------------------------------------------------------------- 913 void 914 DynamicLoaderMacOSXDYLD::Initialize(void *baton, Process *process) 915 { 916 ((DynamicLoaderMacOSXDYLD*)baton)->PrivateInitialize(process); 917 } 918 919 void 920 DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process) 921 { 922 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); 923 Clear(true); 924 m_process = process; 925 } 926 927 928 //---------------------------------------------------------------------- 929 // Static callback function that gets called when the process state 930 // changes. 931 //---------------------------------------------------------------------- 932 void 933 DynamicLoaderMacOSXDYLD::ProcessStateChanged(void *baton, Process *process, StateType state) 934 { 935 ((DynamicLoaderMacOSXDYLD*)baton)->PrivateProcessStateChanged(process, state); 936 } 937 938 bool 939 DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () 940 { 941 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); 942 if (m_break_id == LLDB_INVALID_BREAK_ID) 943 { 944 if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) 945 { 946 Address so_addr; 947 // Set the notification breakpoint and install a breakpoint 948 // callback function that will get called each time the 949 // breakpoint gets hit. We will use this to track when shared 950 // libraries get loaded/unloaded. 951 952 if (m_process->ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr)) 953 { 954 Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get(); 955 dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true); 956 m_break_id = dyld_break->GetID(); 957 } 958 } 959 } 960 return m_break_id != LLDB_INVALID_BREAK_ID; 961 } 962 963 //----------------------------------------------------------------------Target.h 964 965 // Member function that gets called when the process state changes. 966 //---------------------------------------------------------------------- 967 void 968 DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state) 969 { 970 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state)); 971 switch (state) 972 { 973 case eStateAttaching: 974 case eStateLaunching: 975 case eStateInvalid: 976 case eStateUnloaded: 977 case eStateExited: 978 case eStateDetached: 979 Clear(false); 980 break; 981 982 case eStateStopped: 983 // Keep trying find dyld and set our notification breakpoint each time 984 // we stop until we succeed 985 if (!DidSetNotificationBreakpoint () && m_process->IsAlive()) 986 { 987 if (NeedToLocateDYLD ()) 988 LocateDYLD (); 989 990 SetNotificationBreakpoint (); 991 } 992 break; 993 994 case eStateRunning: 995 case eStateStepping: 996 case eStateCrashed: 997 case eStateSuspended: 998 break; 999 1000 default: 1001 break; 1002 } 1003 } 1004 1005 ThreadPlanSP 1006 DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) 1007 { 1008 ThreadPlanSP thread_plan_sp; 1009 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); 1010 const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol); 1011 Symbol *current_symbol = current_context.symbol; 1012 1013 if (current_symbol != NULL) 1014 { 1015 if (current_symbol->IsTrampoline()) 1016 { 1017 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(); 1018 if (trampoline_name) 1019 { 1020 SymbolContextList target_symbols; 1021 ModuleList &images = thread.GetProcess().GetTarget().GetImages(); 1022 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols); 1023 // FIXME - Make the Run to Address take multiple addresses, and 1024 // run to any of them. 1025 if (target_symbols.GetSize() == 1) 1026 { 1027 SymbolContext context; 1028 AddressRange addr_range; 1029 if (target_symbols.GetContextAtIndex(0, context)) 1030 { 1031 context.GetAddressRange (eSymbolContextEverything, addr_range); 1032 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others)); 1033 } 1034 } 1035 else if (target_symbols.GetSize() > 1) 1036 { 1037 Log *log = DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1); 1038 if (log) 1039 { 1040 log->Printf ("Found more than one symbol for trampoline target: \"%s\"", trampoline_name.AsCString()); 1041 } 1042 } 1043 else 1044 { 1045 Log *log = DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1); 1046 if (log) 1047 { 1048 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString()); 1049 } 1050 } 1051 } 1052 } 1053 } 1054 1055 if (thread_plan_sp == NULL && m_objc_trampoline_handler_ap.get()) 1056 thread_plan_sp = m_objc_trampoline_handler_ap->GetStepThroughDispatchPlan (thread, stop_others); 1057 1058 return thread_plan_sp; 1059 } 1060 1061 void 1062 DynamicLoaderMacOSXDYLD::Initialize() 1063 { 1064 PluginManager::RegisterPlugin (GetPluginNameStatic(), 1065 GetPluginDescriptionStatic(), 1066 CreateInstance); 1067 } 1068 1069 void 1070 DynamicLoaderMacOSXDYLD::Terminate() 1071 { 1072 PluginManager::UnregisterPlugin (CreateInstance); 1073 } 1074 1075 1076 const char * 1077 DynamicLoaderMacOSXDYLD::GetPluginNameStatic() 1078 { 1079 return "dynamic-loader.macosx-dyld"; 1080 } 1081 1082 const char * 1083 DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() 1084 { 1085 return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes."; 1086 } 1087 1088 1089 //------------------------------------------------------------------ 1090 // PluginInterface protocol 1091 //------------------------------------------------------------------ 1092 const char * 1093 DynamicLoaderMacOSXDYLD::GetPluginName() 1094 { 1095 return "DynamicLoaderMacOSXDYLD"; 1096 } 1097 1098 const char * 1099 DynamicLoaderMacOSXDYLD::GetShortPluginName() 1100 { 1101 return GetPluginNameStatic(); 1102 } 1103 1104 uint32_t 1105 DynamicLoaderMacOSXDYLD::GetPluginVersion() 1106 { 1107 return 1; 1108 } 1109 1110 void 1111 DynamicLoaderMacOSXDYLD::GetPluginCommandHelp (const char *command, Stream *strm) 1112 { 1113 } 1114 1115 Error 1116 DynamicLoaderMacOSXDYLD::ExecutePluginCommand (Args &command, Stream *strm) 1117 { 1118 Error error; 1119 error.SetErrorString("No plug-in command are currently supported."); 1120 return error; 1121 } 1122 1123 Log * 1124 DynamicLoaderMacOSXDYLD::EnablePluginLogging (Stream *strm, Args &command) 1125 { 1126 return NULL; 1127 } 1128 1129 1130