DynamicLoaderMacOSXDYLD.cpp revision d2a1143a67661c65c6df4f4f1321ba4acdfe84c1
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 35using namespace lldb; 36using 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 43DynamicLoaderMacOSXDYLD::DYLDImageInfo * 44DynamicLoaderMacOSXDYLD::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//---------------------------------------------------------------------- 85DynamicLoader * 86DynamicLoaderMacOSXDYLD::CreateInstance (Process* process, bool force) 87{ 88 bool create = force; 89 if (!create) 90 { 91 create = true; 92 Module* exe_module = process->GetTarget().GetExecutableModulePointer(); 93 if (exe_module) 94 { 95 ObjectFile *object_file = exe_module->GetObjectFile(); 96 if (object_file) 97 { 98 SectionList *section_list = object_file->GetSectionList(); 99 if (section_list) 100 { 101 static ConstString g_kld_section_name ("__KLD"); 102 if (section_list->FindSectionByName (g_kld_section_name)) 103 { 104 create = false; 105 } 106 } 107 } 108 } 109 110 if (create) 111 { 112 const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); 113 create = triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple; 114 } 115 } 116 117 if (create) 118 return new DynamicLoaderMacOSXDYLD (process); 119 return NULL; 120} 121 122//---------------------------------------------------------------------- 123// Constructor 124//---------------------------------------------------------------------- 125DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) : 126 DynamicLoader(process), 127 m_dyld(), 128 m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS), 129 m_dyld_all_image_infos(), 130 m_dyld_all_image_infos_stop_id (UINT32_MAX), 131 m_break_id(LLDB_INVALID_BREAK_ID), 132 m_dyld_image_infos(), 133 m_dyld_image_infos_stop_id (UINT32_MAX), 134 m_mutex(Mutex::eMutexTypeRecursive) 135{ 136} 137 138//---------------------------------------------------------------------- 139// Destructor 140//---------------------------------------------------------------------- 141DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD() 142{ 143 Clear(true); 144} 145 146//------------------------------------------------------------------ 147/// Called after attaching a process. 148/// 149/// Allow DynamicLoader plug-ins to execute some code after 150/// attaching to a process. 151//------------------------------------------------------------------ 152void 153DynamicLoaderMacOSXDYLD::DidAttach () 154{ 155 PrivateInitialize(m_process); 156 LocateDYLD (); 157 SetNotificationBreakpoint (); 158} 159 160//------------------------------------------------------------------ 161/// Called after attaching a process. 162/// 163/// Allow DynamicLoader plug-ins to execute some code after 164/// attaching to a process. 165//------------------------------------------------------------------ 166void 167DynamicLoaderMacOSXDYLD::DidLaunch () 168{ 169 PrivateInitialize(m_process); 170 LocateDYLD (); 171 SetNotificationBreakpoint (); 172} 173 174 175//---------------------------------------------------------------------- 176// Clear out the state of this class. 177//---------------------------------------------------------------------- 178void 179DynamicLoaderMacOSXDYLD::Clear (bool clear_process) 180{ 181 Mutex::Locker locker(m_mutex); 182 183 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) 184 m_process->ClearBreakpointSiteByID(m_break_id); 185 186 if (clear_process) 187 m_process = NULL; 188 m_dyld.Clear(false); 189 m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS; 190 m_dyld_all_image_infos.Clear(); 191 m_break_id = LLDB_INVALID_BREAK_ID; 192 m_dyld_image_infos.clear(); 193} 194 195//---------------------------------------------------------------------- 196// Check if we have found DYLD yet 197//---------------------------------------------------------------------- 198bool 199DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const 200{ 201 return LLDB_BREAK_ID_IS_VALID (m_break_id); 202} 203 204//---------------------------------------------------------------------- 205// Try and figure out where dyld is by first asking the Process 206// if it knows (which currently calls down in the the lldb::Process 207// to get the DYLD info (available on SnowLeopard only). If that fails, 208// then check in the default addresses. 209//---------------------------------------------------------------------- 210bool 211DynamicLoaderMacOSXDYLD::LocateDYLD() 212{ 213 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) 214 m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress (); 215 216 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) 217 { 218 if (ReadAllImageInfosStructure ()) 219 { 220 if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS) 221 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress); 222 else 223 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull); 224 } 225 } 226 227 // Check some default values 228 Module *executable = m_process->GetTarget().GetExecutableModulePointer(); 229 230 if (executable) 231 { 232 const ArchSpec &exe_arch = executable->GetArchitecture(); 233 if (exe_arch.GetAddressByteSize() == 8) 234 { 235 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull); 236 } 237 else if (exe_arch.GetMachine() == llvm::Triple::arm || exe_arch.GetMachine() == llvm::Triple::thumb) 238 { 239 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000); 240 } 241 else 242 { 243 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000); 244 } 245 } 246 return false; 247} 248 249ModuleSP 250DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr) 251{ 252 if (did_create_ptr) 253 *did_create_ptr = false; 254 ModuleSP module_sp; 255 ModuleList &target_images = m_process->GetTarget().GetImages(); 256 const bool image_info_uuid_is_valid = image_info.uuid.IsValid(); 257 if (image_info_uuid_is_valid) 258 module_sp = target_images.FindModule(image_info.uuid); 259 260 if (!module_sp) 261 { 262 ArchSpec arch(image_info.GetArchitecture ()); 263 264 module_sp = target_images.FindFirstModuleForFileSpec (image_info.file_spec, &arch, NULL); 265 266 if (can_create) 267 { 268 if (module_sp) 269 { 270 if (image_info_uuid_is_valid) 271 { 272 if (module_sp->GetUUID() != image_info.uuid) 273 module_sp.reset(); 274 } 275 else 276 { 277 // No UUID, we must rely upon the cached module modification 278 // time and the modification time of the file on disk 279 if (module_sp->GetModificationTime() != module_sp->GetFileSpec().GetModificationTime()) 280 module_sp.reset(); 281 } 282 } 283 284 if (!module_sp) 285 { 286 module_sp = m_process->GetTarget().GetSharedModule (image_info.file_spec, 287 arch, 288 image_info_uuid_is_valid ? &image_info.uuid : NULL); 289 if (did_create_ptr) 290 *did_create_ptr = module_sp; 291 } 292 } 293 } 294 return module_sp; 295} 296 297//---------------------------------------------------------------------- 298// Assume that dyld is in memory at ADDR and try to parse it's load 299// commands 300//---------------------------------------------------------------------- 301bool 302DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr) 303{ 304 DataExtractor data; // Load command data 305 if (ReadMachHeader (addr, &m_dyld.header, &data)) 306 { 307 if (m_dyld.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) 308 { 309 m_dyld.address = addr; 310 ModuleSP dyld_module_sp; 311 if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec)) 312 { 313 if (m_dyld.file_spec) 314 { 315 dyld_module_sp = FindTargetModuleForDYLDImageInfo (m_dyld, true, NULL); 316 317 if (dyld_module_sp) 318 UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld); 319 } 320 } 321 322 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get()) 323 { 324 static ConstString g_dyld_all_image_infos ("dyld_all_image_infos"); 325 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData); 326 if (symbol) 327 m_dyld_all_image_infos_addr = symbol->GetValue().GetLoadAddress(&m_process->GetTarget()); 328 } 329 330 // Update all image infos 331 InitializeFromAllImageInfos (); 332 333 // If we didn't have an executable before, but now we do, then the 334 // dyld module shared pointer might be unique and we may need to add 335 // it again (since Target::SetExecutableModule() will clear the 336 // images). So append the dyld module back to the list if it is 337 /// unique! 338 if (dyld_module_sp && m_process->GetTarget().GetImages().AppendIfNeeded (dyld_module_sp)) 339 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld); 340 341 return true; 342 } 343 } 344 return false; 345} 346 347bool 348DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const 349{ 350 return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS; 351} 352 353bool 354DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module) 355{ 356 bool changed = false; 357 if (module) 358 { 359 ObjectFile *image_object_file = module->GetObjectFile(); 360 if (image_object_file) 361 { 362 SectionList *section_list = image_object_file->GetSectionList (); 363 if (section_list) 364 { 365 uint32_t num_sections = section_list->GetSize(); 366 for (uint32_t i=0; i<num_sections; ++i) 367 { 368 Section* section = section_list->GetSectionAtIndex (i).get(); 369 if (section) 370 { 371 const addr_t new_section_load_addr = section->GetFileAddress (); 372 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section); 373 if (old_section_load_addr == LLDB_INVALID_ADDRESS || 374 old_section_load_addr != new_section_load_addr) 375 { 376 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ())) 377 changed = true; 378 } 379 } 380 } 381 } 382 } 383 } 384 return changed; 385} 386 387//---------------------------------------------------------------------- 388// Update the load addresses for all segments in MODULE using the 389// updated INFO that is passed in. 390//---------------------------------------------------------------------- 391bool 392DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& info) 393{ 394 bool changed = false; 395 if (module) 396 { 397 ObjectFile *image_object_file = module->GetObjectFile(); 398 if (image_object_file) 399 { 400 SectionList *section_list = image_object_file->GetSectionList (); 401 if (section_list) 402 { 403 // We now know the slide amount, so go through all sections 404 // and update the load addresses with the correct values. 405 uint32_t num_segments = info.segments.size(); 406 for (uint32_t i=0; i<num_segments; ++i) 407 { 408 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); 409 const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide; 410 if (section_sp) 411 { 412 const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get()); 413 if (old_section_load_addr == LLDB_INVALID_ADDRESS || 414 old_section_load_addr != new_section_load_addr) 415 { 416 if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr)) 417 changed = true; 418 } 419 } 420 else 421 { 422 fprintf (stderr, 423 "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n", 424 info.segments[i].name.AsCString("<invalid>"), 425 (uint64_t)new_section_load_addr, 426 image_object_file->GetFileSpec().GetDirectory().AsCString(), 427 image_object_file->GetFileSpec().GetFilename().AsCString()); 428 } 429 } 430 } 431 } 432 } 433 return changed; 434} 435 436//---------------------------------------------------------------------- 437// Update the load addresses for all segments in MODULE using the 438// updated INFO that is passed in. 439//---------------------------------------------------------------------- 440bool 441DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& info) 442{ 443 bool changed = false; 444 if (module) 445 { 446 ObjectFile *image_object_file = module->GetObjectFile(); 447 if (image_object_file) 448 { 449 SectionList *section_list = image_object_file->GetSectionList (); 450 if (section_list) 451 { 452 uint32_t num_segments = info.segments.size(); 453 for (uint32_t i=0; i<num_segments; ++i) 454 { 455 SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); 456 if (section_sp) 457 { 458 const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide; 459 if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr)) 460 changed = true; 461 } 462 else 463 { 464 fprintf (stderr, 465 "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n", 466 info.segments[i].name.AsCString("<invalid>"), 467 image_object_file->GetFileSpec().GetDirectory().AsCString(), 468 image_object_file->GetFileSpec().GetFilename().AsCString()); 469 } 470 } 471 } 472 } 473 } 474 return changed; 475} 476 477 478//---------------------------------------------------------------------- 479// Static callback function that gets called when our DYLD notification 480// breakpoint gets hit. We update all of our image infos and then 481// let our super class DynamicLoader class decide if we should stop 482// or not (based on global preference). 483//---------------------------------------------------------------------- 484bool 485DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, 486 StoppointCallbackContext *context, 487 lldb::user_id_t break_id, 488 lldb::user_id_t break_loc_id) 489{ 490 // Let the event know that the images have changed 491 // DYLD passes three arguments to the notification breakpoint. 492 // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing 493 // Arg2: uint32_t infoCount - Number of shared libraries added 494 // Arg3: dyld_image_info info[] - Array of structs of the form: 495 // const struct mach_header *imageLoadAddress 496 // const char *imageFilePath 497 // uintptr_t imageFileModDate (a time_t) 498 499 DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton; 500 501 // First step is to see if we've already initialized the all image infos. If we haven't then this function 502 // will do so and return true. In the course of initializing the all_image_infos it will read the complete 503 // current state, so we don't need to figure out what has changed from the data passed in to us. 504 505 if (dyld_instance->InitializeFromAllImageInfos()) 506 return dyld_instance->GetStopWhenImagesChange(); 507 508 Process *process = context->exe_ctx.GetProcessPtr(); 509 const lldb::ABISP &abi = process->GetABI(); 510 if (abi != NULL) 511 { 512 // Build up the value array to store the three arguments given above, then get the values from the ABI: 513 514 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 515 ValueList argument_values; 516 Value input_value; 517 518 void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); 519 void *clang_uint32_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32); 520 input_value.SetValueType (Value::eValueTypeScalar); 521 input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type); 522 argument_values.PushValue(input_value); 523 argument_values.PushValue(input_value); 524 input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type); 525 argument_values.PushValue (input_value); 526 527 if (abi->GetArgumentValues (context->exe_ctx.GetThreadRef(), argument_values)) 528 { 529 uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1); 530 if (dyld_mode != -1) 531 { 532 // Okay the mode was right, now get the number of elements, and the array of new elements... 533 uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1); 534 if (image_infos_count != -1) 535 { 536 // Got the number added, now go through the array of added elements, putting out the mach header 537 // address, and adding the image. 538 // Note, I'm not putting in logging here, since the AddModules & RemoveModules functions do 539 // all the logging internally. 540 541 lldb::addr_t image_infos_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(); 542 if (dyld_mode == 0) 543 { 544 // This is add: 545 dyld_instance->AddModulesUsingImageInfosAddress (image_infos_addr, image_infos_count); 546 } 547 else 548 { 549 // This is remove: 550 dyld_instance->RemoveModulesUsingImageInfosAddress (image_infos_addr, image_infos_count); 551 } 552 553 } 554 } 555 } 556 } 557 558 // Return true to stop the target, false to just let the target run 559 return dyld_instance->GetStopWhenImagesChange(); 560} 561 562bool 563DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () 564{ 565 Mutex::Locker locker(m_mutex); 566 567 // the all image infos is already valid for this process stop ID 568 if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id) 569 return true; 570 571 m_dyld_all_image_infos.Clear(); 572 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) 573 { 574 ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder(); 575 uint32_t addr_size = 4; 576 if (m_dyld_all_image_infos_addr > UINT32_MAX) 577 addr_size = 8; 578 579 uint8_t buf[256]; 580 DataExtractor data (buf, sizeof(buf), byte_order, addr_size); 581 uint32_t offset = 0; 582 583 const size_t count_v2 = sizeof (uint32_t) + // version 584 sizeof (uint32_t) + // infoArrayCount 585 addr_size + // infoArray 586 addr_size + // notification 587 addr_size + // processDetachedFromSharedRegion + libSystemInitialized + pad 588 addr_size; // dyldImageLoadAddress 589 const size_t count_v11 = count_v2 + 590 addr_size + // jitInfo 591 addr_size + // dyldVersion 592 addr_size + // errorMessage 593 addr_size + // terminationFlags 594 addr_size + // coreSymbolicationShmPage 595 addr_size + // systemOrderFlag 596 addr_size + // uuidArrayCount 597 addr_size + // uuidArray 598 addr_size + // dyldAllImageInfosAddress 599 addr_size + // initialImageCount 600 addr_size + // errorKind 601 addr_size + // errorClientOfDylibPath 602 addr_size + // errorTargetDylibPath 603 addr_size; // errorSymbol 604 assert (sizeof (buf) >= count_v11); 605 606 int count; 607 Error error; 608 if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4) 609 { 610 m_dyld_all_image_infos.version = data.GetU32(&offset); 611 // If anything in the high byte is set, we probably got the byte 612 // order incorrect (the process might not have it set correctly 613 // yet due to attaching to a program without a specified file). 614 if (m_dyld_all_image_infos.version & 0xff000000) 615 { 616 // We have guessed the wrong byte order. Swap it and try 617 // reading the version again. 618 if (byte_order == eByteOrderLittle) 619 byte_order = eByteOrderBig; 620 else 621 byte_order = eByteOrderLittle; 622 623 data.SetByteOrder (byte_order); 624 offset = 0; 625 m_dyld_all_image_infos.version = data.GetU32(&offset); 626 } 627 } 628 else 629 { 630 return false; 631 } 632 633 if (m_dyld_all_image_infos.version >= 11) 634 count = count_v11; 635 else 636 count = count_v2; 637 638 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error); 639 if (bytes_read == count) 640 { 641 offset = 0; 642 m_dyld_all_image_infos.version = data.GetU32(&offset); 643 m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset); 644 m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset); 645 m_dyld_all_image_infos.notification = data.GetPointer(&offset); 646 m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset); 647 m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset); 648 // Adjust for padding. 649 offset += addr_size - 2; 650 m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset); 651 if (m_dyld_all_image_infos.version >= 11) 652 { 653 offset += addr_size * 8; 654 uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset); 655 656 // When we started, we were given the actual address of the all_image_infos 657 // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in 658 // m_dyld_all_image_infos_addr and is the most accurate address we have. 659 660 // We read the dyld_all_image_infos struct from memory; it contains its own address. 661 // If the address in the struct does not match the actual address, 662 // the dyld we're looking at has been loaded at a different location (slid) from 663 // where it intended to load. The addresses in the dyld_all_image_infos struct 664 // are the original, non-slid addresses, and need to be adjusted. Most importantly 665 // the address of dyld and the notification address need to be adjusted. 666 667 if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) 668 { 669 uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress; 670 uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress; 671 m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset; 672 m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset; 673 } 674 } 675 m_dyld_all_image_infos_stop_id = m_process->GetStopID(); 676 return true; 677 } 678 } 679 return false; 680} 681 682 683bool 684DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count) 685{ 686 DYLDImageInfo::collection image_infos; 687 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); 688 if (log) 689 log->Printf ("Adding %d modules.\n", image_infos_count); 690 691 Mutex::Locker locker(m_mutex); 692 if (m_process->GetStopID() == m_dyld_image_infos_stop_id) 693 return true; 694 695 if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos)) 696 return false; 697 698 UpdateImageInfosHeaderAndLoadCommands (image_infos, image_infos_count, false); 699 bool return_value = AddModulesUsingImageInfos (image_infos); 700 m_dyld_image_infos_stop_id = m_process->GetStopID(); 701 return return_value; 702} 703 704// Adds the modules in image_infos to m_dyld_image_infos. 705// NB don't call this passing in m_dyld_image_infos. 706 707bool 708DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos) 709{ 710 // Now add these images to the main list. 711 ModuleList loaded_module_list; 712 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); 713 714 for (uint32_t idx = 0; idx < image_infos.size(); ++idx) 715 { 716 if (log) 717 { 718 log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address); 719 image_infos[idx].PutToLog (log.get()); 720 } 721 722 m_dyld_image_infos.push_back(image_infos[idx]); 723 724 ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], true, NULL)); 725 726 if (image_module_sp) 727 { 728 if (image_infos[idx].header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) 729 image_module_sp->SetIsDynamicLinkEditor (true); 730 731 ObjectFile *objfile = image_module_sp->GetObjectFile (); 732 if (objfile) 733 { 734 SectionList *sections = objfile->GetSectionList(); 735 if (sections) 736 { 737 ConstString commpage_dbstr("__commpage"); 738 Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get(); 739 if (commpage_section) 740 { 741 ModuleList& target_images = m_process->GetTarget().GetImages(); 742 const FileSpec objfile_file_spec = objfile->GetFileSpec(); 743 ArchSpec arch (image_infos[idx].GetArchitecture ()); 744 ModuleSP commpage_image_module_sp(target_images.FindFirstModuleForFileSpec (objfile_file_spec, 745 &arch, 746 &commpage_dbstr)); 747 if (!commpage_image_module_sp) 748 { 749 commpage_image_module_sp 750 = m_process->GetTarget().GetSharedModule (image_infos[idx].file_spec, 751 arch, 752 NULL, 753 &commpage_dbstr, 754 objfile->GetOffset() + commpage_section->GetFileOffset()); 755 } 756 if (commpage_image_module_sp) 757 UpdateCommPageLoadAddress (commpage_image_module_sp.get()); 758 } 759 } 760 } 761 762 // UpdateImageLoadAddress will return true if any segments 763 // change load address. We need to check this so we don't 764 // mention that all loaded shared libraries are newly loaded 765 // each time we hit out dyld breakpoint since dyld will list all 766 // shared libraries each time. 767 if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx])) 768 { 769 loaded_module_list.AppendIfNeeded (image_module_sp); 770 } 771 } 772 } 773 774 if (loaded_module_list.GetSize() > 0) 775 { 776 // FIXME: This should really be in the Runtime handlers class, which should get 777 // called by the target's ModulesDidLoad, but we're doing it all locally for now 778 // to save time. 779 // Also, I'm assuming there can be only one libobjc dylib loaded... 780 781 ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); 782 if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary()) 783 { 784 size_t num_modules = loaded_module_list.GetSize(); 785 for (int i = 0; i < num_modules; i++) 786 { 787 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i))) 788 { 789 objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i)); 790 break; 791 } 792 } 793 } 794 if (log) 795 loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad"); 796 m_process->GetTarget().ModulesDidLoad (loaded_module_list); 797 } 798 return true; 799} 800 801bool 802DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count) 803{ 804 DYLDImageInfo::collection image_infos; 805 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); 806 807 Mutex::Locker locker(m_mutex); 808 if (m_process->GetStopID() == m_dyld_image_infos_stop_id) 809 return true; 810 811 // First read in the image_infos for the removed modules, and their headers & load commands. 812 if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos)) 813 { 814 if (log) 815 log->PutCString ("Failed reading image infos array."); 816 return false; 817 } 818 819 if (log) 820 log->Printf ("Removing %d modules.", image_infos_count); 821 822 ModuleList unloaded_module_list; 823 for (uint32_t idx = 0; idx < image_infos.size(); ++idx) 824 { 825 if (log) 826 { 827 log->Printf ("Removing module at address=0x%16.16llx.", image_infos[idx].address); 828 image_infos[idx].PutToLog (log.get()); 829 } 830 831 // Remove this image_infos from the m_all_image_infos. We do the comparision by address 832 // rather than by file spec because we can have many modules with the same "file spec" in the 833 // case that they are modules loaded from memory. 834 // 835 // Also copy over the uuid from the old entry to the removed entry so we can 836 // use it to lookup the module in the module list. 837 838 DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); 839 for (pos = m_dyld_image_infos.begin(); pos != end; pos++) 840 { 841 if (image_infos[idx].address == (*pos).address) 842 { 843 image_infos[idx].uuid = (*pos).uuid; 844 845 // Add the module from this image_info to the "unloaded_module_list". We'll remove them all at 846 // one go later on. 847 848 ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], false, NULL)); 849 if (unload_image_module_sp.get()) 850 { 851 // When we unload, be sure to use the image info from the old list, 852 // since that has sections correctly filled in. 853 UnloadImageLoadAddress (unload_image_module_sp.get(), *pos); 854 unloaded_module_list.AppendIfNeeded (unload_image_module_sp); 855 } 856 else 857 { 858 if (log) 859 { 860 log->Printf ("Could not find module for unloading info entry:"); 861 image_infos[idx].PutToLog(log.get()); 862 } 863 } 864 865 // Then remove it from the m_dyld_image_infos: 866 867 m_dyld_image_infos.erase(pos); 868 break; 869 } 870 } 871 872 if (pos == end) 873 { 874 if (log) 875 { 876 log->Printf ("Could not find image_info entry for unloading image:"); 877 image_infos[idx].PutToLog(log.get()); 878 } 879 } 880 } 881 if (unloaded_module_list.GetSize() > 0) 882 { 883 if (log) 884 { 885 log->PutCString("Unloaded:"); 886 unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload"); 887 } 888 m_process->GetTarget().ModulesDidUnload (unloaded_module_list); 889 } 890 m_dyld_image_infos_stop_id = m_process->GetStopID(); 891 return true; 892} 893 894bool 895DynamicLoaderMacOSXDYLD::ReadImageInfos (lldb::addr_t image_infos_addr, 896 uint32_t image_infos_count, 897 DYLDImageInfo::collection &image_infos) 898{ 899 const ByteOrder endian = m_dyld.GetByteOrder(); 900 const uint32_t addr_size = m_dyld.GetAddressByteSize(); 901 902 image_infos.resize(image_infos_count); 903 const size_t count = image_infos.size() * 3 * addr_size; 904 DataBufferHeap info_data(count, 0); 905 Error error; 906 const size_t bytes_read = m_process->ReadMemory (image_infos_addr, 907 info_data.GetBytes(), 908 info_data.GetByteSize(), 909 error); 910 if (bytes_read == count) 911 { 912 uint32_t info_data_offset = 0; 913 DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size); 914 for (int i = 0; i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset); i++) 915 { 916 image_infos[i].address = info_data_ref.GetPointer(&info_data_offset); 917 lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset); 918 image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset); 919 920 char raw_path[PATH_MAX]; 921 m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path)); 922 // don't resolve the path 923 const bool resolve_path = false; 924 image_infos[i].file_spec.SetFile(raw_path, resolve_path); 925 } 926 return true; 927 } 928 else 929 { 930 return false; 931 } 932} 933 934//---------------------------------------------------------------------- 935// If we have found where the "_dyld_all_image_infos" lives in memory, 936// read the current info from it, and then update all image load 937// addresses (or lack thereof). Only do this if this is the first time 938// we're reading the dyld infos. Return true if we actually read anything, 939// and false otherwise. 940//---------------------------------------------------------------------- 941bool 942DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos () 943{ 944 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); 945 946 Mutex::Locker locker(m_mutex); 947 if (m_process->GetStopID() == m_dyld_image_infos_stop_id 948 || m_dyld_image_infos.size() != 0) 949 return false; 950 951 if (ReadAllImageInfosStructure ()) 952 { 953 // Nothing to load or unload? 954 if (m_dyld_all_image_infos.dylib_info_count == 0) 955 return true; 956 957 if (m_dyld_all_image_infos.dylib_info_addr == 0) 958 { 959 // DYLD is updating the images now. So we should say we have no images, and then we'll 960 // figure it out when we hit the added breakpoint. 961 return false; 962 } 963 else 964 { 965 if (!AddModulesUsingImageInfosAddress (m_dyld_all_image_infos.dylib_info_addr, 966 m_dyld_all_image_infos.dylib_info_count)) 967 { 968 DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); 969 m_dyld_image_infos.clear(); 970 } 971 } 972 973 // Now we have one more bit of business. If there is a library left in the images for our target that 974 // doesn't have a load address, then it must be something that we were expecting to load (for instance we 975 // read a load command for it) but it didn't in fact load - probably because DYLD_*_PATH pointed 976 // to an equivalent version. We don't want it to stay in the target's module list or it will confuse 977 // us, so unload it here. 978 Target &target = m_process->GetTarget(); 979 ModuleList &modules = target.GetImages(); 980 ModuleList not_loaded_modules; 981 size_t num_modules = modules.GetSize(); 982 for (size_t i = 0; i < num_modules; i++) 983 { 984 ModuleSP module_sp = modules.GetModuleAtIndex(i); 985 if (!module_sp->IsLoadedInTarget (&target)) 986 { 987 if (log) 988 { 989 StreamString s; 990 module_sp->GetDescription (&s); 991 log->Printf ("Unloading pre-run module: %s.", s.GetData ()); 992 } 993 not_loaded_modules.Append (module_sp); 994 } 995 } 996 997 if (not_loaded_modules.GetSize() != 0) 998 { 999 target.ModulesDidUnload(not_loaded_modules); 1000 } 1001 1002 return true; 1003 } 1004 else 1005 return false; 1006} 1007 1008//---------------------------------------------------------------------- 1009// Read a mach_header at ADDR into HEADER, and also fill in the load 1010// command data into LOAD_COMMAND_DATA if it is non-NULL. 1011// 1012// Returns true if we succeed, false if we fail for any reason. 1013//---------------------------------------------------------------------- 1014bool 1015DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data) 1016{ 1017 DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0); 1018 Error error; 1019 size_t bytes_read = m_process->ReadMemory (addr, 1020 header_bytes.GetBytes(), 1021 header_bytes.GetByteSize(), 1022 error); 1023 if (bytes_read == sizeof(llvm::MachO::mach_header)) 1024 { 1025 uint32_t offset = 0; 1026 ::memset (header, 0, sizeof(llvm::MachO::mach_header)); 1027 1028 // Get the magic byte unswapped so we can figure out what we are dealing with 1029 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4); 1030 header->magic = data.GetU32(&offset); 1031 lldb::addr_t load_cmd_addr = addr; 1032 data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic)); 1033 switch (header->magic) 1034 { 1035 case llvm::MachO::HeaderMagic32: 1036 case llvm::MachO::HeaderMagic32Swapped: 1037 data.SetAddressByteSize(4); 1038 load_cmd_addr += sizeof(llvm::MachO::mach_header); 1039 break; 1040 1041 case llvm::MachO::HeaderMagic64: 1042 case llvm::MachO::HeaderMagic64Swapped: 1043 data.SetAddressByteSize(8); 1044 load_cmd_addr += sizeof(llvm::MachO::mach_header_64); 1045 break; 1046 1047 default: 1048 return false; 1049 } 1050 1051 // Read the rest of dyld's mach header 1052 if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1)) 1053 { 1054 if (load_command_data == NULL) 1055 return true; // We were able to read the mach_header and weren't asked to read the load command bytes 1056 1057 DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0)); 1058 1059 size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr, 1060 load_cmd_data_sp->GetBytes(), 1061 load_cmd_data_sp->GetByteSize(), 1062 error); 1063 1064 if (load_cmd_bytes_read == header->sizeofcmds) 1065 { 1066 // Set the load command data and also set the correct endian 1067 // swap settings and the correct address size 1068 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds); 1069 load_command_data->SetByteOrder(data.GetByteOrder()); 1070 load_command_data->SetAddressByteSize(data.GetAddressByteSize()); 1071 return true; // We successfully read the mach_header and the load command data 1072 } 1073 1074 return false; // We weren't able to read the load command data 1075 } 1076 } 1077 return false; // We failed the read the mach_header 1078} 1079 1080 1081//---------------------------------------------------------------------- 1082// Parse the load commands for an image 1083//---------------------------------------------------------------------- 1084uint32_t 1085DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker) 1086{ 1087 uint32_t offset = 0; 1088 uint32_t cmd_idx; 1089 Segment segment; 1090 dylib_info.Clear (true); 1091 1092 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) 1093 { 1094 // Clear out any load command specific data from DYLIB_INFO since 1095 // we are about to read it. 1096 1097 if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command))) 1098 { 1099 llvm::MachO::load_command load_cmd; 1100 uint32_t load_cmd_offset = offset; 1101 load_cmd.cmd = data.GetU32 (&offset); 1102 load_cmd.cmdsize = data.GetU32 (&offset); 1103 switch (load_cmd.cmd) 1104 { 1105 case llvm::MachO::LoadCommandSegment32: 1106 { 1107 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); 1108 // We are putting 4 uint32_t values 4 uint64_t values so 1109 // we have to use multiple 32 bit gets below. 1110 segment.vmaddr = data.GetU32 (&offset); 1111 segment.vmsize = data.GetU32 (&offset); 1112 segment.fileoff = data.GetU32 (&offset); 1113 segment.filesize = data.GetU32 (&offset); 1114 // Extract maxprot, initprot, nsects and flags all at once 1115 data.GetU32(&offset, &segment.maxprot, 4); 1116 dylib_info.segments.push_back (segment); 1117 } 1118 break; 1119 1120 case llvm::MachO::LoadCommandSegment64: 1121 { 1122 segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); 1123 // Extract vmaddr, vmsize, fileoff, and filesize all at once 1124 data.GetU64(&offset, &segment.vmaddr, 4); 1125 // Extract maxprot, initprot, nsects and flags all at once 1126 data.GetU32(&offset, &segment.maxprot, 4); 1127 dylib_info.segments.push_back (segment); 1128 } 1129 break; 1130 1131 case llvm::MachO::LoadCommandDynamicLinkerIdent: 1132 if (lc_id_dylinker) 1133 { 1134 uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset); 1135 const char *path = data.PeekCStr (name_offset); 1136 lc_id_dylinker->SetFile (path, true); 1137 } 1138 break; 1139 1140 case llvm::MachO::LoadCommandUUID: 1141 dylib_info.uuid.SetBytes(data.GetData (&offset, 16)); 1142 break; 1143 1144 default: 1145 break; 1146 } 1147 // Set offset to be the beginning of the next load command. 1148 offset = load_cmd_offset + load_cmd.cmdsize; 1149 } 1150 } 1151 1152 // All sections listed in the dyld image info structure will all 1153 // either be fixed up already, or they will all be off by a single 1154 // slide amount that is determined by finding the first segment 1155 // that is at file offset zero which also has bytes (a file size 1156 // that is greater than zero) in the object file. 1157 1158 // Determine the slide amount (if any) 1159 const size_t num_sections = dylib_info.segments.size(); 1160 for (size_t i = 0; i < num_sections; ++i) 1161 { 1162 // Iterate through the object file sections to find the 1163 // first section that starts of file offset zero and that 1164 // has bytes in the file... 1165 if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0) 1166 { 1167 dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr; 1168 // We have found the slide amount, so we can exit 1169 // this for loop. 1170 break; 1171 } 1172 } 1173 return cmd_idx; 1174} 1175 1176//---------------------------------------------------------------------- 1177// Read the mach_header and load commands for each image that the 1178// _dyld_all_image_infos structure points to and cache the results. 1179//---------------------------------------------------------------------- 1180 1181void 1182DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos, 1183 uint32_t infos_count, 1184 bool update_executable) 1185{ 1186 uint32_t exe_idx = UINT32_MAX; 1187 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); 1188 // Read any UUID values that we can get 1189 for (uint32_t i = 0; i < infos_count; i++) 1190 { 1191 if (!image_infos[i].UUIDValid()) 1192 { 1193 DataExtractor data; // Load command data 1194 if (!ReadMachHeader (image_infos[i].address, &image_infos[i].header, &data)) 1195 continue; 1196 1197 ParseLoadCommands (data, image_infos[i], NULL); 1198 1199 if (image_infos[i].header.filetype == llvm::MachO::HeaderFileTypeExecutable) 1200 exe_idx = i; 1201 1202 } 1203 } 1204 1205 if (exe_idx < image_infos.size()) 1206 { 1207 const bool can_create = true; 1208 ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[exe_idx], can_create, NULL)); 1209 1210 if (!exe_module_sp) 1211 { 1212 ArchSpec exe_arch_spec (image_infos[exe_idx].GetArchitecture ()); 1213 exe_module_sp = m_process->GetTarget().GetSharedModule (image_infos[exe_idx].file_spec, 1214 exe_arch_spec, 1215 &image_infos[exe_idx].uuid); 1216 } 1217 1218 if (exe_module_sp) 1219 { 1220 if (exe_module_sp.get() != m_process->GetTarget().GetExecutableModulePointer()) 1221 { 1222 // Don't load dependent images since we are in dyld where we will know 1223 // and find out about all images that are loaded 1224 const bool get_dependent_images = false; 1225 m_process->GetTarget().SetExecutableModule (exe_module_sp, 1226 get_dependent_images); 1227 } 1228 } 1229 } 1230} 1231 1232//---------------------------------------------------------------------- 1233// Dump a Segment to the file handle provided. 1234//---------------------------------------------------------------------- 1235void 1236DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const 1237{ 1238 if (log) 1239 { 1240 if (slide == 0) 1241 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)", 1242 name.AsCString(""), 1243 vmaddr + slide, 1244 vmaddr + slide + vmsize); 1245 else 1246 log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx", 1247 name.AsCString(""), 1248 vmaddr + slide, 1249 vmaddr + slide + vmsize, 1250 slide); 1251 } 1252} 1253 1254const DynamicLoaderMacOSXDYLD::Segment * 1255DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const 1256{ 1257 const size_t num_segments = segments.size(); 1258 for (size_t i=0; i<num_segments; ++i) 1259 { 1260 if (segments[i].name == name) 1261 return &segments[i]; 1262 } 1263 return NULL; 1264} 1265 1266 1267//---------------------------------------------------------------------- 1268// Dump an image info structure to the file handle provided. 1269//---------------------------------------------------------------------- 1270void 1271DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const 1272{ 1273 if (log == NULL) 1274 return; 1275 uint8_t *u = (uint8_t *)uuid.GetBytes(); 1276 1277 if (address == LLDB_INVALID_ADDRESS) 1278 { 1279 if (u) 1280 { 1281 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)", 1282 mod_date, 1283 u[ 0], u[ 1], u[ 2], u[ 3], 1284 u[ 4], u[ 5], u[ 6], u[ 7], 1285 u[ 8], u[ 9], u[10], u[11], 1286 u[12], u[13], u[14], u[15], 1287 file_spec.GetDirectory().AsCString(), 1288 file_spec.GetFilename().AsCString()); 1289 } 1290 else 1291 log->Printf("\t modtime=0x%8.8llx path='%s/%s' (UNLOADED)", 1292 mod_date, 1293 file_spec.GetDirectory().AsCString(), 1294 file_spec.GetFilename().AsCString()); 1295 } 1296 else 1297 { 1298 if (u) 1299 { 1300 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'", 1301 address, 1302 mod_date, 1303 u[ 0], u[ 1], u[ 2], u[ 3], 1304 u[ 4], u[ 5], u[ 6], u[ 7], 1305 u[ 8], u[ 9], u[10], u[11], 1306 u[12], u[13], u[14], u[15], 1307 file_spec.GetDirectory().AsCString(), 1308 file_spec.GetFilename().AsCString()); 1309 } 1310 else 1311 { 1312 log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'", 1313 address, 1314 mod_date, 1315 file_spec.GetDirectory().AsCString(), 1316 file_spec.GetFilename().AsCString()); 1317 1318 } 1319 for (uint32_t i=0; i<segments.size(); ++i) 1320 segments[i].PutToLog(log, slide); 1321 } 1322} 1323 1324//---------------------------------------------------------------------- 1325// Dump the _dyld_all_image_infos members and all current image infos 1326// that we have parsed to the file handle provided. 1327//---------------------------------------------------------------------- 1328void 1329DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const 1330{ 1331 if (log == NULL) 1332 return; 1333 1334 Mutex::Locker locker(m_mutex); 1335 log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }", 1336 m_dyld_all_image_infos.version, 1337 m_dyld_all_image_infos.dylib_info_count, 1338 (uint64_t)m_dyld_all_image_infos.dylib_info_addr, 1339 (uint64_t)m_dyld_all_image_infos.notification); 1340 size_t i; 1341 const size_t count = m_dyld_image_infos.size(); 1342 if (count > 0) 1343 { 1344 log->PutCString("Loaded:"); 1345 for (i = 0; i<count; i++) 1346 m_dyld_image_infos[i].PutToLog(log); 1347 } 1348} 1349 1350void 1351DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process) 1352{ 1353 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); 1354 Clear(true); 1355 m_process = process; 1356 m_process->GetTarget().GetSectionLoadList().Clear(); 1357} 1358 1359bool 1360DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () 1361{ 1362 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); 1363 if (m_break_id == LLDB_INVALID_BREAK_ID) 1364 { 1365 if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) 1366 { 1367 Address so_addr; 1368 // Set the notification breakpoint and install a breakpoint 1369 // callback function that will get called each time the 1370 // breakpoint gets hit. We will use this to track when shared 1371 // libraries get loaded/unloaded. 1372 1373 if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr)) 1374 { 1375 Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get(); 1376 dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true); 1377 m_break_id = dyld_break->GetID(); 1378 } 1379 } 1380 } 1381 return m_break_id != LLDB_INVALID_BREAK_ID; 1382} 1383 1384//---------------------------------------------------------------------- 1385// Member function that gets called when the process state changes. 1386//---------------------------------------------------------------------- 1387void 1388DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state) 1389{ 1390 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state)); 1391 switch (state) 1392 { 1393 case eStateConnected: 1394 case eStateAttaching: 1395 case eStateLaunching: 1396 case eStateInvalid: 1397 case eStateUnloaded: 1398 case eStateExited: 1399 case eStateDetached: 1400 Clear(false); 1401 break; 1402 1403 case eStateStopped: 1404 // Keep trying find dyld and set our notification breakpoint each time 1405 // we stop until we succeed 1406 if (!DidSetNotificationBreakpoint () && m_process->IsAlive()) 1407 { 1408 if (NeedToLocateDYLD ()) 1409 LocateDYLD (); 1410 1411 SetNotificationBreakpoint (); 1412 } 1413 break; 1414 1415 case eStateRunning: 1416 case eStateStepping: 1417 case eStateCrashed: 1418 case eStateSuspended: 1419 break; 1420 1421 default: 1422 break; 1423 } 1424} 1425 1426// This bit in the n_desc field of the mach file means that this is a 1427// stub that runs arbitrary code to determine the trampoline target. 1428// We've established a naming convention with the CoreOS folks for the 1429// equivalent symbols they will use for this (which the objc guys didn't follow...) 1430// For now we'll just look for all symbols matching that naming convention... 1431 1432#define MACH_O_N_SYMBOL_RESOLVER 0x100 1433 1434ThreadPlanSP 1435DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) 1436{ 1437 ThreadPlanSP thread_plan_sp; 1438 StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); 1439 const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol); 1440 Symbol *current_symbol = current_context.symbol; 1441 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 1442 1443 if (current_symbol != NULL) 1444 { 1445 if (current_symbol->IsTrampoline()) 1446 { 1447 const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled); 1448 1449 if (trampoline_name) 1450 { 1451 SymbolContextList target_symbols; 1452 ModuleList &images = thread.GetProcess().GetTarget().GetImages(); 1453 1454 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols); 1455 1456 size_t num_original_symbols = target_symbols.GetSize(); 1457 // FIXME: The resolver symbol is only valid in object files. In binaries it is reused for the 1458 // shared library slot number. So we'll have to look this up in the dyld info. 1459 // For now, just turn this off. 1460 1461 // bool orig_is_resolver = (current_symbol->GetFlags() & MACH_O_N_SYMBOL_RESOLVER) == MACH_O_N_SYMBOL_RESOLVER; 1462 bool orig_is_resolver = false; 1463 1464 if (num_original_symbols > 0) 1465 { 1466 // We found symbols that look like they are the targets to our symbol. Now look through the 1467 // modules containing our symbols to see if there are any for our symbol. 1468 1469 ModuleList modules_to_search; 1470 1471 for (size_t i = 0; i < num_original_symbols; i++) 1472 { 1473 SymbolContext sc; 1474 target_symbols.GetContextAtIndex(i, sc); 1475 1476 Module* module_to_add = sc.symbol->CalculateSymbolContextModule(); 1477 if (module_to_add) 1478 modules_to_search.AppendIfNeeded(static_cast<ModuleSP>(module_to_add)); 1479 } 1480 1481 // If the original stub symbol is a resolver, then we don't want to break on the symbol with the 1482 // original name, but instead on all the symbols it could resolve to since otherwise we would stop 1483 // in the middle of the resolution... 1484 // Note that the stub is not of the resolver type it will point to the equivalent symbol, 1485 // not the original name, so in that case we don't need to do anything. 1486 1487 if (orig_is_resolver) 1488 { 1489 target_symbols.Clear(); 1490 1491 FindEquivalentSymbols (current_symbol, modules_to_search, target_symbols); 1492 } 1493 1494 // FIXME - Make the Run to Address take multiple addresses, and 1495 // run to any of them. 1496 uint32_t num_symbols = target_symbols.GetSize(); 1497 if (num_symbols > 0) 1498 { 1499 std::vector<lldb::addr_t> addresses; 1500 addresses.resize (num_symbols); 1501 for (uint32_t i = 0; i < num_symbols; i++) 1502 { 1503 SymbolContext context; 1504 AddressRange addr_range; 1505 if (target_symbols.GetContextAtIndex(i, context)) 1506 { 1507 context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); 1508 lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget()); 1509 addresses[i] = load_addr; 1510 } 1511 } 1512 if (addresses.size() > 0) 1513 thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others)); 1514 else 1515 { 1516 if (log) 1517 log->Printf ("Couldn't resolve the symbol contexts."); 1518 } 1519 } 1520 else 1521 { 1522 if (log) 1523 { 1524 log->Printf ("Found a resolver stub for: \"%s\" but could not find any symbols it resolves to.", 1525 trampoline_name.AsCString()); 1526 } 1527 } 1528 } 1529 else 1530 { 1531 if (log) 1532 { 1533 log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString()); 1534 } 1535 } 1536 } 1537 } 1538 } 1539 else 1540 { 1541 if (log) 1542 log->Printf ("Could not find symbol for step through."); 1543 } 1544 1545 return thread_plan_sp; 1546} 1547 1548size_t 1549DynamicLoaderMacOSXDYLD::FindEquivalentSymbols (lldb_private::Symbol *original_symbol, 1550 lldb_private::ModuleList &images, 1551 lldb_private::SymbolContextList &equivalent_symbols) 1552{ 1553 const ConstString &trampoline_name = original_symbol->GetMangled().GetName(Mangled::ePreferMangled); 1554 if (!trampoline_name) 1555 return 0; 1556 1557 size_t initial_size = equivalent_symbols.GetSize(); 1558 1559 static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Z0-9]+)$"; 1560 std::string equivalent_regex_buf("^"); 1561 equivalent_regex_buf.append (trampoline_name.GetCString()); 1562 equivalent_regex_buf.append (resolver_name_regex); 1563 1564 RegularExpression equivalent_name_regex (equivalent_regex_buf.c_str()); 1565 const bool append = true; 1566 images.FindSymbolsMatchingRegExAndType (equivalent_name_regex, eSymbolTypeCode, equivalent_symbols, append); 1567 1568 return equivalent_symbols.GetSize() - initial_size; 1569} 1570 1571Error 1572DynamicLoaderMacOSXDYLD::CanLoadImage () 1573{ 1574 Error error; 1575 // In order for us to tell if we can load a shared library we verify that 1576 // the dylib_info_addr isn't zero (which means no shared libraries have 1577 // been set yet, or dyld is currently mucking with the shared library list). 1578 if (ReadAllImageInfosStructure ()) 1579 { 1580 // TODO: also check the _dyld_global_lock_held variable in libSystem.B.dylib? 1581 // TODO: check the malloc lock? 1582 // TODO: check the objective C lock? 1583 if (m_dyld_all_image_infos.dylib_info_addr != 0) 1584 return error; // Success 1585 } 1586 1587 error.SetErrorString("unsafe to load or unload shared libraries"); 1588 return error; 1589} 1590 1591void 1592DynamicLoaderMacOSXDYLD::Initialize() 1593{ 1594 PluginManager::RegisterPlugin (GetPluginNameStatic(), 1595 GetPluginDescriptionStatic(), 1596 CreateInstance); 1597} 1598 1599void 1600DynamicLoaderMacOSXDYLD::Terminate() 1601{ 1602 PluginManager::UnregisterPlugin (CreateInstance); 1603} 1604 1605 1606const char * 1607DynamicLoaderMacOSXDYLD::GetPluginNameStatic() 1608{ 1609 return "dynamic-loader.macosx-dyld"; 1610} 1611 1612const char * 1613DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() 1614{ 1615 return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes."; 1616} 1617 1618 1619//------------------------------------------------------------------ 1620// PluginInterface protocol 1621//------------------------------------------------------------------ 1622const char * 1623DynamicLoaderMacOSXDYLD::GetPluginName() 1624{ 1625 return "DynamicLoaderMacOSXDYLD"; 1626} 1627 1628const char * 1629DynamicLoaderMacOSXDYLD::GetShortPluginName() 1630{ 1631 return GetPluginNameStatic(); 1632} 1633 1634uint32_t 1635DynamicLoaderMacOSXDYLD::GetPluginVersion() 1636{ 1637 return 1; 1638} 1639 1640