diff options
34 files changed, 1088 insertions, 764 deletions
diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 8a30b56b100..e54e58b61bf 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -416,6 +416,7 @@ public: const ConstString *object_name, off_t object_offset, lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr, bool always_create = false); diff --git a/lldb/include/lldb/Core/UserSettingsController.h b/lldb/include/lldb/Core/UserSettingsController.h index 370bfad516a..a99457a775e 100644 --- a/lldb/include/lldb/Core/UserSettingsController.h +++ b/lldb/include/lldb/Core/UserSettingsController.h @@ -262,6 +262,12 @@ public: FinalizeSettingsController (lldb::UserSettingsControllerSP &controller_sp); + lldb::InstanceSettingsSP + GetDefaultInstanceSettings () + { + return m_default_settings; + } + protected: // ------------------------------------------------------------------------- diff --git a/lldb/include/lldb/Host/Host.h b/lldb/include/lldb/Host/Host.h index d80fab4beea..83691849f2d 100644 --- a/lldb/include/lldb/Host/Host.h +++ b/lldb/include/lldb/Host/Host.h @@ -298,6 +298,28 @@ public: GetModuleFileSpecForHostAddress (const void *host_addr); + + //------------------------------------------------------------------ + /// If you have an executable that is in a bundle and want to get + /// back to the bundle directory from the path itself, this + /// function will change a path to a file within a bundle to the + /// bundle directory itself. + /// + /// @param[in] file + /// A file spec that might point to a file in a bundle. + /// + /// @param[out] bundle_directory + /// An object will be filled in with the bundle directory for + /// the bundle when \b true is returned. Otherwise \a file is + /// left untouched and \b false is returned. + /// + /// @return + /// \b true if \a file was resolved in \a bundle_directory, + /// \b false otherwise. + //------------------------------------------------------------------ + static bool + GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory); + //------------------------------------------------------------------ /// When executable files may live within a directory, where the /// directory represents an executable bundle (like the MacOSX diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index 094285a65ea..bb65be70efb 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -505,6 +505,12 @@ public: size_t MemoryMapSectionData (const Section *section, DataExtractor& section_data) const; + + bool + IsInMemory () const + { + return m_memory_addr != LLDB_INVALID_ADDRESS; + } protected: //------------------------------------------------------------------ // Member variables. @@ -519,11 +525,6 @@ protected: lldb::ProcessWP m_process_wp; const lldb::addr_t m_memory_addr; - bool - IsInMemory () const - { - return m_memory_addr != LLDB_INVALID_ADDRESS; - } //------------------------------------------------------------------ /// Sets the architecture for a module. At present the architecture /// can only be set if it is invalid. It is not allowed to switch from diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index 5cb57ea7361..ac025c418a3 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -108,7 +108,8 @@ namespace lldb_private { virtual Error ResolveExecutable (const FileSpec &exe_file, const ArchSpec &arch, - lldb::ModuleSP &module_sp); + lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr); //------------------------------------------------------------------ /// Resolves the FileSpec to a (possibly) remote path. Remote @@ -237,6 +238,7 @@ namespace lldb_private { const ConstString *object_name_ptr, off_t object_offset, lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 39857610850..f4a4f8e3536 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1601,6 +1601,18 @@ public: error.SetErrorStringWithFormat("error: %s does not support loading core files.", GetShortPluginName()); return error; } + + //------------------------------------------------------------------ + /// Get the dynamic loader plug-in for this process. + /// + /// The default action is to let the DynamicLoader plug-ins check + /// the main executable and the DynamicLoader will select itself + /// automatically. Subclasses can override this if inspecting the + /// executable is not desired, or if Process subclasses can only + /// use a specific DynamicLoader plug-in. + //------------------------------------------------------------------ + virtual DynamicLoader * + GetDynamicLoader (); //------------------------------------------------------------------ /// Attach to an existing process using the process attach info. @@ -2400,7 +2412,7 @@ public: /// vm_addr, \a buf, and \a size updated appropriately. Zero is /// returned to indicate an error. //------------------------------------------------------------------ - size_t + virtual size_t ReadMemory (lldb::addr_t vm_addr, void *buf, size_t size, @@ -2631,7 +2643,9 @@ public: lldb::ModuleSP ReadModuleFromMemory (const FileSpec& file_spec, - lldb::addr_t header_addr); + lldb::addr_t header_addr, + bool add_image_to_target, + bool load_sections_in_target); //------------------------------------------------------------------ /// Attempt to get the attributes for a region of memory in the process. @@ -2976,12 +2990,6 @@ public: const lldb::ABISP & GetABI (); - DynamicLoader * - GetDynamicLoader () - { - return m_dyld_ap.get(); - } - OperatingSystem * GetOperatingSystem () { diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 5e51e4151ea..26e3df68e0c 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -87,6 +87,19 @@ public: return m_source_map; } + FileSpecList & + GetExecutableSearchPaths () + { + return m_exe_search_paths; + } + + const FileSpecList & + GetExecutableSearchPaths () const + { + return m_exe_search_paths; + } + + uint32_t GetMaximumNumberOfChildrenToDisplay() { @@ -225,6 +238,7 @@ protected: int m_prefer_dynamic_value; OptionValueBoolean m_skip_prologue; PathMappingList m_source_map; + FileSpecList m_exe_search_paths; uint32_t m_max_children_display; uint32_t m_max_strlen_length; OptionValueBoolean m_breakpoints_use_platform_avoid; @@ -273,6 +287,9 @@ public: static lldb::UserSettingsControllerSP & GetSettingsController (); + static FileSpecList + GetDefaultExecutableSearchPaths (); + static ArchSpec GetDefaultArchitecture (); diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index a1ec5574b74..09f354e2710 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -46,7 +46,14 @@ SBModule::SBModule (lldb::SBProcess &process, lldb::addr_t header_addr) : { ProcessSP process_sp (process.GetSP()); if (process_sp) - m_opaque_sp = process_sp->ReadModuleFromMemory (FileSpec(), header_addr); + { + const bool add_image_to_target = true; + const bool load_image_sections_in_target = true; + m_opaque_sp = process_sp->ReadModuleFromMemory (FileSpec(), + header_addr, + add_image_to_target, + load_image_sections_in_target); + } } const SBModule & diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 6ea4486b24c..5d8cb5be468 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -211,31 +211,43 @@ public: debugger.GetTargetList().SetSelectedTarget(target_sp.get()); if (core_file) { - ProcessSP process_sp (target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), NULL, &core_file)); char core_path[PATH_MAX]; core_file.GetPath(core_path, sizeof(core_path)); - - if (process_sp) + if (core_file.Exists()) { - // Seems wierd that we Launch a core file, but that is - // what we do! - error = process_sp->LoadCore(); + FileSpec core_file_dir; + core_file_dir.GetDirectory() = core_file.GetDirectory(); + target_sp->GetExecutableSearchPaths ().Append (core_file_dir); - if (error.Fail()) + ProcessSP process_sp (target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), NULL, &core_file)); + + if (process_sp) { - result.AppendError(error.AsCString("can't find plug-in for core file")); - result.SetStatus (eReturnStatusFailed); - return false; + // Seems wierd that we Launch a core file, but that is + // what we do! + error = process_sp->LoadCore(); + + if (error.Fail()) + { + result.AppendError(error.AsCString("can't find plug-in for core file")); + result.SetStatus (eReturnStatusFailed); + return false; + } + else + { + result.AppendMessageWithFormat ("Core file '%s' (%s) was loaded.\n", core_path, target_sp->GetArchitecture().GetArchitectureName()); + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } } else { - result.AppendMessageWithFormat ("Core file '%s' (%s) was loaded.\n", core_path, target_sp->GetArchitecture().GetArchitectureName()); - result.SetStatus (eReturnStatusSuccessFinishNoResult); + result.AppendErrorWithFormat ("Unable to find process plug-in for core file '%s'\n", core_path); + result.SetStatus (eReturnStatusFailed); } } else { - result.AppendErrorWithFormat ("Unable to find process plug-in for core file '%s'\n", core_path); + result.AppendErrorWithFormat ("Core file '%s' does not exist\n", core_path); result.SetStatus (eReturnStatusFailed); } } diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 360c868cb5a..f1715758e59 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -729,6 +729,7 @@ ModuleList::GetSharedModule const ConstString *object_name_ptr, off_t object_offset, ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr, bool always_create diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index d230815df9a..5f0362bcae4 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -754,6 +754,14 @@ Host::GetModuleFileSpecForHostAddress (const void *host_addr) } #if !defined (__APPLE__) // see Host.mm + +bool +Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle) +{ + bundle.Clear(); + return false; +} + bool Host::ResolveExecutableInBundle (FileSpec &file) { diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index ac5f5f6dead..fe3c450e167 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -137,6 +137,28 @@ Host::ThreadCreated (const char *thread_name) } } +bool +Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory) +{ +#if defined (__APPLE__) + if (file.GetFileType () == FileSpec::eFileTypeDirectory) + { + char path[PATH_MAX]; + if (file.GetPath(path, sizeof(path))) + { + CFCBundle bundle (path); + if (bundle.GetPath (path, sizeof(path))) + { + bundle_directory.SetFile (path, false); + return true; + } + } + } +#endif + bundle_directory.Clear(); + return false; +} + bool Host::ResolveExecutableInBundle (FileSpec &file) @@ -1215,7 +1237,8 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info) lldb::ModuleSP exe_module_sp; error = host_platform_sp->ResolveExecutable (exe_spec, arch_spec, - exe_module_sp); + exe_module_sp, + NULL); if (error.Fail()) return error; diff --git a/lldb/source/Host/macosx/Symbols.cpp b/lldb/source/Host/macosx/Symbols.cpp index 820126674bb..50161def0db 100644 --- a/lldb/source/Host/macosx/Symbols.cpp +++ b/lldb/source/Host/macosx/Symbols.cpp @@ -367,7 +367,8 @@ LocateMacOSXFilesUsingDebugSymbols if (out_exec_fspec) { - CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));; + CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get())); + bool success = false; if (dict.get()) { char uuid_cstr_buf[64]; @@ -381,10 +382,13 @@ LocateMacOSXFilesUsingDebugSymbols { ++items_found; out_exec_fspec->SetFile(path, path[0] == '~'); + if (out_exec_fspec->Exists()) + success = true; } } } - else + + if (!success) { // No dictionary, check near the dSYM bundle for an executable that matches... if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1)) diff --git a/lldb/source/Host/macosx/cfcpp/CFCBundle.cpp b/lldb/source/Host/macosx/cfcpp/CFCBundle.cpp index 6e68af5c597..71b07499366 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCBundle.cpp +++ b/lldb/source/Host/macosx/cfcpp/CFCBundle.cpp @@ -55,6 +55,22 @@ CFCBundle::SetPath (const char *path) return get() != NULL; } +bool +CFCBundle::GetPath (char *dst, size_t dst_len) +{ + CFBundleRef bundle = get(); + if (bundle) + { + CFCReleaser<CFURLRef> bundle_url (CFBundleCopyBundleURL (bundle)); + if (bundle_url.get()) + { + Boolean resolveAgainstBase = 0; + return ::CFURLGetFileSystemRepresentation (bundle_url.get(), resolveAgainstBase, (UInt8 *)dst, dst_len) != 0; + } + } + return false; +} + CFStringRef CFCBundle::GetIdentifier () const { diff --git a/lldb/source/Host/macosx/cfcpp/CFCBundle.h b/lldb/source/Host/macosx/cfcpp/CFCBundle.h index c07a48cb055..1cd1b681af8 100644 --- a/lldb/source/Host/macosx/cfcpp/CFCBundle.h +++ b/lldb/source/Host/macosx/cfcpp/CFCBundle.h @@ -34,6 +34,9 @@ public: GetValueForInfoDictionaryKey(CFStringRef key) const; bool + GetPath (char *dst, size_t dst_len); + + bool SetPath (const char *path); private: diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index b82d6869edf..c719654998c 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -154,246 +154,178 @@ DynamicLoaderDarwinKernel::Clear (bool clear_process) } -//---------------------------------------------------------------------- -// Load the kernel module and initialize the "m_kernel" member. Return -// true _only_ if the kernel is loaded the first time through (subsequent -// calls to this function should return false after the kernel has been -// already loaded). -//---------------------------------------------------------------------- -void -DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() -{ - if (!m_kext_summary_header_ptr_addr.IsValid()) - { - m_kernel.Clear(false); - m_kernel.module_sp = m_process->GetTarget().GetExecutableModule(); - if (m_kernel.module_sp) - { - static ConstString mach_header_name ("_mh_execute_header"); - static ConstString kext_summary_symbol ("gLoadedKextSummaries"); - const Symbol *symbol = NULL; - symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData); - if (symbol) - m_kext_summary_header_ptr_addr = symbol->GetValue(); - - symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute); - if (symbol) - { - // The "_mh_execute_header" symbol is absolute and not a section based - // symbol that will have a valid address, so we need to resolve it... - m_process->GetTarget().GetImages().ResolveFileAddress (symbol->GetValue().GetFileAddress(), m_kernel.so_address); - DataExtractor data; // Load command data - if (ReadMachHeader (m_kernel, &data)) - { - if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeExecutable) - { - if (ParseLoadCommands (data, m_kernel)) - UpdateImageLoadAddress (m_kernel); - - // Update all image infos - ReadAllKextSummaries (); - } - } - else - { - m_kernel.Clear(false); - } - } - } - } -} - bool -DynamicLoaderDarwinKernel::FindTargetModule (OSKextLoadedKextSummary &image_info, bool can_create, bool *did_create_ptr) +DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageUsingMemoryModule (Process *process) { - if (did_create_ptr) - *did_create_ptr = false; - - const bool image_info_uuid_is_valid = image_info.uuid.IsValid(); + if (IsLoaded()) + return true; - if (image_info.module_sp) - { - if (image_info_uuid_is_valid) - { - if (image_info.module_sp->GetUUID() == image_info.uuid) - return true; - else - image_info.module_sp.reset(); - } - else - return true; - } + bool uuid_is_valid = uuid.IsValid(); - ModuleList &target_images = m_process->GetTarget().GetImages(); - if (image_info_uuid_is_valid) - image_info.module_sp = target_images.FindModule(image_info.uuid); - - if (image_info.module_sp) - return true; - - ArchSpec arch (image_info.GetArchitecture ()); - if (can_create) + Target &target = process->GetTarget(); + ModuleSP memory_module_sp; + // Use the memory module as the module if we have one... + if (address != LLDB_INVALID_ADDRESS) { - if (image_info_uuid_is_valid) + FileSpec file_spec; + if (module_sp) + file_spec = module_sp->GetFileSpec(); + else + file_spec.SetFile (name, false); + + memory_module_sp = process->ReadModuleFromMemory (file_spec, address, false, false); + if (memory_module_sp && !uuid_is_valid) { - image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(), - arch, - &image_info.uuid); - if (did_create_ptr) - *did_create_ptr = image_info.module_sp; + uuid = memory_module_sp->GetUUID(); + uuid_is_valid = uuid.IsValid(); } } - return image_info.module_sp; -} -bool -DynamicLoaderDarwinKernel::UpdateCommPageLoadAddress(Module *module) -{ - bool changed = false; - if (module) + if (!module_sp) { - ObjectFile *image_object_file = module->GetObjectFile(); - if (image_object_file) + bool uuid_is_valid = uuid.IsValid(); + if (uuid_is_valid) { - SectionList *section_list = image_object_file->GetSectionList (); - if (section_list) - { - uint32_t num_sections = section_list->GetSize(); - for (uint32_t i=0; i<num_sections; ++i) - { - Section* section = section_list->GetSectionAtIndex (i).get(); - if (section) - { - const addr_t new_section_load_addr = section->GetFileAddress (); - const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section); - if (old_section_load_addr == LLDB_INVALID_ADDRESS || - old_section_load_addr != new_section_load_addr) - { - if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ())) - changed = true; - } - } - } - } + ModuleList &target_images = target.GetImages(); + module_sp = target_images.FindModule(uuid); + + if (!module_sp) + module_sp = target.GetSharedModule (FileSpec(), target.GetArchitecture(), &uuid); } } - return changed; -} + -//---------------------------------------------------------------------- -// Update the load addresses for all segments in MODULE using the -// updated INFO that is passed in. -//---------------------------------------------------------------------- -bool -DynamicLoaderDarwinKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info) -{ - Module *module = info.module_sp.get(); - bool changed = false; - if (module) + if (memory_module_sp) { - ObjectFile *image_object_file = module->GetObjectFile(); - if (image_object_file) + // Someone already supplied a file, make sure it is the right one. + if (module_sp) { - SectionList *section_list = image_object_file->GetSectionList (); - if (section_list) + if (module_sp->GetUUID() == memory_module_sp->GetUUID()) { - // We now know the slide amount, so go through all sections - // and update the load addresses with the correct values. - uint32_t num_segments = info.segments.size(); - for (uint32_t i=0; i<num_segments; ++i) + ObjectFile *ondisk_object_file = module_sp->GetObjectFile(); + ObjectFile *memory_object_file = memory_module_sp->GetObjectFile(); + if (memory_object_file && ondisk_object_file) { - const addr_t new_section_load_addr = info.segments[i].vmaddr; - if (section_list->FindSectionByName(info.segments[i].name)) + SectionList *ondisk_section_list = ondisk_object_file->GetSectionList (); + SectionList *memory_section_list = memory_object_file->GetSectionList (); + if (memory_section_list && ondisk_section_list) { - SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); - if (section_sp) + const uint32_t num_sections = ondisk_section_list->GetSize(); + // There may be CTF sections in the memory image so we can't + // always just compare the number of sections (which are actually + // segments in mach-o parlance) + uint32_t sect_idx = 0; + const Section *memory_section; + const Section *ondisk_section; + // Always use the number of sections from the on disk file + // in case there are extra sections added to the memory image. + for (sect_idx=0; sect_idx<num_sections; ++sect_idx) { - const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get()); - if (old_section_load_addr == LLDB_INVALID_ADDRESS || - old_section_load_addr != new_section_load_addr) + memory_section = memory_section_list->GetSectionAtIndex(sect_idx).get(); + ondisk_section = ondisk_section_list->GetSectionAtIndex(sect_idx).get(); + if (memory_section->GetName() != ondisk_section->GetName()) { - if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr)) - changed = true; + // Section count was the same, but the sections themselves do not match + module_sp.reset(); + break; } } - else - { - Host::SystemLog (Host::eSystemLogWarning, "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString("<invalid>"), - (uint64_t)new_section_load_addr, - image_object_file->GetFileSpec().GetDirectory().AsCString(), - image_object_file->GetFileSpec().GetFilename().AsCString()); - } - } - else - { - // The segment name is empty which means this is a .o file. - // Object files in LLDB end up getting reorganized so that - // the segment name that is in the section is promoted into - // an actual segment, so we just need to go through all sections - // and slide them by a single amount. - - uint32_t num_sections = section_list->GetSize(); - for (uint32_t i=0; i<num_sections; ++i) + if (module_sp) { - Section* section = section_list->GetSectionAtIndex (i).get(); - if (section) + for (sect_idx=0; sect_idx<num_sections; ++sect_idx) { - if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress() + new_section_load_addr)) - changed = true; + memory_section = memory_section_list->GetSectionAtIndex(sect_idx).get(); + ondisk_section = ondisk_section_list->GetSectionAtIndex(sect_idx).get(); + target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section, memory_section->GetFileAddress()); } + if (num_sections > 0) + load_process_stop_id = process->GetStopID(); } } + else + module_sp.reset(); // One or both section lists } + else + module_sp.reset(); // One or both object files missing } + else + module_sp.reset(); // UUID mismatch + } + + // Use the memory module as the module if we didn't like the file + // module we either found or were supplied with + if (!module_sp) + { + module_sp = memory_module_sp; + // Load the memory image in the target as all adresses are already correct + bool changed = false; + target.GetImages().Append (memory_module_sp); + if (module_sp->SetLoadAddress (target, 0, changed)) + load_process_stop_id = process->GetStopID(); } } - return changed; + bool is_loaded = IsLoaded(); + + if (so_address.IsValid()) + { + if (is_loaded) + so_address.SetLoadAddress (address, &target); + else + target.GetImages().ResolveFileAddress (address, so_address); + + } + return is_loaded; } //---------------------------------------------------------------------- -// Update the load addresses for all segments in MODULE using the -// updated INFO that is passed in. +// Load the kernel module and initialize the "m_kernel" member. Return +// true _only_ if the kernel is loaded the first time through (subsequent +// calls to this function should return false after the kernel has been +// already loaded). //---------------------------------------------------------------------- -bool -DynamicLoaderDarwinKernel::UnloadImageLoadAddress (OSKextLoadedKextSummary& info) +void +DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() { - Module *module = info.module_sp.get(); - bool changed = false; - if (module) + if (!m_kext_summary_header_ptr_addr.IsValid()) { - ObjectFile *image_object_file = module->GetObjectFile(); - if (image_object_file) + m_kernel.Clear(false); + m_kernel.module_sp = m_process->GetTarget().GetExecutableModule(); + strncpy(m_kernel.name, "mach_kernel", sizeof(m_kernel.name)); + if (m_kernel.address == LLDB_INVALID_ADDRESS) { - SectionList *section_list = image_object_file->GetSectionList (); - if (section_list) + m_kernel.address = m_process->GetImageInfoAddress (); + if (m_kernel.address == LLDB_INVALID_ADDRESS && m_kernel.module_sp) { - uint32_t num_segments = info.segments.size(); - for (uint32_t i=0; i<num_segments; ++i) - { - SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); - if (section_sp) - { - const addr_t old_section_load_addr = info.segments[i].vmaddr; - if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr)) - changed = true; - } - else - { - Host::SystemLog (Host::eSystemLogWarning, - "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString("<invalid>"), - image_object_file->GetFileSpec().GetDirectory().AsCString(), - image_object_file->GetFileSpec().GetFilename().AsCString()); - } - } + // We didn't get a hint from the process, so we will + // try the kernel at the address that it exists at in + // the file if we have one + ObjectFile *kernel_object_file = m_kernel.module_sp->GetObjectFile(); + if (kernel_object_file) + m_kernel.address = kernel_object_file->GetHeaderAddress().GetFileAddress(); } } + + if (m_kernel.address != LLDB_INVALID_ADDRESS) + m_kernel.LoadImageUsingMemoryModule (m_process); + + if (m_kernel.IsLoaded()) + { + static ConstString kext_summary_symbol ("gLoadedKextSummaries"); + const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData); + if (symbol) + { + m_kext_summary_header_ptr_addr = symbol->GetValue(); + // Update all image infos + ReadAllKextSummaries (); + } + } + else + { + m_kernel.Clear(false); + } } - return changed; } - //---------------------------------------------------------------------- // Static callback function that gets called when our DYLD notification // breakpoint gets hit. We update all of our image infos and then @@ -513,18 +445,20 @@ DynamicLoaderDarwinKernel::ParseKextSummaries (const Address &kext_summary_addr, } } - DataExtractor data; // Load command data - if (ReadMachHeader (kext_summaries[i], &data)) - { - ParseLoadCommands (data, kext_summaries[i]); - } - + kext_summaries[i].LoadImageUsingMemoryModule (m_process); + if (s) { if (kext_summaries[i].module_sp) - s->Printf("\n found kext: %s/%s\n", - kext_summaries[i].module_sp->GetFileSpec().GetDirectory().AsCString(), - kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString()); + { + if (kext_summaries[i].module_sp->GetFileSpec().GetDirectory()) + s->Printf("\n found kext: %s/%s\n", + kext_summaries[i].module_sp->GetFileSpec().GetDirectory().AsCString(), + kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString()); + else + s->Printf("\n found kext: %s\n", + kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString()); + } else s->Printf (" failed to locate/load.\n"); } @@ -547,20 +481,11 @@ DynamicLoaderDarwinKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::c for (uint32_t idx = 0; idx < image_infos.size(); ++idx) { - m_kext_summaries.push_back(image_infos[idx]); + OSKextLoadedKextSummary &image_info = image_infos[idx]; + m_kext_summaries.push_back(image_info); - if (FindTargetModule (image_infos[idx], true, NULL)) - { - // UpdateImageLoadAddress will return true if any segments - // change load address. We need to check this so we don't - // mention that all loaded shared libraries are newly loaded - // each time we hit out dyld breakpoint since dyld will list all - // shared libraries each time. - if (UpdateImageLoadAddress (image_infos[idx])) - { - loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp); - } - } + if (image_info.module_sp && m_process->GetStopID() == image_info.load_process_stop_id) + loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp); } if (loaded_module_list.GetSize() > 0) @@ -644,6 +569,14 @@ DynamicLoaderDarwinKernel::ReadKextSummaries (const Address &kext_summary_addr, { image_infos[i].reference_list = 0; } + printf ("[%3u] %*.*s: address=0x%16.16llx, size=0x%16.16llx, version=0x%16.16llx, load_tag=0x%8.8x, flags=0x%8.8x\n", + i, + KERNEL_MODULE_MAX_NAME, KERNEL_MODULE_MAX_NAME, (char *)name_data, + image_infos[i].address, + image_infos[i].size, + image_infos[i].version, + image_infos[i].load_tag, + image_infos[i].flags); } if (i < image_infos.size()) image_infos.resize(i); @@ -679,215 +612,6 @@ DynamicLoaderDarwinKernel::ReadAllKextSummaries () } //---------------------------------------------------------------------- -// Read a mach_header at ADDR into HEADER, and also fill in the load -// command data into LOAD_COMMAND_DATA if it is non-NULL. -// -// Returns true if we succeed, false if we fail for any reason. -//---------------------------------------------------------------------- -bool -DynamicLoaderDarwinKernel::ReadMachHeader (OSKextLoadedKextSummary& kext_summary, DataExtractor *load_command_data) -{ - DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0); - Error error; - const bool prefer_file_cache = false; - size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary.so_address, - prefer_file_cache, - header_bytes.GetBytes(), - header_bytes.GetByteSize(), - error); - if (bytes_read == sizeof(llvm::MachO::mach_header)) - { - uint32_t offset = 0; - ::memset (&kext_summary.header, 0, sizeof(kext_summary.header)); - - // Get the magic byte unswapped so we can figure out what we are dealing with - DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), endian::InlHostByteOrder(), 4); - kext_summary.header.magic = data.GetU32(&offset); - Address load_cmd_addr = kext_summary.so_address; - data.SetByteOrder(DynamicLoaderDarwinKernel::GetByteOrderFromMagic(kext_summary.header.magic)); - switch (kext_summary.header.magic) - { - case llvm::MachO::HeaderMagic32: - case llvm::MachO::HeaderMagic32Swapped: - data.SetAddressByteSize(4); - load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header)); - break; - - case llvm::MachO::HeaderMagic64: - case llvm::MachO::HeaderMagic64Swapped: - data.SetAddressByteSize(8); - load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header_64)); - break; - - default: - return false; - } - - // Read the rest of dyld's mach header - if (data.GetU32(&offset, &kext_summary.header.cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1)) - { - if (load_command_data == NULL) - return true; // We were able to read the mach_header and weren't asked to read the load command bytes - - DataBufferSP load_cmd_data_sp(new DataBufferHeap(kext_summary.header.sizeofcmds, 0)); - - size_t load_cmd_bytes_read = m_process->GetTarget().ReadMemory (load_cmd_addr, - prefer_file_cache, - load_cmd_data_sp->GetBytes(), - load_cmd_data_sp->GetByteSize(), - error); - - if (load_cmd_bytes_read == kext_summary.header.sizeofcmds) - { - // Set the load command data and also set the correct endian - // swap settings and the correct address size - load_command_data->SetData(load_cmd_data_sp, 0, kext_summary.header.sizeofcmds); - load_command_data->SetByteOrder(data.GetByteOrder()); - load_command_data->SetAddressByteSize(data.GetAddressByteSize()); - return true; // We successfully read the mach_header and the load command data - } - - return false; // We weren't able to read the load command data - } - } - return false; // We failed the read the mach_header -} - - -//---------------------------------------------------------------------- -// Parse the load commands for an image -//---------------------------------------------------------------------- -uint32_t -DynamicLoaderDarwinKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& image_info) -{ - uint32_t offset = 0; - uint32_t cmd_idx; - Segment segment; - image_info.Clear (true); - - for (cmd_idx = 0; cmd_idx < image_info.header.ncmds; cmd_idx++) - { - // Clear out any load command specific data from image_info since - // we are about to read it. - - if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command))) - { - llvm::MachO::load_command load_cmd; - uint32_t load_cmd_offset = offset; - load_cmd.cmd = data.GetU32 (&offset); - load_cmd.cmdsize = data.GetU32 (&offset); - switch (load_cmd.cmd) - { - case llvm::MachO::LoadCommandSegment32: - { - segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); - // We are putting 4 uint32_t values 4 uint64_t values so - // we have to use multiple 32 bit gets below. - segment.vmaddr = data.GetU32 (&offset); - segment.vmsize = data.GetU32 (&offset); - segment.fileoff = data.GetU32 (&offset); - segment.filesize = data.GetU32 (&offset); - // Extract maxprot, initprot, nsects and flags all at once - data.GetU32(&offset, &segment.maxprot, 4); - image_info.segments.push_back (segment); - } - break; - - case llvm::MachO::LoadCommandSegment64: - { - segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); - // Extract vmaddr, vmsize, fileoff, and filesize all at once - data.GetU64(&offset, &segment.vmaddr, 4); - // Extract maxprot, initprot, nsects and flags all at once - data.GetU32(&offset, &segment.maxprot, 4); - image_info.segments.push_back (segment); - } - break; - - case llvm::MachO::LoadCommandUUID: - image_info.uuid.SetBytes(data.GetData (&offset, 16)); - break; - - default: - break; - } - // Set offset to be the beginning of the next load command. - offset = load_cmd_offset + load_cmd.cmdsize; - } - } -#if 0 - // No slide in the kernel... - - // All sections listed in the dyld image info structure will all - // either be fixed up already, or they will all be off by a single - // slide amount that is determined by finding the first segment - // that is at file offset zero which also has bytes (a file size - // that is greater than zero) in the object file. - - // Determine the slide amount (if any) - const size_t num_sections = image_info.segments.size(); - for (size_t i = 0; i < num_sections; ++i) - { - // Iterate through the object file sections to find the - // first section that starts of file offset zero and that - // has bytes in the file... - if (image_info.segments[i].fileoff == 0 && image_info.segments[i].filesize > 0) - { - image_info.slide = image_info.address - image_info.segments[i].vmaddr; - // We have found the slide amount, so we can exit - // this for loop. - break; - } - } -#endif - if (image_info.uuid.IsValid()) - { - bool did_create = false; - if (FindTargetModule(image_info, true, &did_create)) - { - if (did_create) - image_info.module_create_stop_id = m_process->GetStopID(); - } - } - return cmd_idx; -} - -//---------------------------------------------------------------------- -// Dump a Segment to the file handle provided. -//---------------------------------------------------------------------- -void -DynamicLoaderDarwinKernel::Segment::PutToLog (Log *log, addr_t slide) const -{ - if (log) - { - if (slide == 0) - log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)", - name.AsCString(""), - vmaddr + slide, - vmaddr + slide + vmsize); - else - log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx", - name.AsCString(""), - vmaddr + slide, - vmaddr + slide + vmsize, - slide); - } -} - -const DynamicLoaderDarwinKernel::Segment * -DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const -{ - const size_t num_segments = segments.size(); - for (size_t i=0; i<num_segments; ++i) - { - if (segments[i].name == name) - return &segments[i]; - } - return NULL; -} - - -//---------------------------------------------------------------------- // Dump an image info structure to the file handle provided. //---------------------------------------------------------------------- void @@ -927,8 +651,6 @@ DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const address, address+size, version, load_tag, flags, reference_list, name); } - for (uint32_t i=0; i<segments.size(); ++i) - segments[i].PutToLog(log, 0); } } @@ -971,7 +693,7 @@ DynamicLoaderDarwinKernel::PrivateInitialize(Process *process) void DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded () { - if (m_break_id == LLDB_INVALID_BREAK_ID) + if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.module_sp) { DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h index fd8a14a0236..4d9b42207cd 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h @@ -113,22 +113,9 @@ protected: lldb::user_id_t break_id, lldb::user_id_t break_loc_id); uint32_t - AddrByteSize() + GetAddrByteSize() { - switch (m_kernel.header.magic) - { - case llvm::MachO::HeaderMagic32: - case llvm::MachO::HeaderMagic32Swapped: - return 4; - - case llvm::MachO::HeaderMagic64: - case llvm::MachO::HeaderMagic64Swapped: - return 8; - - default: - break; - } - return 0; + return m_kernel.GetAddressByteSize(); } static lldb::ByteOrder @@ -152,46 +139,6 @@ protected: } return lldb::eByteOrderInvalid; } - - class Segment - { - public: - - Segment() : - name(), - vmaddr(LLDB_INVALID_ADDRESS), - vmsize(0), - fileoff(0), - filesize(0), - maxprot(0), - initprot(0), - nsects(0), - flags(0) - { - } - - lldb_private::ConstString name; - lldb::addr_t vmaddr; - lldb::addr_t vmsize; - lldb::addr_t fileoff; - lldb::addr_t filesize; - uint32_t maxprot; - uint32_t initprot; - uint32_t nsects; - uint32_t flags; - - bool - operator==(const Segment& rhs) const - { - return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; - } - - void - PutToLog (lldb_private::Log *log, - lldb::addr_t slide) const; - - }; - enum { KERNEL_MODULE_MAX_NAME = 64u, @@ -206,7 +153,7 @@ protected: { char name[KERNEL_MODULE_MAX_NAME]; lldb::ModuleSP module_sp; - uint32_t module_create_stop_id; + uint32_t load_process_stop_id; lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros lldb_private::Address so_address; // The section offset address for this kext in case it can be read from object files uint64_t address; @@ -215,12 +162,10 @@ protected: uint32_t load_tag; uint32_t flags; uint64_t reference_list; - llvm::MachO::mach_header header; // The mach header for this image - std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) OSKextLoadedKextSummary() : module_sp (), - module_create_stop_id (UINT32_MAX), + load_process_stop_id (UINT32_MAX), uuid (), so_address (), address (LLDB_INVALID_ADDRESS), @@ -228,12 +173,16 @@ protected: version (0), load_tag (0), flags (0), - reference_list (0), - header(), - segments() + reference_list (0) { name[0] = '\0'; } + + bool + IsLoaded () + { + return load_process_stop_id != UINT32_MAX; + } void Clear (bool load_cmd_data_only) @@ -248,30 +197,28 @@ protected: flags = 0; reference_list = 0; name[0] = '\0'; - ::memset (&header, 0, sizeof(header)); } module_sp.reset(); - module_create_stop_id = UINT32_MAX; - uuid.Clear(); - segments.clear(); + load_process_stop_id = UINT32_MAX; } bool - operator == (const OSKextLoadedKextSummary& rhs) const - { - return address == rhs.address - && size == rhs.size - //&& module_sp.get() == rhs.module_sp.get() - && uuid == rhs.uuid - && version == rhs.version - && load_tag == rhs.load_tag - && flags == rhs.flags - && reference_list == rhs.reference_list - && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0 - && memcmp(&header, &rhs.header, sizeof(header)) == 0 - && segments == rhs.segments; - } - + LoadImageUsingMemoryModule (lldb_private::Process *process); + +// bool +// operator == (const OSKextLoadedKextSummary& rhs) const +// { +// return address == rhs.address +// && size == rhs.size +// //&& module_sp.get() == rhs.module_sp.get() +// && uuid == rhs.uuid +// && version == rhs.version +// && load_tag == rhs.load_tag +// && flags == rhs.flags +// && reference_list == rhs.reference_list +// && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0; +// } +// bool UUIDValid() const { @@ -281,47 +228,27 @@ protected: uint32_t GetAddressByteSize () { - if (header.cputype) - { - if (header.cputype & llvm::MachO::CPUArchABI64) - return 8; - else - return 4; - } + if (module_sp) + return module_sp->GetArchitecture().GetAddressByteSize(); return 0; } lldb::ByteOrder GetByteOrder() { - switch (header.magic) - { - case llvm::MachO::HeaderMagic32: // MH_MAGIC - case llvm::MachO::HeaderMagic64: // MH_MAGIC_64 - return lldb::endian::InlHostByteOrder(); - - case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM - case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64 - if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) - return lldb::eByteOrderBig; - else - return lldb::eByteOrderLittle; - default: - assert (!"invalid header.magic value"); - break; - } + if (module_sp) + return module_sp->GetArchitecture().GetByteOrder(); return lldb::endian::InlHostByteOrder(); } lldb_private::ArchSpec GetArchitecture () const { - return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype); + if (module_sp) + return module_sp->GetArchitecture(); + return lldb_private::ArchSpec (); } - const Segment * - FindSegment (const lldb_private::ConstString &name) const; - void PutToLog (lldb_private::Log *log) const; @@ -374,28 +301,12 @@ protected: } }; - bool - ReadMachHeader (OSKextLoadedKextSummary& kext_summary, - lldb_private::DataExtractor *load_command_data); - void RegisterNotificationCallbacks(); void UnregisterNotificationCallbacks(); - uint32_t - ParseLoadCommands (const lldb_private::DataExtractor& data, - OSKextLoadedKextSummary& dylib_info); - - bool - UpdateImageLoadAddress(OSKextLoadedKextSummary& info); - - bool - FindTargetModule (OSKextLoadedKextSummary &image_info, - bool can_create, - bool *did_create_ptr); - void SetNotificationBreakpointIfNeeded (); @@ -417,17 +328,11 @@ protected: uint32_t infos_count, bool update_executable); - bool - UpdateCommPageLoadAddress (lldb_private::Module *module); - uint32_t ReadKextSummaries (const lldb_private::Address &kext_summary_addr, uint32_t image_infos_count, OSKextLoadedKextSummary::collection &image_infos); - bool - UnloadImageLoadAddress (OSKextLoadedKextSummary& info); - OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used lldb_private::Address m_kext_summary_header_ptr_addr; lldb_private::Address m_kext_summary_header_addr; diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index f929ce13466..e3c48e2f85c 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -210,7 +210,7 @@ DynamicLoaderMacOSXDYLD::LocateDYLD() // Check the image info addr as it might point to the // mach header for dyld, or it might point to the // dyld_all_image_infos struct - addr_t shlib_addr = m_process->GetImageInfoAddress (); + const addr_t shlib_addr = m_process->GetImageInfoAddress (); ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder(); uint8_t buf[4]; @@ -310,8 +310,14 @@ DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo & arch, image_info_uuid_is_valid ? &image_info.uuid : NULL); if (!module_sp || module_sp->GetObjectFile() == NULL) + { + const bool add_image_to_target = true; + const bool load_image_sections_in_target = false; module_sp = m_process->ReadModuleFromMemory (image_info.file_spec, - image_info.address); + image_info.address, + add_image_to_target, + load_image_sections_in_target); + } if (did_create_ptr) *did_create_ptr = module_sp; @@ -434,14 +440,22 @@ DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& { SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name)); const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide; + static ConstString g_section_name_LINKEDIT ("__LINKEDIT"); + if (section_sp) { - const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get()); - if (old_section_load_addr == LLDB_INVALID_ADDRESS || - old_section_load_addr != new_section_load_addr) + // Don't ever load any __LINKEDIT sections since the ones in the shared + // cached will be coalesced into a single section and we will get warnings + // about multiple sections mapping to the same address. + if (section_sp->GetName() != g_section_name_LINKEDIT) { - if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr)) - changed = true; + const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get()); + if (old_section_load_addr == LLDB_INVALID_ADDRESS || + old_section_load_addr != new_section_load_addr) + { + if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr)) + changed = true; + } } } else @@ -780,10 +794,14 @@ DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &i &commpage_dbstr, objfile->GetOffset() + commpage_section->GetFileOffset()); if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL) + { + const bool add_image_to_target = true; + const bool load_image_sections_in_target = false; commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec, - image_infos[idx].address); - - + image_infos[idx].address, + add_image_to_target, + load_image_sections_in_target); + } } if (commpage_image_module_sp) UpdateCommPageLoadAddress (commpage_image_module_sp.get()); @@ -1249,8 +1267,14 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::co exe_arch_spec, &image_infos[exe_idx].uuid); if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) + { + const bool add_image_to_target = true; + const bool load_image_sections_in_target = false; exe_module_sp = m_process->ReadModuleFromMemory (image_infos[exe_idx].file_spec, - image_infos[exe_idx].address); + image_infos[exe_idx].address, + add_image_to_target, + load_image_sections_in_target); + } } if (exe_module_sp) diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 565682360c3..d233ece6cb7 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -27,6 +27,8 @@ #include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" +#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h" +#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h" #include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h" @@ -52,44 +54,162 @@ public: void SetRegisterDataFrom_LC_THREAD (const DataExtractor &data) { - int flavor; uint32_t offset = 0; SetError (GPRRegSet, Read, -1); SetError (FPURegSet, Read, -1); SetError (EXCRegSet, Read, -1); - while ((flavor = data.GetU32 (&offset)) > 0) + bool done = false; + + while (!done) { - uint32_t i; - uint32_t count = data.GetU32 (&offset); - switch (flavor) + int flavor = data.GetU32 (&offset); + if (flavor == 0) + done = true; + else { - case 7: - case 8: - case 9: - // Goofy extra flavor inside state... - flavor = data.GetU32 (&offset); - count = data.GetU32 (&offset); - default: - break; + uint32_t i; + uint32_t count = data.GetU32 (&offset); + switch (flavor) + { + case GPRRegSet: + for (i=0; i<count; ++i) + (&gpr.rax)[i] = data.GetU64(&offset); + SetError (GPRRegSet, Read, 0); + done = true; + + break; + case FPURegSet: + // TODO: fill in FPU regs.... + //SetError (FPURegSet, Read, -1); + done = true; + + break; + case EXCRegSet: + exc.trapno = data.GetU32(&offset); + exc.err = data.GetU32(&offset); + exc.faultvaddr = data.GetU64(&offset); + SetError (EXCRegSet, Read, 0); + done = true; + break; + case 7: + case 8: + case 9: + // fancy flavors that encapsulate of the the above + // falvors... + break; + + default: + done = true; + break; + } } + } + } +protected: + virtual int + DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) + { + return 0; + } + + virtual int + DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) + { + return 0; + } + + virtual int + DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) + { + return 0; + } + + virtual int + DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) + { + return 0; + } + + virtual int + DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) + { + return 0; + } + + virtual int + DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) + { + return 0; + } +}; - switch (flavor) + +class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386 +{ +public: + RegisterContextDarwin_i386_Mach (lldb_private::Thread &thread, const DataExtractor &data) : + RegisterContextDarwin_i386 (thread, 0) + { + SetRegisterDataFrom_LC_THREAD (data); + } + + virtual void + InvalidateAllRegisters () + { + // Do nothing... registers are always valid... + } + + void + SetRegisterDataFrom_LC_THREAD (const DataExtractor &data) + { + uint32_t offset = 0; + SetError (GPRRegSet, Read, -1); + SetError (FPURegSet, Read, -1); + SetError (EXCRegSet, Read, -1); + bool done = false; + + while (!done) + { + int flavor = data.GetU32 (&offset); + if (flavor == 0) + done = true; + else { - case GPRRegSet: - for (i=0; i<count; ++i) - (&gpr.rax)[i] = data.GetU64(&offset); - SetError (GPRRegSet, Read, 0); - break; - case FPURegSet: - // TODO: fill in FPU regs.... - //SetError (FPURegSet, Read, -1); - break; - case EXCRegSet: - exc.trapno = data.GetU32(&offset); - exc.err = data.GetU32(&offset); - exc.faultvaddr = data.GetU64(&offset); - SetError (EXCRegSet, Read, 0); - break; + uint32_t i; + uint32_t count = data.GetU32 (&offset); + switch (flavor) + { + case GPRRegSet: + for (i=0; i<count; ++i) + (&gpr.eax)[i] = data.GetU32(&offset); + SetError (GPRRegSet, Read, 0); + done = true; + + break; + case FPURegSet: + // TODO: fill in FPU regs.... + //SetError (FPURegSet, Read, -1); + done = true; + + break; + case EXCRegSet: + exc.trapno = data.GetU32(&offset); + exc.err = data.GetU32(&offset); + exc.faultvaddr = data.GetU32(&offset); + SetError (EXCRegSet, Read, 0); + done = true; + break; + case 7: + case 8: + case 9: + // fancy flavors that encapsulate of the the above + // falvors... + break; + + default: + done = true; + break; + } } } } @@ -131,6 +251,87 @@ protected: } }; +class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm +{ +public: + RegisterContextDarwin_arm_Mach (lldb_private::Thread &thread, const DataExtractor &data) : + RegisterContextDarwin_arm (thread, 0) + { + SetRegisterDataFrom_LC_THREAD (data); + } + + virtual void + InvalidateAllRegisters () + { + // Do nothing... registers are always valid... + } + + void + SetRegisterDataFrom_LC_THREAD (const DataExtractor &data) + { + uint32_t offset = 0; + SetError (GPRRegSet, Read, -1); + SetError (FPURegSet, Read, -1); + SetError (EXCRegSet, Read, -1); + int flavor = data.GetU32 (&offset); + uint32_t count = data.GetU32 (&offset); + switch (flavor) + { + case GPRRegSet: + for (uint32_t i=0; i<count; ++i) + gpr.r[i] = data.GetU32(&offset); + SetError (GPRRegSet, Read, 0); + break; + case FPURegSet: + // TODO: fill in FPU regs.... + //SetError (FPURegSet, Read, -1); + break; + case EXCRegSet: + exc.exception = data.GetU32(&offset); + exc.fsr = data.GetU32(&offset); + exc.far = data.GetU32(&offset); + SetError (EXCRegSet, Read, 0); + break; + } + } +protected: + virtual int + DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) + { + return 0; + } + + virtual int + DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) + { + return 0; + } + + virtual int + DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) + { + return 0; + } + + virtual int + DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) + { + return 0; + } + + virtual int + DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) + { + return 0; + } + + virtual int + DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) + { + return 0; + } +}; + #define MACHO_NLIST_ARM_SYMBOL_IS_THUMB 0x0008 void @@ -1017,9 +1218,11 @@ ObjectFileMachO::ParseSymtab (bool minimize) const addr_t symoff_addr = linkedit_load_addr + symtab_load_command.symoff - linkedit_file_offset; const addr_t stroff_addr = linkedit_load_addr + symtab_load_command.stroff - linkedit_file_offset; DataBufferSP nlist_data_sp (ReadMemory (process_sp, symoff_addr, nlist_data_byte_size)); + if (nlist_data_sp) + nlist_data.SetData (nlist_data_sp, 0, nlist_data_sp->GetByteSize()); DataBufferSP strtab_data_sp (ReadMemory (process_sp, stroff_addr, strtab_data_byte_size)); - nlist_data.SetData (nlist_data_sp, 0, nlist_data_sp->GetByteSize()); - strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize()); + if (strtab_data_sp) + strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize()); } } else @@ -2104,12 +2307,24 @@ ObjectFileMachO::GetThreadContextAtIndex (uint32_t idx, lldb_private::Thread &th lldb::RegisterContextSP reg_ctx_sp; const FileRangeArray::Entry *thread_context_file_range = m_thread_context_offsets.GetEntryAtIndex (idx); - if (thread_context_file_range) + + DataExtractor data (m_data, + thread_context_file_range->GetRangeBase(), + thread_context_file_range->GetByteSize()); + + switch (m_header.cputype) { - DataExtractor data (m_data, - thread_context_file_range->GetRangeBase(), - thread_context_file_range->GetByteSize()); - reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data)); + case llvm::MachO::CPUTypeARM: + reg_ctx_sp.reset (new RegisterContextDarwin_arm_Mach (thread, data)); + break; + + case llvm::MachO::CPUTypeI386: + reg_ctx_sp.reset (new RegisterContextDarwin_i386_Mach (thread, data)); + break; + + case llvm::MachO::CPUTypeX86_64: + reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data)); + break; } return reg_ctx_sp; } diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index 9c8ca825c70..67e6ac85ead 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -46,7 +46,8 @@ PlatformDarwin::~PlatformDarwin() Error PlatformDarwin::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, - lldb::ModuleSP &exe_module_sp) + lldb::ModuleSP &exe_module_sp, + const FileSpecList *module_search_paths_ptr) { Error error; // Nothing special to do here, just use the actual file and architecture @@ -84,7 +85,8 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file, { error = m_remote_platform_sp->ResolveExecutable (exe_file, exe_arch, - exe_module_sp); + exe_module_sp, + module_search_paths_ptr); } else { @@ -111,6 +113,7 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file, NULL, 0, exe_module_sp, + module_search_paths_ptr, NULL, NULL); @@ -139,6 +142,7 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file, NULL, 0, exe_module_sp, + module_search_paths_ptr, NULL, NULL); // Did we find an executable using one of the @@ -171,6 +175,100 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file, } + +Error +PlatformDarwin::GetSharedModule (const FileSpec &platform_file, + const ArchSpec &arch, + const UUID *uuid_ptr, + const ConstString *object_name_ptr, + off_t object_offset, + ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, + ModuleSP *old_module_sp_ptr, + bool *did_create_ptr) +{ + Error error; + module_sp.reset(); + + if (IsRemote()) + { + // If we have a remote platform always, let it try and locate + // the shared module first. + if (m_remote_platform_sp) + { + error = m_remote_platform_sp->GetSharedModule (platform_file, + arch, + uuid_ptr, + object_name_ptr, + object_offset, + module_sp, + module_search_paths_ptr, + old_module_sp_ptr, + did_create_ptr); + } + } + + if (!module_sp) + { + // Fall back to the local platform and find the file locally + error = Platform::GetSharedModule (platform_file, + arch, + uuid_ptr, + object_name_ptr, + object_offset, + module_sp, + module_search_paths_ptr, + old_module_sp_ptr, + did_create_ptr); + + if (!module_sp && module_search_paths_ptr && platform_file) + { + // We can try to pull off part of the file path up to the bundle + // directory level and try any module search paths... + FileSpec bundle_directory; + if (Host::GetBundleDirectory (platform_file, bundle_directory)) + { + char platform_path[PATH_MAX]; + char bundle_dir[PATH_MAX]; + platform_file.GetPath (platform_path, sizeof(platform_path)); + const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir)); + char new_path[PATH_MAX]; + size_t num_module_search_paths = module_search_paths_ptr->GetSize(); + for (size_t i=0; i<num_module_search_paths; ++i) + { + const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path)); + if (search_path_len < sizeof(new_path)) + { + snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len); + FileSpec new_file_spec (new_path, false); + if (new_file_spec.Exists()) + { + Error new_error (Platform::GetSharedModule (new_file_spec, + arch, + uuid_ptr, + object_name_ptr, + object_offset, + module_sp, + NULL, + old_module_sp_ptr, + did_create_ptr)); + + if (module_sp) + { + module_sp->SetPlatformFileSpec(new_file_spec); + return new_error; + } + } + } + } + } + } + } + if (module_sp) + module_sp->SetPlatformFileSpec(platform_file); + return error; +} + size_t PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) { diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h index 0052a8efde4..abb8326d1e7 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -30,7 +30,19 @@ public: virtual lldb_private::Error ResolveExecutable (const lldb_private::FileSpec &exe_file, const lldb_private::ArchSpec &arch, - lldb::ModuleSP &module_sp); + lldb::ModuleSP &module_sp, + const lldb_private::FileSpecList *module_search_paths_ptr); + + virtual lldb_private::Error + GetSharedModule (const lldb_private::FileSpec &platform_file, + const lldb_private::ArchSpec &arch, + const lldb_private::UUID *uuid_ptr, + const lldb_private::ConstString *object_name_ptr, + off_t object_offset, + lldb::ModuleSP &module_sp, + const lldb_private::FileSpecList *module_search_paths_ptr, + lldb::ModuleSP *old_module_sp_ptr, + bool *did_create_ptr); virtual size_t GetSoftwareBreakpointTrapOpcode (lldb_private::Target &target, diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp index 3a0e036f055..3ca4dd604cf 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -128,53 +128,6 @@ PlatformMacOSX::GetFile (const FileSpec &platform_file, return Error(); } -Error -PlatformMacOSX::GetSharedModule (const FileSpec &platform_file, - const ArchSpec &arch, - const UUID *uuid_ptr, - const ConstString *object_name_ptr, - off_t object_offset, - ModuleSP &module_sp, - ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) -{ - Error error; - module_sp.reset(); - - if (IsRemote()) - { - // If we have a remote platform always, let it try and locate - // the shared module first. - if (m_remote_platform_sp) - { - error = m_remote_platform_sp->GetSharedModule (platform_file, - arch, - uuid_ptr, - object_name_ptr, - object_offset, - module_sp, - old_module_sp_ptr, - did_create_ptr); - } - } - - if (!module_sp) - { - // Fall back to the local platform and find the file locally - error = Platform::GetSharedModule (platform_file, - arch, - uuid_ptr, - object_name_ptr, - object_offset, - module_sp, - old_module_sp_ptr, - did_create_ptr); - } - if (module_sp) - module_sp->SetPlatformFileSpec(platform_file); - return error; -} - bool PlatformMacOSX::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) { diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h index 0642ff38ffb..4a47b7fb50c 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h @@ -81,16 +81,6 @@ public: const lldb_private::UUID *uuid_ptr, lldb_private::FileSpec &local_file); - lldb_private::Error - GetSharedModule (const lldb_private::FileSpec &platform_file, - const lldb_private::ArchSpec &arch, - const lldb_private::UUID *uuid_ptr, - const lldb_private::ConstString *object_name_ptr, - off_t object_offset, - lldb::ModuleSP &module_sp, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr); - virtual bool GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp index 12c104b24de..4a32e718e72 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp @@ -121,7 +121,8 @@ PlatformRemoteiOS::GetStatus (Stream &strm) Error PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, - lldb::ModuleSP &exe_module_sp) + lldb::ModuleSP &exe_module_sp, + const FileSpecList *module_search_paths_ptr) { Error error; // Nothing special to do here, just use the actual file and architecture @@ -148,6 +149,7 @@ PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file, NULL, 0, exe_module_sp, + NULL, NULL, NULL); @@ -168,6 +170,7 @@ PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file, NULL, 0, exe_module_sp, + NULL, NULL, NULL); // Did we find an executable using one of the @@ -429,6 +432,7 @@ PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file, const ConstString *object_name_ptr, off_t object_offset, ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { @@ -441,8 +445,7 @@ PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file, error = GetFile (platform_file, uuid_ptr, local_file); if (error.Success()) { - - error = ResolveExecutable (local_file, arch, module_sp); + error = ResolveExecutable (local_file, arch, module_sp, module_search_paths_ptr); } else { @@ -453,6 +456,7 @@ PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file, object_name_ptr, object_offset, module_sp, + module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, always_create); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h index 08968f4f110..13fd11e5a9b 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h @@ -76,7 +76,8 @@ public: virtual lldb_private::Error ResolveExecutable (const lldb_private::FileSpec &exe_file, const lldb_private::ArchSpec &arch, - lldb::ModuleSP &module_sp); + lldb::ModuleSP &module_sp, + const lldb_private::FileSpecList *module_search_paths_ptr); virtual const char * GetDescription () @@ -92,13 +93,14 @@ public: const lldb_private::UUID *uuid_ptr, lldb_private::FileSpec &local_file); - lldb_private::Error + virtual lldb_private::Error GetSharedModule (const lldb_private::FileSpec &platform_file, const lldb_private::ArchSpec &arch, const lldb_private::UUID *uuid_ptr, const lldb_private::ConstString *object_name_ptr, off_t object_offset, lldb::ModuleSP &module_sp, + const lldb_private::FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 7114ac5a8e1..248475af9c3 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -92,7 +92,8 @@ PlatformRemoteGDBServer::GetDescription () Error PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, - lldb::ModuleSP &exe_module_sp) + lldb::ModuleSP &exe_module_sp, + const FileSpecList *module_search_paths_ptr) { Error error; error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented"); diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index e141f7fc080..48f36136aef 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -72,7 +72,8 @@ public: virtual lldb_private::Error ResolveExecutable (const lldb_private::FileSpec &exe_file, const lldb_private::ArchSpec &arch, - lldb::ModuleSP &module_sp); + lldb::ModuleSP &module_sp, + const lldb_private::FileSpecList *module_search_paths_ptr); virtual const char * GetDescription (); diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index 9bfc0ff2e00..0dff8fd8572 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -13,6 +13,7 @@ // C++ Includes #include "llvm/Support/MachO.h" +#include "llvm/Support/MathExtras.h" // Other libraries and framework includes #include "lldb/Core/Debugger.h" @@ -27,6 +28,9 @@ #include "ThreadMachCore.h" #include "StopInfoMachException.h" +#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" +#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" + using namespace lldb; using namespace lldb_private; @@ -67,7 +71,15 @@ ProcessMachCore::CanDebug(Target &target, bool plugin_specified_by_name) // For now we are just making sure the file exists for a given module if (!m_core_module_sp && m_core_file.Exists()) { - Error error (ModuleList::GetSharedModule(m_core_file, target.GetArchitecture(), NULL, NULL, 0, m_core_module_sp, NULL, NULL)); + Error error (ModuleList::GetSharedModule (m_core_file, + target.GetArchitecture(), + NULL, + NULL, + 0, + m_core_module_sp, + NULL, + NULL, + NULL)); if (m_core_module_sp) { @@ -92,7 +104,8 @@ ProcessMachCore::ProcessMachCore(Target& target, Listener &listener, const FileS m_core_aranges (), m_core_module_sp (), m_core_file (core_file), - m_shlib_addr (LLDB_INVALID_ADDRESS) + m_dyld_addr (LLDB_INVALID_ADDRESS), + m_dyld_plugin_name () { } @@ -130,6 +143,61 @@ ProcessMachCore::GetPluginVersion() return 1; } +bool +ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr) +{ + llvm::MachO::mach_header header; + Error error; + if (DoReadMemory (addr, &header, sizeof(header), error) != sizeof(header)) + return false; + if (header.magic == llvm::MachO::HeaderMagic32Swapped || + header.magic == llvm::MachO::HeaderMagic64Swapped) + { + header.magic = llvm::ByteSwap_32(header.magic); + header.cputype = llvm::ByteSwap_32(header.cputype); + header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype); + header.filetype = llvm::ByteSwap_32(header.filetype); + header.ncmds = llvm::ByteSwap_32(header.ncmds); + header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds); + header.flags = llvm::ByteSwap_32(header.flags); + } + + // TODO: swap header if needed... + //printf("0x%16.16llx: magic = 0x%8.8x, file_type= %u\n", vaddr, header.magic, header.filetype); + if (header.magic == llvm::MachO::HeaderMagic32 || + header.magic == llvm::MachO::HeaderMagic64) + { + // Check MH_EXECUTABLE to see if we can find the mach image + // that contains the shared library list. The dynamic loader + // (dyld) is what contains the list for user applications, + // and the mach kernel contains a global that has the list + // of kexts to load + switch (header.filetype) + { + case llvm::MachO::HeaderFileTypeDynamicLinkEditor: + //printf("0x%16.16llx: file_type = MH_DYLINKER\n", vaddr); + // Address of dyld "struct mach_header" in the core file + m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); + m_dyld_addr = addr; + return true; + + case llvm::MachO::HeaderFileTypeExecutable: + //printf("0x%16.16llx: file_type = MH_EXECUTE\n", vaddr); + // Check MH_EXECUTABLE file types to see if the dynamic link object flag + // is NOT set. If it isn't, then we have a mach_kernel. + if ((header.flags & llvm::MachO::HeaderFlagBitIsDynamicLinkObject) == 0) + { + m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); + // Address of the mach kernel "struct mach_header" in the core file. + m_dyld_addr = addr; + return true; + } + break; + } + } + return false; +} + //---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- @@ -137,7 +205,12 @@ Error ProcessMachCore::DoLoadCore () { Error error; - DataExtractor data; + if (!m_core_module_sp) + { + error.SetErrorString ("invalid core module"); + return error; + } + ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); if (core_objfile == NULL) { @@ -157,6 +230,13 @@ ProcessMachCore::DoLoadCore () error.SetErrorString ("core file has no sections"); return error; } + + llvm::MachO::mach_header header; + DataExtractor data (&header, + sizeof(header), + m_core_module_sp->GetArchitecture().GetByteOrder(), + m_core_module_sp->GetArchitecture().GetAddressByteSize()); + bool ranges_are_sorted = true; addr_t vm_addr = 0; for (uint32_t i=0; i<num_sections; ++i) @@ -165,44 +245,6 @@ ProcessMachCore::DoLoadCore () if (section) { lldb::addr_t section_vm_addr = section->GetFileAddress(); - - if (m_shlib_addr == LLDB_INVALID_ADDRESS) - { - if (core_objfile->ReadSectionData (section, data)) - { - uint32_t offset = 0; - llvm::MachO::mach_header header; - if (data.GetU32(&offset, &header, sizeof(header)/sizeof(uint32_t))) - { - - if (header.magic == llvm::MachO::HeaderMagic32 || - header.magic == llvm::MachO::HeaderMagic64) - { - // Check MH_EXECUTABLE to see if we can find the mach image - // that contains the shared library list. The dynamic loader - // (dyld) is what contains the list for user applications, - // and the mach kernel contains a global that has the list - // of kexts to load - switch (header.filetype) - { - case llvm::MachO::HeaderFileTypeDynamicLinkEditor: - // Address of dyld "struct mach_header" in the core file - m_shlib_addr = section_vm_addr; - break; - case llvm::MachO::HeaderFileTypeExecutable: - // Check MH_EXECUTABLE file types to see if the dynamic link object flag - // is NOT set. If it isn't, then we have a mach_kernel. - if ((header.flags & llvm::MachO::HeaderFlagBitIsDynamicLinkObject) == 0) - { - // Address of the mach kernel "struct mach_header" in the core file. - m_shlib_addr = section_vm_addr; - } - break; - } - } - } - } - } FileRange file_range (section->GetFileOffset(), section->GetFileSize()); VMRangeToFileOffset::Entry range_entry (section_vm_addr, section->GetByteSize(), @@ -212,29 +254,91 @@ ProcessMachCore::DoLoadCore () ranges_are_sorted = false; vm_addr = section->GetFileAddress(); VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); +// printf ("LC_SEGMENT[%u] arange=[0x%16.16llx - 0x%16.16llx), frange=[0x%8.8x - 0x%8.8x)\n", +// i, +// range_entry.GetRangeBase(), +// range_entry.GetRangeEnd(), +// range_entry.data.GetRangeBase(), +// range_entry.data.GetRangeEnd()); + if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) { last_entry->SetRangeEnd (range_entry.GetRangeEnd()); last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd()); + //puts("combine"); } else { m_core_aranges.Append(range_entry); } + + // After we have added this section to our m_core_aranges map, + // we can check the start of the section to see if it might + // contain dyld for user space apps, or the mach kernel file + // for kernel cores. + if (m_dyld_addr == LLDB_INVALID_ADDRESS) + GetDynamicLoaderAddress (section_vm_addr); } } if (!ranges_are_sorted) { m_core_aranges.Sort(); } - if (!m_target.GetArchitecture().IsValid()) - m_target.SetArchitecture(m_core_module_sp->GetArchitecture()); + + // Even if the architecture is set in the target, we need to override + // it to match the core file which is always single arch. + ArchSpec arch (m_core_module_sp->GetArchitecture()); + if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) + { + arch.SetTriple ("i386", m_target.GetPlatform().get()); + } + if (arch.IsValid()) + m_target.SetArchitecture(arch); + + if (m_dyld_addr == LLDB_INVALID_ADDRESS) + { + // Check the magic kernel address for the mach image header address in case + // it is there. + if (arch.GetAddressByteSize() == 8) + { + Error header_addr_error; + addr_t header_addr = ReadPointerFromMemory (0xffffff8000002010ull, header_addr_error); + if (header_addr != LLDB_INVALID_ADDRESS) + GetDynamicLoaderAddress (header_addr); + } + +// if (m_dyld_addr == LLDB_INVALID_ADDRESS) +// { +// // We haven't found our dyld or mach_kernel yet, +// // so we need to exhaustively look +// const size_t num_core_aranges = m_core_aranges.GetSize(); +// bool done = false; +// for (size_t i=0; !done && i<num_core_aranges; ++i) +// { +// const addr_t start_vaddr = m_core_aranges.GetEntryRef(i).GetRangeBase(); +// const addr_t end_vaddr = m_core_aranges.GetEntryRef(i).GetRangeEnd(); +// // printf("core_arange[%u] [0x%16.16llx - 0x%16.16llx)\n", (uint32_t)i, start_vaddr, end_vaddr); +// +// for (addr_t vaddr = start_vaddr; !done && start_vaddr < end_vaddr; vaddr += 0x1000) +// { +// done = GetDynamicLoaderAddress (vaddr); +// } +// } +// } + } return error; } +lldb_private::DynamicLoader * +ProcessMachCore::GetDynamicLoader () +{ + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.empty() ? NULL : m_dyld_plugin_name.c_str())); + return m_dyld_ap.get(); +} uint32_t ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) @@ -293,6 +397,14 @@ ProcessMachCore::IsAlive () // Process Memory //------------------------------------------------------------------ size_t +ProcessMachCore::ReadMemory (addr_t addr, void *buf, size_t size, Error &error) +{ + // Don't allow the caching that lldb_private::Process::ReadMemory does + // since in core files we have it all cached our our core file anyway. + return DoReadMemory (addr, buf, size, error); +} + +size_t ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error) { ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); @@ -340,7 +452,7 @@ ProcessMachCore::Initialize() addr_t ProcessMachCore::GetImageInfoAddress() { - return m_shlib_addr; + return m_dyld_addr; } diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h index 79b18e58bdd..924f549475e 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h @@ -68,6 +68,9 @@ public: virtual lldb_private::Error DoLoadCore (); + virtual lldb_private::DynamicLoader * + GetDynamicLoader (); + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -99,6 +102,9 @@ public: // Process Memory //------------------------------------------------------------------ virtual size_t + ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error); + + virtual size_t DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error); virtual lldb::addr_t @@ -120,6 +126,9 @@ protected: return m_core_module_sp->GetObjectFile(); } private: + bool + GetDynamicLoaderAddress (lldb::addr_t addr); + //------------------------------------------------------------------ // For ProcessMachCore only //------------------------------------------------------------------ @@ -129,7 +138,8 @@ private: VMRangeToFileOffset m_core_aranges; lldb::ModuleSP m_core_module_sp; lldb_private::FileSpec m_core_file; - lldb::addr_t m_shlib_addr; + lldb::addr_t m_dyld_addr; + std::string m_dyld_plugin_name; DISALLOW_COPY_AND_ASSIGN (ProcessMachCore); }; diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 737b8d4914b..1c07db9c644 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -94,6 +94,7 @@ Platform::GetSharedModule (const FileSpec &platform_file, const ConstString *object_name_ptr, off_t object_offset, ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { @@ -111,6 +112,7 @@ Platform::GetSharedModule (const FileSpec &platform_file, object_name_ptr, object_offset, module_sp, + module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, always_create); @@ -403,7 +405,8 @@ Platform::SetOSVersion (uint32_t major, Error Platform::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, - lldb::ModuleSP &exe_module_sp) + lldb::ModuleSP &exe_module_sp, + const FileSpecList *module_search_paths_ptr) { Error error; if (exe_file.Exists()) @@ -416,6 +419,7 @@ Platform::ResolveExecutable (const FileSpec &exe_file, NULL, 0, exe_module_sp, + module_search_paths_ptr, NULL, NULL); } @@ -433,6 +437,7 @@ Platform::ResolveExecutable (const FileSpec &exe_file, NULL, 0, exe_module_sp, + module_search_paths_ptr, NULL, NULL); // Did we find an executable using one of the diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 6ed2b2ac040..10922feb7db 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -2193,14 +2193,23 @@ Process::DeallocateMemory (addr_t ptr) } ModuleSP -Process::ReadModuleFromMemory (const FileSpec& file_spec, lldb::addr_t header_addr) +Process::ReadModuleFromMemory (const FileSpec& file_spec, + lldb::addr_t header_addr, + bool add_image_to_target, + bool load_sections_in_target) { ModuleSP module_sp (new Module (file_spec, shared_from_this(), header_addr)); if (module_sp) { - m_target.GetImages().Append(module_sp); - bool changed = false; - module_sp->SetLoadAddress (m_target, 0, changed); + if (add_image_to_target) + { + m_target.GetImages().Append(module_sp); + if (load_sections_in_target) + { + bool changed = false; + module_sp->SetLoadAddress (m_target, 0, changed); + } + } } return module_sp; } @@ -2306,9 +2315,9 @@ Process::Launch (const ProcessLaunchInfo &launch_info) DidLaunch (); - m_dyld_ap.reset (DynamicLoader::FindPlugin (this, NULL)); - if (m_dyld_ap.get()) - m_dyld_ap->DidLaunch(); + DynamicLoader *dyld = GetDynamicLoader (); + if (dyld) + dyld->DidLaunch(); m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); // This delays passing the stopped event to listeners till DidLaunch gets @@ -2349,7 +2358,11 @@ Process::LoadCore () else StartPrivateStateThread (); - CompleteAttach (); + DynamicLoader *dyld = GetDynamicLoader (); + if (dyld) + dyld->DidAttach(); + + m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); // We successfully loaded a core file, now pretend we stopped so we can // show all of the threads in the core file and explore the crashed // state. @@ -2359,6 +2372,13 @@ Process::LoadCore () return error; } +DynamicLoader * +Process::GetDynamicLoader () +{ + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL)); + return m_dyld_ap.get(); +} Process::NextEventAction::EventActionResult @@ -2622,9 +2642,9 @@ Process::CompleteAttach () // We have completed the attach, now it is time to find the dynamic loader // plug-in - m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL)); - if (m_dyld_ap.get()) - m_dyld_ap->DidAttach(); + DynamicLoader *dyld = GetDynamicLoader (); + if (dyld) + dyld->DidAttach(); m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); // Figure out which one is the executable, and set that in our target: diff --git a/lldb/source/Target/SectionLoadList.cpp b/lldb/source/Target/SectionLoadList.cpp index 09431abc00f..df2802378b1 100644 --- a/lldb/source/Target/SectionLoadList.cpp +++ b/lldb/source/Target/SectionLoadList.cpp @@ -74,6 +74,9 @@ SectionLoadList::SetSectionLoadAddress (const Section *section, addr_t load_addr load_addr); } + if (section->GetByteSize() == 0) + return false; // No change + Mutex::Locker locker(m_mutex); sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section); if (sta_pos != m_sect_to_addr.end()) @@ -89,7 +92,19 @@ SectionLoadList::SetSectionLoadAddress (const Section *section, addr_t load_addr addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr); if (ats_pos != m_addr_to_sect.end()) { - assert (section != ats_pos->second); + if (section != ats_pos->second) + { + Module *module = section->GetModule(); + if (module) + { + module->ReportWarning ("address 0x%16.16llx maps to more than one section: %s.%s and %s.%s", + load_addr, + module->GetFileSpec().GetFilename().GetCString(), + section->GetName().GetCString(), + ats_pos->second->GetModule()->GetFileSpec().GetFilename().GetCString(), + ats_pos->second->GetName().GetCString()); + } + } ats_pos->second = section; } else diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 20b8e938fe1..6a6cb0eae7e 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -869,6 +869,7 @@ Target::SetArchitecture (const ArchSpec &arch_spec) NULL, 0, executable_sp, + &GetExecutableSearchPaths(), NULL, NULL); @@ -1227,7 +1228,15 @@ Target::GetSharedModule if (m_image_search_paths.RemapPath (file_spec.GetDirectory(), transformed_spec.GetDirectory())) { transformed_spec.GetFilename() = file_spec.GetFilename(); - error = ModuleList::GetSharedModule (transformed_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module); + error = ModuleList::GetSharedModule (transformed_spec, + arch, + uuid_ptr, + object_name, + object_offset, + module_sp, + &GetExecutableSearchPaths(), + &old_module_sp, + &did_create_module); } } @@ -1242,6 +1251,7 @@ Target::GetSharedModule object_name, object_offset, module_sp, + &GetExecutableSearchPaths(), &old_module_sp, &did_create_module); } @@ -1395,6 +1405,20 @@ Target::GetSettingsController () return g_settings_controller_sp; } +FileSpecList +Target::GetDefaultExecutableSearchPaths () +{ + lldb::UserSettingsControllerSP settings_controller_sp (GetSettingsController()); + if (settings_controller_sp) + { + lldb::InstanceSettingsSP instance_settings_sp (settings_controller_sp->GetDefaultInstanceSettings ()); + if (instance_settings_sp) + return static_cast<TargetInstanceSettings *>(instance_settings_sp.get())->GetExecutableSearchPaths (); + } + return FileSpecList(); +} + + ArchSpec Target::GetDefaultArchitecture () { @@ -2016,6 +2040,7 @@ Target::SettingsController::CreateInstanceSettings (const char *instance_name) #define TSC_PREFER_DYNAMIC "prefer-dynamic-value" #define TSC_SKIP_PROLOGUE "skip-prologue" #define TSC_SOURCE_MAP "source-map" +#define TSC_EXE_SEARCH_PATHS "exec-search-paths" #define TSC_MAX_CHILDREN "max-children-count" #define TSC_MAX_STRLENSUMMARY "max-string-summary-length" #define TSC_PLATFORM_AVOID "breakpoints-use-platform-avoid-list" @@ -2058,6 +2083,13 @@ GetSettingNameForSourcePathMap () } static const ConstString & +GetSettingNameForExecutableSearchPaths () +{ + static ConstString g_const_string (TSC_EXE_SEARCH_PATHS); + return g_const_string; +} + +static const ConstString & GetSettingNameForSkipPrologue () { static ConstString g_const_string (TSC_SKIP_PROLOGUE); @@ -2193,6 +2225,7 @@ TargetInstanceSettings::TargetInstanceSettings m_prefer_dynamic_value (2), m_skip_prologue (true, true), m_source_map (NULL, NULL), + m_exe_search_paths (), m_max_children_display(256), m_max_strlen_length(1024), m_breakpoints_use_platform_avoid (true, true), @@ -2231,6 +2264,7 @@ TargetInstanceSettings::TargetInstanceSettings (const TargetInstanceSettings &rh m_prefer_dynamic_value (rhs.m_prefer_dynamic_value), m_skip_prologue (rhs.m_skip_prologue), m_source_map (rhs.m_source_map), + m_exe_search_paths (rhs.m_exe_search_paths), m_max_children_display (rhs.m_max_children_display), m_max_strlen_length (rhs.m_max_strlen_length), m_breakpoints_use_platform_avoid (rhs.m_breakpoints_use_platform_avoid), @@ -2265,6 +2299,7 @@ TargetInstanceSettings::operator= (const TargetInstanceSettings &rhs) m_prefer_dynamic_value = rhs.m_prefer_dynamic_value; m_skip_prologue = rhs.m_skip_prologue; m_source_map = rhs.m_source_map; + m_exe_search_paths = rhs.m_exe_search_paths; m_max_children_display = rhs.m_max_children_display; m_max_strlen_length = rhs.m_max_strlen_length; m_breakpoints_use_platform_avoid = rhs.m_breakpoints_use_platform_avoid; @@ -2357,6 +2392,49 @@ TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_n if (ok) m_max_strlen_length = new_value; } + else if (var_name == GetSettingNameForExecutableSearchPaths()) + { + switch (op) + { + case eVarSetOperationReplace: + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + default: + break; + case eVarSetOperationAssign: + m_exe_search_paths.Clear(); + // Fall through to append.... + case eVarSetOperationAppend: + { + Args args(value); + const uint32_t argc = args.GetArgumentCount(); + if (argc > 0) + { + const char *exe_search_path_dir; + for (uint32_t idx = 0; (exe_search_path_dir = args.GetArgumentAtIndex(idx)) != NULL; ++idx) + { + FileSpec file_spec; + file_spec.GetDirectory().SetCString(exe_search_path_dir); + FileSpec::FileType file_type = file_spec.GetFileType(); + if (file_type == FileSpec::eFileTypeDirectory || file_type == FileSpec::eFileTypeInvalid) + { + m_exe_search_paths.Append(file_spec); + } + else + { + err.SetErrorStringWithFormat("executable search path '%s' exists, but it does not resolve to a directory", exe_search_path_dir); + } + } + } + } + break; + + case eVarSetOperationClear: + m_exe_search_paths.Clear(); + break; + } + } else if (var_name == GetSettingNameForSourcePathMap ()) { switch (op) @@ -2487,6 +2565,16 @@ TargetInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry, else value.AppendString ("false"); } + else if (var_name == GetSettingNameForExecutableSearchPaths()) + { + if (m_exe_search_paths.GetSize()) + { + for (size_t i = 0, n = m_exe_search_paths.GetSize(); i < n; ++i) + { + value.AppendString(m_exe_search_paths.GetFileSpecAtIndex (i).GetDirectory().AsCString()); + } + } + } else if (var_name == GetSettingNameForSourcePathMap ()) { if (m_source_map.GetSize()) @@ -2670,6 +2758,7 @@ Target::SettingsController::instance_settings_table[] = { TSC_PREFER_DYNAMIC , eSetVarTypeEnum , NULL , g_dynamic_value_types, false, false, "Should printed values be shown as their dynamic value." }, { TSC_SKIP_PROLOGUE , eSetVarTypeBoolean, "true" , NULL, false, false, "Skip function prologues when setting breakpoints by name." }, { TSC_SOURCE_MAP , eSetVarTypeArray , NULL , NULL, false, false, "Source path remappings to use when locating source files from debug information." }, + { TSC_EXE_SEARCH_PATHS , eSetVarTypeArray , NULL , NULL, false, false, "Executable search paths to use when locating executable files whose paths don't match the local file system." }, { TSC_MAX_CHILDREN , eSetVarTypeInt , "256" , NULL, true, false, "Maximum number of children to expand in any level of depth." }, { TSC_MAX_STRLENSUMMARY , eSetVarTypeInt , "1024" , NULL, true, false, "Maximum number of characters to show when using %s in summary strings." }, { TSC_PLATFORM_AVOID , eSetVarTypeBoolean, "true" , NULL, false, false, "Consult the platform module avoid list when setting non-module specific breakpoints." }, diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp index 6ca58b86ef5..e412beb1da5 100644 --- a/lldb/source/Target/TargetList.cpp +++ b/lldb/source/Target/TargetList.cpp @@ -92,6 +92,16 @@ TargetList::CreateTarget (Debugger &debugger, get_dependent_files, platform_sp, target_sp); + + if (target_sp) + { + if (file.GetDirectory()) + { + FileSpec file_dir; + file_dir.GetDirectory() = file.GetDirectory(); + target_sp->GetExecutableSearchPaths ().Append (file_dir); + } + } return error; } @@ -120,7 +130,12 @@ TargetList::CreateTarget FileSpec resolved_file(file); if (platform_sp) - error = platform_sp->ResolveExecutable (file, arch, exe_module_sp); + { + FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); + error = platform_sp->ResolveExecutable (file, arch, + exe_module_sp, + executable_search_paths.GetSize() ? &executable_search_paths : NULL); + } if (error.Success() && exe_module_sp) { |

