diff options
7 files changed, 139 insertions, 42 deletions
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index 103395cee2e..5c878c9b792 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -947,6 +947,29 @@ class ModuleCache; virtual const std::vector<ConstString> & GetTrapHandlerSymbolNames (); + + //------------------------------------------------------------------ + /// Find a support executable that may not live within in the + /// standard locations related to LLDB. + /// + /// Executable might exist within the Platform SDK directories, or + /// in standard tool directories within the current IDE that is + /// running LLDB. + /// + /// @param[in] basename + /// The basename of the executable to locate in the current + /// platform. + /// + /// @return + /// A FileSpec pointing to the executable on disk, or an invalid + /// FileSpec if the executable cannot be found. + //------------------------------------------------------------------ + virtual FileSpec + LocateExecutable (const char *basename) + { + return FileSpec(); + } + protected: bool m_is_host; // Set to true when we are able to actually set the OS version while diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index 26fc4b79d92..b9eb303edde 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -1211,11 +1211,13 @@ static const char *const sdk_strings[] = { static FileSpec GetXcodeContentsPath () { - const char substr[] = ".app/Contents/"; - - // First, try based on the current shlib's location + static FileSpec g_xcode_filespec; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + + const char substr[] = ".app/Contents/"; - { + // First, try based on the current shlib's location FileSpec fspec; if (HostInfo::GetLLDBPath (lldb::ePathTypeLLDBShlibDir, fspec)) @@ -1225,42 +1227,42 @@ GetXcodeContentsPath () if (pos != std::string::npos) { path_to_shlib.erase(pos + strlen(substr)); - return FileSpec(path_to_shlib.c_str(), false); + g_xcode_filespec = FileSpec(path_to_shlib.c_str(), false); } } - } - - // Fall back to using xcrun - - { - int status = 0; - int signo = 0; - std::string output; - const char *command = "xcrun -sdk macosx --show-sdk-path"; - lldb_private::Error error = Host::RunShellCommand (command, // shell command to run - NULL, // current working directory - &status, // Put the exit status of the process in here - &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 - if (status == 0 && !output.empty()) + + // Fall back to using xcrun + if (!g_xcode_filespec) { - size_t first_non_newline = output.find_last_not_of("\r\n"); - if (first_non_newline != std::string::npos) - { - output.erase(first_non_newline+1); - } - - size_t pos = output.rfind(substr); - if (pos != std::string::npos) + int status = 0; + int signo = 0; + std::string output; + const char *command = "xcrun -sdk macosx --show-sdk-path"; + lldb_private::Error error = Host::RunShellCommand (command, // shell command to run + NULL, // current working directory + &status, // Put the exit status of the process in here + &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 + if (status == 0 && !output.empty()) { - output.erase(pos + strlen(substr)); - return FileSpec(output.c_str(), false); + size_t first_non_newline = output.find_last_not_of("\r\n"); + if (first_non_newline != std::string::npos) + { + output.erase(first_non_newline+1); + } + + size_t pos = output.rfind(substr); + if (pos != std::string::npos) + { + output.erase(pos + strlen(substr)); + g_xcode_filespec = FileSpec(output.c_str(), false); + } } } - } + }); - return FileSpec(); + return g_xcode_filespec; } bool @@ -1543,3 +1545,59 @@ PlatformDarwin::GetFullNameForDylib (ConstString basename) return ConstString(stream.GetData()); } + +lldb_private::FileSpec +PlatformDarwin::LocateExecutable (const char *basename) +{ + // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled in with + // 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. + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + + // When locating executables, trust the DEVELOPER_DIR first if it is set + FileSpec xcode_contents_dir; + const char *developer_dir_env_var = getenv("DEVELOPER_DIR"); + if (developer_dir_env_var && developer_dir_env_var[0]) + { + xcode_contents_dir = FileSpec(developer_dir_env_var, true); + if (xcode_contents_dir.Exists()) + xcode_contents_dir.RemoveLastPathComponent(); + } + if (!xcode_contents_dir) + { + xcode_contents_dir = GetXcodeContentsPath(); + if (!xcode_contents_dir.Exists()) + xcode_contents_dir.Clear(); + } + if (xcode_contents_dir) + { + FileSpec xcode_lldb_resources = xcode_contents_dir; + xcode_lldb_resources.AppendPathComponent("SharedFrameworks"); + xcode_lldb_resources.AppendPathComponent("LLDB.framework"); + xcode_lldb_resources.AppendPathComponent("Resources"); + if (xcode_lldb_resources.Exists()) + { + FileSpec dir; + dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str()); + g_executable_dirs.push_back(dir); + } + } + }); + + // Now search the global list of executable directories for the executable we + // are looking for + for (const auto &executable_dir : g_executable_dirs) + { + FileSpec executable_file; + executable_file.GetDirectory() = executable_dir.GetDirectory(); + executable_file.GetFilename().SetCString(basename); + if (executable_file.Exists()) + return executable_file; + } + + return FileSpec(); +} diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h index ee604146e7a..4a9e1fc0eec 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -88,6 +88,9 @@ public: lldb_private::ConstString GetFullNameForDylib (lldb_private::ConstString basename) override; + lldb_private::FileSpec + LocateExecutable (const char *basename) override; + protected: void diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index e5ea80f2fae..0bbee854dc4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -30,6 +30,7 @@ #include "lldb/Host/StringConvert.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" +#include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "llvm/ADT/SmallString.h" @@ -1113,6 +1114,7 @@ GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg) Error GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, uint16_t in_port, + Platform *platform, ProcessLaunchInfo &launch_info, uint16_t &out_port) { @@ -1157,11 +1159,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, } else { - if (log) - log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); - + debugserver_file_spec = platform->LocateExecutable(DEBUGSERVER_BASENAME); + if (debugserver_file_spec) + { + // Platform::LocateExecutable() wouldn't return a path if it doesn't exist + debugserver_exists = true; + } + else + { + if (log) + log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); + } + // Don't cache the platform specific GDB server binary as it could change + // from platform to platform g_debugserver_file_spec.Clear(); - debugserver_file_spec.Clear(); } } } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 7379bb3aa09..94ffa512884 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -169,6 +169,7 @@ public: Error StartDebugserverProcess (const char *hostname, uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit + Platform *platform, // If non NULL, then check with the platform for the GDB server binary if it can't be located ProcessLaunchInfo &launch_info, uint16_t &out_port); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 742dee57ca5..592d7f7f27c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -138,11 +138,11 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); UNUSED_IF_ASSERT_DISABLED(ok); assert(ok); - Error error = StartDebugserverProcess ( - platform_ip.c_str(), - port, - debugserver_launch_info, - port); + Error error = StartDebugserverProcess (platform_ip.c_str(), + port, + nullptr, + debugserver_launch_info, + port); lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 84dc10a5afc..5b6f9794f5a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -3568,6 +3568,7 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info error = m_gdb_comm.StartDebugserverProcess (hostname, port, + GetTarget().GetPlatform().get(), debugserver_launch_info, port); |