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/ObjCLanguageRuntime.h" 19 #include "lldb/Target/RegisterContext.h" 20 #include "lldb/Target/Target.h" 21 #include "lldb/Target/Thread.h" 22 #include "lldb/Target/ThreadPlanRunToAddress.h" 23 #include "lldb/Target/StackFrame.h" 24 25 #include "DynamicLoaderMacOSXDYLD.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 /// FIXME - The ObjC Runtime trampoline handler doesn't really belong here. 39 /// I am putting it here so I can invoke it in the Trampoline code here, but 40 /// it should be moved to the ObjC Runtime support when it is set up. 41 42 43 DynamicLoaderMacOSXDYLD::DYLDImageInfo * 44 DynamicLoaderMacOSXDYLD::GetImageInfo (Module *module) 45 { 46 const UUID &module_uuid = module->GetUUID(); 47 DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); 48 49 // First try just by UUID as it is the safest. 50 if (module_uuid.IsValid()) 51 { 52 for (pos = m_dyld_image_infos.begin(); pos != end; ++pos) 53 { 54 if (pos->uuid == module_uuid) 55 return &(*pos); 56 } 57 58 if (m_dyld.uuid == module_uuid) 59 return &m_dyld; 60 } 61 62 // Next try by platform path only for things that don't have a valid UUID 63 // since if a file has a valid UUID in real life it should also in the 64 // dyld info. This is the next safest because the paths in the dyld info 65 // are platform paths, not local paths. For local debugging platform == local 66 // paths. 67 const FileSpec &platform_file_spec = module->GetPlatformFileSpec(); 68 for (pos = m_dyld_image_infos.begin(); pos != end; ++pos) 69 { 70 if (pos->file_spec == platform_file_spec && pos->uuid.IsValid() == false) 71 return &(*pos); 72 } 73 74 if (m_dyld.file_spec == platform_file_spec && m_dyld.uuid.IsValid() == false) 75 return &m_dyld; 76 77 return NULL; 78 } 79 80 //---------------------------------------------------------------------- 81 // Create an instance of this class. This function is filled into 82 // the plugin info class that gets handed out by the plugin factory and 83 // allows the lldb to instantiate an instance of this class. 84 //---------------------------------------------------------------------- 85 DynamicLoader * 86 DynamicLoaderMacOSXDYLD::CreateInstance (Process* process, bool force) 87 { 88 bool create = force; 89 if (!create) 90 { 91 const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); 92 if (triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple) 93 create = true; 94 } 95 96 if (create) 97 return new DynamicLoaderMacOSXDYLD (process); 98 return NULL; 99 } 100 101 //---------------------------------------------------------------------- 102 // Constructor 103 //---------------------------------------------------------------------- 104 DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) : 105 DynamicLoader(process), 106 m_dyld(), 107 m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS), 108 m_dyld_all_image_infos(), 109 m_dyld_all_image_infos_stop_id (UINT32_MAX), 110 m_break_id(LLDB_INVALID_BREAK_ID), 111 m_dyld_image_infos(), 112 m_dyld_image_infos_stop_id (UINT32_MAX), 113 m_mutex(Mutex::eMutexTypeRecursive) 114 { 115 } 116 117 //---------------------------------------------------------------------- 118 // Destructor 119 //---------------------------------------------------------------------- 120 DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD() 121 { 122 Clear(true); 123 } 124 125 //------------------------------------------------------------------ 126 /// Called after attaching a process. 127 /// 128 /// Allow DynamicLoader plug-ins to execute some code after 129 /// attaching to a process. 130 //------------------------------------------------------------------ 131 void 132 DynamicLoaderMacOSXDYLD::DidAttach () 133 { 134 PrivateInitialize(m_process); 135 LocateDYLD (); 136 SetNotificationBreakpoint (); 137 } 138 139 //------------------------------------------------------------------ 140 /// Called after attaching a process. 141 /// 142 /// Allow DynamicLoader plug-ins to execute some code after 143 /// attaching to a process. 144 //------------------------------------------------------------------ 145 void 146 DynamicLoaderMacOSXDYLD::DidLaunch () 147 { 148 PrivateInitialize(m_process); 149 LocateDYLD (); 150 SetNotificationBreakpoint (); 151 } 152 153 154 //---------------------------------------------------------------------- 155 // Clear out the state of this class. 156 //---------------------------------------------------------------------- 157 void 158 DynamicLoaderMacOSXDYLD::Clear (bool clear_process) 159 { 160 Mutex::Locker locker(m_mutex); 161 162 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) 163 m_process->ClearBreakpointSiteByID(m_break_id); 164 165 if (clear_process) 166 m_process = NULL; 167 m_dyld.Clear(false); 168 m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS; 169 m_dyld_all_image_infos.Clear(); 170 m_break_id = LLDB_INVALID_BREAK_ID; 171 m_dyld_image_infos.clear(); 172 } 173 174 //---------------------------------------------------------------------- 175 // Check if we have found DYLD yet 176 //---------------------------------------------------------------------- 177 bool 178 DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const 179 { 180 return LLDB_BREAK_ID_IS_VALID (m_break_id); 181 } 182 183 //---------------------------------------------------------------------- 184 // Try and figure out where dyld is by first asking the Process 185 // if it knows (which currently calls down in the the lldb::Process 186 // to get the DYLD info (available on SnowLeopard only). If that fails, 187 // then check in the default addresses. 188 //---------------------------------------------------------------------- 189 bool 190 DynamicLoaderMacOSXDYLD::LocateDYLD() 191 { 192 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) 193 m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress (); 194 195 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) 196 { 197 if (ReadAllImageInfosStructure ()) 198 { 199 if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS) 200 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress); 201 else 202 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull); 203 } 204 } 205 206 // Check some default values 207 Module *executable = m_process->GetTarget().GetExecutableModule().get(); 208 209 if (executable) 210 { 211 if (executable->GetArchitecture().GetAddressByteSize() == 8) 212 { 213 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull); 214 } 215 #if defined (__arm__) 216 else 217 { 218 ArchSpec arm_arch("arm"); 219 if (arm_arch == executable->Arch()) 220 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000); 221 } 222 #endif 223 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000); 224 } 225 return false; 226 } 227 228 ModuleSP 229 DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr) 230 { 231 if (did_create_ptr) 232 *did_create_ptr = false; 233 ModuleSP module_sp; 234 ModuleList &target_images = m_process->GetTarget().GetImages(); 235 const bool image_info_uuid_is_valid = image_info.uuid.IsValid(); 236 if (image_info_uuid_is_valid) 237 module_sp = target_images.FindModule(image_info.uuid); 238 239 if (!module_sp) 240 { 241 ArchSpec arch(image_info.GetArchitecture ()); 242 243 module_sp = target_images.FindFirstModuleForFileSpec (image_info.file_spec, &arch, NULL); 244 245 if (can_create && !module_sp) 246 { 247 module_sp = m_process->GetTarget().GetSharedModule (image_info.file_spec, 248 arch, 249 image_info_uuid_is_valid ? &image_info.uuid : NULL); 250 if (did_create_ptr) 251 *did_create_ptr = module_sp; 252 } 253 } 254 return module_sp; 255 } 256 257 //---------------------------------------------------------------------- 258 // Assume that dyld is in memory at ADDR and try to parse it's load 259 // commands 260 //---------------------------------------------------------------------- 261 bool 262 DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr) 263 { 264 DataExtractor data; // Load command data 265 if (ReadMachHeader (addr, &m_dyld.header, &data)) 266 { 267 if (m_dyld.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) 268 { 269 m_dyld.address = addr; 270 ModuleSP dyld_module_sp; 271 if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec)) 272 { 273 if (m_dyld.file_spec) 274 { 275 dyld_module_sp = FindTargetModuleForDYLDImageInfo (m_dyld, true, NULL); 276 277 if (dyld_module_sp) 278 UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld); 279 } 280 } 281 282 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get()) 283 { 284 static ConstString g_dyld_all_image_infos ("dyld_all_image_infos"); 285 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData); 286 if (symbol) 287 m_dyld_all_image_infos_addr = symbol->GetValue().GetLoadAddress(&m_process->GetTarget()); 288 } 289 290 // Update all image infos 291 UpdateAllImageInfos(); 292 293 // If we didn't have an executable before, but now we do, then the 294 // dyld module shared pointer might be unique and we may need to add 295 // it again (since Target::SetExecutableModule() will clear the 296 // images). So append the dyld module back to the list if it is 297 /// unique! 298 if (dyld_module_sp && m_process->GetTarget().GetImages().AppendIfNeeded (dyld_module_sp)) 299 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld); 300 301 return true; 302 } 303 } 304 return false; 305 } 306 307 bool 308 DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const 309 { 310 return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS; 311 } 312 313 bool 314 DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module) 315 { 316 bool changed = false; 317 if (module) 318 { 319 ObjectFile *image_object_file = module->GetObjectFile(); 320 if (image_object_file) 321 { 322 SectionList *section_list = image_object_file->GetSectionList (); 323 if (section_list) 324 { 325 uint32_t num_sections = section_list->GetSize(); 326 for (uint32_t i=0; i<num_sections; ++i) 327 { 328 Section* section = section_list->GetSectionAtIndex (i).get(); 329 if (section) 330 { 331 const addr_t new_section_load_addr = section->GetFileAddress (); 332 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section); 333 if (old_section_load_addr == LLDB_INVALID_ADDRESS || 334 old_section_load_addr != new_section_load_addr) 335 { 336 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ())) 337 changed = true; 338 } 339 } 340 } 341 } 342 } 343 } 344 return changed; 345 } 346 347 //---------------------------------------------------------------------- 348 // Update the load addresses for all segments in MODULE using the 349 // updated INFO that is passed in. 350 //---------------------------------------------------------------------- 351 bool 352 DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& info) 353 { 354 bool changed = false; 355 if (module) 356 { 357 ObjectFile *image_object_file = module->GetObjectFile(); 358 if (image_object_file) 359 { 360 SectionList *section_list = image_object_file->GetSectionList (); 361 if (section_list) 362 { 363 // All sections listed in the dyld image info structure will all 364 // either be fixed up already, or they will all be off by a single 365 // slide amount that is determined by finding the first segment 366 // that is at file offset zero which also has bytes (a file size 367 // that is greater than zero) in the object file. 368 369 // Determine the slide amount (if any) 370 info.slide = 0; 371 const size_t num_sections = section_list->GetSize(); 372 size_t sect_idx = 0; 373 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) 374 { 375 // Iterate through the object file sections to find the 376 // first section that starts of file offset zero and that 377 // has bytes in the file... 378 Section *section = section_list->GetSectionAtIndex (sect_idx).get(); 379 if (section) 380 { 381 // Find the first section that begins at file offset zero 382 // a file size (skip page zero). 383 if (section->GetFileOffset() == 0 && section->GetFileSize() > 0) 384 { 385 // We have now found the section, lets match it up 386 // with the section in the dyld image info structure. 387 const Segment *dyld_segment = info.FindSegment (section->GetName()); 388 if (dyld_segment) 389 info.slide = info.address - dyld_segment->addr; 390 // We have found the slide amount, so we can exit 391 // this for loop. 392 break; 393 } 394 } 395 } 396 397 // We now know the slide amount, so go through all sections 398 // and update the load addresses with the correct values. 399 uint32_t num_segments = info.segments.size(); 400 for (uint32_t i=0; i<num_segments; ++i) 401 { 402 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); 403 assert (section_sp.get() != NULL); 404 const addr_t new_section_load_addr = info.segments[i].addr + info.slide; 405 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get()); 406 if (old_section_load_addr == LLDB_INVALID_ADDRESS || 407 old_section_load_addr != new_section_load_addr) 408 { 409 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr)) 410 changed = true; 411 } 412 } 413 } 414 } 415 } 416 return changed; 417 } 418 419 //---------------------------------------------------------------------- 420 // Update the load addresses for all segments in MODULE using the 421 // updated INFO that is passed in. 422 //---------------------------------------------------------------------- 423 bool 424 DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& info) 425 { 426 bool changed = false; 427 if (module) 428 { 429 ObjectFile *image_object_file = module->GetObjectFile(); 430 if (image_object_file) 431 { 432 SectionList *section_list = image_object_file->GetSectionList (); 433 if (section_list) 434 { 435 uint32_t num_segments = info.segments.size(); 436 for (uint32_t i=0; i<num_segments; ++i) 437 { 438 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); 439 assert (section_sp.get() != NULL); 440 const addr_t old_section_load_addr = info.segments[i].addr + info.slide; 441 if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr)) 442 changed = true; 443 } 444 } 445 } 446 } 447 return changed; 448 } 449 450 451 //---------------------------------------------------------------------- 452 // Static callback function that gets called when our DYLD notification 453 // breakpoint gets hit. We update all of our image infos and then 454 // let our super class DynamicLoader class decide if we should stop 455 // or not (based on global preference). 456 //---------------------------------------------------------------------- 457 bool 458 DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id) 459 { 460 // Let the event know that the images have changed 461 DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton; 462 dyld_instance->UpdateAllImageInfos(); 463 // Return true to stop the target, false to just let the target run 464 return dyld_instance->GetStopWhenImagesChange(); 465 } 466 467 bool 468 DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () 469 { 470 Mutex::Locker locker(m_mutex); 471 472 // the all image infos is already valid for this process stop ID 473 if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id) 474 return true; 475 476 m_dyld_all_image_infos.Clear(); 477 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) 478 { 479 ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder(); 480 uint32_t addr_size = 4; 481 if (m_dyld_all_image_infos_addr > UINT32_MAX) 482 addr_size = 8; 483 484 uint8_t buf[256]; 485 DataExtractor data (buf, sizeof(buf), byte_order, addr_size); 486 uint32_t offset = 0; 487 488 const size_t count_v2 = sizeof (uint32_t) + // version 489 sizeof (uint32_t) + // infoArrayCount 490 addr_size + // infoArray 491 addr_size + // notification 492 addr_size + // processDetachedFromSharedRegion + libSystemInitialized + pad 493 addr_size; // dyldImageLoadAddress 494 const size_t count_v11 = count_v2 + 495 addr_size + // jitInfo 496 addr_size + // dyldVersion 497 addr_size + // errorMessage 498 addr_size + // terminationFlags 499 addr_size + // coreSymbolicationShmPage 500 addr_size + // systemOrderFlag 501 addr_size + // uuidArrayCount 502 addr_size + // uuidArray 503 addr_size + // dyldAllImageInfosAddress 504 addr_size + // initialImageCount 505 addr_size + // errorKind 506 addr_size + // errorClientOfDylibPath 507 addr_size + // errorTargetDylibPath 508 addr_size; // errorSymbol 509 assert (sizeof (buf) > count_v11); 510 511 int count; 512 Error error; 513 if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4) 514 { 515 m_dyld_all_image_infos.version = data.GetU32(&offset); 516 // If anything in the high byte is set, we probably got the byte 517 // order incorrect (the process might not have it set correctly 518 // yet due to attaching to a program without a specified file). 519 if (m_dyld_all_image_infos.version & 0xff000000) 520 { 521 // We have guessed the wrong byte order. Swap it and try 522 // reading the version again. 523 if (byte_order == eByteOrderLittle) 524 byte_order = eByteOrderBig; 525 else 526 byte_order = eByteOrderLittle; 527 528 data.SetByteOrder (byte_order); 529 offset = 0; 530 m_dyld_all_image_infos.version = data.GetU32(&offset); 531 } 532 } 533 else 534 { 535 return false; 536 } 537 538 if (m_dyld_all_image_infos.version >= 11) 539 count = count_v11; 540 else 541 count = count_v2; 542 543 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error); 544 if (bytes_read == count) 545 { 546 offset = 0; 547 m_dyld_all_image_infos.version = data.GetU32(&offset); 548 m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset); 549 m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset); 550 m_dyld_all_image_infos.notification = data.GetPointer(&offset); 551 m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset); 552 m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset); 553 // Adjust for padding. 554 offset += addr_size - 2; 555 m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset); 556 if (m_dyld_all_image_infos.version >= 11) 557 { 558 offset += addr_size * 8; 559 uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset); 560 561 // When we started, we were given the actual address of the all_image_infos 562 // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in 563 // m_dyld_all_image_infos_addr and is the most accurate address we have. 564 565 // We read the dyld_all_image_infos struct from memory; it contains its own address. 566 // If the address in the struct does not match the actual address, 567 // the dyld we're looking at has been loaded at a different location (slid) from 568 // where it intended to load. The addresses in the dyld_all_image_infos struct 569 // are the original, non-slid addresses, and need to be adjusted. Most importantly 570 // the address of dyld and the notification address need to be adjusted. 571 572 if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) 573 { 574 uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress; 575 uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress; 576 m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset; 577 m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset; 578 } 579 } 580 m_dyld_all_image_infos_stop_id = m_process->GetStopID(); 581 return true; 582 } 583 } 584 return false; 585 } 586 587 //---------------------------------------------------------------------- 588 // If we have found where the "_dyld_all_image_infos" lives in memory, 589 // read the current info from it, and then update all image load 590 // addresses (or lack thereof). 591 //---------------------------------------------------------------------- 592 uint32_t 593 DynamicLoaderMacOSXDYLD::UpdateAllImageInfos() 594 { 595 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); 596 ModuleList& target_images = m_process->GetTarget().GetImages(); 597 598 if (ReadAllImageInfosStructure ()) 599 { 600 Mutex::Locker locker(m_mutex); 601 if (m_process->GetStopID() == m_dyld_image_infos_stop_id) 602 m_dyld_image_infos.size(); 603 604 uint32_t idx; 605 uint32_t i = 0; 606 // Since we can't downsize a vector, we must do this using the swap method 607 DYLDImageInfo::collection old_dyld_all_image_infos; 608 old_dyld_all_image_infos.swap(m_dyld_image_infos); 609 610 // If we made it here, we are assuming that the all dylib info data should 611 // be valid, lets read the info array. 612 const ByteOrder endian = m_dyld.GetByteOrder(); 613 const uint32_t addr_size = m_dyld.GetAddressByteSize(); 614 615 if (m_dyld_all_image_infos.dylib_info_count > 0) 616 { 617 if (m_dyld_all_image_infos.dylib_info_addr == 0) 618 { 619 // DYLD is updating the images right now... 620 } 621 else 622 { 623 m_dyld_image_infos.resize(m_dyld_all_image_infos.dylib_info_count); 624 const size_t count = m_dyld_image_infos.size() * 3 * addr_size; 625 DataBufferHeap info_data(count, 0); 626 Error error; 627 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos.dylib_info_addr, 628 info_data.GetBytes(), 629 info_data.GetByteSize(), 630 error); 631 if (bytes_read == count) 632 { 633 uint32_t info_data_offset = 0; 634 DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size); 635 for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++) 636 { 637 assert (i < m_dyld_image_infos.size()); 638 m_dyld_image_infos[i].address = info_data_ref.GetPointer(&info_data_offset); 639 lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset); 640 m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset); 641 642 char raw_path[PATH_MAX]; 643 m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path)); 644 char raw_path2[PATH_MAX];// TODO: remove after assertion doesn't assert 645 m_process->ReadMemory (path_addr, raw_path2, sizeof(raw_path2), error);// TODO: remove after assertion doesn't assert 646 assert (strcmp (raw_path, raw_path2) == 0);// TODO: remove after assertion doesn't assert 647 m_dyld_image_infos[i].file_spec.SetFile(raw_path, true); 648 } 649 assert(i == m_dyld_all_image_infos.dylib_info_count); 650 651 UpdateAllImageInfosHeaderAndLoadCommands(); 652 } 653 else 654 { 655 DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); 656 m_dyld_image_infos.clear(); 657 } 658 } 659 } 660 661 // If our new list is smaller than our old list, we have unloaded 662 // some shared libraries 663 if (m_dyld_image_infos.size() != old_dyld_all_image_infos.size()) 664 { 665 ModuleList unloaded_module_list; 666 if (old_dyld_all_image_infos.size() == 0) 667 { 668 // This is the first time we are loading shared libraries, 669 // we need to make sure to trim anything that isn't in the 670 // m_dyld_image_infos out of the target module list since 671 // we might have shared libraries that got loaded from 672 // elsewhere due to DYLD_FRAMEWORK_PATH, or DYLD_LIBRARY_PATH 673 // environment variables... 674 const size_t num_images = target_images.GetSize(); 675 for (idx = 0; idx < num_images; ++idx) 676 { 677 ModuleSP module_sp (target_images.GetModuleAtIndex (idx)); 678 679 if (GetImageInfo (module_sp.get()) == NULL) 680 unloaded_module_list.AppendIfNeeded (module_sp); 681 } 682 } 683 else 684 { 685 uint32_t old_idx; 686 for (idx = 0; idx < old_dyld_all_image_infos.size(); ++idx) 687 { 688 for (old_idx = idx; old_idx < old_dyld_all_image_infos.size(); ++old_idx) 689 { 690 if (m_dyld_image_infos[idx].file_spec == old_dyld_all_image_infos[old_idx].file_spec) 691 { 692 old_dyld_all_image_infos[old_idx].address = LLDB_INVALID_ADDRESS; 693 break; 694 } 695 } 696 } 697 698 for (old_idx = 0; old_idx < old_dyld_all_image_infos.size(); ++old_idx) 699 { 700 if (old_dyld_all_image_infos[old_idx].address != LLDB_INVALID_ADDRESS) 701 { 702 if (log) 703 old_dyld_all_image_infos[old_idx].PutToLog (log.get()); 704 ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (old_dyld_all_image_infos[old_idx], false, NULL)); 705 if (unload_image_module_sp.get()) 706 { 707 if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[old_idx])) 708 unloaded_module_list.AppendIfNeeded (unload_image_module_sp); 709 } 710 } 711 } 712 } 713 714 if (unloaded_module_list.GetSize() > 0) 715 { 716 if (log) 717 { 718 log->PutCString("Unloaded:"); 719 unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload"); 720 } 721 m_process->GetTarget().ModulesDidUnload (unloaded_module_list); 722 } 723 } 724 else 725 { 726 if (log) 727 PutToLog(log.get()); 728 } 729 m_dyld_image_infos_stop_id = m_process->GetStopID(); 730 } 731 else 732 { 733 m_dyld_image_infos.clear(); 734 } 735 736 const uint32_t num_dylibs = m_dyld_image_infos.size(); 737 if (num_dylibs > 0) 738 { 739 ModuleList loaded_module_list; 740 for (uint32_t idx = 0; idx<num_dylibs; ++idx) 741 { 742 ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (m_dyld_image_infos[idx], true, NULL)); 743 744 if (image_module_sp) 745 { 746 if (m_dyld_image_infos[idx].header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) 747 image_module_sp->SetIsDynamicLinkEditor (true); 748 749 ObjectFile *objfile = image_module_sp->GetObjectFile (); 750 if (objfile) 751 { 752 SectionList *sections = objfile->GetSectionList(); 753 if (sections) 754 { 755 ConstString commpage_dbstr("__commpage"); 756 Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get(); 757 if (commpage_section) 758 { 759 const FileSpec objfile_file_spec = objfile->GetFileSpec(); 760 ArchSpec arch (m_dyld_image_infos[idx].GetArchitecture ()); 761 ModuleSP commpage_image_module_sp(target_images.FindFirstModuleForFileSpec (objfile_file_spec, &arch, &commpage_dbstr)); 762 if (!commpage_image_module_sp) 763 { 764 commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec, 765 arch, 766 NULL, 767 &commpage_dbstr, 768 objfile->GetOffset() + commpage_section->GetFileOffset()); 769 } 770 if (commpage_image_module_sp) 771 UpdateCommPageLoadAddress (commpage_image_module_sp.get()); 772 } 773 } 774 } 775 776 // UpdateImageLoadAddress will return true if any segments 777 // change load address. We need to check this so we don't 778 // mention that all loaded shared libraries are newly loaded 779 // each time we hit out dyld breakpoint since dyld will list all 780 // shared libraries each time. 781 if (UpdateImageLoadAddress (image_module_sp.get(), m_dyld_image_infos[idx])) 782 { 783 loaded_module_list.AppendIfNeeded (image_module_sp); 784 } 785 } 786 } 787 if (loaded_module_list.GetSize() > 0) 788 { 789 // FIXME: This should really be in the Runtime handlers class, which should get 790 // called by the target's ModulesDidLoad, but we're doing it all locally for now 791 // to save time. 792 // Also, I'm assuming there can be only one libobjc dylib loaded... 793 794 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); 795 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary()) 796 { 797 size_t num_modules = loaded_module_list.GetSize(); 798 for (int i = 0; i < num_modules; i++) 799 { 800 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i))) 801 { 802 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i)); 803 break; 804 } 805 } 806 } 807 if (log) 808 loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad"); 809 m_process->GetTarget().ModulesDidLoad (loaded_module_list); 810 } 811 } 812 return m_dyld_image_infos.size(); 813 } 814 815 //---------------------------------------------------------------------- 816 // Read a mach_header at ADDR into HEADER, and also fill in the load 817 // command data into LOAD_COMMAND_DATA if it is non-NULL. 818 // 819 // Returns true if we succeed, false if we fail for any reason. 820 //---------------------------------------------------------------------- 821 bool 822 DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data) 823 { 824 DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0); 825 Error error; 826 size_t bytes_read = m_process->ReadMemory (addr, 827 header_bytes.GetBytes(), 828 header_bytes.GetByteSize(), 829 error); 830 if (bytes_read == sizeof(llvm::MachO::mach_header)) 831 { 832 uint32_t offset = 0; 833 ::memset (header, 0, sizeof(header)); 834 835 // Get the magic byte unswapped so we can figure out what we are dealing with 836 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4); 837 header->magic = data.GetU32(&offset); 838 lldb::addr_t load_cmd_addr = addr; 839 data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic)); 840 switch (header->magic) 841 { 842 case llvm::MachO::HeaderMagic32: 843 case llvm::MachO::HeaderMagic32Swapped: 844 data.SetAddressByteSize(4); 845 load_cmd_addr += sizeof(llvm::MachO::mach_header); 846 break; 847 848 case llvm::MachO::HeaderMagic64: 849 case llvm::MachO::HeaderMagic64Swapped: 850 data.SetAddressByteSize(8); 851 load_cmd_addr += sizeof(llvm::MachO::mach_header_64); 852 break; 853 854 default: 855 return false; 856 } 857 858 // Read the rest of dyld's mach header 859 if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1)) 860 { 861 if (load_command_data == NULL) 862 return true; // We were able to read the mach_header and weren't asked to read the load command bytes 863 864 DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0)); 865 866 size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr, 867 load_cmd_data_sp->GetBytes(), 868 load_cmd_data_sp->GetByteSize(), 869 error); 870 871 if (load_cmd_bytes_read == header->sizeofcmds) 872 { 873 // Set the load command data and also set the correct endian 874 // swap settings and the correct address size 875 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds); 876 load_command_data->SetByteOrder(data.GetByteOrder()); 877 load_command_data->SetAddressByteSize(data.GetAddressByteSize()); 878 return true; // We successfully read the mach_header and the load command data 879 } 880 881 return false; // We weren't able to read the load command data 882 } 883 } 884 return false; // We failed the read the mach_header 885 } 886 887 888 //---------------------------------------------------------------------- 889 // Parse the load commands for an image 890 //---------------------------------------------------------------------- 891 uint32_t 892 DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker) 893 { 894 uint32_t offset = 0; 895 uint32_t cmd_idx; 896 Segment segment; 897 dylib_info.Clear (true); 898 899 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) 900 { 901 // Clear out any load command specific data from DYLIB_INFO since 902 // we are about to read it. 903 904 if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command))) 905 { 906 llvm::MachO::load_command load_cmd; 907 uint32_t load_cmd_offset = offset; 908 load_cmd.cmd = data.GetU32 (&offset); 909 load_cmd.cmdsize = data.GetU32 (&offset); 910 switch (load_cmd.cmd) 911 { 912 case llvm::MachO::LoadCommandSegment32: 913 { 914 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); 915 segment.addr = data.GetU32 (&offset); 916 segment.size = data.GetU32 (&offset); 917 dylib_info.segments.push_back (segment); 918 } 919 break; 920 921 case llvm::MachO::LoadCommandSegment64: 922 { 923 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); 924 segment.addr = data.GetU64 (&offset); 925 segment.size = data.GetU64 (&offset); 926 dylib_info.segments.push_back (segment); 927 } 928 break; 929 930 case llvm::MachO::LoadCommandDynamicLinkerIdent: 931 if (lc_id_dylinker) 932 { 933 uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset); 934 const char *path = data.PeekCStr (name_offset); 935 lc_id_dylinker->SetFile (path, true); 936 } 937 break; 938 939 case llvm::MachO::LoadCommandUUID: 940 dylib_info.uuid.SetBytes(data.GetData (&offset, 16)); 941 break; 942 943 default: 944 break; 945 } 946 // Set offset to be the beginning of the next load command. 947 offset = load_cmd_offset + load_cmd.cmdsize; 948 } 949 } 950 return cmd_idx; 951 } 952 953 //---------------------------------------------------------------------- 954 // Read the mach_header and load commands for each image that the 955 // _dyld_all_image_infos structure points to and cache the results. 956 //---------------------------------------------------------------------- 957 void 958 DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands() 959 { 960 uint32_t exe_idx = UINT32_MAX; 961 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); 962 // Read any UUID values that we can get 963 for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++) 964 { 965 if (!m_dyld_image_infos[i].UUIDValid()) 966 { 967 DataExtractor data; // Load command data 968 if (!ReadMachHeader (m_dyld_image_infos[i].address, &m_dyld_image_infos[i].header, &data)) 969 continue; 970 971 ParseLoadCommands (data, m_dyld_image_infos[i], NULL); 972 973 if (m_dyld_image_infos[i].header.filetype == llvm::MachO::HeaderFileTypeExecutable) 974 exe_idx = i; 975 976 if (log) 977 m_dyld_image_infos[i].PutToLog (log.get()); 978 } 979 } 980 981 if (exe_idx < m_dyld_image_infos.size()) 982 { 983 ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (m_dyld_image_infos[exe_idx], false, NULL)); 984 985 if (!exe_module_sp) 986 { 987 ArchSpec exe_arch_spec (m_dyld_image_infos[exe_idx].GetArchitecture ()); 988 exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec, 989 exe_arch_spec, 990 &m_dyld_image_infos[exe_idx].uuid); 991 } 992 993 if (exe_module_sp) 994 { 995 if (exe_module_sp.get() != m_process->GetTarget().GetExecutableModule().get()) 996 { 997 // Don't load dependent images since we are in dyld where we will know 998 // and find out about all images that are loaded 999 bool get_dependent_images = false; 1000 m_process->GetTarget().SetExecutableModule (exe_module_sp, 1001 get_dependent_images); 1002 } 1003 } 1004 } 1005 } 1006 1007 //---------------------------------------------------------------------- 1008 // Dump a Segment to the file handle provided. 1009 //---------------------------------------------------------------------- 1010 void 1011 DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const 1012 { 1013 if (log) 1014 log->Printf("\t\t%16s [0x%16.16llx - 0x%16.16llx)", name.AsCString(""), addr + slide, addr + slide + size); 1015 } 1016 1017 const DynamicLoaderMacOSXDYLD::Segment * 1018 DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const 1019 { 1020 const size_t num_segments = segments.size(); 1021 for (size_t i=0; i<num_segments; ++i) 1022 { 1023 if (segments[i].name == name) 1024 return &segments[i]; 1025 } 1026 return NULL; 1027 } 1028 1029 1030 //---------------------------------------------------------------------- 1031 // Dump an image info structure to the file handle provided. 1032 //---------------------------------------------------------------------- 1033 void 1034 DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const 1035 { 1036 if (log == NULL) 1037 return; 1038 uint8_t *u = (uint8_t *)uuid.GetBytes(); 1039 1040 if (address == LLDB_INVALID_ADDRESS) 1041 { 1042 if (u) 1043 { 1044 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)", 1045 mod_date, 1046 u[ 0], u[ 1], u[ 2], u[ 3], 1047 u[ 4], u[ 5], u[ 6], u[ 7], 1048 u[ 8], u[ 9], u[10], u[11], 1049 u[12], u[13], u[14], u[15], 1050 file_spec.GetDirectory().AsCString(), 1051 file_spec.GetFilename().AsCString()); 1052 } 1053 else 1054 log->Printf("\t modtime=0x%8.8llx path='%s/%s' (UNLOADED)", 1055 mod_date, 1056 file_spec.GetDirectory().AsCString(), 1057 file_spec.GetFilename().AsCString()); 1058 } 1059 else 1060 { 1061 if (u) 1062 { 1063 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'", 1064 address, 1065 mod_date, 1066 u[ 0], u[ 1], u[ 2], u[ 3], 1067 u[ 4], u[ 5], u[ 6], u[ 7], 1068 u[ 8], u[ 9], u[10], u[11], 1069 u[12], u[13], u[14], u[15], 1070 file_spec.GetDirectory().AsCString(), 1071 file_spec.GetFilename().AsCString()); 1072 } 1073 else 1074 { 1075 log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'", 1076 address, 1077 mod_date, 1078 file_spec.GetDirectory().AsCString(), 1079 file_spec.GetFilename().AsCString()); 1080 1081 } 1082 for (uint32_t i=0; i<segments.size(); ++i) 1083 segments[i].PutToLog(log, slide); 1084 } 1085 } 1086 1087 //---------------------------------------------------------------------- 1088 // Dump the _dyld_all_image_infos members and all current image infos 1089 // that we have parsed to the file handle provided. 1090 //---------------------------------------------------------------------- 1091 void 1092 DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const 1093 { 1094 if (log == NULL) 1095 return; 1096 1097 Mutex::Locker locker(m_mutex); 1098 log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }", 1099 m_dyld_all_image_infos.version, 1100 m_dyld_all_image_infos.dylib_info_count, 1101 (uint64_t)m_dyld_all_image_infos.dylib_info_addr, 1102 (uint64_t)m_dyld_all_image_infos.notification); 1103 size_t i; 1104 const size_t count = m_dyld_image_infos.size(); 1105 if (count > 0) 1106 { 1107 log->PutCString("Loaded:"); 1108 for (i = 0; i<count; i++) 1109 m_dyld_image_infos[i].PutToLog(log); 1110 } 1111 } 1112 1113 void 1114 DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process) 1115 { 1116 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); 1117 Clear(true); 1118 m_process = process; 1119 m_process->GetTarget().GetSectionLoadList().Clear(); 1120 } 1121 1122 bool 1123 DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () 1124 { 1125 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); 1126 if (m_break_id == LLDB_INVALID_BREAK_ID) 1127 { 1128 if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) 1129 { 1130 Address so_addr; 1131 // Set the notification breakpoint and install a breakpoint 1132 // callback function that will get called each time the 1133 // breakpoint gets hit. We will use this to track when shared 1134 // libraries get loaded/unloaded. 1135 1136 if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr)) 1137 { 1138 Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get(); 1139 dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true); 1140 m_break_id = dyld_break->GetID(); 1141 } 1142 } 1143 } 1144 return m_break_id != LLDB_INVALID_BREAK_ID; 1145 } 1146 1147 //---------------------------------------------------------------------- 1148 // Member function that gets called when the process state changes. 1149 //---------------------------------------------------------------------- 1150 void 1151 DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state) 1152 { 1153 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state)); 1154 switch (state) 1155 { 1156 case eStateConnected: 1157 case eStateAttaching: 1158 case eStateLaunching: 1159 case eStateInvalid: 1160 case eStateUnloaded: 1161 case eStateExited: 1162 case eStateDetached: 1163 Clear(false); 1164 break; 1165 1166 case eStateStopped: 1167 // Keep trying find dyld and set our notification breakpoint each time 1168 // we stop until we succeed 1169 if (!DidSetNotificationBreakpoint () && m_process->IsAlive()) 1170 { 1171 if (NeedToLocateDYLD ()) 1172 LocateDYLD (); 1173 1174 SetNotificationBreakpoint (); 1175 } 1176 break; 1177 1178 case eStateRunning: 1179 case eStateStepping: 1180 case eStateCrashed: 1181 case eStateSuspended: 1182 break; 1183 1184 default: 1185 break; 1186 } 1187 } 1188 1189 ThreadPlanSP 1190 DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) 1191 { 1192 ThreadPlanSP thread_plan_sp; 1193 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); 1194 const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol); 1195 Symbol *current_symbol = current_context.symbol; 1196 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 1197 1198 if (current_symbol != NULL) 1199 { 1200 if (current_symbol->IsTrampoline()) 1201 { 1202 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled); 1203 1204 if (trampoline_name) 1205 { 1206 SymbolContextList target_symbols; 1207 ModuleList &images = thread.GetProcess().GetTarget().GetImages(); 1208 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols); 1209 // FIXME - Make the Run to Address take multiple addresses, and 1210 // run to any of them. 1211 uint32_t num_symbols = target_symbols.GetSize(); 1212 if (num_symbols == 1) 1213 { 1214 SymbolContext context; 1215 AddressRange addr_range; 1216 if (target_symbols.GetContextAtIndex(0, context)) 1217 { 1218 context.GetAddressRange (eSymbolContextEverything, addr_range); 1219 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others)); 1220 } 1221 else 1222 { 1223 if (log) 1224 log->Printf ("Couldn't resolve the symbol context."); 1225 } 1226 } 1227 else if (num_symbols > 1) 1228 { 1229 std::vector<lldb::addr_t> addresses; 1230 addresses.resize (num_symbols); 1231 for (uint32_t i = 0; i < num_symbols; i++) 1232 { 1233 SymbolContext context; 1234 AddressRange addr_range; 1235 if (target_symbols.GetContextAtIndex(i, context)) 1236 { 1237 context.GetAddressRange (eSymbolContextEverything, addr_range); 1238 lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget()); 1239 addresses[i] = load_addr; 1240 } 1241 } 1242 if (addresses.size() > 0) 1243 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others)); 1244 else 1245 { 1246 if (log) 1247 log->Printf ("Couldn't resolve the symbol contexts."); 1248 } 1249 } 1250 else 1251 { 1252 if (log) 1253 { 1254 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString()); 1255 } 1256 } 1257 } 1258 } 1259 } 1260 else 1261 { 1262 if (log) 1263 log->Printf ("Could not find symbol for step through."); 1264 } 1265 1266 return thread_plan_sp; 1267 } 1268 1269 Error 1270 DynamicLoaderMacOSXDYLD::CanLoadImage () 1271 { 1272 Error error; 1273 // In order for us to tell if we can load a shared library we verify that 1274 // the dylib_info_addr isn't zero (which means no shared libraries have 1275 // been set yet, or dyld is currently mucking with the shared library list). 1276 if (ReadAllImageInfosStructure ()) 1277 { 1278 // TODO: also check the _dyld_global_lock_held variable in libSystem.B.dylib? 1279 // TODO: check the malloc lock? 1280 // TODO: check the objective C lock? 1281 if (m_dyld_all_image_infos.dylib_info_addr != 0) 1282 return error; // Success 1283 } 1284 1285 error.SetErrorString("unsafe to load or unload shared libraries"); 1286 return error; 1287 } 1288 1289 void 1290 DynamicLoaderMacOSXDYLD::Initialize() 1291 { 1292 PluginManager::RegisterPlugin (GetPluginNameStatic(), 1293 GetPluginDescriptionStatic(), 1294 CreateInstance); 1295 } 1296 1297 void 1298 DynamicLoaderMacOSXDYLD::Terminate() 1299 { 1300 PluginManager::UnregisterPlugin (CreateInstance); 1301 } 1302 1303 1304 const char * 1305 DynamicLoaderMacOSXDYLD::GetPluginNameStatic() 1306 { 1307 return "dynamic-loader.macosx-dyld"; 1308 } 1309 1310 const char * 1311 DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() 1312 { 1313 return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes."; 1314 } 1315 1316 1317 //------------------------------------------------------------------ 1318 // PluginInterface protocol 1319 //------------------------------------------------------------------ 1320 const char * 1321 DynamicLoaderMacOSXDYLD::GetPluginName() 1322 { 1323 return "DynamicLoaderMacOSXDYLD"; 1324 } 1325 1326 const char * 1327 DynamicLoaderMacOSXDYLD::GetShortPluginName() 1328 { 1329 return GetPluginNameStatic(); 1330 } 1331 1332 uint32_t 1333 DynamicLoaderMacOSXDYLD::GetPluginVersion() 1334 { 1335 return 1; 1336 } 1337 1338