DynamicLoaderMacOSXDYLD.cpp revision cf0150574a0a97049efe2dce2cc0aa433705feb3
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 35using namespace lldb; 36using 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//---------------------------------------------------------------------- 48DynamicLoader * 49DynamicLoaderMacOSXDYLD::CreateInstance (Process* process) 50{ 51 return new DynamicLoaderMacOSXDYLD (process); 52} 53 54//---------------------------------------------------------------------- 55// Constructor 56//---------------------------------------------------------------------- 57DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 72DynamicLoaderMacOSXDYLD::~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//------------------------------------------------------------------ 83void 84DynamicLoaderMacOSXDYLD::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//------------------------------------------------------------------ 99void 100DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 113void 114DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 133bool 134DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 145bool 146DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 188bool 189DynamicLoaderMacOSXDYLD::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(eArchTypeMachO, 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 241bool 242DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const 243{ 244 return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS; 245} 246 247bool 248DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 285bool 286DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 357bool 358DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 391bool 392DynamicLoaderMacOSXDYLD::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 401bool 402DynamicLoaderMacOSXDYLD::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_v2 = sizeof (uint32_t) + // version 412 sizeof (uint32_t) + // infoArrayCount 413 addr_size + // infoArray 414 addr_size + // notification 415 addr_size + // processDetachedFromSharedRegion + libSystemInitialized + pad 416 addr_size; // dyldImageLoadAddress 417 const size_t count_v11 = count_v2 + 418 addr_size + // jitInfo 419 addr_size + // dyldVersion 420 addr_size + // errorMessage 421 addr_size + // terminationFlags 422 addr_size + // coreSymbolicationShmPage 423 addr_size + // systemOrderFlag 424 addr_size + // uuidArrayCount 425 addr_size + // uuidArray 426 addr_size + // dyldAllImageInfosAddress 427 addr_size + // initialImageCount 428 addr_size + // errorKind 429 addr_size + // errorClientOfDylibPath 430 addr_size + // errorTargetDylibPath 431 addr_size; // errorSymbol 432 assert (sizeof (buf) > count_v11); 433 434 int count; 435 Error error; 436 if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4) 437 { 438 DataExtractor data(buf, 4, endian, addr_size); 439 uint32_t offset = 0; 440 m_dyld_all_image_infos.version = data.GetU32(&offset); 441 } 442 else 443 { 444 return false; 445 } 446 447 if (m_dyld_all_image_infos.version >= 11) 448 count = count_v11; 449 else 450 count = count_v2; 451 452 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error); 453 if (bytes_read == count) 454 { 455 DataExtractor data(buf, count, endian, addr_size); 456 uint32_t offset = 0; 457 m_dyld_all_image_infos.version = data.GetU32(&offset); 458 m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset); 459 m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset); 460 m_dyld_all_image_infos.notification = data.GetPointer(&offset); 461 m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset); 462 m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset); 463 // Adjust for padding. 464 offset += addr_size - 2; 465 m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset); 466 if (m_dyld_all_image_infos.version >= 11) 467 { 468 offset += addr_size * 8; 469 uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset); 470 471 // When we started, we were given the actual address of the all_image_infos 472 // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in 473 // m_dyld_all_image_infos_addr and is the most accurate address we have. 474 475 // We read the dyld_all_image_infos struct from memory; it contains its own address. 476 // If the address in the struct does not match the actual address, 477 // the dyld we're looking at has been loaded at a different location (slid) from 478 // where it intended to load. The addresses in the dyld_all_image_infos struct 479 // are the original, non-slid addresses, and need to be adjusted. Most importantly 480 // the address of dyld and the notification address need to be adjusted. 481 482 if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) 483 { 484 uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress; 485 uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress; 486 m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset; 487 m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset; 488 } 489 } 490 return true; 491 } 492 } 493 return false; 494} 495 496//---------------------------------------------------------------------- 497// If we have found where the "_dyld_all_image_infos" lives in memory, 498// read the current info from it, and then update all image load 499// addresses (or lack thereof). 500//---------------------------------------------------------------------- 501uint32_t 502DynamicLoaderMacOSXDYLD::UpdateAllImageInfos() 503{ 504 if (ReadAllImageInfosStructure ()) 505 { 506 Mutex::Locker locker(m_mutex); 507 uint32_t idx; 508 Error error; 509 uint32_t i = 0; 510 DYLDImageInfo::collection old_dyld_all_image_infos; 511 old_dyld_all_image_infos.swap(m_dyld_image_infos); 512 513 // If we made it here, we are assuming that the all dylib info data should 514 // be valid, lets read the info array. 515 const ByteOrder endian = m_process->GetByteOrder(); 516 const uint32_t addr_size = m_process->GetAddressByteSize(); 517 518 if (m_dyld_all_image_infos.dylib_info_count > 0) 519 { 520 if (m_dyld_all_image_infos.dylib_info_addr == 0) 521 { 522 // DYLD is updating the images right now... 523 } 524 else 525 { 526 m_dyld_image_infos.resize(m_dyld_all_image_infos.dylib_info_count); 527 const size_t count = m_dyld_image_infos.size() * 3 * addr_size; 528 DataBufferHeap info_data(count, 0); 529 Error error; 530 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos.dylib_info_addr, 531 info_data.GetBytes(), 532 info_data.GetByteSize(), 533 error); 534 if (bytes_read == count) 535 { 536 uint32_t info_data_offset = 0; 537 DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size); 538 for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++) 539 { 540 assert (i < m_dyld_image_infos.size()); 541 m_dyld_image_infos[i].address = info_data_ref.GetPointer(&info_data_offset); 542 lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset); 543 m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset); 544 545 char raw_path[PATH_MAX]; 546 m_process->ReadMemory (path_addr, raw_path, sizeof(raw_path), error); 547 m_dyld_image_infos[i].file_spec.SetFile(raw_path); 548 } 549 assert(i == m_dyld_all_image_infos.dylib_info_count); 550 551 UpdateAllImageInfosHeaderAndLoadCommands(); 552 } 553 else 554 { 555 DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); 556 m_dyld_image_infos.clear(); 557 } 558 } 559 } 560 else 561 { 562 m_dyld_image_infos.clear(); 563 } 564 565 // If our new list is smaller than our old list, we have unloaded 566 // some shared libraries 567 if (m_dyld_image_infos.size() < old_dyld_all_image_infos.size()) 568 { 569 ModuleList unloaded_module_list; 570 for (idx = m_dyld_image_infos.size(); idx < old_dyld_all_image_infos.size(); ++idx) 571 { 572 ModuleSP unload_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (old_dyld_all_image_infos[idx].file_spec)); 573 if (unload_image_module_sp.get()) 574 { 575 if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[idx])) 576 unloaded_module_list.AppendInNeeded (unload_image_module_sp); 577 } 578 } 579 if (unloaded_module_list.GetSize() > 0) 580 m_process->GetTarget().ModulesDidUnload (unloaded_module_list); 581 } 582 } 583 else 584 { 585 m_dyld_image_infos.clear(); 586 } 587 588 const uint32_t num_dylibs = m_dyld_image_infos.size(); 589 if (num_dylibs > 0) 590 { 591 ModuleList loaded_module_list; 592 for (uint32_t idx = 0; idx<num_dylibs; ++idx) 593 { 594 ArchSpec arch_spec(eArchTypeMachO, m_dyld_image_infos[idx].header.cputype, m_dyld_image_infos[idx].header.cpusubtype); 595 ModuleSP image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld_image_infos[idx].file_spec)); 596 if (image_module_sp.get() == NULL || image_module_sp->GetArchitecture() != arch_spec) 597 { 598 image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec, 599 arch_spec, 600 &m_dyld_image_infos[idx].uuid); 601 } 602 603 if (image_module_sp) 604 { 605 ObjectFile *objfile = image_module_sp->GetObjectFile (); 606 if (objfile) 607 { 608 SectionList *sections = objfile->GetSectionList(); 609 if (sections) 610 { 611 ConstString commpage_dbstr("__commpage"); 612 Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get(); 613 if (commpage_section) 614 { 615 FileSpec objfile_file_spec(objfile->GetFileSpec()); 616 ModuleSP commpage_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (objfile_file_spec, &commpage_dbstr)); 617 if (commpage_image_module_sp.get() == NULL) 618 { 619 commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec, 620 arch_spec, 621 &m_dyld_image_infos[idx].uuid, 622 &commpage_dbstr, 623 objfile->GetOffset() + commpage_section->GetOffset()); 624 UpdateCommPageLoadAddress(commpage_image_module_sp.get()); 625 } 626 } 627 } 628 } 629 630 // UpdateImageLoadAddress will return true if any segments 631 // change load address. We need to check this so we don't 632 // mention that all loaded shared libraries are newly loaded 633 // each time we hit out dyld breakpoint since dyld will list all 634 // shared libraries each time. 635 if (UpdateImageLoadAddress (image_module_sp.get(), m_dyld_image_infos[idx])) 636 { 637 loaded_module_list.AppendInNeeded (image_module_sp); 638 } 639 } 640 } 641 PutToLog(DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1)); 642 if (loaded_module_list.GetSize() > 0) 643 { 644 // FIXME: This should really be in the Runtime handlers class, which should get 645 // called by the target's ModulesDidLoad, but we're doing it all locally for now 646 // to save time. 647 // Also, I'm assuming there can be only one libobjc dylib loaded... 648 649 if (m_objc_trampoline_handler_ap.get() == NULL) 650 { 651 size_t num_modules = loaded_module_list.GetSize(); 652 for (int i = 0; i < num_modules; i++) 653 { 654 if (ObjCTrampolineHandler::ModuleIsObjCLibrary (loaded_module_list.GetModuleAtIndex (i))) 655 { 656 m_objc_trampoline_handler_ap.reset (new ObjCTrampolineHandler(m_process->GetSP(), loaded_module_list.GetModuleAtIndex (i))); 657 break; 658 } 659 } 660 } 661 m_process->GetTarget().ModulesDidLoad (loaded_module_list); 662 } 663 } 664 return m_dyld_image_infos.size(); 665} 666 667//---------------------------------------------------------------------- 668// Read a mach_header at ADDR into HEADER, and also fill in the load 669// command data into LOAD_COMMAND_DATA if it is non-NULL. 670// 671// Returns true if we succeed, false if we fail for any reason. 672//---------------------------------------------------------------------- 673bool 674DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, struct mach_header *header, DataExtractor *load_command_data) 675{ 676 DataBufferHeap header_bytes(sizeof(struct mach_header), 0); 677 Error error; 678 size_t bytes_read = m_process->ReadMemory (addr, 679 header_bytes.GetBytes(), 680 header_bytes.GetByteSize(), 681 error); 682 if (bytes_read == sizeof(struct mach_header)) 683 { 684 uint32_t offset = 0; 685 ::memset (header, 0, sizeof(header)); 686 687 // Get the magic byte unswapped so we can figure out what we are dealing with 688 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), eByteOrderHost, 4); 689 header->magic = data.GetU32(&offset); 690 lldb::addr_t load_cmd_addr = addr; 691 data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic)); 692 switch (header->magic) 693 { 694 case MH_MAGIC: 695 case MH_CIGAM: 696 data.SetAddressByteSize(4); 697 load_cmd_addr += sizeof(struct mach_header); 698 break; 699 700 case MH_MAGIC_64: 701 case MH_CIGAM_64: 702 data.SetAddressByteSize(8); 703 load_cmd_addr += sizeof(struct mach_header_64); 704 break; 705 706 default: 707 return false; 708 } 709 710 // Read the rest of dyld's mach header 711 if (data.GetU32(&offset, &header->cputype, (sizeof(struct mach_header)/sizeof(uint32_t)) - 1)) 712 { 713 if (load_command_data == NULL) 714 return true; // We were able to read the mach_header and weren't asked to read the load command bytes 715 716 DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0)); 717 718 size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr, 719 load_cmd_data_sp->GetBytes(), 720 load_cmd_data_sp->GetByteSize(), 721 error); 722 723 if (load_cmd_bytes_read == header->sizeofcmds) 724 { 725 // Set the load command data and also set the correct endian 726 // swap settings and the correct address size 727 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds); 728 load_command_data->SetByteOrder(data.GetByteOrder()); 729 load_command_data->SetAddressByteSize(data.GetAddressByteSize()); 730 return true; // We successfully read the mach_header and the load command data 731 } 732 733 return false; // We weren't able to read the load command data 734 } 735 } 736 return false; // We failed the read the mach_header 737} 738 739 740//---------------------------------------------------------------------- 741// Parse the load commands for an image 742//---------------------------------------------------------------------- 743uint32_t 744DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker) 745{ 746 uint32_t offset = 0; 747 uint32_t cmd_idx; 748 Segment segment; 749 dylib_info.Clear (true); 750 751 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) 752 { 753 // Clear out any load command specific data from DYLIB_INFO since 754 // we are about to read it. 755 756 if (data.ValidOffsetForDataOfSize (offset, sizeof(struct load_command))) 757 { 758 struct load_command load_cmd; 759 uint32_t load_cmd_offset = offset; 760 load_cmd.cmd = data.GetU32 (&offset); 761 load_cmd.cmdsize = data.GetU32 (&offset); 762 switch (load_cmd.cmd) 763 { 764 case LC_SEGMENT: 765 { 766 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); 767 segment.addr = data.GetU32 (&offset); 768 segment.size = data.GetU32 (&offset); 769 dylib_info.segments.push_back (segment); 770 } 771 break; 772 773 case LC_SEGMENT_64: 774 { 775 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); 776 segment.addr = data.GetU64 (&offset); 777 segment.size = data.GetU64 (&offset); 778 dylib_info.segments.push_back (segment); 779 } 780 break; 781 782 case LC_ID_DYLINKER: 783 if (lc_id_dylinker) 784 { 785 uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset); 786 const char *path = data.PeekCStr (name_offset); 787 lc_id_dylinker->SetFile (path); 788 } 789 break; 790 791 case LC_UUID: 792 dylib_info.uuid.SetBytes(data.GetData (&offset, 16)); 793 break; 794 795 default: 796 break; 797 } 798 // Set offset to be the beginning of the next load command. 799 offset = load_cmd_offset + load_cmd.cmdsize; 800 } 801 } 802 return cmd_idx; 803} 804 805//---------------------------------------------------------------------- 806// Read the mach_header and load commands for each image that the 807// _dyld_all_image_infos structure points to and cache the results. 808//---------------------------------------------------------------------- 809void 810DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands() 811{ 812 uint32_t exe_idx = UINT32_MAX; 813 // Read any UUID values that we can get 814 for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++) 815 { 816 if (!m_dyld_image_infos[i].UUIDValid()) 817 { 818 DataExtractor data; // Load command data 819 if (!ReadMachHeader (m_dyld_image_infos[i].address, &m_dyld_image_infos[i].header, &data)) 820 continue; 821 822 ParseLoadCommands (data, m_dyld_image_infos[i], NULL); 823 824 if (m_dyld_image_infos[i].header.filetype == MH_EXECUTE) 825 exe_idx = i; 826 } 827 } 828 829 if (exe_idx < m_dyld_image_infos.size()) 830 { 831 bool set_executable = false; 832 ArchSpec dyld_exe_arch_spec(eArchTypeMachO, m_dyld_image_infos[exe_idx].header.cputype, m_dyld_image_infos[exe_idx].header.cpusubtype); 833 ModuleSP exe_module_sp(m_process->GetTarget().GetExecutableModule()); 834 if (exe_module_sp.get()) 835 { 836 if (exe_module_sp->GetFileSpec() != m_dyld_image_infos[exe_idx].file_spec || 837 exe_module_sp->GetArchitecture() != dyld_exe_arch_spec) 838 set_executable = true; 839 } 840 else 841 set_executable = true; 842 843 if (set_executable) 844 { 845 exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec, 846 dyld_exe_arch_spec, 847 &m_dyld_image_infos[exe_idx].uuid); 848 if (exe_module_sp.get()) 849 { 850 // If we found the file where it purported to be, then it should 851 // be safe to load dependent images. 852 bool get_dependent_images = exe_module_sp->GetFileSpec() == m_dyld_image_infos[exe_idx].file_spec; 853 854 m_process->GetTarget().SetExecutableModule (exe_module_sp, get_dependent_images); 855 } 856 } 857 } 858} 859 860//---------------------------------------------------------------------- 861// Dump a Segment to the file handle provided. 862//---------------------------------------------------------------------- 863void 864DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const 865{ 866 if (log) 867 log->Printf("\t\t%16s [0x%16.16llx - 0x%16.16llx)", name.AsCString(""), addr + slide, addr + slide + size); 868} 869 870const DynamicLoaderMacOSXDYLD::Segment * 871DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const 872{ 873 const size_t num_segments = segments.size(); 874 for (size_t i=0; i<num_segments; ++i) 875 { 876 if (segments[i].name == name) 877 return &segments[i]; 878 } 879 return NULL; 880} 881 882 883//---------------------------------------------------------------------- 884// Dump an image info structure to the file handle provided. 885//---------------------------------------------------------------------- 886void 887DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const 888{ 889 if (log == NULL) 890 return; 891 uint8_t *u = (uint8_t *)uuid.GetBytes(); 892 893 if (address == LLDB_INVALID_ADDRESS) 894 { 895 if (u) 896 { 897 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)", 898 mod_date, 899 u[ 0], u[ 1], u[ 2], u[ 3], 900 u[ 4], u[ 5], u[ 6], u[ 7], 901 u[ 8], u[ 9], u[10], u[11], 902 u[12], u[13], u[14], u[15], 903 file_spec.GetDirectory().AsCString(), 904 file_spec.GetFilename().AsCString()); 905 } 906 else 907 log->Printf("\t modtime=0x%8.8llx path='%s/%s' (UNLOADED)", 908 mod_date, 909 file_spec.GetDirectory().AsCString(), 910 file_spec.GetFilename().AsCString()); 911 } 912 else 913 { 914 if (u) 915 { 916 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'", 917 address, 918 mod_date, 919 u[ 0], u[ 1], u[ 2], u[ 3], 920 u[ 4], u[ 5], u[ 6], u[ 7], 921 u[ 8], u[ 9], u[10], u[11], 922 u[12], u[13], u[14], u[15], 923 file_spec.GetDirectory().AsCString(), 924 file_spec.GetFilename().AsCString()); 925 } 926 else 927 { 928 log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'", 929 address, 930 mod_date, 931 file_spec.GetDirectory().AsCString(), 932 file_spec.GetFilename().AsCString()); 933 934 } 935 for (uint32_t i=0; i<segments.size(); ++i) 936 segments[i].PutToLog(log, slide); 937 } 938} 939 940//---------------------------------------------------------------------- 941// Dump the _dyld_all_image_infos members and all current image infos 942// that we have parsed to the file handle provided. 943//---------------------------------------------------------------------- 944void 945DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const 946{ 947 if (log == NULL) 948 return; 949 950 Mutex::Locker locker(m_mutex); 951 log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }", 952 m_dyld_all_image_infos.version, 953 m_dyld_all_image_infos.dylib_info_count, 954 (uint64_t)m_dyld_all_image_infos.dylib_info_addr, 955 (uint64_t)m_dyld_all_image_infos.notification); 956 size_t i; 957 const size_t count = m_dyld_image_infos.size(); 958 if (count > 0) 959 { 960 log->Printf("\tdyld_image_infos"); 961 for (i = 0; i<count; i++) 962 m_dyld_image_infos[i].PutToLog(log); 963 } 964} 965 966//---------------------------------------------------------------------- 967// Static callback function that gets called when the process state 968// changes. 969//---------------------------------------------------------------------- 970void 971DynamicLoaderMacOSXDYLD::Initialize(void *baton, Process *process) 972{ 973 ((DynamicLoaderMacOSXDYLD*)baton)->PrivateInitialize(process); 974} 975 976void 977DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process) 978{ 979 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); 980 Clear(true); 981 m_process = process; 982} 983 984 985//---------------------------------------------------------------------- 986// Static callback function that gets called when the process state 987// changes. 988//---------------------------------------------------------------------- 989void 990DynamicLoaderMacOSXDYLD::ProcessStateChanged(void *baton, Process *process, StateType state) 991{ 992 ((DynamicLoaderMacOSXDYLD*)baton)->PrivateProcessStateChanged(process, state); 993} 994 995bool 996DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () 997{ 998 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); 999 if (m_break_id == LLDB_INVALID_BREAK_ID) 1000 { 1001 if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) 1002 { 1003 Address so_addr; 1004 // Set the notification breakpoint and install a breakpoint 1005 // callback function that will get called each time the 1006 // breakpoint gets hit. We will use this to track when shared 1007 // libraries get loaded/unloaded. 1008 1009 if (m_process->ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr)) 1010 { 1011 Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get(); 1012 dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true); 1013 m_break_id = dyld_break->GetID(); 1014 } 1015 } 1016 } 1017 return m_break_id != LLDB_INVALID_BREAK_ID; 1018} 1019 1020//----------------------------------------------------------------------Target.h 1021 1022// Member function that gets called when the process state changes. 1023//---------------------------------------------------------------------- 1024void 1025DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state) 1026{ 1027 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state)); 1028 switch (state) 1029 { 1030 case eStateAttaching: 1031 case eStateLaunching: 1032 case eStateInvalid: 1033 case eStateUnloaded: 1034 case eStateExited: 1035 case eStateDetached: 1036 Clear(false); 1037 break; 1038 1039 case eStateStopped: 1040 // Keep trying find dyld and set our notification breakpoint each time 1041 // we stop until we succeed 1042 if (!DidSetNotificationBreakpoint () && m_process->IsAlive()) 1043 { 1044 if (NeedToLocateDYLD ()) 1045 LocateDYLD (); 1046 1047 SetNotificationBreakpoint (); 1048 } 1049 break; 1050 1051 case eStateRunning: 1052 case eStateStepping: 1053 case eStateCrashed: 1054 case eStateSuspended: 1055 break; 1056 1057 default: 1058 break; 1059 } 1060} 1061 1062ThreadPlanSP 1063DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) 1064{ 1065 ThreadPlanSP thread_plan_sp; 1066 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); 1067 const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol); 1068 Symbol *current_symbol = current_context.symbol; 1069 1070 if (current_symbol != NULL) 1071 { 1072 if (current_symbol->IsTrampoline()) 1073 { 1074 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(); 1075 if (trampoline_name) 1076 { 1077 SymbolContextList target_symbols; 1078 ModuleList &images = thread.GetProcess().GetTarget().GetImages(); 1079 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols); 1080 // FIXME - Make the Run to Address take multiple addresses, and 1081 // run to any of them. 1082 if (target_symbols.GetSize() == 1) 1083 { 1084 SymbolContext context; 1085 AddressRange addr_range; 1086 if (target_symbols.GetContextAtIndex(0, context)) 1087 { 1088 context.GetAddressRange (eSymbolContextEverything, addr_range); 1089 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others)); 1090 } 1091 } 1092 else if (target_symbols.GetSize() > 1) 1093 { 1094 Log *log = DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1); 1095 if (log) 1096 { 1097 log->Printf ("Found more than one symbol for trampoline target: \"%s\"", trampoline_name.AsCString()); 1098 } 1099 } 1100 else 1101 { 1102 Log *log = DynamicLoaderMacOSXDYLDLog::GetLogIfAllCategoriesSet (1); 1103 if (log) 1104 { 1105 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString()); 1106 } 1107 } 1108 } 1109 } 1110 } 1111 1112 if (thread_plan_sp == NULL && m_objc_trampoline_handler_ap.get()) 1113 thread_plan_sp = m_objc_trampoline_handler_ap->GetStepThroughDispatchPlan (thread, stop_others); 1114 1115 return thread_plan_sp; 1116} 1117 1118void 1119DynamicLoaderMacOSXDYLD::Initialize() 1120{ 1121 PluginManager::RegisterPlugin (GetPluginNameStatic(), 1122 GetPluginDescriptionStatic(), 1123 CreateInstance); 1124} 1125 1126void 1127DynamicLoaderMacOSXDYLD::Terminate() 1128{ 1129 PluginManager::UnregisterPlugin (CreateInstance); 1130} 1131 1132 1133const char * 1134DynamicLoaderMacOSXDYLD::GetPluginNameStatic() 1135{ 1136 return "dynamic-loader.macosx-dyld"; 1137} 1138 1139const char * 1140DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() 1141{ 1142 return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes."; 1143} 1144 1145 1146//------------------------------------------------------------------ 1147// PluginInterface protocol 1148//------------------------------------------------------------------ 1149const char * 1150DynamicLoaderMacOSXDYLD::GetPluginName() 1151{ 1152 return "DynamicLoaderMacOSXDYLD"; 1153} 1154 1155const char * 1156DynamicLoaderMacOSXDYLD::GetShortPluginName() 1157{ 1158 return GetPluginNameStatic(); 1159} 1160 1161uint32_t 1162DynamicLoaderMacOSXDYLD::GetPluginVersion() 1163{ 1164 return 1; 1165} 1166 1167void 1168DynamicLoaderMacOSXDYLD::GetPluginCommandHelp (const char *command, Stream *strm) 1169{ 1170} 1171 1172Error 1173DynamicLoaderMacOSXDYLD::ExecutePluginCommand (Args &command, Stream *strm) 1174{ 1175 Error error; 1176 error.SetErrorString("No plug-in command are currently supported."); 1177 return error; 1178} 1179 1180Log * 1181DynamicLoaderMacOSXDYLD::EnablePluginLogging (Stream *strm, Args &command) 1182{ 1183 return NULL; 1184} 1185 1186 1187