From: Jason Molenda Date: Thu, 21 Jul 2016 08:30:55 +0000 (+0000) Subject: Add a new DynamicLoader plugin that uses SPI that are in development X-Git-Tag: llvmorg-4.0.0-rc1~14660 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9ab5dc2417f6338cc5ad6ab117f62ba895cc8c20;p=platform%2Fupstream%2Fllvm.git Add a new DynamicLoader plugin that uses SPI that are in development for the fall (northern hemisphere) 2016 Darwin platforms to learn about loaded images, instead of reading dyld internal data structures. These new SPI don't exist on older releases, and new packets are needed from debugserver to use them (those changes are already committed). I had to change the minimum deployment target for debugserver in the xcode project file to macOS 10.10 so that debugserver will use the [[NSProcessInfo processInfo] operatingSystemVersion] call in MachProcess::GetOSVersionNumbers to get the operarting system version # -- this API is only available in macOS 10.10 and newer ("OS X Yosemite", released Oct 2014). If we have many people building llvm.org lldb on older systems still, we can back off on this for the llvm.org sources. There should be no change in behavior with this commit, either to older darwin systems or newer darwin systems. For now the new DynamicLoader plugin is never activated - I'm forcing the old plugin to be used in DynamicLoaderDarwin::UseDYLDSPI. I'll remove that unconditional use of the old plugin soon, so the newer plugin is used on the newest Darwin platforms. llvm-svn: 276254 --- diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 57787f2..5e71ffd 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1918,6 +1918,9 @@ public: //------------------------------------------------------------------ /// Retrieve the list of shared libraries that are loaded for this process + /// This method is used on pre-macOS 10.12, pre-iOS 10, pre-tvOS 10, + /// pre-watchOS 3 systems. The following two methods are for newer versions + /// of those OSes. /// /// For certain platforms, the time it takes for the DynamicLoader plugin to /// read all of the shared libraries out of memory over a slow communication @@ -1946,6 +1949,22 @@ public: return StructuredData::ObjectSP(); } + // On macOS 10.12, tvOS 10, iOS 10, watchOS 3 and newer, debugserver can return + // the full list of loaded shared libraries without needing any input. + virtual lldb_private::StructuredData::ObjectSP + GetLoadedDynamicLibrariesInfos () + { + return StructuredData::ObjectSP(); + } + + // On macOS 10.12, tvOS 10, iOS 10, watchOS 3 and newer, debugserver can return + // information about binaries given their load addresses. + virtual lldb_private::StructuredData::ObjectSP + GetLoadedDynamicLibrariesInfos (const std::vector &load_addresses) + { + return StructuredData::ObjectSP(); + } + //------------------------------------------------------------------ /// Print a user-visible warning about a module being built with optimization /// diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index c031d9d..305c5bf 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -894,6 +894,8 @@ AF26703B1852D01E00B6CC36 /* QueueList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2670391852D01E00B6CC36 /* QueueList.cpp */; }; AF27AD551D3603EA00CF2833 /* DynamicLoaderDarwin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */; }; AF27AD561D3603EA00CF2833 /* DynamicLoaderDarwin.h in Headers */ = {isa = PBXBuildFile; fileRef = AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */; }; + AF2907BF1D3F082400E10654 /* DynamicLoaderMacOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */; }; + AF2907C01D3F082400E10654 /* DynamicLoaderMacOS.h in Headers */ = {isa = PBXBuildFile; fileRef = AF2907BE1D3F082400E10654 /* DynamicLoaderMacOS.h */; }; AF2BA6EC1A707E3400C5248A /* UriParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33064C991A5C7A330033D415 /* UriParser.cpp */; }; AF2BCA6C18C7EFDE005B4526 /* JITLoaderGDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2BCA6918C7EFDE005B4526 /* JITLoaderGDB.cpp */; }; AF33B4BE1C1FA441001B28D9 /* NetBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */; }; @@ -2817,6 +2819,8 @@ AF2670391852D01E00B6CC36 /* QueueList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = QueueList.cpp; path = source/Target/QueueList.cpp; sourceTree = ""; }; AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderDarwin.cpp; sourceTree = ""; }; AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderDarwin.h; sourceTree = ""; }; + AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderMacOS.cpp; sourceTree = ""; }; + AF2907BE1D3F082400E10654 /* DynamicLoaderMacOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderMacOS.h; sourceTree = ""; }; AF2BCA6918C7EFDE005B4526 /* JITLoaderGDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITLoaderGDB.cpp; sourceTree = ""; }; AF2BCA6A18C7EFDE005B4526 /* JITLoaderGDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITLoaderGDB.h; sourceTree = ""; }; AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetBSDSignals.cpp; path = Utility/NetBSDSignals.cpp; sourceTree = ""; }; @@ -3297,6 +3301,8 @@ children = ( AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */, AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */, + AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */, + AF2907BE1D3F082400E10654 /* DynamicLoaderMacOS.h */, 260C897A10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.cpp */, 260C897B10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.h */, ); @@ -6950,6 +6956,7 @@ 268900ED13353E6F00698AC0 /* ObjCLanguageRuntime.cpp in Sources */, 268900EE13353E6F00698AC0 /* PathMappingList.cpp in Sources */, 4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */, + AF2907BF1D3F082400E10654 /* DynamicLoaderMacOS.cpp in Sources */, 268900EF13353E6F00698AC0 /* Platform.cpp in Sources */, 268900F013353E6F00698AC0 /* Process.cpp in Sources */, 26BC17AD18C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp in Sources */, diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp index 038f96c..2050096 100644 --- a/lldb/source/API/SystemInitializerFull.cpp +++ b/lldb/source/API/SystemInitializerFull.cpp @@ -43,6 +43,7 @@ #include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h" #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" +#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" #include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" @@ -383,6 +384,7 @@ SystemInitializerFull::Initialize() process_gdb_remote::ProcessGDBRemote::Initialize(); DynamicLoaderMacOSXDYLD::Initialize(); + DynamicLoaderMacOS::Initialize(); DynamicLoaderPOSIXDYLD::Initialize(); DynamicLoaderStatic::Initialize(); DynamicLoaderWindowsDYLD::Initialize(); @@ -506,6 +508,7 @@ SystemInitializerFull::Terminate() platform_gdb_server::PlatformRemoteGDBServer::Terminate(); process_gdb_remote::ProcessGDBRemote::Terminate(); DynamicLoaderMacOSXDYLD::Terminate(); + DynamicLoaderMacOS::Terminate(); DynamicLoaderPOSIXDYLD::Terminate(); DynamicLoaderStatic::Terminate(); DynamicLoaderWindowsDYLD::Terminate(); diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt index 4d916b1..7dc3e98 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt @@ -1,4 +1,5 @@ add_lldb_library(lldbPluginDynamicLoaderMacOSXDYLD DynamicLoaderMacOSXDYLD.cpp + DynamicLoaderMacOS.cpp DynamicLoaderDarwin.cpp ) diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp index efca1be..b17d171 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -151,21 +151,6 @@ DynamicLoaderDarwin::FindTargetModuleForImageInfo (ImageInfo &image_info, bool c return module_sp; } -DynamicLoaderDarwin::ImageInfo * -DynamicLoaderDarwin::FindImageInfoForAddress (addr_t load_address) -{ - std::lock_guard guard(m_mutex); - const size_t image_count = m_dyld_image_infos.size(); - for (size_t i = 0; i < image_count; i++) - { - if (load_address == m_dyld_image_infos[i].address) - { - return &m_dyld_image_infos[i]; - } - } - return NULL; -} - void DynamicLoaderDarwin::UnloadImages (const std::vector &solib_addresses) { @@ -223,6 +208,46 @@ DynamicLoaderDarwin::UnloadImages (const std::vector &solib_addres } } +void +DynamicLoaderDarwin::UnloadAllImages () +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + ModuleList unloaded_modules_list; + + Target &target = m_process->GetTarget(); + const ModuleList &target_modules = target.GetImages(); + std::lock_guard guard(target_modules.GetMutex()); + + size_t num_modules = target_modules.GetSize(); + ModuleSP dyld_sp (GetDYLDModule()); + + for (size_t i = 0; i < num_modules; i++) + { + ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked (i); + + // Don't remove dyld - else we'll lose our breakpoint notifying us about libraries + // being re-loaded... + if (module_sp.get() != nullptr + && module_sp.get() != dyld_sp.get()) + { + UnloadSections (module_sp); + unloaded_modules_list.Append (module_sp); + } + } + + if (unloaded_modules_list.GetSize() != 0) + { + if (log) + { + log->PutCString("Unloaded:"); + unloaded_modules_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::UnloadAllImages"); + } + target.GetImages().Remove(unloaded_modules_list); + m_dyld_image_infos.clear(); + m_dyld_image_infos_stop_id = m_process->GetStopID(); + } +} + //---------------------------------------------------------------------- // Update the load addresses for all segments in MODULE using the // updated INFO that is passed in. @@ -401,6 +426,23 @@ DynamicLoaderDarwin::JSONImageInformationIntoImageInfo (StructuredData::ObjectSP image_infos[i].header.cpusubtype = mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue(); image_infos[i].header.filetype = mh->GetValueForKey("filetype")->GetAsInteger()->GetValue(); + if (image->HasKey("min_version_os_name")) + { + std::string os_name = image->GetValueForKey("min_version_os_name")->GetAsString()->GetValue(); + if (os_name == "macosx") + image_infos[i].os_type = llvm::Triple::MacOSX; + else if (os_name == "ios" || os_name == "iphoneos") + image_infos[i].os_type = llvm::Triple::IOS; + else if (os_name == "tvos") + image_infos[i].os_type = llvm::Triple::TvOS; + else if (os_name == "watchos") + image_infos[i].os_type = llvm::Triple::WatchOS; + } + if (image->HasKey("min_version_os_sdk")) + { + image_infos[i].min_version_os_sdk = image->GetValueForKey("min_version_os_sdk")->GetAsString()->GetValue(); + } + // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't currently send them // in the reply. @@ -483,71 +525,99 @@ DynamicLoaderDarwin::JSONImageInformationIntoImageInfo (StructuredData::ObjectSP } void -DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfos (ImageInfo::collection &image_infos) +DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos (ImageInfo::collection &image_infos) { + uint32_t exe_idx = UINT32_MAX; + uint32_t dyld_idx = UINT32_MAX; + Target &target = m_process->GetTarget(); + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + ConstString g_dyld_sim_filename ("dyld_sim"); + + ArchSpec target_arch = target.GetArchitecture(); const size_t image_infos_size = image_infos.size(); for (size_t i = 0; i < image_infos_size; i++) { if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER) { - UpdateDYLDImageInfoFromNewImageInfo (image_infos[i]); - break; // FIXME simulator debugging w/ multiple dylds + // In a "simulator" process (an x86 process that is ios/tvos/watchos) + // we will have two dyld modules -- a "dyld" that we want to keep track of, + // and a "dyld_sim" which we don't need to keep track of here. + // If the target is an x86 system and the OS of the dyld binary is + // ios/tvos/watchos, then we are looking at dyld_sym. + + // debugserver has only recently (late 2016) started sending up the + // os type for each binary it sees -- so if we don't have an os + // type, use a filename check as our next best guess. + if (image_infos[i].os_type == llvm::Triple::OSType::UnknownOS) + { + if (image_infos[i].file_spec.GetFilename() != g_dyld_sim_filename) + { + dyld_idx = i; + } + } + else if (target_arch.GetTriple().getArch() == llvm::Triple::x86 + || target_arch.GetTriple().getArch() == llvm::Triple::x86_64) + { + if (image_infos[i].os_type != llvm::Triple::OSType::IOS + && image_infos[i].os_type != llvm::Triple::TvOS + && image_infos[i].os_type != llvm::Triple::WatchOS) + { + dyld_idx = i; + } + } + } + else if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) + { + exe_idx = i; } } -} -void -DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo (ImageInfo &image_info) -{ - // FIXME simulator debugging w/ multiple dylds - if (image_info.header.filetype == llvm::MachO::MH_DYLINKER) + if (exe_idx != UINT32_MAX) { const bool can_create = true; - ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_info, can_create, NULL); + ModuleSP exe_module_sp (FindTargetModuleForImageInfo (image_infos[exe_idx], can_create, NULL)); + if (exe_module_sp) + { + if (log) + log->Printf ("Found executable module: %s", exe_module_sp->GetFileSpec().GetPath().c_str()); + target.GetImages().AppendIfNeeded (exe_module_sp); + UpdateImageLoadAddress (exe_module_sp.get(), image_infos[exe_idx]); + if (exe_module_sp.get() != target.GetExecutableModulePointer()) + { + const bool get_dependent_images = false; + target.SetExecutableModule (exe_module_sp, get_dependent_images); + } + } + } + + if (dyld_idx != UINT32_MAX) + { + const bool can_create = true; + ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_infos[dyld_idx], can_create, NULL); if (dyld_sp.get()) { - Target &target = m_process->GetTarget(); + if (log) + log->Printf ("Found dyld module: %s", dyld_sp->GetFileSpec().GetPath().c_str()); target.GetImages().AppendIfNeeded (dyld_sp); - UpdateImageLoadAddress (dyld_sp.get(), image_info); + UpdateImageLoadAddress (dyld_sp.get(), image_infos[dyld_idx]); SetDYLDModule (dyld_sp); } } } void -DynamicLoaderDarwin::AddExecutableModuleIfInImageInfos (ImageInfo::collection &image_infos) +DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo (ImageInfo &image_info) { - const size_t image_infos_size = image_infos.size(); - for (size_t i = 0; i < image_infos_size; i++) + if (image_info.header.filetype == llvm::MachO::MH_DYLINKER) { - if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) + const bool can_create = true; + ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_info, can_create, NULL); + if (dyld_sp.get()) { Target &target = m_process->GetTarget(); - const bool can_create = true; - ModuleSP exe_module_sp (FindTargetModuleForImageInfo (image_infos[i], can_create, NULL)); - - if (exe_module_sp) - { - UpdateImageLoadAddress (exe_module_sp.get(), image_infos[i]); - - if (exe_module_sp.get() != target.GetExecutableModulePointer()) - { - // Don't load dependent images since we are in dyld where we will know - // and find out about all images that are loaded. Also when setting the - // executable module, it will clear the targets module list, and if we - // have an in memory dyld module, it will get removed from the list - // so we will need to add it back after setting the executable module, - // so we first try and see if we already have a weak pointer to the - // dyld module, make it into a shared pointer, then add the executable, - // then re-add it back to make sure it is always in the list. - - const bool get_dependent_images = false; - m_process->GetTarget().SetExecutableModule (exe_module_sp, - get_dependent_images); - - UpdateDYLDImageInfoFromNewImageInfos (image_infos); - } - } + target.GetImages().AppendIfNeeded (dyld_sp); + UpdateImageLoadAddress (dyld_sp.get(), image_info); + SetDYLDModule (dyld_sp); } } } @@ -1141,3 +1211,57 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp, const ll return LLDB_INVALID_ADDRESS; } +bool +DynamicLoaderDarwin::UseDYLDSPI (Process *process) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + uint32_t major, minor, update; + + bool use_new_spi_interface = false; + + if (process->GetHostOSVersion (major, minor, update)) + { + const llvm::Triple::OSType os_type = process->GetTarget().GetArchitecture().GetTriple().getOS(); + + // macOS 10.12 and newer + if (os_type == llvm::Triple::MacOSX + && (major >= 10 || (major == 10 && minor >= 12))) + { + use_new_spi_interface = true; + } + + // iOS 10 and newer + if (os_type == llvm::Triple::IOS && major >= 10) + { + use_new_spi_interface = true; + } + + // tvOS 10 and newer + if (os_type == llvm::Triple::TvOS && major >= 10) + { + use_new_spi_interface = true; + } + + // watchOS 3 and newer + if (os_type == llvm::Triple::WatchOS && major >= 3) + { + use_new_spi_interface = true; + } + } + + + // FIXME: Temporarily force the use of the old DynamicLoader plugin until all + // the different use cases have been tested & the updated SPIs are available + // everywhere. + use_new_spi_interface = false; + + if (log) + { + if (use_new_spi_interface) + log->Printf ("DynamicLoaderDarwin::UseDYLDSPI: Use new DynamicLoader plugin"); + else + log->Printf ("DynamicLoaderDarwin::UseDYLDSPI: Use old DynamicLoader plugin"); + + } + return use_new_spi_interface; +} diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h index b7dd51d..9804218 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h @@ -26,6 +26,8 @@ #include "lldb/Target/Process.h" #include "lldb/Utility/SafeMachO.h" +#include "llvm/ADT/Triple.h" + namespace lldb_private { class DynamicLoaderDarwin : public lldb_private::DynamicLoader @@ -137,6 +139,8 @@ protected: llvm::MachO::mach_header header; // The mach header for this image std::vector segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) uint32_t load_stop_id; // The process stop ID that the sections for this image were loaded + llvm::Triple::OSType os_type; // LC_VERSION_MIN_... load command os type + std::string min_version_os_sdk; // LC_VERSION_MIN_... sdk value ImageInfo() : address(LLDB_INVALID_ADDRESS), @@ -146,7 +150,9 @@ protected: uuid(), header(), segments(), - load_stop_id(0) + load_stop_id(0), + os_type (llvm::Triple::OSType::UnknownOS), + min_version_os_sdk() { } @@ -164,6 +170,8 @@ protected: uuid.Clear(); segments.clear(); load_stop_id = 0; + os_type = llvm::Triple::OSType::UnknownOS; + min_version_os_sdk.clear(); } bool @@ -175,7 +183,8 @@ protected: && file_spec == rhs.file_spec && uuid == rhs.uuid && memcmp(&header, &rhs.header, sizeof(header)) == 0 - && segments == rhs.segments; + && segments == rhs.segments + && os_type == rhs.os_type; } bool @@ -220,9 +229,6 @@ protected: bool UnloadModuleSections (lldb_private::Module *module, ImageInfo& info); - ImageInfo * - FindImageInfoForAddress (lldb::addr_t load_address); - lldb::ModuleSP FindTargetModuleForImageInfo (ImageInfo &image_info, bool can_create, @@ -231,6 +237,9 @@ protected: void UnloadImages (const std::vector &solib_addresses); + void + UnloadAllImages (); + virtual bool SetNotificationBreakpoint () = 0; @@ -258,10 +267,10 @@ protected: bool JSONImageInformationIntoImageInfo (lldb_private::StructuredData::ObjectSP image_details, ImageInfo::collection &image_infos); - // If image_infos contains / may contain dyld image, call this method - // to keep our internal record keeping of the special dyld binary up-to-date. + // If image_infos contains / may contain dyld or executable image, call this method + // to keep our internal record keeping of the special binaries up-to-date. void - UpdateDYLDImageInfoFromNewImageInfos (ImageInfo::collection &image_infos); + UpdateSpecialBinariesFromNewImageInfos (ImageInfo::collection &image_infos); // if image_info is a dyld binary, call this method void @@ -275,7 +284,13 @@ protected: bool AddModulesUsingImageInfos (ImageInfo::collection &image_infos); - lldb::ModuleWP m_dyld_module_wp; + // Whether we should use the new dyld SPI to get shared library information, or read + // it directly out of the dyld_all_image_infos. Whether we use the (newer) DynamicLoaderMacOS + // plugin or the (older) DynamicLoaderMacOSX plugin. + static bool + UseDYLDSPI (lldb_private::Process *process); + + lldb::ModuleWP m_dyld_module_wp; // the dyld whose file type (mac, ios, etc) matches the process lldb::ModuleWP m_libpthread_module_wp; lldb_private::Address m_pthread_getspecific_addr; ThreadIDToTLSMap m_tid_to_tls_map; diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp new file mode 100644 index 0000000..bc1cc62 --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp @@ -0,0 +1,528 @@ +//===-- DynamicLoaderMacOS.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/State.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/StackFrame.h" + +#include "DynamicLoaderMacOS.h" +#include "DynamicLoaderDarwin.h" + +using namespace lldb; +using namespace lldb_private; + + +//---------------------------------------------------------------------- +// Create an instance of this class. This function is filled into +// the plugin info class that gets handed out by the plugin factory and +// allows the lldb to instantiate an instance of this class. +//---------------------------------------------------------------------- +DynamicLoader * +DynamicLoaderMacOS::CreateInstance (Process* process, bool force) +{ + bool create = force; + if (!create) + { + create = true; + Module* exe_module = process->GetTarget().GetExecutableModulePointer(); + if (exe_module) + { + ObjectFile *object_file = exe_module->GetObjectFile(); + if (object_file) + { + create = (object_file->GetStrata() == ObjectFile::eStrataUser); + } + } + + if (create) + { + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); + switch (triple_ref.getOS()) + { + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + case llvm::Triple::TvOS: + case llvm::Triple::WatchOS: + create = triple_ref.getVendor() == llvm::Triple::Apple; + break; + default: + create = false; + break; + } + } + } + + if (UseDYLDSPI (process) == false) + { + create = false; + } + + if (create) + return new DynamicLoaderMacOS (process); + return NULL; +} + +//---------------------------------------------------------------------- +// Constructor +//---------------------------------------------------------------------- +DynamicLoaderMacOS::DynamicLoaderMacOS (Process* process) : + DynamicLoaderDarwin(process), + m_image_infos_stop_id (UINT32_MAX), + m_break_id(LLDB_INVALID_BREAK_ID), + m_mutex() +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +DynamicLoaderMacOS::~DynamicLoaderMacOS() +{ + if (LLDB_BREAK_ID_IS_VALID(m_break_id)) + m_process->GetTarget().RemoveBreakpointByID (m_break_id); +} + +bool +DynamicLoaderMacOS::ProcessDidExec () +{ + std::lock_guard baseclass_guard(GetMutex()); + bool did_exec = false; + if (m_process) + { + // If we are stopped after an exec, we will have only one thread... + if (m_process->GetThreadList().GetSize() == 1) + { + // See if we are stopped at '_dyld_start' + ThreadSP thread_sp (m_process->GetThreadList().GetThreadAtIndex(0)); + if (thread_sp) + { + lldb::StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex(0)); + if (frame_sp) + { + const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; + if (symbol) + { + if (symbol->GetName() == ConstString("_dyld_start")) + did_exec = true; + } + } + } + + } + } + + if (did_exec) + { + m_libpthread_module_wp.reset(); + m_pthread_getspecific_addr.Clear(); + } + return did_exec; +} + +//---------------------------------------------------------------------- +// Clear out the state of this class. +//---------------------------------------------------------------------- +void +DynamicLoaderMacOS::DoClear () +{ + std::lock_guard guard(m_mutex); + + if (LLDB_BREAK_ID_IS_VALID(m_break_id)) + m_process->GetTarget().RemoveBreakpointByID (m_break_id); + + m_break_id = LLDB_INVALID_BREAK_ID; +} + +//---------------------------------------------------------------------- +// Check if we have found DYLD yet +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOS::DidSetNotificationBreakpoint() +{ + return LLDB_BREAK_ID_IS_VALID (m_break_id); +} + +void +DynamicLoaderMacOS::ClearNotificationBreakpoint () +{ + if (LLDB_BREAK_ID_IS_VALID (m_break_id)) + { + m_process->GetTarget().RemoveBreakpointByID (m_break_id); + } +} + +//---------------------------------------------------------------------- +// Try and figure out where dyld is by first asking the Process +// if it knows (which currently calls down in the lldb::Process +// to get the DYLD info (available on SnowLeopard only). If that fails, +// then check in the default addresses. +//---------------------------------------------------------------------- +void +DynamicLoaderMacOS::DoInitialImageFetch() +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + + StructuredData::ObjectSP all_image_info_json_sp (m_process->GetLoadedDynamicLibrariesInfos ()); + ImageInfo::collection image_infos; + if (all_image_info_json_sp.get() + && all_image_info_json_sp->GetAsDictionary() + && all_image_info_json_sp->GetAsDictionary()->HasKey("images") + && all_image_info_json_sp->GetAsDictionary()->GetValueForKey("images")->GetAsArray()) + { + if (JSONImageInformationIntoImageInfo (all_image_info_json_sp, image_infos)) + { + if (log) + log->Printf ("Initial module fetch: Adding %" PRId64 " modules.\n", (uint64_t) image_infos.size()); + + UpdateSpecialBinariesFromNewImageInfos (image_infos); + AddModulesUsingImageInfos (image_infos); + } + } + + m_dyld_image_infos_stop_id = m_process->GetStopID(); +} + +bool +DynamicLoaderMacOS::NeedToDoInitialImageFetch () +{ + return true; +} + +//---------------------------------------------------------------------- +// Static callback function that gets called when our DYLD notification +// breakpoint gets hit. We update all of our image infos and then +// let our super class DynamicLoader class decide if we should stop +// or not (based on global preference). +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOS::NotifyBreakpointHit (void *baton, + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) +{ + // Let the event know that the images have changed + // DYLD passes three arguments to the notification breakpoint. + // Arg1: enum dyld_notify_mode mode - 0 = adding, 1 = removing, 2 = remove all + // Arg2: unsigned long icount - Number of shared libraries added/removed + // Arg3: uint64_t mach_headers[] - Array of load addresses of binaries added/removed + + DynamicLoaderMacOS* dyld_instance = (DynamicLoaderMacOS*) baton; + + ExecutionContext exe_ctx (context->exe_ctx_ref); + Process *process = exe_ctx.GetProcessPtr(); + + // This is a sanity check just in case this dyld_instance is an old dyld plugin's breakpoint still lying around. + if (process != dyld_instance->m_process) + return false; + + if (dyld_instance->m_image_infos_stop_id != UINT32_MAX + && process->GetStopID() < dyld_instance->m_image_infos_stop_id) + { + return false; + } + + const lldb::ABISP &abi = process->GetABI(); + if (abi) + { + // Build up the value array to store the three arguments given above, then get the values from the ABI: + + ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); + ValueList argument_values; + + Value mode_value; // enum dyld_notify_mode { dyld_notify_adding=0, dyld_notify_removing=1, dyld_notify_remove_all=2 }; + Value count_value; // unsigned long count + Value headers_value; // uint64_t machHeaders[] (aka void*) + + CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + CompilerType clang_uint32_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32); + CompilerType clang_uint64_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32); + + mode_value.SetValueType (Value::eValueTypeScalar); + mode_value.SetCompilerType (clang_uint32_type); + + if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 4) + { + count_value.SetValueType (Value::eValueTypeScalar); + count_value.SetCompilerType (clang_uint32_type); + } + else + { + count_value.SetValueType (Value::eValueTypeScalar); + count_value.SetCompilerType (clang_uint64_type); + } + + headers_value.SetValueType (Value::eValueTypeScalar); + headers_value.SetCompilerType (clang_void_ptr_type); + + argument_values.PushValue (mode_value); + argument_values.PushValue (count_value); + argument_values.PushValue (headers_value); + + if (abi->GetArgumentValues (exe_ctx.GetThreadRef(), argument_values)) + { + uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1); + if (dyld_mode != static_cast(-1)) + { + // Okay the mode was right, now get the number of elements, and the array of new elements... + uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1); + if (image_infos_count != static_cast(-1)) + { + addr_t header_array = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(-1); + if (header_array != static_cast(-1)) + { + std::vector image_load_addresses; + for (uint64_t i = 0; i < image_infos_count ; i++) + { + Error error; + addr_t addr = process->ReadUnsignedIntegerFromMemory (header_array + (8 * i), 8, LLDB_INVALID_ADDRESS, error); + if (addr != LLDB_INVALID_ADDRESS) + { + image_load_addresses.push_back (addr); + } + } + if (dyld_mode == 0) + { + // dyld_notify_adding + dyld_instance->AddBinaries (image_load_addresses); + } + else if (dyld_mode == 1) + { + // dyld_notify_removing + dyld_instance->UnloadImages (image_load_addresses); + } + else if (dyld_mode == 2) + { + // dyld_notify_remove_all + dyld_instance->UnloadAllImages (); + } + } + } + } + } + } + else + { + process->GetTarget().GetDebugger().GetAsyncErrorStream()->Printf("No ABI plugin located for triple %s -- shared libraries will not be registered!\n", process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); + } + + // Return true to stop the target, false to just let the target run + return dyld_instance->GetStopWhenImagesChange(); +} + +void +DynamicLoaderMacOS::AddBinaries (const std::vector &load_addresses) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + ImageInfo::collection image_infos; + + if (log) + log->Printf ("Adding %" PRId64 " modules.", (uint64_t) load_addresses.size()); + StructuredData::ObjectSP binaries_info_sp = m_process->GetLoadedDynamicLibrariesInfos (load_addresses); + if (binaries_info_sp.get() + && binaries_info_sp->GetAsDictionary() + && binaries_info_sp->GetAsDictionary()->HasKey("images") + && binaries_info_sp->GetAsDictionary()->GetValueForKey("images")->GetAsArray() + && binaries_info_sp->GetAsDictionary()->GetValueForKey("images")->GetAsArray()->GetSize() == load_addresses.size()) + { + if (JSONImageInformationIntoImageInfo (binaries_info_sp, image_infos)) + { + UpdateSpecialBinariesFromNewImageInfos (image_infos); + AddModulesUsingImageInfos (image_infos); + } + m_dyld_image_infos_stop_id = m_process->GetStopID(); + } +} + + +// Dump the _dyld_all_image_infos members and all current image infos +// that we have parsed to the file handle provided. +//---------------------------------------------------------------------- +void +DynamicLoaderMacOS::PutToLog(Log *log) const +{ + if (log == NULL) + return; +} + +bool +DynamicLoaderMacOS::SetNotificationBreakpoint () +{ + if (m_break_id == LLDB_INVALID_BREAK_ID) + { + ConstString g_symbol_name ("_dyld_debugger_notification"); + const Symbol *symbol = nullptr; + ModuleSP dyld_sp (GetDYLDModule()); + if (dyld_sp) + { + symbol = dyld_sp->FindFirstSymbolWithNameAndType (g_symbol_name, eSymbolTypeCode); + } + if (symbol && (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) + { + addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&m_process->GetTarget()); + if (symbol_address != LLDB_INVALID_ADDRESS) + { + bool internal = true; + bool hardware = false; + Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get(); + breakpoint->SetCallback (DynamicLoaderMacOS::NotifyBreakpointHit, this, true); + breakpoint->SetBreakpointKind ("shared-library-event"); + m_break_id = breakpoint->GetID(); + } + } + } + return m_break_id != LLDB_INVALID_BREAK_ID; +} + + +addr_t +DynamicLoaderMacOS::GetDyldLockVariableAddressFromModule (Module *module) +{ + SymbolContext sc; + SymbolVendor *sym_vendor = module->GetSymbolVendor (); + Target &target = m_process->GetTarget (); + if (sym_vendor) + { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab) + { + std::vector match_indexes; + ConstString g_symbol_name ("_dyld_global_lock_held"); + uint32_t num_matches = 0; + num_matches = symtab->AppendSymbolIndexesWithName (g_symbol_name, match_indexes); + if (num_matches == 1) + { + Symbol *symbol = symtab->SymbolAtIndex (match_indexes[0]); + if (symbol && (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) + { + return symbol->GetAddressRef().GetOpcodeLoadAddress(&target); + } + } + } + } + return LLDB_INVALID_ADDRESS; +} + +// Look for this symbol: +// +// int __attribute__((visibility("hidden"))) _dyld_global_lock_held = 0; +// +// in libdyld.dylib. +Error +DynamicLoaderMacOS::CanLoadImage () +{ + Error error; + addr_t symbol_address = LLDB_INVALID_ADDRESS; + Target &target = m_process->GetTarget (); + const ModuleList &target_modules = target.GetImages(); + std::lock_guard guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + ConstString g_libdyld_name ("libdyld.dylib"); + + // Find any modules named "libdyld.dylib" and look for the symbol there first + for (size_t i = 0; i < num_modules; i++) + { + Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked (i); + if (module_pointer) + { + if (module_pointer->GetFileSpec().GetFilename() == g_libdyld_name) + { + symbol_address = GetDyldLockVariableAddressFromModule (module_pointer); + if (symbol_address != LLDB_INVALID_ADDRESS) + break; + } + } + } + + // Search through all modules looking for the symbol in them + if (symbol_address == LLDB_INVALID_ADDRESS) + { + for (size_t i = 0; i < num_modules; i++) + { + Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked (i); + if (module_pointer) + { + addr_t symbol_address = GetDyldLockVariableAddressFromModule (module_pointer); + if (symbol_address != LLDB_INVALID_ADDRESS) + break; + } + } + } + + // Default assumption is that it is OK to load images. + // Only say that we cannot load images if we find the symbol in libdyld and it indicates that + // we cannot. + + if (symbol_address != LLDB_INVALID_ADDRESS) + { + { + int lock_held = m_process->ReadUnsignedIntegerFromMemory (symbol_address, 4, 0, error); + if (lock_held != 0) + { + error.SetErrorToGenericError(); + } + } + } + return error; +} + +void +DynamicLoaderMacOS::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); +} + +void +DynamicLoaderMacOS::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + + +lldb_private::ConstString +DynamicLoaderMacOS::GetPluginNameStatic() +{ + static ConstString g_name("macos-dyld"); + return g_name; +} + +const char * +DynamicLoaderMacOS::GetPluginDescriptionStatic() +{ + return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes."; +} + + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +DynamicLoaderMacOS::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +DynamicLoaderMacOS::GetPluginVersion() +{ + return 1; +} diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h new file mode 100644 index 0000000..79eee51 --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h @@ -0,0 +1,129 @@ +//===-- DynamicLoaderMacOS.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / watchOS) +// platforms late 2016 and newer, where lldb will call dyld SPI functions to get +// information about shared libraries, information about the shared cache, and +// the _dyld_debugger_notification function we put a breakpoint on give us an +// array of load addresses for solibs loaded and unloaded. The SPI will tell us +// about both dyld and the executable, in addition to all of the usual solibs. + +#ifndef liblldb_DynamicLoaderMacOS_h_ +#define liblldb_DynamicLoaderMacOS_h_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/StructuredData.h" +#include "lldb/Core/UUID.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/SafeMachO.h" + +#include "DynamicLoaderDarwin.h" + +class DynamicLoaderMacOS : public lldb_private::DynamicLoaderDarwin +{ +public: + DynamicLoaderMacOS(lldb_private::Process *process); + + virtual ~DynamicLoaderMacOS() override; + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::ConstString + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + static lldb_private::DynamicLoader * + CreateInstance (lldb_private::Process *process, bool force); + + //------------------------------------------------------------------ + /// Called after attaching a process. + /// + /// Allow DynamicLoader plug-ins to execute some code after + /// attaching to a process. + //------------------------------------------------------------------ + bool + ProcessDidExec() override; + + lldb_private::Error + CanLoadImage() override; + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + +protected: + void + PutToLog(lldb_private::Log *log) const; + + void + DoInitialImageFetch () override; + + bool + NeedToDoInitialImageFetch () override; + + bool + DidSetNotificationBreakpoint () override; + + void + AddBinaries (const std::vector &load_addresses); + + void + DoClear () override; + + static bool + NotifyBreakpointHit (void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + bool + SetNotificationBreakpoint () override; + + void + ClearNotificationBreakpoint () override; + + void + UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, + uint32_t infos_count, + bool update_executable); + + lldb::addr_t + GetDyldLockVariableAddressFromModule (lldb_private::Module *module); + + uint32_t m_image_infos_stop_id; // The Stop ID the last time we loaded/unloaded images + lldb::user_id_t m_break_id; + mutable std::recursive_mutex m_mutex; + +private: + DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOS); +}; + +#endif // liblldb_DynamicLoaderMacOS_h_ diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index a8bc216..109abd0 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -89,6 +89,11 @@ DynamicLoaderMacOSXDYLD::CreateInstance (Process* process, bool force) } } } + + if (UseDYLDSPI (process) == true) + { + create = false; + } if (create) return new DynamicLoaderMacOSXDYLD (process); @@ -296,6 +301,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb:: { std::lock_guard baseclass_guard(GetMutex()); DataExtractor data; // Load command data + static ConstString g_dyld_all_image_infos ("dyld_all_image_infos"); if (ReadMachHeader (addr, &m_dyld.header, &data)) { if (m_dyld.header.filetype == llvm::MachO::MH_DYLINKER) @@ -316,7 +322,6 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb:: if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get()) { - static ConstString g_dyld_all_image_infos ("dyld_all_image_infos"); const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData); if (symbol) m_dyld_all_image_infos_addr = symbol->GetLoadAddress(&target); @@ -340,6 +345,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb:: target.ModulesDidLoad(modules); SetDYLDModule (dyld_module_sp); } + return true; } } @@ -592,7 +598,7 @@ DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_in bool return_value = false; if (JSONImageInformationIntoImageInfo (image_infos_json_sp, image_infos)) { - AddExecutableModuleIfInImageInfos (image_infos); + UpdateSpecialBinariesFromNewImageInfos (image_infos); return_value = AddModulesUsingImageInfos (image_infos); } m_dyld_image_infos_stop_id = m_process->GetStopID(); @@ -1105,7 +1111,7 @@ DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () bool resolved = m_process->GetTarget().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr); if (!resolved) { - ModuleSP dyld_module_sp = m_dyld_module_wp.lock(); + ModuleSP dyld_module_sp = GetDYLDModule(); if (dyld_module_sp) { std::lock_guard baseclass_guard(GetMutex()); diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h index 637bd86..81e16d1 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h @@ -7,6 +7,17 @@ // //===----------------------------------------------------------------------===// + +// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / watchOS) +// platforms earlier than 2016, where lldb would read the "dyld_all_image_infos" +// dyld internal structure to understand where things were loaded and the +// solib loaded/unloaded notification function we put a breakpoint on gives us +// an array of (load address, mod time, file path) tuples. +// +// As of late 2016, the new DynamicLoaderMacOS plugin should be used, which uses +// dyld SPI functions to get the same information without reading internal dyld +// data structures. + #ifndef liblldb_DynamicLoaderMacOSXDYLD_h_ #define liblldb_DynamicLoaderMacOSXDYLD_h_ diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 4d56f6e..728c512 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -4165,7 +4165,7 @@ ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid) StreamString packet; packet << "jThreadExtendedInfo:"; - args_dict->Dump (packet); + args_dict->Dump (packet, false); // FIXME the final character of a JSON dictionary, '}', is the escape // character in gdb-remote binary mode. lldb currently doesn't escape @@ -4194,6 +4194,44 @@ ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid) StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count) { + + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); + args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address); + args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count); + + return GetLoadedDynamicLibrariesInfos_sender (args_dict); +} + +StructuredData::ObjectSP +ProcessGDBRemote::GetLoadedDynamicLibrariesInfos () +{ + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); + + args_dict->GetAsDictionary()->AddBooleanItem ("fetch_all_solibs", true); + + return GetLoadedDynamicLibrariesInfos_sender (args_dict); +} + +StructuredData::ObjectSP +ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (const std::vector &load_addresses) +{ + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); + StructuredData::ArraySP addresses(new StructuredData::Array); + + for (auto addr : load_addresses) + { + StructuredData::ObjectSP addr_sp (new StructuredData::Integer (addr)); + addresses->AddItem (addr_sp); + } + + args_dict->GetAsDictionary()->AddItem ("solib_addresses", addresses); + + return GetLoadedDynamicLibrariesInfos_sender (args_dict); +} + +StructuredData::ObjectSP +ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args_dict) +{ StructuredData::ObjectSP object_sp; if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) @@ -4201,13 +4239,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres // Scope for the scoped timeout object GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10); - StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); - args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address); - args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count); - StreamString packet; packet << "jGetLoadedDynamicLibrariesInfos:"; - args_dict->Dump (packet); + args_dict->Dump (packet, false); // FIXME the final character of a JSON dictionary, '}', is the escape // character in gdb-remote binary mode. lldb currently doesn't escape @@ -4233,6 +4267,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres return object_sp; } + + + // Establish the largest memory read/write payloads we should use. // If the remote stub has a max packet size, stay under that size. // diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 6d373965..694e166 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -261,6 +261,15 @@ public: StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count) override; + StructuredData::ObjectSP + GetLoadedDynamicLibrariesInfos () override; + + StructuredData::ObjectSP + GetLoadedDynamicLibrariesInfos (const std::vector &load_addresses) override; + + StructuredData::ObjectSP + GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args); + protected: friend class ThreadGDBRemote; friend class GDBRemoteCommunicationClient; diff --git a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj index 295a2bf..18b986a 100644 --- a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj +++ b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj @@ -610,6 +610,7 @@ "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression"; LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1"; LLDB_ZLIB_LDFLAGS = "-lz"; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; STRIP_INSTALLED_PRODUCT = NO; @@ -651,6 +652,7 @@ "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression"; LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1"; LLDB_ZLIB_LDFLAGS = "-lz"; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; STRIPFLAGS = "-x"; @@ -690,6 +692,7 @@ "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression"; LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1"; LLDB_ZLIB_LDFLAGS = "-lz"; + MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CFLAGS = ""; STRIPFLAGS = "-x"; STRIP_STYLE = debugging; @@ -1317,6 +1320,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; "SDKROOT[arch=i386]" = macosx; @@ -1455,6 +1459,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; "SDKROOT[arch=i386]" = macosx; @@ -1672,6 +1677,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; "SDKROOT[arch=i386]" = macosx; @@ -1800,6 +1806,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; "SDKROOT[arch=i386]" = macosx;