diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
| commit | f73363f1dd94996356cefbf24388f561891acf0b (patch) | |
| tree | e3c31248bdb36eaec5fd833490d4278162dba2a0 /source/Plugins/Platform | |
| parent | 160ee69dd7ae18978f4068116777639ea98dc951 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Platform')
32 files changed, 917 insertions, 774 deletions
diff --git a/source/Plugins/Platform/Android/AdbClient.cpp b/source/Plugins/Platform/Android/AdbClient.cpp index 6e15eb2b1dcb..4cd8c645dd76 100644 --- a/source/Plugins/Platform/Android/AdbClient.cpp +++ b/source/Plugins/Platform/Android/AdbClient.cpp @@ -165,8 +165,8 @@ Status AdbClient::GetDevices(DeviceIDList &device_list) { for (const auto device : devices) device_list.push_back(device.split('\t').first); - // Force disconnect since ADB closes connection after host:devices - // response is sent. + // Force disconnect since ADB closes connection after host:devices response + // is sent. m_conn.reset(); return error; } diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp index 5b85bcdf7fdd..1cedcde97a92 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -83,9 +83,9 @@ PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) { break; #if defined(__ANDROID__) - // Only accept "unknown" for the vendor if the host is android and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified_ + // Only accept "unknown" for the vendor if the host is android and it + // "unknown" wasn't specified (it was just returned because it was NOT + // specified_ case llvm::Triple::VendorType::UnknownVendor: create = !arch->TripleVendorWasSpecified(); break; @@ -100,9 +100,9 @@ PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) { break; #if defined(__ANDROID__) - // Only accept "unknown" for the OS if the host is android and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is android and it + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::OSType::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -193,8 +193,7 @@ Status PlatformAndroid::GetFile(const FileSpec &source, if (IsHost() || !m_remote_platform_sp) return PlatformLinux::GetFile(source, destination); - FileSpec source_spec(source.GetPath(false), false, - FileSpec::ePathSyntaxPosix); + FileSpec source_spec(source.GetPath(false), false, FileSpec::Style::posix); if (source_spec.IsRelative()) source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( source_spec.GetCString(false)); @@ -222,8 +221,8 @@ Status PlatformAndroid::GetFile(const FileSpec &source, if (strchr(source_file, '\'') != nullptr) return Status("Doesn't support single-quotes in filenames"); - // mode == 0 can signify that adbd cannot access the file - // due security constraints - try "cat ..." as a fallback. + // mode == 0 can signify that adbd cannot access the file due security + // constraints - try "cat ..." as a fallback. AdbClient adb(m_device_id); char cmd[PATH_MAX]; @@ -239,7 +238,7 @@ Status PlatformAndroid::PutFile(const FileSpec &source, return PlatformLinux::PutFile(source, destination, uid, gid); FileSpec destination_spec(destination.GetPath(false), false, - FileSpec::ePathSyntaxPosix); + FileSpec::Style::posix); if (destination_spec.IsRelative()) destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( destination_spec.GetCString(false)); @@ -306,7 +305,7 @@ Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) { // For oat file we can try to fetch additional debug info from the device ConstString extension = module_sp->GetFileSpec().GetFileNameExtension(); - if (extension != ConstString("oat") && extension != ConstString("odex")) + if (extension != ConstString(".oat") && extension != ConstString(".odex")) return Status( "Symbol file downloading only supported for oat and odex files"); @@ -361,10 +360,8 @@ Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp, } bool PlatformAndroid::GetRemoteOSVersion() { - m_major_os_version = GetSdkVersion(); - m_minor_os_version = 0; - m_update_os_version = 0; - return m_major_os_version != 0; + m_os_version = llvm::VersionTuple(GetSdkVersion()); + return !m_os_version.empty(); } llvm::StringRef diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp index dbc74833e287..2415da31daf0 100644 --- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp @@ -180,9 +180,9 @@ Status PlatformAndroidRemoteGDBServer::MakeConnectURL( static const int kAttempsNum = 5; Status error; - // There is a race possibility that somebody will occupy - // a port while we're in between FindUnusedPort and ForwardPortWithAdb - - // adding the loop to mitigate such problem. + // There is a race possibility that somebody will occupy a port while we're + // in between FindUnusedPort and ForwardPortWithAdb - adding the loop to + // mitigate such problem. for (auto i = 0; i < kAttempsNum; ++i) { uint16_t local_port = 0; error = FindUnusedPort(local_port); @@ -208,10 +208,9 @@ lldb::ProcessSP PlatformAndroidRemoteGDBServer::ConnectProcess( lldb_private::Debugger &debugger, lldb_private::Target *target, lldb_private::Status &error) { // We don't have the pid of the remote gdbserver when it isn't started by us - // but we still want - // to store the list of port forwards we set up in our port forward map. - // Generate a fake pid for - // these cases what won't collide with any other valid pid on android. + // but we still want to store the list of port forwards we set up in our port + // forward map. Generate a fake pid for these cases what won't collide with + // any other valid pid on android. static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL; int remote_port; diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 73c7d21f0a06..bc8111d1078b 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -32,8 +32,8 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" -// Define these constants from FreeBSD mman.h for use when targeting -// remote FreeBSD systems even when host has different values. +// Define these constants from FreeBSD mman.h for use when targeting remote +// FreeBSD systems even when host has different values. #define MAP_PRIVATE 0x0002 #define MAP_ANON 0x1000 @@ -60,9 +60,8 @@ PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) { break; #if defined(__FreeBSD__) - // Only accept "unknown" for the OS if the host is BSD and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is BSD and it "unknown" + // wasn't specified (it was just returned because it was NOT specified) case llvm::Triple::OSType::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -143,7 +142,8 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx, arch = hostArch; return arch.IsValid(); } else if (idx == 1) { - // If the default host architecture is 64-bit, look for a 32-bit variant + // If the default host architecture is 64-bit, look for a 32-bit + // variant if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) { arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); return arch.IsValid(); @@ -187,13 +187,10 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx, return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the - // vendor by - // calling triple.SetVendorName("unknown") so that it is a "unspecified - // unknown". - // This means when someone calls triple.GetVendorName() it will return an - // empty string - // which indicates that the vendor can be set when two architectures are - // merged + // vendor by calling triple.SetVendorName("unknown") so that it is a + // "unspecified unknown". This means when someone calls + // triple.GetVendorName() it will return an empty string which indicates + // that the vendor can be set when two architectures are merged // Now set the triple into "arch" and return true arch.SetTriple(triple); @@ -228,16 +225,16 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target, switch (target.GetArchitecture().GetMachine()) { case llvm::Triple::arm: { lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); - AddressClass addr_class = eAddressClassUnknown; + AddressClass addr_class = AddressClass::eUnknown; if (bp_loc_sp) { addr_class = bp_loc_sp->GetAddress().GetAddressClass(); - if (addr_class == eAddressClassUnknown && + if (addr_class == AddressClass::eUnknown && (bp_loc_sp->GetAddress().GetFileAddress() & 1)) - addr_class = eAddressClassCodeAlternateISA; + addr_class = AddressClass::eCodeAlternateISA; } - if (addr_class == eAddressClassCodeAlternateISA) { + if (addr_class == AddressClass::eCodeAlternateISA) { // TODO: Enable when FreeBSD supports thumb breakpoints. // FreeBSD kernel as of 10.x, does not support thumb breakpoints return 0; @@ -286,9 +283,9 @@ lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); - // The freebsd always currently uses the GDB remote debugger plug-in - // so even when debugging locally we are debugging remotely! - // Just like the darwin plugin. + // The freebsd always currently uses the GDB remote debugger plug-in so + // even when debugging locally we are debugging remotely! Just like the + // darwin plugin. process_sp = target->CreateProcess( attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp index 8186eae0e8c4..dbde91d7ab2d 100644 --- a/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -30,8 +30,8 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" -// Define these constants from Linux mman.h for use when targeting -// remote linux systems even when host has different values. +// Define these constants from Linux mman.h for use when targeting remote linux +// systems even when host has different values. #define MAP_PRIVATE 2 #define MAP_ANON 0x20 @@ -58,9 +58,8 @@ PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) { break; #if defined(__linux__) - // Only accept "unknown" for the OS if the host is linux and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is linux and it "unknown" + // wasn't specified (it was just returned because it was NOT specified) case llvm::Triple::OSType::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -142,7 +141,8 @@ bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx, arch = hostArch; return arch.IsValid(); } else if (idx == 1) { - // If the default host architecture is 64-bit, look for a 32-bit variant + // If the default host architecture is 64-bit, look for a 32-bit + // variant if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) { arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); return arch.IsValid(); @@ -192,13 +192,10 @@ bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx, return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the - // vendor by - // calling triple.SetVendorName("unknown") so that it is a "unspecified - // unknown". - // This means when someone calls triple.GetVendorName() it will return an - // empty string - // which indicates that the vendor can be set when two architectures are - // merged + // vendor by calling triple.SetVendorName("unknown") so that it is a + // "unspecified unknown". This means when someone calls + // triple.GetVendorName() it will return an empty string which indicates + // that the vendor can be set when two architectures are merged // Now set the triple into "arch" and return true arch.SetTriple(triple); @@ -212,8 +209,8 @@ void PlatformLinux::GetStatus(Stream &strm) { #ifndef LLDB_DISABLE_POSIX // Display local kernel information only when we are running in host mode. - // Otherwise, we would end up printing non-Linux information (when running - // on Mac OS for example). + // Otherwise, we would end up printing non-Linux information (when running on + // Mac OS for example). if (IsHost()) { struct utsname un; @@ -272,8 +269,8 @@ bool PlatformLinux::CanDebugProcess() { } // For local debugging, Linux will override the debug logic to use llgs-launch -// rather than lldb-launch, llgs-attach. This differs from current lldb-launch, -// debugserver-attach approach on MacOSX. +// rather than lldb-launch, llgs-attach. This differs from current lldb- +// launch, debugserver-attach approach on MacOSX. lldb::ProcessSP PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new @@ -297,8 +294,8 @@ PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, launch_info.GetFlags().Set(eLaunchFlagDebug); // We always launch the process we are going to debug in a separate process - // group, since then we can handle ^C interrupts ourselves w/o having to worry - // about the target getting them as well. + // group, since then we can handle ^C interrupts ourselves w/o having to + // worry about the target getting them as well. launch_info.SetLaunchInSeparateProcessGroup(true); // Ensure we have a target. diff --git a/source/Plugins/Platform/MacOSX/CMakeLists.txt b/source/Plugins/Platform/MacOSX/CMakeLists.txt index f8d911b321f8..f9663559069a 100644 --- a/source/Plugins/Platform/MacOSX/CMakeLists.txt +++ b/source/Plugins/Platform/MacOSX/CMakeLists.txt @@ -11,13 +11,14 @@ list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES list(APPEND PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES PlatformAppleSimulator.cpp PlatformiOSSimulator.cpp - PlatformiOSSimulatorCoreSimulatorSupport.mm PlatformAppleTVSimulator.cpp PlatformAppleWatchSimulator.cpp ) if(CMAKE_SYSTEM_NAME MATCHES "Darwin") include_directories(${LIBXML2_INCLUDE_DIR}) + add_subdirectory(objcxx) + set(OBJC_LIBS "lldbPluginPlatformMacOSXObjCXX") list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES ${PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES}) else() @@ -38,6 +39,7 @@ add_lldb_library(lldbPluginPlatformMacOSX PLUGIN lldbTarget lldbUtility lldbPluginPlatformPOSIX + ${OBJC_LIBS} LINK_COMPONENTS Support ) diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp index a216e3839dd9..6852097117a1 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp @@ -84,8 +84,8 @@ lldb_private::Status PlatformAppleSimulator::LaunchProcess( void PlatformAppleSimulator::GetStatus(Stream &strm) { #if defined(__APPLE__) - // This will get called by subclasses, so just output status on the - // current simulator + // This will get called by subclasses, so just output status on the current + // simulator PlatformAppleSimulator::LoadCoreSimulator(); CoreSimulatorSupport::DeviceSet devices = @@ -183,8 +183,8 @@ lldb::ProcessSP PlatformAppleSimulator::DebugProcess( // Make sure we stop at the entry point launch_info.GetFlags().Set(eLaunchFlagDebug); // We always launch the process we are going to debug in a separate process - // group, since then we can handle ^C interrupts ourselves w/o having to worry - // about the target getting them as well. + // group, since then we can handle ^C interrupts ourselves w/o having to + // worry about the target getting them as well. launch_info.SetLaunchInSeparateProcessGroup(true); error = LaunchProcess(launch_info); @@ -201,10 +201,10 @@ lldb::ProcessSP PlatformAppleSimulator::DebugProcess( // process if this happens. process_sp->SetShouldDetach(false); - // If we didn't have any file actions, the pseudo terminal might - // have been used where the slave side was given as the file to - // open for stdin/out/err after we have already opened the master - // so we can read/write stdin/out/err. + // If we didn't have any file actions, the pseudo terminal might have + // been used where the slave side was given as the file to open for + // stdin/out/err after we have already opened the master so we can + // read/write stdin/out/err. int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h index 44feb019dc73..2536854e9630 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h +++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h @@ -16,8 +16,8 @@ // Other libraries and framework includes // Project includes -#include "PlatformDarwin.h" -#include "PlatformiOSSimulatorCoreSimulatorSupport.h" +#include "Plugins/Platform/MacOSX/PlatformDarwin.h" +#include "Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h" #include "lldb/Utility/FileSpec.h" #include "llvm/ADT/Optional.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp index e0558f8b200e..e55cc0f4f6a4 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp @@ -90,9 +90,9 @@ PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force, break; #if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the vendor if the host is Apple and it + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; @@ -107,9 +107,9 @@ PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force, break; #if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is Apple and it + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -199,9 +199,9 @@ Status PlatformAppleTVSimulator::ResolveExecutable( return error; exe_module_sp.reset(); } - // No valid architecture was specified or the exact ARM slice wasn't - // found so ask the platform for the architectures that we should be - // using (in the correct order) and see if we can find a match that way + // No valid architecture was specified or the exact ARM slice wasn't found + // so ask the platform for the architectures that we should be using (in + // the correct order) and see if we can find a match that way StreamString arch_names; ArchSpec platform_arch; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( @@ -293,8 +293,8 @@ const char *PlatformAppleTVSimulator::GetSDKDirectoryAsCString() { m_sdk_directory.assign(1, '\0'); } - // We should have put a single NULL character into m_sdk_directory - // or it should have a valid path if the code gets here + // We should have put a single NULL character into m_sdk_directory or it + // should have a valid path if the code gets here assert(m_sdk_directory.empty() == false); if (m_sdk_directory[0]) return m_sdk_directory.c_str(); @@ -315,12 +315,12 @@ Status PlatformAppleTVSimulator::GetSymbolFile(const FileSpec &platform_file, platform_file_path); // First try in the SDK and see if the file is in there - local_file.SetFile(resolved_path, true); + local_file.SetFile(resolved_path, true, FileSpec::Style::native); if (local_file.Exists()) return error; // Else fall back to the actual path itself - local_file.SetFile(platform_file_path, true); + local_file.SetFile(platform_file_path, true, FileSpec::Style::native); if (local_file.Exists()) return error; } @@ -337,10 +337,9 @@ Status PlatformAppleTVSimulator::GetSharedModule( const ModuleSpec &module_spec, lldb_private::Process *process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - // For AppleTV, the SDK files are all cached locally on the host - // system. So first we ask for the file in the cached SDK, - // then we attempt to get a shared module for the right architecture - // with the right UUID. + // For AppleTV, the SDK files are all cached locally on the host system. So + // first we ask for the file in the cached SDK, then we attempt to get a + // shared module for the right architecture with the right UUID. Status error; ModuleSpec platform_module_spec(module_spec); const FileSpec &platform_file = module_spec.GetFileSpec(); diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp index 9b2608f68625..8bbe0af0aec2 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp @@ -89,9 +89,9 @@ PlatformSP PlatformAppleWatchSimulator::CreateInstance(bool force, break; #if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the vendor if the host is Apple and it + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; @@ -106,9 +106,9 @@ PlatformSP PlatformAppleWatchSimulator::CreateInstance(bool force, break; #if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is Apple and it + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -199,9 +199,9 @@ Status PlatformAppleWatchSimulator::ResolveExecutable( return error; exe_module_sp.reset(); } - // No valid architecture was specified or the exact ARM slice wasn't - // found so ask the platform for the architectures that we should be - // using (in the correct order) and see if we can find a match that way + // No valid architecture was specified or the exact ARM slice wasn't found + // so ask the platform for the architectures that we should be using (in + // the correct order) and see if we can find a match that way StreamString arch_names; ArchSpec platform_arch; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( @@ -293,8 +293,8 @@ const char *PlatformAppleWatchSimulator::GetSDKDirectoryAsCString() { m_sdk_directory.assign(1, '\0'); } - // We should have put a single NULL character into m_sdk_directory - // or it should have a valid path if the code gets here + // We should have put a single NULL character into m_sdk_directory or it + // should have a valid path if the code gets here assert(m_sdk_directory.empty() == false); if (m_sdk_directory[0]) return m_sdk_directory.c_str(); @@ -315,12 +315,12 @@ Status PlatformAppleWatchSimulator::GetSymbolFile(const FileSpec &platform_file, platform_file_path); // First try in the SDK and see if the file is in there - local_file.SetFile(resolved_path, true); + local_file.SetFile(resolved_path, true, FileSpec::Style::native); if (local_file.Exists()) return error; // Else fall back to the actual path itself - local_file.SetFile(platform_file_path, true); + local_file.SetFile(platform_file_path, true, FileSpec::Style::native); if (local_file.Exists()) return error; } @@ -337,10 +337,9 @@ Status PlatformAppleWatchSimulator::GetSharedModule( const ModuleSpec &module_spec, lldb_private::Process *process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - // For AppleWatch, the SDK files are all cached locally on the host - // system. So first we ask for the file in the cached SDK, - // then we attempt to get a shared module for the right architecture - // with the right UUID. + // For AppleWatch, the SDK files are all cached locally on the host system. + // So first we ask for the file in the cached SDK, then we attempt to get a + // shared module for the right architecture with the right UUID. Status error; ModuleSpec platform_module_spec(module_spec); const FileSpec &platform_file = module_spec.GetFileSpec(); diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index b04d72f755f6..886e3b6d9a05 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -16,8 +16,6 @@ #include <algorithm> #include <mutex> -// Other libraries and framework includes -#include "clang/Basic/VersionTuple.h" // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointSite.h" @@ -42,6 +40,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Threading.h" +#include "llvm/Support/VersionTuple.h" #if defined(__APPLE__) #include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH @@ -73,10 +72,9 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources( // NB some extensions might be meaningful and should not be stripped - // "this.binary.file" // should not lose ".file" but GetFileNameStrippingExtension() will do - // precisely that. - // Ideally, we should have a per-platform list of extensions (".exe", - // ".app", ".dSYM", ".framework") - // which should be stripped while leaving "this.binary.file" as-is. + // precisely that. Ideally, we should have a per-platform list of + // extensions (".exe", ".app", ".dSYM", ".framework") which should be + // stripped while leaving "this.binary.file" as-is. ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); @@ -101,14 +99,11 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources( // FIXME: for Python, we cannot allow certain characters in // module // filenames we import. Theoretically, different scripting - // languages may - // have different sets of forbidden tokens in filenames, and - // that should - // be dealt with by each ScriptInterpreter. For now, we just - // replace dots - // with underscores, but if we ever support anything other than - // Python - // we will need to rework this + // languages may have different sets of forbidden tokens in + // filenames, and that should be dealt with by each + // ScriptInterpreter. For now, we just replace dots with + // underscores, but if we ever support anything other than + // Python we will need to rework this std::replace(module_basename.begin(), module_basename.end(), '.', '_'); std::replace(module_basename.begin(), module_basename.end(), @@ -125,9 +120,9 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources( StreamString path_string; StreamString original_path_string; // for OSX we are going to be in - // .dSYM/Contents/Resources/DWARF/<basename> - // let us go to .dSYM/Contents/Resources/Python/<basename>.py - // and see if the file exists + // .dSYM/Contents/Resources/DWARF/<basename> let us go to + // .dSYM/Contents/Resources/Python/<basename>.py and see if the + // file exists path_string.Printf("%s/../Python/%s.py", symfile_spec.GetDirectory().GetCString(), module_basename.c_str()); @@ -140,9 +135,8 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources( true); // if we did some replacements of reserved characters, and a - // file with the untampered name - // exists, then warn the user that the file as-is shall not be - // loaded + // file with the untampered name exists, then warn the user + // that the file as-is shall not be loaded if (feedback_stream) { if (module_basename != original_module_basename && orig_script_fspec.Exists()) { @@ -178,8 +172,8 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources( break; } - // If we didn't find the python file, then keep - // stripping the extensions and try again + // If we didn't find the python file, then keep stripping the + // extensions and try again ConstString filename_no_extension( module_spec.GetFileNameStrippingExtension()); if (module_spec.GetFilename() == filename_no_extension) @@ -270,8 +264,8 @@ lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache( FileSpec module_cache_spec(cache_path, false); // if rsync is supported, always bring in the file - rsync will be very - // efficient - // when files are the same on the local and remote end of the connection + // efficient when files are the same on the local and remote end of the + // connection if (this->GetSupportsRSync()) { err = BringInRemoteFile(this, module_spec, module_cache_spec); if (err.Fail()) @@ -370,8 +364,8 @@ Status PlatformDarwin::GetSharedModule( module_sp.reset(); if (IsRemote()) { - // If we have a remote platform always, let it try and locate - // the shared module first. + // 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( module_spec, process, module_sp, module_search_paths_ptr, @@ -453,8 +447,8 @@ PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target, switch (machine) { case llvm::Triple::aarch64: { // TODO: fix this with actual darwin breakpoint opcode for arm64. - // right now debugging uses the Z packets with GDB remote so this - // is not needed, but the size needs to be correct... + // right now debugging uses the Z packets with GDB remote so this is not + // needed, but the size needs to be correct... static const uint8_t g_arm64_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7}; trap_opcode = g_arm64_breakpoint_opcode; trap_opcode_size = sizeof(g_arm64_breakpoint_opcode); @@ -472,7 +466,7 @@ PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target, lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); if (bp_loc_sp) bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() == - eAddressClassCodeAlternateISA; + AddressClass::eCodeAlternateISA; } if (bp_is_thumb) { trap_opcode = g_thumb_breakpooint_opcode; @@ -548,8 +542,8 @@ bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx, HostInfo::GetArchitecture(HostInfo::eArchKind64)); if (platform_arch.IsExactMatch(platform_arch64)) { // This macosx platform supports both 32 and 64 bit. Since we already - // returned the 64 bit arch for idx == 0, return the 32 bit arch - // for idx == 1 + // returned the 64 bit arch for idx == 0, return the 32 bit arch for + // idx == 1 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); return arch.IsValid(); } @@ -558,9 +552,9 @@ bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx, return false; } -// The architecture selection rules for arm processors -// These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run -// fine on an armv7f processor. +// The architecture selection rules for arm processors These cpu subtypes have +// distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f +// processor. bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) { @@ -1138,14 +1132,15 @@ const char *PlatformDarwin::GetDeveloperDirectory() { if (m_developer_directory.empty()) { bool developer_dir_path_valid = false; char developer_dir_path[PATH_MAX]; - FileSpec temp_file_spec; // Get the lldb framework's file path, and if it exists, truncate some // components to only the developer directory path. - if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, temp_file_spec)) { + FileSpec temp_file_spec = HostInfo::GetShlibDir(); + if (temp_file_spec) { if (temp_file_spec.GetPath(developer_dir_path, sizeof(developer_dir_path))) { - // e.g. /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework + // e.g. + // /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework char *shared_frameworks = strstr(developer_dir_path, "/SharedFrameworks/LLDB.framework"); if (shared_frameworks) { @@ -1153,7 +1148,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() { strncat (developer_dir_path, "/Developer", sizeof (developer_dir_path) - 1); // add /Developer on developer_dir_path_valid = true; } else { - // e.g. /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework + // e.g. + // /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework char *developer_toolchains = strstr(developer_dir_path, "/Contents/Developer/Toolchains/"); if (developer_toolchains) { @@ -1171,7 +1167,7 @@ const char *PlatformDarwin::GetDeveloperDirectory() { if (xcode_select_prefix_dir) xcode_dir_path.append(xcode_select_prefix_dir); xcode_dir_path.append("/usr/share/xcode-select/xcode_dir_path"); - temp_file_spec.SetFile(xcode_dir_path, false); + temp_file_spec.SetFile(xcode_dir_path, false, FileSpec::Style::native); auto dir_buffer = DataBufferLLVM::CreateFromPath(temp_file_spec.GetPath()); if (dir_buffer && dir_buffer->GetByteSize() > 0) { @@ -1196,7 +1192,7 @@ const char *PlatformDarwin::GetDeveloperDirectory() { Host::RunShellCommand("/usr/bin/xcode-select --print-path", NULL, // current working directory &exit_status, &signo, &command_output, - 2, // short timeout + std::chrono::seconds(2), // short timeout false); // don't run in a shell if (error.Success() && exit_status == 0 && !command_output.empty()) { const char *cmd_output_ptr = command_output.c_str(); @@ -1219,7 +1215,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() { } if (developer_dir_path_valid) { - temp_file_spec.SetFile(developer_dir_path, false); + temp_file_spec.SetFile(developer_dir_path, false, + FileSpec::Style::native); if (temp_file_spec.Exists()) { m_developer_directory.assign(developer_dir_path); return m_developer_directory.c_str(); @@ -1230,8 +1227,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() { m_developer_directory.assign(1, '\0'); } - // We should have put a single NULL character into m_developer_directory - // or it should have a valid path if the code gets here + // We should have put a single NULL character into m_developer_directory or + // it should have a valid path if the code gets here assert(m_developer_directory.empty() == false); if (m_developer_directory[0]) return m_developer_directory.c_str(); @@ -1279,17 +1276,11 @@ PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { shell_name++; if (strcmp(shell_name, "sh") == 0) { - // /bin/sh re-exec's itself as /bin/bash requiring another resume. - // But it only does this if the COMMAND_MODE environment variable - // is set to "legacy". - const char **envp = - launch_info.GetEnvironmentEntries().GetConstArgumentVector(); - if (envp != NULL) { - for (int i = 0; envp[i] != NULL; i++) { - if (strcmp(envp[i], "COMMAND_MODE=legacy") == 0) - return 2; - } - } + // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it + // only does this if the COMMAND_MODE environment variable is set to + // "legacy". + if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy") + return 2; return 1; } else if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 || @@ -1310,7 +1301,7 @@ static const char *const sdk_strings[] = { static FileSpec CheckPathForXcode(const FileSpec &fspec) { if (fspec.Exists()) { - const char substr[] = ".app/Contents/"; + const char substr[] = ".app/Contents"; std::string path_to_shlib = fspec.GetPath(); size_t pos = path_to_shlib.rfind(substr); @@ -1339,9 +1330,8 @@ static FileSpec GetXcodeContentsPath() { // First get the program file spec. If lldb.so or LLDB.framework is running // in a program and that program is Xcode, the path returned with be the - // path - // to Xcode.app/Contents/MacOS/Xcode, so this will be the correct Xcode to - // use. + // path to Xcode.app/Contents/MacOS/Xcode, so this will be the correct + // Xcode to use. fspec = HostInfo::GetProgramFileSpec(); if (fspec) { @@ -1375,7 +1365,7 @@ static FileSpec GetXcodeContentsPath() { &signo, // Put the signal that caused the process to exit in here &output, // Get the output from the command and place it in this // string - 3); // Timeout in seconds to wait for shell program to finish + std::chrono::seconds(3)); if (status == 0 && !output.empty()) { size_t first_non_newline = output.find_last_not_of("\r\n"); if (first_non_newline != std::string::npos) { @@ -1392,18 +1382,14 @@ static FileSpec GetXcodeContentsPath() { return g_xcode_filespec; } -bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, uint32_t major, - uint32_t minor, uint32_t micro) { +bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, + llvm::VersionTuple version) { switch (sdk_type) { case SDKType::MacOSX: - if (major > 10 || (major == 10 && minor >= 10)) - return true; - break; + return version >= llvm::VersionTuple(10, 10); case SDKType::iPhoneOS: case SDKType::iPhoneSimulator: - if (major >= 8) - return true; - break; + return version >= llvm::VersionTuple(8); } return false; @@ -1425,32 +1411,10 @@ bool PlatformDarwin::SDKSupportsModules(SDKType desired_type, return false; } - const size_t major_dot_offset = version_part.find('.'); - if (major_dot_offset == llvm::StringRef::npos) - return false; - - const llvm::StringRef major_version = - version_part.slice(0, major_dot_offset); - const llvm::StringRef minor_part = - version_part.drop_front(major_dot_offset + 1); - - const size_t minor_dot_offset = minor_part.find('.'); - if (minor_dot_offset == llvm::StringRef::npos) - return false; - - const llvm::StringRef minor_version = minor_part.slice(0, minor_dot_offset); - - unsigned int major = 0; - unsigned int minor = 0; - unsigned int micro = 0; - - if (major_version.getAsInteger(10, major)) - return false; - - if (minor_version.getAsInteger(10, minor)) + llvm::VersionTuple version; + if (version.tryParse(version_part)) return false; - - return SDKSupportsModules(desired_type, major, minor, micro); + return SDKSupportsModules(desired_type, version); } return false; @@ -1522,18 +1486,17 @@ FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) { sdks_spec.AppendPathComponent("SDKs"); if (sdk_type == SDKType::MacOSX) { - uint32_t major = 0; - uint32_t minor = 0; - uint32_t micro = 0; + llvm::VersionTuple version = HostInfo::GetOSVersion(); - if (HostInfo::GetOSVersion(major, minor, micro)) { - if (SDKSupportsModules(SDKType::MacOSX, major, minor, micro)) { + if (!version.empty()) { + if (SDKSupportsModules(SDKType::MacOSX, version)) { // We slightly prefer the exact SDK for this machine. See if it is // there. FileSpec native_sdk_spec = sdks_spec; StreamString native_sdk_name; - native_sdk_name.Printf("MacOSX%u.%u.sdk", major, minor); + native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(), + version.getMinor().getValueOr(0)); native_sdk_spec.AppendPathComponent(native_sdk_name.GetString()); if (native_sdk_spec.Exists()) { @@ -1546,14 +1509,14 @@ FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) { return FindSDKInXcodeForModules(sdk_type, sdks_spec); } -std::tuple<uint32_t, uint32_t, uint32_t, llvm::StringRef> +std::tuple<llvm::VersionTuple, llvm::StringRef> PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) { - uint32_t major, minor, update; llvm::StringRef build; llvm::StringRef version_str; llvm::StringRef build_str; std::tie(version_str, build_str) = dir.split(' '); - if (Args::StringToVersion(version_str, major, minor, update) || + llvm::VersionTuple version; + if (!version.tryParse(version_str) || build_str.empty()) { if (build_str.consume_front("(")) { size_t pos = build_str.find(')'); @@ -1561,7 +1524,7 @@ PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) { } } - return std::make_tuple(major, minor, update, build); + return std::make_tuple(version, build); } void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( @@ -1573,7 +1536,6 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( options.insert(options.end(), apple_arguments.begin(), apple_arguments.end()); StreamString minimum_version_option; - uint32_t versions[3] = {0, 0, 0}; bool use_current_os_version = false; switch (sdk_type) { case SDKType::iPhoneOS: @@ -1597,9 +1559,9 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( break; } - bool versions_valid = false; + llvm::VersionTuple version; if (use_current_os_version) - versions_valid = GetOSVersion(versions[0], versions[1], versions[2]); + version = GetOSVersion(); else if (target) { // Our OS doesn't match our executable so we need to get the min OS version // from the object file @@ -1607,35 +1569,23 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( if (exe_module_sp) { ObjectFile *object_file = exe_module_sp->GetObjectFile(); if (object_file) - versions_valid = object_file->GetMinimumOSVersion(versions, 3) > 0; + version = object_file->GetMinimumOSVersion(); } } // Only add the version-min options if we got a version from somewhere - if (versions_valid && versions[0] != UINT32_MAX) { - // Make any invalid versions be zero if needed - if (versions[1] == UINT32_MAX) - versions[1] = 0; - if (versions[2] == UINT32_MAX) - versions[2] = 0; - + if (!version.empty()) { switch (sdk_type) { case SDKType::iPhoneOS: minimum_version_option.PutCString("-mios-version-min="); - minimum_version_option.PutCString( - clang::VersionTuple(versions[0], versions[1], versions[2]) - .getAsString()); + minimum_version_option.PutCString(version.getAsString()); break; case SDKType::iPhoneSimulator: minimum_version_option.PutCString("-mios-simulator-version-min="); - minimum_version_option.PutCString( - clang::VersionTuple(versions[0], versions[1], versions[2]) - .getAsString()); + minimum_version_option.PutCString(version.getAsString()); break; case SDKType::MacOSX: minimum_version_option.PutCString("-mmacosx-version-min="); - minimum_version_option.PutCString( - clang::VersionTuple(versions[0], versions[1], versions[2]) - .getAsString()); + minimum_version_option.PutCString(version.getAsString()); } options.push_back(minimum_version_option.GetString()); } @@ -1662,49 +1612,35 @@ ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) { return ConstString(stream.GetString()); } -bool PlatformDarwin::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update, Process *process) { +llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) { if (process && strstr(GetPluginName().GetCString(), "-simulator")) { lldb_private::ProcessInstanceInfo proc_info; if (Host::GetProcessInfo(process->GetID(), proc_info)) { - Args &env = proc_info.GetEnvironmentEntries(); - const size_t n = env.GetArgumentCount(); - const llvm::StringRef k_runtime_version("SIMULATOR_RUNTIME_VERSION="); - const llvm::StringRef k_dyld_root_path("DYLD_ROOT_PATH="); - std::string dyld_root_path; - - for (size_t i = 0; i < n; ++i) { - const char *env_cstr = env.GetArgumentAtIndex(i); - if (env_cstr) { - llvm::StringRef env_str(env_cstr); - if (env_str.consume_front(k_runtime_version)) { - if (Args::StringToVersion(env_str, major, minor, update)) - return true; - } else if (env_str.consume_front(k_dyld_root_path)) { - dyld_root_path = env_str; - } - } - } + const Environment &env = proc_info.GetEnvironment(); + llvm::VersionTuple result; + if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION"))) + return result; + + std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH"); if (!dyld_root_path.empty()) { dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist"; ApplePropertyList system_version_plist(dyld_root_path.c_str()); std::string product_version; if (system_version_plist.GetValueAsString("ProductVersion", product_version)) { - return Args::StringToVersion(product_version, major, minor, update); + if (!result.tryParse(product_version)) + return result; } } } // For simulator platforms, do NOT call back through - // Platform::GetOSVersion() - // as it might call Process::GetHostOSVersion() which we don't want as it - // will be - // incorrect - return false; + // Platform::GetOSVersion() as it might call Process::GetHostOSVersion() + // which we don't want as it will be incorrect + return llvm::VersionTuple(); } - return Platform::GetOSVersion(major, minor, update, process); + return Platform::GetOSVersion(process); } lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) { @@ -1713,8 +1649,8 @@ lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) { // any executable directories that should be searched. static std::vector<FileSpec> g_executable_dirs; - // Find the global list of directories that we will search for - // executables once so we don't keep doing the work over and over. + // Find the global list of directories that we will search for executables + // once so we don't keep doing the work over and over. static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { @@ -1748,22 +1684,19 @@ lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) { lldb_private::Status PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) { - // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr - // if the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't - // require any specific value; rather, it just needs to exist). - // We will set it here as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag - // is not set. Xcode makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell + // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if + // the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't require + // any specific value; rather, it just needs to exist). We will set it here + // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set. Xcode + // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they // specifically want it unset. const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE"; - auto &env_vars = launch_info.GetEnvironmentEntries(); - if (!env_vars.ContainsEnvironmentVariable(llvm::StringRef(disable_env_var))) { - // We want to make sure that OS_ACTIVITY_DT_MODE is set so that - // we get os_log and NSLog messages mirrored to the target process - // stderr. - if (!env_vars.ContainsEnvironmentVariable( - llvm::StringRef("OS_ACTIVITY_DT_MODE"))) - env_vars.AppendArgument(llvm::StringRef("OS_ACTIVITY_DT_MODE=enable")); + auto &env_vars = launch_info.GetEnvironment(); + if (!env_vars.count(disable_env_var)) { + // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get + // os_log and NSLog messages mirrored to the target process stderr. + env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable"); } // Let our parent class do the real launching. @@ -1777,24 +1710,23 @@ PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { const FileSpec &platform_file = module_spec.GetFileSpec(); - // See if the file is present in any of the module_search_paths_ptr directories. + // See if the file is present in any of the module_search_paths_ptr + // directories. if (!module_sp && module_search_paths_ptr && platform_file) { - // create a vector of all the file / directory names in platform_file - // e.g. this might be + // create a vector of all the file / directory names in platform_file e.g. + // this might be // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation // - // We'll need to look in the module_search_paths_ptr directories for - // both "UIFoundation" and "UIFoundation.framework" -- most likely the - // latter will be the one we find there. + // We'll need to look in the module_search_paths_ptr directories for both + // "UIFoundation" and "UIFoundation.framework" -- most likely the latter + // will be the one we find there. FileSpec platform_pull_apart(platform_file); std::vector<std::string> path_parts; - ConstString unix_root_dir("/"); - while (true) { + path_parts.push_back( + platform_pull_apart.GetLastPathComponent().AsCString()); + while (platform_pull_apart.RemoveLastPathComponent()) { ConstString part = platform_pull_apart.GetLastPathComponent(); - platform_pull_apart.RemoveLastPathComponent(); - if (part.IsEmpty() || part == unix_root_dir) - break; path_parts.push_back(part.AsCString()); } const size_t path_parts_size = path_parts.size(); @@ -1804,25 +1736,24 @@ PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log_verbose) log_verbose->Printf ("PlatformRemoteDarwinDevice::GetSharedModule searching for binary in search-path %s", module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str()); - // Create a new FileSpec with this module_search_paths_ptr - // plus just the filename ("UIFoundation"), then the parent - // dir plus filename ("UIFoundation.framework/UIFoundation") - // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") + // Create a new FileSpec with this module_search_paths_ptr plus just the + // filename ("UIFoundation"), then the parent dir plus filename + // ("UIFoundation.framework/UIFoundation") etc - up to four names (to + // handle "Foo.framework/Contents/MacOS/Foo") for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); // Add the components backwards. For - // .../PrivateFrameworks/UIFoundation.framework/UIFoundation - // path_parts is + // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts + // is // [0] UIFoundation // [1] UIFoundation.framework // [2] PrivateFrameworks // // and if 'j' is 2, we want to append path_parts[1] and then - // path_parts[0], aka - // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr - // path. + // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the + // module_search_paths_ptr path. for (int k = j; k >= 0; --k) { path_to_try.AppendPathComponent(path_parts[k]); diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h index c04318e98cae..3ad29ec1a0b9 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -69,8 +69,8 @@ public: void CalculateTrapHandlerSymbolNames() override; - bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update, - lldb_private::Process *process = nullptr) override; + llvm::VersionTuple + GetOSVersion(lldb_private::Process *process = nullptr) override; bool SupportsModules() override { return true; } @@ -82,7 +82,7 @@ public: lldb_private::Status LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override; - static std::tuple<uint32_t, uint32_t, uint32_t, llvm::StringRef> + static std::tuple<llvm::VersionTuple, llvm::StringRef> ParseVersionBuildDir(llvm::StringRef str); protected: @@ -101,8 +101,7 @@ protected: iPhoneOS, }; - static bool SDKSupportsModules(SDKType sdk_type, uint32_t major, - uint32_t minor, uint32_t micro); + static bool SDKSupportsModules(SDKType sdk_type, llvm::VersionTuple version); static bool SDKSupportsModules(SDKType desired_type, const lldb_private::FileSpec &sdk_path); diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp index e5d27fc28949..1e3216c0af5a 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp @@ -92,11 +92,9 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force, } // This is a special plugin that we don't want to activate just based on an - // ArchSpec for normal - // userland debugging. It is only useful in kernel debug sessions and the - // DynamicLoaderDarwinPlugin - // (or a user doing 'platform select') will force the creation of this - // Platform plugin. + // ArchSpec for normal userland debugging. It is only useful in kernel debug + // sessions and the DynamicLoaderDarwinPlugin (or a user doing 'platform + // select') will force the creation of this Platform plugin. if (force == false) { if (log) log->Printf("PlatformDarwinKernel::%s() aborting creation of platform " @@ -115,9 +113,8 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force, create = true; break; - // Only accept "unknown" for vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for vendor if the host is Apple and it "unknown" + // wasn't specified (it was just returned because it was NOT specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; @@ -133,9 +130,8 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force, case llvm::Triple::WatchOS: case llvm::Triple::TvOS: break; - // Only accept "vendor" for vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "vendor" for vendor if the host is Apple and it "unknown" + // wasn't specified (it was just returned because it was NOT specified) case llvm::Triple::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -341,11 +337,9 @@ void PlatformDarwinKernel::GetStatus(Stream &strm) { void PlatformDarwinKernel::CollectKextAndKernelDirectories() { // Differentiate between "ios debug session" and "mac debug session" so we - // don't index - // kext bundles that won't be used in this debug session. If this is an ios - // kext debug - // session, looking in /System/Library/Extensions is a waste of stat()s, for - // example. + // don't index kext bundles that won't be used in this debug session. If + // this is an ios kext debug session, looking in /System/Library/Extensions + // is a waste of stat()s, for example. // DeveloperDirectory is something like // "/Applications/Xcode.app/Contents/Developer" @@ -368,9 +362,8 @@ void PlatformDarwinKernel::CollectKextAndKernelDirectories() { AddSDKSubdirsToSearchPaths("/Volumes/KernelDebugKit"); AddSDKSubdirsToSearchPaths("/AppleInternal/Developer/KDKs"); - // The KDKs distributed from Apple installed on external - // developer systems may be in directories like - // /Library/Developer/KDKs/KDK_10.10_14A298i.kdk + // The KDKs distributed from Apple installed on external developer systems + // may be in directories like /Library/Developer/KDKs/KDK_10.10_14A298i.kdk AddSDKSubdirsToSearchPaths("/Library/Developer/KDKs"); if (m_ios_debug_session != eLazyBoolNo) { @@ -438,8 +431,8 @@ void PlatformDarwinKernel::AddSDKSubdirsToSearchPaths(const std::string &dir) { FileSpec::EnumerateDirectoryResult PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory( void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) { - static ConstString g_sdk_suffix = ConstString("sdk"); - static ConstString g_kdk_suffix = ConstString("kdk"); + static ConstString g_sdk_suffix = ConstString(".sdk"); + static ConstString g_kdk_suffix = ConstString(".kdk"); PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton; if (ft == llvm::sys::fs::file_type::directory_file && @@ -450,9 +443,8 @@ PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory( return FileSpec::eEnumerateDirectoryResultNext; } -// Recursively search trough m_search_directories looking for -// kext and kernel binaries, adding files found to the appropriate -// lists. +// Recursively search trough m_search_directories looking for kext and kernel +// binaries, adding files found to the appropriate lists. void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() { const uint32_t num_dirs = m_search_directories.size(); for (uint32_t i = 0; i < num_dirs; i++) { @@ -476,13 +468,11 @@ void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() { } } -// We're only doing a filename match here. We won't try opening the file to see -// if it's really -// a kernel or not until we need to find a kernel of a given UUID. There's no -// cheap way to find -// the UUID of a file (or if it's a Mach-O binary at all) without creating a -// whole Module for -// the file and throwing it away if it's not wanted. +// We're only doing a filename match here. We won't try opening the file to +// see if it's really a kernel or not until we need to find a kernel of a given +// UUID. There's no cheap way to find the UUID of a file (or if it's a Mach-O +// binary at all) without creating a whole Module for the file and throwing it +// away if it's not wanted. // // Recurse into any subdirectories found. @@ -502,8 +492,8 @@ FileSpec::EnumerateDirectoryResult PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper( void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec, bool recurse) { - static ConstString g_kext_suffix = ConstString("kext"); - static ConstString g_dsym_suffix = ConstString("dSYM"); + static ConstString g_kext_suffix = ConstString(".kext"); + static ConstString g_dsym_suffix = ConstString(".dSYM"); static ConstString g_bundle_suffix = ConstString("Bundle"); ConstString file_spec_extension = file_spec.GetFileNameExtension(); @@ -633,7 +623,7 @@ bool PlatformDarwinKernel::KextHasdSYMSibling( kext_bundle_filepath.GetPath() + "/Contents/MacOS/"; deep_bundle_str += executable_name.AsCString(); deep_bundle_str += ".dSYM"; - dsym_fspec.SetFile(deep_bundle_str, true); + dsym_fspec.SetFile(deep_bundle_str, true, FileSpec::Style::native); if (llvm::sys::fs::is_directory(dsym_fspec.GetPath())) { return true; } @@ -643,15 +633,15 @@ bool PlatformDarwinKernel::KextHasdSYMSibling( std::string shallow_bundle_str = kext_bundle_filepath.GetPath() + "/"; shallow_bundle_str += executable_name.AsCString(); shallow_bundle_str += ".dSYM"; - dsym_fspec.SetFile(shallow_bundle_str, true); + dsym_fspec.SetFile(shallow_bundle_str, true, FileSpec::Style::native); if (llvm::sys::fs::is_directory(dsym_fspec.GetPath())) { return true; } return false; } -// Given a FileSpec of /dir/dir/mach.development.t7004 -// Return true if a dSYM exists next to it: +// Given a FileSpec of /dir/dir/mach.development.t7004 Return true if a dSYM +// exists next to it: // /dir/dir/mach.development.t7004.dSYM bool PlatformDarwinKernel::KernelHasdSYMSibling(const FileSpec &kernel_binary) { FileSpec kernel_dsym = kernel_binary; @@ -694,8 +684,8 @@ Status PlatformDarwinKernel::GetSharedModule( } } - // Give the generic methods, including possibly calling into - // DebugSymbols framework on macOS systems, a chance. + // Give the generic methods, including possibly calling into DebugSymbols + // framework on macOS systems, a chance. error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); @@ -749,8 +739,8 @@ Status PlatformDarwinKernel::GetSharedModule( } } - // Give the generic methods, including possibly calling into - // DebugSymbols framework on macOS systems, a chance. + // Give the generic methods, including possibly calling into DebugSymbols + // framework on macOS systems, a chance. error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); @@ -789,37 +779,53 @@ Status PlatformDarwinKernel::GetSharedModule( return error; } +std::vector<lldb_private::FileSpec> +PlatformDarwinKernel::SearchForExecutablesRecursively(const std::string &dir) { + std::vector<FileSpec> executables; + std::error_code EC; + for (llvm::sys::fs::recursive_directory_iterator it(dir.c_str(), EC), + end; + it != end && !EC; it.increment(EC)) { + auto status = it->status(); + if (!status) + break; + if (llvm::sys::fs::is_regular_file(*status) && + llvm::sys::fs::can_execute(it->path())) + executables.emplace_back(it->path(), false); + } + return executables; +} + Status PlatformDarwinKernel::ExamineKextForMatchingUUID( const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, const ArchSpec &arch, ModuleSP &exe_module_sp) { - Status error; - FileSpec exe_file = kext_bundle_path; - Host::ResolveExecutableInBundle(exe_file); - if (exe_file.Exists()) { - ModuleSpec exe_spec(exe_file); - exe_spec.GetUUID() = uuid; - if (!uuid.IsValid()) { - exe_spec.GetArchitecture() = arch; - } + for (const auto &exe_file : + SearchForExecutablesRecursively(kext_bundle_path.GetPath())) { + if (exe_file.Exists()) { + ModuleSpec exe_spec(exe_file); + exe_spec.GetUUID() = uuid; + if (!uuid.IsValid()) { + exe_spec.GetArchitecture() = arch; + } - // First try to create a ModuleSP with the file / arch and see if the UUID - // matches. - // If that fails (this exec file doesn't have the correct uuid), don't call - // GetSharedModule - // (which may call in to the DebugSymbols framework and therefore can be - // slow.) - ModuleSP module_sp(new Module(exe_spec)); - if (module_sp && module_sp->GetObjectFile() && - module_sp->MatchesModuleSpec(exe_spec)) { - error = ModuleList::GetSharedModule(exe_spec, exe_module_sp, NULL, NULL, - NULL); - if (exe_module_sp && exe_module_sp->GetObjectFile()) { - return error; + // First try to create a ModuleSP with the file / arch and see if the UUID + // matches. If that fails (this exec file doesn't have the correct uuid), + // don't call GetSharedModule (which may call in to the DebugSymbols + // framework and therefore can be slow.) + ModuleSP module_sp(new Module(exe_spec)); + if (module_sp && module_sp->GetObjectFile() && + module_sp->MatchesModuleSpec(exe_spec)) { + Status error = ModuleList::GetSharedModule(exe_spec, exe_module_sp, + NULL, NULL, NULL); + if (exe_module_sp && exe_module_sp->GetObjectFile()) { + return error; + } } + exe_module_sp.reset(); } - exe_module_sp.reset(); } - return error; + + return {}; } bool PlatformDarwinKernel::GetSupportedArchitectureAtIndex(uint32_t idx, @@ -851,17 +857,13 @@ void PlatformDarwinKernel::CalculateTrapHandlerSymbolNames() { #else // __APPLE__ -// Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on -// PlatformDarwinKernel for the plug-in name, we compile just the plug-in name -// in -// here to avoid issues. We are tracking an internal bug to resolve this issue -// by -// either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to -// make -// PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently -// not -// compiled on other platforms due to the use of the Mac-specific -// source/Host/macosx/cfcpp utilities. +// Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies +// on PlatformDarwinKernel for the plug-in name, we compile just the plug-in +// name in here to avoid issues. We are tracking an internal bug to resolve +// this issue by either not compiling in DynamicLoaderDarwinKernel for non- +// apple builds, or to make PlatformDarwinKernel build on all systems. +// PlatformDarwinKernel is currently not compiled on other platforms due to the +// use of the Mac-specific source/Host/macosx/cfcpp utilities. lldb_private::ConstString PlatformDarwinKernel::GetPluginNameStatic() { static lldb_private::ConstString g_name("darwin-kernel"); diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h index 9b3ec5e0d717..7f603cac2bec 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h +++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h @@ -127,6 +127,9 @@ protected: const lldb_private::FileSpec &file_spec, bool recurse); + static std::vector<lldb_private::FileSpec> + SearchForExecutablesRecursively(const std::string &dir); + static void AddKextToMap(PlatformDarwinKernel *thisp, const lldb_private::FileSpec &file_spec); @@ -201,6 +204,7 @@ public: // source/Host/macosx/cfcpp utilities. class PlatformDarwinKernel { +public: static lldb_private::ConstString GetPluginNameStatic(); }; diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp index 43f4d8bbf023..99f603b01f43 100644 --- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -91,9 +91,8 @@ PlatformSP PlatformMacOSX::CreateInstance(bool force, const ArchSpec *arch) { break; #if defined(__APPLE__) - // Only accept "unknown" for vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for vendor if the host is Apple and it "unknown" + // wasn't specified (it was just returned because it was NOT specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; @@ -109,9 +108,8 @@ PlatformSP PlatformMacOSX::CreateInstance(bool force, const ArchSpec *arch) { case llvm::Triple::MacOSX: break; #if defined(__APPLE__) - // Only accept "vendor" for vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "vendor" for vendor if the host is Apple and it "unknown" + // wasn't specified (it was just returned because it was NOT specified) case llvm::Triple::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -175,7 +173,8 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) { FileSpec fspec; uint32_t versions[2]; if (objfile->GetSDKVersion(versions, sizeof(versions))) { - if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, fspec)) { + fspec = HostInfo::GetShlibDir(); + if (fspec) { std::string path; xcode_contents_path = fspec.GetPath(); size_t pos = xcode_contents_path.find("/Xcode.app/Contents/"); @@ -198,7 +197,7 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) { // here &output, // Get the output from the command and place it in this // string - 3); // Timeout in seconds to wait for shell program to finish + std::chrono::seconds(3)); if (status == 0 && !output.empty()) { size_t first_non_newline = output.find_last_not_of("\r\n"); if (first_non_newline != std::string::npos) @@ -219,13 +218,13 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) { "SDKs/MacOSX%u.%u.sdk", xcode_contents_path.c_str(), versions[0], versions[1]); - fspec.SetFile(sdk_path.GetString(), false); + fspec.SetFile(sdk_path.GetString(), false, FileSpec::Style::native); if (fspec.Exists()) return ConstString(sdk_path.GetString()); } if (!default_xcode_sdk.empty()) { - fspec.SetFile(default_xcode_sdk, false); + fspec.SetFile(default_xcode_sdk, false, FileSpec::Style::native); if (fspec.Exists()) return ConstString(default_xcode_sdk); } diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp index 1eef643d3904..be4c829a981c 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp @@ -99,8 +99,8 @@ PlatformSP PlatformRemoteAppleTV::CreateInstance(bool force, #if defined(__APPLE__) // Only accept "unknown" for the vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp index 17ae67bc28de..6159511d4a18 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp @@ -94,8 +94,8 @@ PlatformSP PlatformRemoteAppleWatch::CreateInstance(bool force, #if defined(__APPLE__) // Only accept "unknown" for the vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; @@ -123,8 +123,8 @@ PlatformSP PlatformRemoteAppleWatch::CreateInstance(bool force, #if defined(__APPLE__) && \ (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) - // If lldb is running on a watch, this isn't a RemoteWatch environment; it's a - // local system environment. + // If lldb is running on a watch, this isn't a RemoteWatch environment; it's + // a local system environment. if (force == false) { create = false; } diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp index cb064aad6155..930d062fe41e 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp @@ -31,12 +31,10 @@ using namespace lldb_private; PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo( const lldb_private::FileSpec &sdk_dir) - : directory(sdk_dir), build(), version_major(0), version_minor(0), - version_update(0), user_cached(false) { + : directory(sdk_dir), build(), user_cached(false) { llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef(); llvm::StringRef build_str; - std::tie(version_major, version_minor, version_update, build_str) = - ParseVersionBuildDir(dirname_str); + std::tie(version, build_str) = ParseVersionBuildDir(dirname_str); build.SetString(build_str); } @@ -97,9 +95,9 @@ Status PlatformRemoteDarwinDevice::ResolveExecutable( return error; exe_module_sp.reset(); } - // No valid architecture was specified or the exact ARM slice wasn't - // found so ask the platform for the architectures that we should be - // using (in the correct order) and see if we can find a match that way + // No valid architecture was specified or the exact ARM slice wasn't found + // so ask the platform for the architectures that we should be using (in + // the correct order) and see if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( idx, resolved_module_spec.GetArchitecture()); @@ -183,8 +181,8 @@ bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() { &builtin_sdk_directory_infos); // Only add SDK directories that have symbols in them, some SDKs only - // contain - // developer disk images and no symbols, so they aren't useful to us. + // contain developer disk images and no symbols, so they aren't useful to + // us. FileSpec sdk_symbols_symlink_fspec; for (const auto &sdk_directory_info : builtin_sdk_directory_infos) { sdk_symbols_symlink_fspec = sdk_directory_info.directory; @@ -244,8 +242,8 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() { if (UpdateSDKDirectoryInfosIfNeeded()) { const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - // Check to see if the user specified a build string. If they did, then - // be sure to match it. + // Check to see if the user specified a build string. If they did, then be + // sure to match it. std::vector<bool> check_sdk_info(num_sdk_infos, true); ConstString build(m_sdk_build); if (build) { @@ -253,26 +251,25 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() { check_sdk_info[i] = m_sdk_directory_infos[i].build == build; } - // If we are connected we can find the version of the OS the platform - // us running on and select the right SDK - uint32_t major, minor, update; - if (GetOSVersion(major, minor, update)) { + // If we are connected we can find the version of the OS the platform us + // running on and select the right SDK + llvm::VersionTuple version = GetOSVersion(); + if (!version.empty()) { if (UpdateSDKDirectoryInfosIfNeeded()) { // First try for an exact match of major, minor and update for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version_major == major && - m_sdk_directory_infos[i].version_minor == minor && - m_sdk_directory_infos[i].version_update == update) { + if (m_sdk_directory_infos[i].version == version) return &m_sdk_directory_infos[i]; - } } } // First try for an exact match of major and minor for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version_major == major && - m_sdk_directory_infos[i].version_minor == minor) { + if (m_sdk_directory_infos[i].version.getMajor() == + version.getMajor() && + m_sdk_directory_infos[i].version.getMinor() == + version.getMinor()) { return &m_sdk_directory_infos[i]; } } @@ -280,7 +277,8 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() { // Lastly try to match of major version only.. for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version_major == major) { + if (m_sdk_directory_infos[i].version.getMajor() == + version.getMajor()) { return &m_sdk_directory_infos[i]; } } @@ -300,25 +298,13 @@ const PlatformRemoteDarwinDevice::SDKDirectoryInfo * PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() { const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = NULL; if (UpdateSDKDirectoryInfosIfNeeded()) { - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - // First try for an exact match of major, minor and update - for (uint32_t i = 0; i < num_sdk_infos; ++i) { - const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; - if (sdk_dir_info.version_major != UINT32_MAX) { - if (result == NULL || - sdk_dir_info.version_major > result->version_major) { - result = &sdk_dir_info; - } else if (sdk_dir_info.version_major == result->version_major) { - if (sdk_dir_info.version_minor > result->version_minor) { - result = &sdk_dir_info; - } else if (sdk_dir_info.version_minor == result->version_minor) { - if (sdk_dir_info.version_update > result->version_update) { - result = &sdk_dir_info; - } - } - } - } - } + auto max = std::max_element( + m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(), + [](const SDKDirectoryInfo &a, const SDKDirectoryInfo &b) { + return a.version < b.version; + }); + if (max != m_sdk_directory_infos.end()) + result = &*max; } return result; } @@ -366,8 +352,8 @@ const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() } } // We should have put a single NULL character into - // m_device_support_directory_for_os_version - // or it should have a valid path if the code gets here + // m_device_support_directory_for_os_version or it should have a valid path + // if the code gets here assert(m_device_support_directory_for_os_version.empty() == false); if (m_device_support_directory_for_os_version[0]) return m_device_support_directory_for_os_version.c_str(); @@ -409,7 +395,7 @@ bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path, const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr}; for (size_t i = 0; paths_to_try[i] != nullptr; i++) { - local_file.SetFile(sdkroot_path, false); + local_file.SetFile(sdkroot_path, false, FileSpec::Style::native); if (paths_to_try[i][0] != '\0') local_file.AppendPathComponent(paths_to_try[i]); local_file.AppendPathComponent(platform_file_path); @@ -442,7 +428,7 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file, ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir, platform_file_path); - local_file.SetFile(resolved_path, true); + local_file.SetFile(resolved_path, true, FileSpec::Style::native); if (local_file.Exists()) { if (log) { log->Printf("Found a copy of %s in the DeviceSupport dir %s", @@ -454,7 +440,7 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file, ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s", os_version_dir, platform_file_path); - local_file.SetFile(resolved_path, true); + local_file.SetFile(resolved_path, true, FileSpec::Style::native); if (local_file.Exists()) { if (log) { log->Printf( @@ -466,7 +452,7 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file, ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s", os_version_dir, platform_file_path); - local_file.SetFile(resolved_path, true); + local_file.SetFile(resolved_path, true, FileSpec::Style::native); if (local_file.Exists()) { if (log) { log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols", @@ -492,10 +478,9 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - // For iOS, the SDK files are all cached locally on the host - // system. So first we ask for the file in the cached SDK, - // then we attempt to get a shared module for the right architecture - // with the right UUID. + // For iOS, the SDK files are all cached locally on the host system. So first + // we ask for the file in the cached SDK, then we attempt to get a shared + // module for the right architecture with the right UUID. const FileSpec &platform_file = module_spec.GetFileSpec(); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); @@ -510,8 +495,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); // If we are connected we migth be able to correctly deduce the SDK - // directory - // using the OS build. + // directory using the OS build. const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); if (connected_sdk_idx < num_sdk_infos) { LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, @@ -528,8 +512,8 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( } } - // Try the last SDK index if it is set as most files from an SDK - // will tend to be valid in that same SDK. + // Try the last SDK index if it is set as most files from an SDK will tend + // to be valid in that same SDK. if (m_last_module_sdk_idx < num_sdk_infos) { LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, m_sdk_directory_infos[m_last_module_sdk_idx].directory); @@ -544,9 +528,9 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( } } - // First try for an exact match of major, minor and update: - // If a particalar SDK version was specified via --version or --build, look - // for a match on disk. + // First try for an exact match of major, minor and update: If a particalar + // SDK version was specified via --version or --build, look for a match on + // disk. const SDKDirectoryInfo *current_sdk_info = GetSDKDirectoryForCurrentOSVersion(); const uint32_t current_sdk_idx = @@ -570,8 +554,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( // Second try all SDKs that were found. for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { if (m_last_module_sdk_idx == sdk_idx) { - // Skip the last module SDK index if we already searched - // it above + // Skip the last module SDK index if we already searched it above continue; } LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, @@ -582,8 +565,8 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( error = ResolveExecutable(platform_module_spec, module_sp, NULL); if (module_sp) { - // Remember the index of the last SDK that we found a file - // in in case the wrong SDK was selected. + // Remember the index of the last SDK that we found a file in in case + // the wrong SDK was selected. m_last_module_sdk_idx = sdk_idx; error.Clear(); return error; diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h index f159e8575d76..8ddfd51600fd 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h @@ -60,9 +60,7 @@ protected: SDKDirectoryInfo(const lldb_private::FileSpec &sdk_dir_spec); lldb_private::FileSpec directory; lldb_private::ConstString build; - uint32_t version_major; - uint32_t version_minor; - uint32_t version_update; + llvm::VersionTuple version; bool user_cached; }; diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp index 5bff792525bc..150bfdbfc118 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp @@ -89,8 +89,8 @@ PlatformSP PlatformRemoteiOS::CreateInstance(bool force, const ArchSpec *arch) { #if defined(__APPLE__) // Only accept "unknown" for the vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp index ee1f90311e7e..26feec282322 100644 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp @@ -91,9 +91,9 @@ PlatformSP PlatformiOSSimulator::CreateInstance(bool force, break; #if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the vendor if the host is Apple and it + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; @@ -112,9 +112,9 @@ PlatformSP PlatformiOSSimulator::CreateInstance(bool force, break; #if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is Apple and it + // "unknown" wasn't specified (it was just returned because it was NOT + // specified) case llvm::Triple::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -205,9 +205,9 @@ Status PlatformiOSSimulator::ResolveExecutable( return error; exe_module_sp.reset(); } - // No valid architecture was specified or the exact ARM slice wasn't - // found so ask the platform for the architectures that we should be - // using (in the correct order) and see if we can find a match that way + // No valid architecture was specified or the exact ARM slice wasn't found + // so ask the platform for the architectures that we should be using (in + // the correct order) and see if we can find a match that way StreamString arch_names; ArchSpec platform_arch; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( @@ -298,8 +298,8 @@ const char *PlatformiOSSimulator::GetSDKDirectoryAsCString() { m_sdk_directory.assign(1, '\0'); } - // We should have put a single NULL character into m_sdk_directory - // or it should have a valid path if the code gets here + // We should have put a single NULL character into m_sdk_directory or it + // should have a valid path if the code gets here assert(m_sdk_directory.empty() == false); if (m_sdk_directory[0]) return m_sdk_directory.c_str(); @@ -320,12 +320,12 @@ Status PlatformiOSSimulator::GetSymbolFile(const FileSpec &platform_file, platform_file_path); // First try in the SDK and see if the file is in there - local_file.SetFile(resolved_path, true); + local_file.SetFile(resolved_path, true, FileSpec::Style::native); if (local_file.Exists()) return error; // Else fall back to the actual path itself - local_file.SetFile(platform_file_path, true); + local_file.SetFile(platform_file_path, true, FileSpec::Style::native); if (local_file.Exists()) return error; } @@ -342,10 +342,9 @@ Status PlatformiOSSimulator::GetSharedModule( const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - // For iOS, the SDK files are all cached locally on the host - // system. So first we ask for the file in the cached SDK, - // then we attempt to get a shared module for the right architecture - // with the right UUID. + // For iOS, the SDK files are all cached locally on the host system. So first + // we ask for the file in the cached SDK, then we attempt to get a shared + // module for the right architecture with the right UUID. Status error; ModuleSpec platform_module_spec(module_spec); const FileSpec &platform_file = module_spec.GetFileSpec(); @@ -409,14 +408,14 @@ bool PlatformiOSSimulator::GetSupportedArchitectureAtIndex(uint32_t idx, if (arch.IsValid()) { if (idx == 2) arch.GetTriple().setOS(llvm::Triple::IOS); - // 32/64: return "i386-apple-ios" for architecture 2 - // 32/64: return "i386-apple-macosx" for architecture 3 + // 32/64: return "i386-apple-ios" for architecture 2 32/64: return + // "i386-apple-macosx" for architecture 3 return true; } } } else if (idx == 1) { - // This macosx platform supports only 32 bit, so return the *-apple-macosx - // version + // This macosx platform supports only 32 bit, so return the *-apple- + // macosx version arch = platform_arch; return true; } diff --git a/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt b/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt new file mode 100644 index 000000000000..946ff0a64c26 --- /dev/null +++ b/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt @@ -0,0 +1,17 @@ +remove_module_flags() +include_directories(.) + +add_lldb_library(lldbPluginPlatformMacOSXObjCXX + PlatformiOSSimulatorCoreSimulatorSupport.mm + + LINK_LIBS + lldbCore + lldbSymbol + lldbTarget + lldbUtility + ${EXTRA_LIBS} + + LINK_COMPONENTS + Object + Support + ) diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h index 31e11a60e419..083e2d6c5687 100644 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h +++ b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h @@ -24,8 +24,8 @@ typedef void *id; #endif // Project includes -#include "lldb/Interpreter/Args.h" #include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Utility/Args.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm index 7bd37683d2fd..4516a66ee8ca 100644 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm +++ b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm @@ -478,26 +478,17 @@ CoreSimulatorSupport::Device::Spawn(ProcessLaunchInfo &launch_info) { [options setObject:args_array forKey:kSimDeviceSpawnArguments]; } - if (launch_info.GetEnvironmentEntries().GetArgumentCount()) { - const Args &envs(launch_info.GetEnvironmentEntries()); - NSMutableDictionary *env_dict = [[NSMutableDictionary alloc] init]; - for (size_t idx = 0; idx < envs.GetArgumentCount(); idx++) { - llvm::StringRef arg_sr(envs.GetArgumentAtIndex(idx)); - auto first_eq = arg_sr.find('='); - if (first_eq == llvm::StringRef::npos) - continue; - llvm::StringRef key = arg_sr.substr(0, first_eq); - llvm::StringRef value = arg_sr.substr(first_eq + 1); - - NSString *key_ns = [NSString stringWithUTF8String:key.str().c_str()]; - NSString *value_ns = [NSString stringWithUTF8String:value.str().c_str()]; - - [env_dict setValue:value_ns forKey:key_ns]; - } + NSMutableDictionary *env_dict = [[NSMutableDictionary alloc] init]; + + for (const auto &KV : launch_info.GetEnvironment()) { + NSString *key_ns = [NSString stringWithUTF8String:KV.first().str().c_str()]; + NSString *value_ns = [NSString stringWithUTF8String:KV.second.c_str()]; - [options setObject:env_dict forKey:kSimDeviceSpawnEnvironment]; + [env_dict setValue:value_ns forKey:key_ns]; } + [options setObject:env_dict forKey:kSimDeviceSpawnEnvironment]; + Status error; File stdin_file; File stdout_file; diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index 38bdf60c1ced..3aa8ecb4c228 100644 --- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -30,8 +30,8 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" -// Define these constants from NetBSD mman.h for use when targeting -// remote netbsd systems even when host has different values. +// Define these constants from NetBSD mman.h for use when targeting remote +// netbsd systems even when host has different values. #define MAP_PRIVATE 0x0002 #define MAP_ANON 0x1000 @@ -45,19 +45,9 @@ static uint32_t g_initialize_count = 0; PlatformSP PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformNetBSD::%s(force=%s, arch={%s,%s})", __FUNCTION__, - force ? "true" : "false", arch_name, triple_cstr); - } + LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force, + arch ? arch->GetArchitectureName() : "<null>", + arch ? arch->GetTriple().getTriple() : "<null>"); bool create = force; if (create == false && arch && arch->IsValid()) { @@ -72,18 +62,10 @@ PlatformSP PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch) { } } + LLDB_LOG(log, "create = {0}", create); if (create) { - if (log) - log->Printf("PlatformNetBSD::%s() creating remote-netbsd platform", - __FUNCTION__); return PlatformSP(new PlatformNetBSD(false)); } - - if (log) - log->Printf( - "PlatformNetBSD::%s() aborting creation of remote-netbsd platform", - __FUNCTION__); - return PlatformSP(); } @@ -152,7 +134,8 @@ bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx, arch = hostArch; return arch.IsValid(); } else if (idx == 1) { - // If the default host architecture is 64-bit, look for a 32-bit variant + // If the default host architecture is 64-bit, look for a 32-bit + // variant if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) { arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); return arch.IsValid(); @@ -178,13 +161,10 @@ bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx, return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the - // vendor by - // calling triple.SetVendorName("unknown") so that it is a "unspecified - // unknown". - // This means when someone calls triple.GetVendorName() it will return an - // empty string - // which indicates that the vendor can be set when two architectures are - // merged + // vendor by calling triple.SetVendorName("unknown") so that it is a + // "unspecified unknown". This means when someone calls + // triple.GetVendorName() it will return an empty string which indicates + // that the vendor can be set when two architectures are merged // Now set the triple into "arch" and return true arch.SetTriple(triple); @@ -258,19 +238,15 @@ bool PlatformNetBSD::CanDebugProcess() { } // For local debugging, NetBSD will override the debug logic to use llgs-launch -// rather than -// lldb-launch, llgs-attach. This differs from current lldb-launch, -// debugserver-attach -// approach on MacOSX. -lldb::ProcessSP PlatformNetBSD::DebugProcess( - ProcessLaunchInfo &launch_info, Debugger &debugger, - Target *target, // Can be NULL, if NULL create a new - // target, else use existing one - Status &error) { +// rather than lldb-launch, llgs-attach. This differs from current lldb- +// launch, debugserver-attach approach on MacOSX. +lldb::ProcessSP +PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, + Target *target, // Can be NULL, if NULL create a new + // target, else use existing one + Status &error) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("PlatformNetBSD::%s entered (target %p)", __FUNCTION__, - static_cast<void *>(target)); + LLDB_LOG(log, "target {0}", target); // If we're a remote host, use standard behavior from parent class. if (!IsHost()) @@ -287,67 +263,48 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess( launch_info.GetFlags().Set(eLaunchFlagDebug); // We always launch the process we are going to debug in a separate process - // group, since then we can handle ^C interrupts ourselves w/o having to worry - // about the target getting them as well. + // group, since then we can handle ^C interrupts ourselves w/o having to + // worry about the target getting them as well. launch_info.SetLaunchInSeparateProcessGroup(true); // Ensure we have a target. if (target == nullptr) { - if (log) - log->Printf("PlatformNetBSD::%s creating new target", __FUNCTION__); - + LLDB_LOG(log, "creating new target"); TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget(debugger, "", "", false, nullptr, new_target_sp); if (error.Fail()) { - if (log) - log->Printf("PlatformNetBSD::%s failed to create new target: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOG(log, "failed to create new target: {0}", error); return process_sp; } target = new_target_sp.get(); if (!target) { error.SetErrorString("CreateTarget() returned nullptr"); - if (log) - log->Printf("PlatformNetBSD::%s failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOG(log, "error: {0}", error); return process_sp; } - } else { - if (log) - log->Printf("PlatformNetBSD::%s using provided target", __FUNCTION__); } // Mark target as currently selected target. debugger.GetTargetList().SetSelectedTarget(target); // Now create the gdb-remote process. - if (log) - log->Printf( - "PlatformNetBSD::%s having target create process with gdb-remote plugin", - __FUNCTION__); + LLDB_LOG(log, "having target create process with gdb-remote plugin"); process_sp = target->CreateProcess( launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr); if (!process_sp) { error.SetErrorString("CreateProcess() failed for gdb-remote process"); - if (log) - log->Printf("PlatformNetBSD::%s failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOG(log, "error: {0}", error); return process_sp; - } else { - if (log) - log->Printf("PlatformNetBSD::%s successfully created process", - __FUNCTION__); } + LLDB_LOG(log, "successfully created process"); // Adjust launch for a hijacker. ListenerSP listener_sp; if (!launch_info.GetHijackListener()) { - if (log) - log->Printf("PlatformNetBSD::%s setting up hijacker", __FUNCTION__); - + LLDB_LOG(log, "setting up hijacker"); listener_sp = Listener::MakeListener("lldb.PlatformNetBSD.DebugProcess.hijack"); launch_info.SetHijackListener(listener_sp); @@ -356,16 +313,13 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess( // Log file actions. if (log) { - log->Printf( - "PlatformNetBSD::%s launching process with the following file actions:", - __FUNCTION__); - + LLDB_LOG(log, "launching process with the following file actions:"); StreamString stream; size_t i = 0; const FileAction *file_action; while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) { file_action->Dump(stream); - log->PutCString(stream.GetData()); + LLDB_LOG(log, "{0}", stream.GetData()); stream.Clear(); } } @@ -378,16 +332,7 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess( const StateType state = process_sp->WaitForProcessToStop( llvm::None, NULL, false, listener_sp); - if (state == eStateStopped) { - if (log) - log->Printf("PlatformNetBSD::%s pid %" PRIu64 " state %s\n", - __FUNCTION__, process_sp->GetID(), StateAsCString(state)); - } else { - if (log) - log->Printf("PlatformNetBSD::%s pid %" PRIu64 - " state is not stopped - %s\n", - __FUNCTION__, process_sp->GetID(), StateAsCString(state)); - } + LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state); } // Hook up process PTY if we have one (which we should for local debugging @@ -395,20 +340,11 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess( int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); - if (log) - log->Printf("PlatformNetBSD::%s pid %" PRIu64 - " hooked up STDIO pty to process", - __FUNCTION__, process_sp->GetID()); - } else { - if (log) - log->Printf("PlatformNetBSD::%s pid %" PRIu64 - " not using process STDIO pty", - __FUNCTION__, process_sp->GetID()); - } + LLDB_LOG(log, "hooked up STDIO pty to process"); + } else + LLDB_LOG(log, "not using process STDIO pty"); } else { - if (log) - log->Printf("PlatformNetBSD::%s process launch failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOG(log, "process launch failed: {0}", error); // FIXME figure out appropriate cleanup here. Do we delete the target? Do // we delete the process? Does our caller do that? } diff --git a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp index 050639aba7cc..10ca8fbfbdd7 100644 --- a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp +++ b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp @@ -30,8 +30,8 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" -// Define these constants from OpenBSD mman.h for use when targeting -// remote openbsd systems even when host has different values. +// Define these constants from OpenBSD mman.h for use when targeting remote +// openbsd systems even when host has different values. #define MAP_PRIVATE 0x0002 #define MAP_ANON 0x1000 @@ -58,9 +58,8 @@ PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) { break; #if defined(__OpenBSD__) - // Only accept "unknown" for the OS if the host is BSD and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is BSD and it "unknown" + // wasn't specified (it was just returned because it was NOT specified) case llvm::Triple::OSType::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -167,13 +166,10 @@ bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx, return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the - // vendor by - // calling triple.SetVendorName("unknown") so that it is a "unspecified - // unknown". - // This means when someone calls triple.GetVendorName() it will return an - // empty string - // which indicates that the vendor can be set when two architectures are - // merged + // vendor by calling triple.SetVendorName("unknown") so that it is a + // "unspecified unknown". This means when someone calls + // triple.GetVendorName() it will return an empty string which indicates + // that the vendor can be set when two architectures are merged // Now set the triple into "arch" and return true arch.SetTriple(triple); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index d45a54ee2499..5e7ffe71918e 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -18,17 +18,22 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UserExpression.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/File.h" #include "lldb/Host/FileCache.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" @@ -97,17 +102,14 @@ lldb_private::Status PlatformPOSIX::RunShellCommand( // process to exit std::string *command_output, // Pass NULL if you don't want the command output - uint32_t - timeout_sec) // Timeout in seconds to wait for shell program to finish -{ + const Timeout<std::micro> &timeout) { if (IsHost()) return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, - command_output, timeout_sec); + command_output, timeout); else { if (m_remote_platform_sp) - return m_remote_platform_sp->RunShellCommand(command, working_dir, - status_ptr, signo_ptr, - command_output, timeout_sec); + return m_remote_platform_sp->RunShellCommand( + command, working_dir, status_ptr, signo_ptr, command_output, timeout); else return Status("unable to run a remote command without a platform"); } @@ -124,11 +126,12 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec, ModuleSpec resolved_module_spec(module_spec); if (IsHost()) { - // If we have "ls" as the exe_file, resolve the executable location based on - // the current path variables + // If we have "ls" as the exe_file, resolve the executable location based + // on the current path variables if (!resolved_module_spec.GetFileSpec().Exists()) { resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); - resolved_module_spec.GetFileSpec().SetFile(exe_path, true); + resolved_module_spec.GetFileSpec().SetFile(exe_path, true, + FileSpec::Style::native); } if (!resolved_module_spec.GetFileSpec().Exists()) @@ -210,9 +213,9 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec, resolved_module_spec.GetArchitecture().GetArchitectureName()); } } else { - // No valid architecture was specified, ask the platform for - // the architectures that we should be using (in the correct order) - // and see if we can find a match that way + // No valid architecture was specified, ask the platform for the + // architectures that we should be using (in the correct order) and see + // if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( idx, resolved_module_spec.GetArchitecture()); @@ -367,7 +370,8 @@ static uint32_t chown_file(Platform *platform, const char *path, command.Printf(":%d", gid); command.Printf("%s", path); int status; - platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10); + platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, + std::chrono::seconds(10)); return status; } @@ -391,7 +395,8 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source, StreamString command; command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); int status; - RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10); + RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, + std::chrono::seconds(10)); if (status != 0) return Status("unable to perform copy"); if (uid == UINT32_MAX && gid == UINT32_MAX) @@ -421,7 +426,8 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source, if (log) log->Printf("[PutFile] Running command: %s\n", command.GetData()); int retcode; - Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60); + Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, + std::chrono::minutes(1)); if (retcode == 0) { // Don't chown a local file for a remote system // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) @@ -495,7 +501,8 @@ lldb_private::Status PlatformPOSIX::GetFile( StreamString cp_command; cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); int status; - RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL, 10); + RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL, + std::chrono::seconds(10)); if (status != 0) return Status("unable to perform copy"); return Status(); @@ -516,11 +523,12 @@ lldb_private::Status PlatformPOSIX::GetFile( if (log) log->Printf("[GetFile] Running command: %s\n", command.GetData()); int retcode; - Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60); + Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, + std::chrono::minutes(1)); if (retcode == 0) return Status(); - // If we are here, rsync has failed - let's try the slow way before giving - // up + // If we are here, rsync has failed - let's try the slow way before + // giving up } // open src and dst // read/write, read/write, read/write, ... @@ -645,9 +653,10 @@ bool PlatformPOSIX::SetRemoteWorkingDirectory(const FileSpec &working_dir) { } bool PlatformPOSIX::GetRemoteOSVersion() { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetOSVersion( - m_major_os_version, m_minor_os_version, m_update_os_version); + if (m_remote_platform_sp) { + m_os_version = m_remote_platform_sp->GetOSVersion(); + return !m_os_version.empty(); + } return false; } @@ -658,13 +667,13 @@ bool PlatformPOSIX::GetRemoteOSBuildString(std::string &s) { return false; } -size_t PlatformPOSIX::GetEnvironment(StringList &env) { +Environment PlatformPOSIX::GetEnvironment() { if (IsRemote()) { if (m_remote_platform_sp) - return m_remote_platform_sp->GetEnvironment(env); - return 0; + return m_remote_platform_sp->GetEnvironment(); + return Environment(); } - return Host::GetEnvironment(env); + return Host::GetEnvironment(); } bool PlatformPOSIX::GetRemoteOSKernelDescription(std::string &s) { @@ -861,12 +870,12 @@ PlatformPOSIX::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, if (IsHost()) { // We are going to hand this process off to debugserver which will be in - // charge of setting the exit status. - // We still need to reap it from lldb but if we let the monitor thread also - // set the exit status, we set up a - // race between debugserver & us for who will find out about the debugged - // process's death. - launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus); + // charge of setting the exit status. However, we still need to reap it + // from lldb. So, make sure we use a exit callback which does not set exit + // status. + const bool monitor_signals = false; + launch_info.SetMonitorProcessCallback( + &ProcessLaunchInfo::NoOpMonitorCallback, monitor_signals); process_sp = Platform::DebugProcess(launch_info, debugger, target, error); } else { if (m_remote_platform_sp) @@ -923,64 +932,380 @@ Status PlatformPOSIX::EvaluateLibdlExpression( return Status(); } +std::unique_ptr<UtilityFunction> +PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx, + Status &error) { + // Remember to prepend this with the prefix from + // GetLibdlFunctionDeclarations. The returned values are all in + // __lldb_dlopen_result for consistency. The wrapper returns a void * but + // doesn't use it because UtilityFunctions don't work with void returns at + // present. + static const char *dlopen_wrapper_code = R"( + struct __lldb_dlopen_result { + void *image_ptr; + const char *error_str; + }; + + extern void *memcpy(void *, const void *, size_t size); + extern size_t strlen(const char *); + + + void * __lldb_dlopen_wrapper (const char *name, + const char *path_strings, + char *buffer, + __lldb_dlopen_result *result_ptr) + { + // This is the case where the name is the full path: + if (!path_strings) { + result_ptr->image_ptr = dlopen(name, 2); + if (result_ptr->image_ptr) + result_ptr->error_str = nullptr; + return nullptr; + } + + // This is the case where we have a list of paths: + size_t name_len = strlen(name); + while (path_strings && path_strings[0] != '\0') { + size_t path_len = strlen(path_strings); + memcpy((void *) buffer, (void *) path_strings, path_len); + buffer[path_len] = '/'; + char *target_ptr = buffer+path_len+1; + memcpy((void *) target_ptr, (void *) name, name_len + 1); + result_ptr->image_ptr = dlopen(buffer, 2); + if (result_ptr->image_ptr) { + result_ptr->error_str = nullptr; + break; + } + result_ptr->error_str = dlerror(); + path_strings = path_strings + path_len + 1; + } + return nullptr; + } + )"; + + static const char *dlopen_wrapper_name = "__lldb_dlopen_wrapper"; + Process *process = exe_ctx.GetProcessSP().get(); + // Insert the dlopen shim defines into our generic expression: + std::string expr(GetLibdlFunctionDeclarations(process)); + expr.append(dlopen_wrapper_code); + Status utility_error; + DiagnosticManager diagnostics; + + std::unique_ptr<UtilityFunction> dlopen_utility_func_up(process + ->GetTarget().GetUtilityFunctionForLanguage(expr.c_str(), + eLanguageTypeObjC, + dlopen_wrapper_name, + utility_error)); + if (utility_error.Fail()) { + error.SetErrorStringWithFormat("dlopen error: could not make utility" + "function: %s", utility_error.AsCString()); + return nullptr; + } + if (!dlopen_utility_func_up->Install(diagnostics, exe_ctx)) { + error.SetErrorStringWithFormat("dlopen error: could not install utility" + "function: %s", + diagnostics.GetString().c_str()); + return nullptr; + } + + Value value; + ValueList arguments; + FunctionCaller *do_dlopen_function = nullptr; + + // Fetch the clang types we will need: + ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext(); + + CompilerType clang_void_pointer_type + = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + CompilerType clang_char_pointer_type + = ast->GetBasicType(eBasicTypeChar).GetPointerType(); + + // We are passing four arguments, the basename, the list of places to look, + // a buffer big enough for all the path + name combos, and + // a pointer to the storage we've made for the result: + value.SetValueType(Value::eValueTypeScalar); + value.SetCompilerType(clang_void_pointer_type); + arguments.PushValue(value); + value.SetCompilerType(clang_char_pointer_type); + arguments.PushValue(value); + arguments.PushValue(value); + arguments.PushValue(value); + + do_dlopen_function = dlopen_utility_func_up->MakeFunctionCaller( + clang_void_pointer_type, arguments, exe_ctx.GetThreadSP(), utility_error); + if (utility_error.Fail()) { + error.SetErrorStringWithFormat("dlopen error: could not make function" + "caller: %s", utility_error.AsCString()); + return nullptr; + } + + do_dlopen_function = dlopen_utility_func_up->GetFunctionCaller(); + if (!do_dlopen_function) { + error.SetErrorString("dlopen error: could not get function caller."); + return nullptr; + } + + // We made a good utility function, so cache it in the process: + return dlopen_utility_func_up; +} + uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, const lldb_private::FileSpec &remote_file, - lldb_private::Status &error) { - char path[PATH_MAX]; - remote_file.GetPath(path, sizeof(path)); - - StreamString expr; - expr.Printf(R"( - struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result; - the_result.image_ptr = dlopen ("%s", 2); - if (the_result.image_ptr == (void *) 0x0) - { - the_result.error_str = dlerror(); - } - else - { - the_result.error_str = (const char *) 0x0; - } - the_result; - )", - path); - llvm::StringRef prefix = GetLibdlFunctionDeclarations(process); - lldb::ValueObjectSP result_valobj_sp; - error = EvaluateLibdlExpression(process, expr.GetData(), prefix, - result_valobj_sp); - if (error.Fail()) + const std::vector<std::string> *paths, + lldb_private::Status &error, + lldb_private::FileSpec *loaded_image) { + if (loaded_image) + loaded_image->Clear(); + + std::string path; + path = remote_file.GetPath(); + + ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); + if (!thread_sp) { + error.SetErrorString("dlopen error: no thread available to call dlopen."); return LLDB_INVALID_IMAGE_TOKEN; - - error = result_valobj_sp->GetError(); - if (error.Fail()) + } + + DiagnosticManager diagnostics; + + ExecutionContext exe_ctx; + thread_sp->CalculateExecutionContext(exe_ctx); + + Status utility_error; + UtilityFunction *dlopen_utility_func; + ValueList arguments; + FunctionCaller *do_dlopen_function = nullptr; + + // The UtilityFunction is held in the Process. Platforms don't track the + // lifespan of the Targets that use them, we can't put this in the Platform. + dlopen_utility_func = process->GetLoadImageUtilityFunction( + this, [&]() -> std::unique_ptr<UtilityFunction> { + return MakeLoadImageUtilityFunction(exe_ctx, error); + }); + // If we couldn't make it, the error will be in error, so we can exit here. + if (!dlopen_utility_func) return LLDB_INVALID_IMAGE_TOKEN; - - Scalar scalar; - ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true); - if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar)) { - error.SetErrorStringWithFormat("unable to load '%s'", path); + + do_dlopen_function = dlopen_utility_func->GetFunctionCaller(); + if (!do_dlopen_function) { + error.SetErrorString("dlopen error: could not get function caller."); return LLDB_INVALID_IMAGE_TOKEN; } - - addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); - if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) - return process->AddImageToken(image_ptr); - - if (image_ptr == 0) { - ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true); - if (error_str_sp) { - DataBufferSP buffer_sp(new DataBufferHeap(10240, 0)); - size_t num_chars = - error_str_sp->ReadPointedString(buffer_sp, error, 10240).first; - if (error.Success() && num_chars > 0) - error.SetErrorStringWithFormat("dlopen error: %s", - buffer_sp->GetBytes()); - else - error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); + arguments = do_dlopen_function->GetArgumentValues(); + + // Now insert the path we are searching for and the result structure into the + // target. + uint32_t permissions = ePermissionsReadable|ePermissionsWritable; + size_t path_len = path.size() + 1; + lldb::addr_t path_addr = process->AllocateMemory(path_len, + permissions, + utility_error); + if (path_addr == LLDB_INVALID_ADDRESS) { + error.SetErrorStringWithFormat("dlopen error: could not allocate memory" + "for path: %s", utility_error.AsCString()); + return LLDB_INVALID_IMAGE_TOKEN; + } + + // Make sure we deallocate the input string memory: + CleanUp path_cleanup([process, path_addr] { + process->DeallocateMemory(path_addr); + }); + + process->WriteMemory(path_addr, path.c_str(), path_len, utility_error); + if (utility_error.Fail()) { + error.SetErrorStringWithFormat("dlopen error: could not write path string:" + " %s", utility_error.AsCString()); + return LLDB_INVALID_IMAGE_TOKEN; + } + + // Make space for our return structure. It is two pointers big: the token + // and the error string. + const uint32_t addr_size = process->GetAddressByteSize(); + lldb::addr_t return_addr = process->CallocateMemory(2*addr_size, + permissions, + utility_error); + if (utility_error.Fail()) { + error.SetErrorStringWithFormat("dlopen error: could not allocate memory" + "for path: %s", utility_error.AsCString()); + return LLDB_INVALID_IMAGE_TOKEN; + } + + // Make sure we deallocate the result structure memory + CleanUp return_cleanup([process, return_addr] { + process->DeallocateMemory(return_addr); + }); + + // This will be the address of the storage for paths, if we are using them, + // or nullptr to signal we aren't. + lldb::addr_t path_array_addr = 0x0; + llvm::Optional<CleanUp> path_array_cleanup; + + // This is the address to a buffer large enough to hold the largest path + // conjoined with the library name we're passing in. This is a convenience + // to avoid having to call malloc in the dlopen function. + lldb::addr_t buffer_addr = 0x0; + llvm::Optional<CleanUp> buffer_cleanup; + + // Set the values into our args and write them to the target: + if (paths != nullptr) { + // First insert the paths into the target. This is expected to be a + // continuous buffer with the strings laid out null terminated and + // end to end with an empty string terminating the buffer. + // We also compute the buffer's required size as we go. + size_t buffer_size = 0; + std::string path_array; + for (auto path : *paths) { + // Don't insert empty paths, they will make us abort the path + // search prematurely. + if (path.empty()) + continue; + size_t path_size = path.size(); + path_array.append(path); + path_array.push_back('\0'); + if (path_size > buffer_size) + buffer_size = path_size; + } + path_array.push_back('\0'); + + path_array_addr = process->AllocateMemory(path_array.size(), + permissions, + utility_error); + if (path_array_addr == LLDB_INVALID_ADDRESS) { + error.SetErrorStringWithFormat("dlopen error: could not allocate memory" + "for path array: %s", + utility_error.AsCString()); + return LLDB_INVALID_IMAGE_TOKEN; + } + + // Make sure we deallocate the paths array. + path_array_cleanup.emplace([process, path_array_addr] { + process->DeallocateMemory(path_array_addr); + }); + + process->WriteMemory(path_array_addr, path_array.data(), + path_array.size(), utility_error); + + if (utility_error.Fail()) { + error.SetErrorStringWithFormat("dlopen error: could not write path array:" + " %s", utility_error.AsCString()); + return LLDB_INVALID_IMAGE_TOKEN; + } + // Now make spaces in the target for the buffer. We need to add one for + // the '/' that the utility function will insert and one for the '\0': + buffer_size += path.size() + 2; + + buffer_addr = process->AllocateMemory(buffer_size, + permissions, + utility_error); + if (buffer_addr == LLDB_INVALID_ADDRESS) { + error.SetErrorStringWithFormat("dlopen error: could not allocate memory" + "for buffer: %s", + utility_error.AsCString()); return LLDB_INVALID_IMAGE_TOKEN; } + + // Make sure we deallocate the buffer memory: + buffer_cleanup.emplace([process, buffer_addr] { + process->DeallocateMemory(buffer_addr); + }); } - error.SetErrorStringWithFormat("unable to load '%s'", path); + + arguments.GetValueAtIndex(0)->GetScalar() = path_addr; + arguments.GetValueAtIndex(1)->GetScalar() = path_array_addr; + arguments.GetValueAtIndex(2)->GetScalar() = buffer_addr; + arguments.GetValueAtIndex(3)->GetScalar() = return_addr; + + lldb::addr_t func_args_addr = LLDB_INVALID_ADDRESS; + + diagnostics.Clear(); + if (!do_dlopen_function->WriteFunctionArguments(exe_ctx, + func_args_addr, + arguments, + diagnostics)) { + error.SetErrorStringWithFormat("dlopen error: could not write function " + "arguments: %s", + diagnostics.GetString().c_str()); + return LLDB_INVALID_IMAGE_TOKEN; + } + + // Make sure we clean up the args structure. We can't reuse it because the + // Platform lives longer than the process and the Platforms don't get a + // signal to clean up cached data when a process goes away. + CleanUp args_cleanup([do_dlopen_function, &exe_ctx, func_args_addr] { + do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr); + }); + + // Now run the caller: + EvaluateExpressionOptions options; + options.SetExecutionPolicy(eExecutionPolicyAlways); + options.SetLanguage(eLanguageTypeC_plus_plus); + options.SetIgnoreBreakpoints(true); + options.SetUnwindOnError(true); + options.SetTrapExceptions(false); // dlopen can't throw exceptions, so + // don't do the work to trap them. + options.SetTimeout(std::chrono::seconds(2)); + + Value return_value; + // Fetch the clang types we will need: + ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext(); + + CompilerType clang_void_pointer_type + = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + + return_value.SetCompilerType(clang_void_pointer_type); + + ExpressionResults results = do_dlopen_function->ExecuteFunction( + exe_ctx, &func_args_addr, options, diagnostics, return_value); + if (results != eExpressionCompleted) { + error.SetErrorStringWithFormat("dlopen error: failed executing " + "dlopen wrapper function: %s", + diagnostics.GetString().c_str()); + return LLDB_INVALID_IMAGE_TOKEN; + } + + // Read the dlopen token from the return area: + lldb::addr_t token = process->ReadPointerFromMemory(return_addr, + utility_error); + if (utility_error.Fail()) { + error.SetErrorStringWithFormat("dlopen error: could not read the return " + "struct: %s", utility_error.AsCString()); + return LLDB_INVALID_IMAGE_TOKEN; + } + + // The dlopen succeeded! + if (token != 0x0) { + if (loaded_image && buffer_addr != 0x0) + { + // Capture the image which was loaded. We leave it in the buffer on + // exit from the dlopen function, so we can just read it from there: + std::string name_string; + process->ReadCStringFromMemory(buffer_addr, name_string, utility_error); + if (utility_error.Success()) + loaded_image->SetFile(name_string, false, + llvm::sys::path::Style::posix); + } + return process->AddImageToken(token); + } + + // We got an error, lets read in the error string: + std::string dlopen_error_str; + lldb::addr_t error_addr + = process->ReadPointerFromMemory(return_addr + addr_size, utility_error); + if (utility_error.Fail()) { + error.SetErrorStringWithFormat("dlopen error: could not read error string: " + "%s", utility_error.AsCString()); + return LLDB_INVALID_IMAGE_TOKEN; + } + + size_t num_chars = process->ReadCStringFromMemory(error_addr + addr_size, + dlopen_error_str, + utility_error); + if (utility_error.Success() && num_chars > 0) + error.SetErrorStringWithFormat("dlopen error: %s", + dlopen_error_str.c_str()); + else + error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); + return LLDB_INVALID_IMAGE_TOKEN; } diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 93bebeb332ca..cc6f7299c194 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -85,7 +85,7 @@ public: const lldb::UnixSignalsSP &GetRemoteUnixSignals() override; - size_t GetEnvironment(lldb_private::StringList &environment) override; + lldb_private::Environment GetEnvironment() override; bool IsConnected() const override; @@ -99,8 +99,7 @@ public: // the process to exit std::string *command_output, // Pass nullptr if you don't want the command output - uint32_t timeout_sec) - override; // Timeout in seconds to wait for shell program to finish + const lldb_private::Timeout<std::micro> &timeout) override; lldb_private::Status ResolveExecutable( const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, @@ -166,7 +165,9 @@ public: uint32_t DoLoadImage(lldb_private::Process *process, const lldb_private::FileSpec &remote_file, - lldb_private::Status &error) override; + const std::vector<std::string> *paths, + lldb_private::Status &error, + lldb_private::FileSpec *loaded_image) override; lldb_private::Status UnloadImage(lldb_private::Process *process, uint32_t image_token) override; @@ -201,6 +202,10 @@ protected: llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp); + std::unique_ptr<lldb_private::UtilityFunction> + MakeLoadImageUtilityFunction(lldb_private::ExecutionContext &exe_ctx, + lldb_private::Status &error); + virtual llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process); diff --git a/source/Plugins/Platform/Windows/PlatformWindows.cpp b/source/Plugins/Platform/Windows/PlatformWindows.cpp index 3535df0c65cc..ed2bcf0cbee4 100644 --- a/source/Plugins/Platform/Windows/PlatformWindows.cpp +++ b/source/Plugins/Platform/Windows/PlatformWindows.cpp @@ -194,7 +194,8 @@ Status PlatformWindows::ResolveExecutable( // variables if (!resolved_module_spec.GetFileSpec().Exists()) { resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); - resolved_module_spec.GetFileSpec().SetFile(exe_path, true); + resolved_module_spec.GetFileSpec().SetFile(exe_path, true, + FileSpec::Style::native); } if (!resolved_module_spec.GetFileSpec().Exists()) @@ -237,9 +238,9 @@ Status PlatformWindows::ResolveExecutable( resolved_module_spec.GetArchitecture().GetArchitectureName()); } } else { - // No valid architecture was specified, ask the platform for - // the architectures that we should be using (in the correct order) - // and see if we can find a match that way + // No valid architecture was specified, ask the platform for the + // architectures that we should be using (in the correct order) and see + // if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( idx, resolved_module_spec.GetArchitecture()); @@ -279,9 +280,10 @@ Status PlatformWindows::ResolveExecutable( } bool PlatformWindows::GetRemoteOSVersion() { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetOSVersion( - m_major_os_version, m_minor_os_version, m_update_os_version); + if (m_remote_platform_sp) { + m_os_version = m_remote_platform_sp->GetOSVersion(); + return !m_os_version.empty(); + } return false; } @@ -413,29 +415,23 @@ ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, Status &error) { // Windows has special considerations that must be followed when launching or - // attaching to a process. The - // key requirement is that when launching or attaching to a process, you must - // do it from the same the thread - // that will go into a permanent loop which will then receive debug events - // from the process. In particular, - // this means we can't use any of LLDB's generic mechanisms to do it for us, - // because it doesn't have the - // special knowledge required for setting up the background thread or passing - // the right flags. + // attaching to a process. The key requirement is that when launching or + // attaching to a process, you must do it from the same the thread that will + // go into a permanent loop which will then receive debug events from the + // process. In particular, this means we can't use any of LLDB's generic + // mechanisms to do it for us, because it doesn't have the special knowledge + // required for setting up the background thread or passing the right flags. // // Another problem is that that LLDB's standard model for debugging a process - // is to first launch it, have - // it stop at the entry point, and then attach to it. In Windows this doesn't - // quite work, you have to - // specify as an argument to CreateProcess() that you're going to debug the - // process. So we override DebugProcess - // here to handle this. Launch operations go directly to the process plugin, - // and attach operations almost go - // directly to the process plugin (but we hijack the events first). In - // essence, we encapsulate all the logic - // of Launching and Attaching in the process plugin, and - // PlatformWindows::DebugProcess is just a pass-through - // to get to the process plugin. + // is to first launch it, have it stop at the entry point, and then attach to + // it. In Windows this doesn't quite work, you have to specify as an + // argument to CreateProcess() that you're going to debug the process. So we + // override DebugProcess here to handle this. Launch operations go directly + // to the process plugin, and attach operations almost go directly to the + // process plugin (but we hijack the events first). In essence, we + // encapsulate all the logic of Launching and Attaching in the process + // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to + // the process plugin. if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { // This is a process attach. Don't need to launch anything. @@ -538,8 +534,8 @@ Status PlatformWindows::GetSharedModule( module_sp.reset(); if (IsRemote()) { - // If we have a remote platform always, let it try and locate - // the shared module first. + // 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( module_spec, process, module_sp, module_search_paths_ptr, @@ -572,29 +568,21 @@ void PlatformWindows::GetStatus(Stream &strm) { Platform::GetStatus(strm); #ifdef _WIN32 - uint32_t major; - uint32_t minor; - uint32_t update; - if (!HostInfo::GetOSVersion(major, minor, update)) { - strm << "Windows"; - return; - } - - strm << "Host: Windows " << major << '.' << minor << " Build: " << update - << '\n'; + llvm::VersionTuple version = HostInfo::GetOSVersion(); + strm << "Host: Windows " << version.getAsString() << '\n'; #endif } bool PlatformWindows::CanDebugProcess() { return true; } -size_t PlatformWindows::GetEnvironment(StringList &env) { +Environment PlatformWindows::GetEnvironment() { if (IsRemote()) { if (m_remote_platform_sp) - return m_remote_platform_sp->GetEnvironment(env); - return 0; + return m_remote_platform_sp->GetEnvironment(); + return Environment(); } - return Host::GetEnvironment(env); + return Host::GetEnvironment(); } ConstString PlatformWindows::GetFullNameForDylib(ConstString basename) { diff --git a/source/Plugins/Platform/Windows/PlatformWindows.h b/source/Plugins/Platform/Windows/PlatformWindows.h index 9af42116680e..3a15271c5762 100644 --- a/source/Plugins/Platform/Windows/PlatformWindows.h +++ b/source/Plugins/Platform/Windows/PlatformWindows.h @@ -118,7 +118,7 @@ public: bool CanDebugProcess() override; - size_t GetEnvironment(StringList &env) override; + Environment GetEnvironment() override; // FIXME not sure what the _sigtramp equivalent would be on this platform void CalculateTrapHandlerSymbolNames() override {} diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 759ec7fd1d29..348bb825a5c5 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -118,9 +118,9 @@ Status PlatformRemoteGDBServer::ResolveExecutable( return error; exe_module_sp.reset(); } - // No valid architecture was specified or the exact arch wasn't - // found so ask the platform for the architectures that we should be - // using (in the correct order) and see if we can find a match that way + // No valid architecture was specified or the exact arch wasn't found so + // ask the platform for the architectures that we should be using (in the + // correct order) and see if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( idx, resolved_module_spec.GetArchitecture()); @@ -236,14 +236,8 @@ size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode( } bool PlatformRemoteGDBServer::GetRemoteOSVersion() { - uint32_t major, minor, update; - if (m_gdb_client.GetOSVersion(major, minor, update)) { - m_major_os_version = major; - m_minor_os_version = minor; - m_update_os_version = update; - return true; - } - return false; + m_os_version = m_gdb_client.GetOSVersion(); + return !m_os_version.empty(); } bool PlatformRemoteGDBServer::GetRemoteOSBuildString(std::string &s) { @@ -277,8 +271,7 @@ bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory( const FileSpec &working_dir) { if (IsConnected()) { // Clear the working directory it case it doesn't get set correctly. This - // will - // for use to re-read it + // will for use to re-read it Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); if (log) log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", @@ -423,16 +416,7 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { } // Send the environment and the program + arguments after we connect - const char **envp = - launch_info.GetEnvironmentEntries().GetConstArgumentVector(); - - if (envp) { - const char *env_entry; - for (int i = 0; (env_entry = envp[i]); ++i) { - if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0) - break; - } - } + m_gdb_client.SendEnvironment(launch_info.GetEnvironment()); ArchSpec arch_spec = launch_info.GetArchitecture(); const char *arch_triple = arch_spec.GetTriple().str().c_str(); @@ -549,9 +533,8 @@ bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, bool launch_result = false; if (remote_triple.getVendor() == llvm::Triple::Apple && remote_triple.getOS() == llvm::Triple::IOS) { - // When remote debugging to iOS, we use a USB mux that always talks - // to localhost, so we will need the remote debugserver to accept - // connections + // When remote debugging to iOS, we use a USB mux that always talks to + // localhost, so we will need the remote debugserver to accept connections // only from localhost, no matter what our current hostname is launch_result = m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name); @@ -731,11 +714,9 @@ Status PlatformRemoteGDBServer::RunShellCommand( // process to exit std::string *command_output, // Pass NULL if you don't want the command output - uint32_t - timeout_sec) // Timeout in seconds to wait for shell program to finish -{ + const Timeout<std::micro> &timeout) { return m_gdb_client.RunShellCommand(command, working_dir, status_ptr, - signo_ptr, command_output, timeout_sec); + signo_ptr, command_output, timeout); } void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() { @@ -749,8 +730,8 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() { if (m_remote_signals_sp) return m_remote_signals_sp; - // If packet not implemented or JSON failed to parse, - // we'll guess the signal set based on the remote architecture. + // If packet not implemented or JSON failed to parse, we'll guess the signal + // set based on the remote architecture. m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture()); StringExtractorGDBRemote response; diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 210544f752e6..a31933b5d9b0 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -17,7 +17,7 @@ // Other libraries and framework includes // Project includes -#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h" +#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" #include "Plugins/Process/Utility/GDBRemoteSignals.h" #include "lldb/Target/Platform.h" @@ -155,8 +155,7 @@ public: // process to exit std::string *command_output, // Pass NULL if you don't want the command output - uint32_t timeout_sec) - override; // Timeout in seconds to wait for shell program to finish + const lldb_private::Timeout<std::micro> &timeout) override; void CalculateTrapHandlerSymbolNames() override; |
