diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:33:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:33:56 +0000 |
commit | fdea456ad833fbab0d3a296a58250950f11a498c (patch) | |
tree | 3db481072633e348326ee97c01d69518ed66b145 /source/Host | |
parent | 4befb1f96d641a958548654b2c3b674f0ce8404c (diff) |
Notes
Diffstat (limited to 'source/Host')
-rw-r--r-- | source/Host/CMakeLists.txt | 6 | ||||
-rw-r--r-- | source/Host/common/Host.cpp | 423 | ||||
-rw-r--r-- | source/Host/common/NativeProcessProtocol.cpp | 38 | ||||
-rw-r--r-- | source/Host/macosx/Host.mm | 299 | ||||
-rw-r--r-- | source/Host/posix/ProcessLauncherPosix.cpp | 34 | ||||
-rw-r--r-- | source/Host/posix/ProcessLauncherPosixFork.cpp | 8 | ||||
-rw-r--r-- | source/Host/windows/Host.cpp | 13 |
7 files changed, 365 insertions, 456 deletions
diff --git a/source/Host/CMakeLists.txt b/source/Host/CMakeLists.txt index 2a73c30f85243..b9079ce26a2c6 100644 --- a/source/Host/CMakeLists.txt +++ b/source/Host/CMakeLists.txt @@ -90,12 +90,6 @@ else() posix/ProcessLauncherPosixFork.cpp ) - if (NOT (CMAKE_SYSTEM_NAME MATCHES "Android")) - add_host_subdirectory(posix - posix/ProcessLauncherPosix.cpp - ) - endif() - if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR}) add_host_subdirectory(macosx diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index d78961e5bffc3..af0b572489225 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -68,15 +68,14 @@ #include "lldb/Utility/Status.h" #include "lldb/lldb-private-forward.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #if defined(_WIN32) #include "lldb/Host/windows/ProcessLauncherWindows.h" -#elif defined(__linux__) || defined(__NetBSD__) -#include "lldb/Host/posix/ProcessLauncherPosixFork.h" #else -#include "lldb/Host/posix/ProcessLauncherPosix.h" +#include "lldb/Host/posix/ProcessLauncherPosixFork.h" #endif #if defined(__APPLE__) @@ -407,25 +406,6 @@ const char *Host::GetSignalAsCString(int signo) { #endif -#ifndef _WIN32 - -lldb::thread_key_t -Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { - pthread_key_t key; - ::pthread_key_create(&key, callback); - return key; -} - -void *Host::ThreadLocalStorageGet(lldb::thread_key_t key) { - return ::pthread_getspecific(key); -} - -void Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) { - ::pthread_setspecific(key, value); -} - -#endif - #if !defined(__APPLE__) // see Host.mm bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle) { @@ -602,359 +582,14 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, return error; } -// LaunchProcessPosixSpawn for Apple, Linux, FreeBSD, NetBSD and other GLIBC -// systems - -#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || \ - defined(__GLIBC__) || defined(__NetBSD__) -#if !defined(__ANDROID__) -// this method needs to be visible to macosx/Host.cpp and -// common/Host.cpp. - -short Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) { - short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; - -#if defined(__APPLE__) - if (launch_info.GetFlags().Test(eLaunchFlagExec)) - flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag - - if (launch_info.GetFlags().Test(eLaunchFlagDebug)) - flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag - - if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR)) - flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag - - if (launch_info.GetLaunchInSeparateProcessGroup()) - flags |= POSIX_SPAWN_SETPGROUP; - -#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT -#if defined(__APPLE__) && (defined(__x86_64__) || defined(__i386__)) - static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; - if (g_use_close_on_exec_flag == eLazyBoolCalculate) { - g_use_close_on_exec_flag = eLazyBoolNo; - - uint32_t major, minor, update; - if (HostInfo::GetOSVersion(major, minor, update)) { - // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or - // earlier - if (major > 10 || (major == 10 && minor > 7)) { - // Only enable for 10.8 and later OS versions - g_use_close_on_exec_flag = eLazyBoolYes; - } - } - } -#else - static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; -#endif - // Close all files exception those with file actions if this is supported. - if (g_use_close_on_exec_flag == eLazyBoolYes) - flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; -#endif -#endif // #if defined (__APPLE__) - return flags; -} - -Status Host::LaunchProcessPosixSpawn(const char *exe_path, - const ProcessLaunchInfo &launch_info, - lldb::pid_t &pid) { - Status error; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | - LIBLLDB_LOG_PROCESS)); - - posix_spawnattr_t attr; - error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX); - - if (error.Fail()) { - LLDB_LOG(log, "error: {0}, ::posix_spawnattr_init ( &attr )", error); - return error; - } - - // Make a quick class that will cleanup the posix spawn attributes in case - // we return in the middle of this function. - lldb_utility::CleanUp<posix_spawnattr_t *, int> posix_spawnattr_cleanup( - &attr, posix_spawnattr_destroy); - - sigset_t no_signals; - sigset_t all_signals; - sigemptyset(&no_signals); - sigfillset(&all_signals); - ::posix_spawnattr_setsigmask(&attr, &no_signals); -#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) - ::posix_spawnattr_setsigdefault(&attr, &no_signals); -#else - ::posix_spawnattr_setsigdefault(&attr, &all_signals); -#endif - - short flags = GetPosixspawnFlags(launch_info); - - error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX); - if (error.Fail()) { - LLDB_LOG(log, - "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )", - error, flags); - return error; - } - -// posix_spawnattr_setbinpref_np appears to be an Apple extension per: -// http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ -#if defined(__APPLE__) && !defined(__arm__) - - // Don't set the binpref if a shell was provided. After all, that's only - // going to affect what version of the shell - // is launched, not what fork of the binary is launched. We insert "arch - // --arch <ARCH> as part of the shell invocation - // to do that job on OSX. - - if (launch_info.GetShell() == nullptr) { - // We don't need to do this for ARM, and we really shouldn't now that we - // have multiple CPU subtypes and no posix_spawnattr call that allows us - // to set which CPU subtype to launch... - const ArchSpec &arch_spec = launch_info.GetArchitecture(); - cpu_type_t cpu = arch_spec.GetMachOCPUType(); - cpu_type_t sub = arch_spec.GetMachOCPUSubType(); - if (cpu != 0 && cpu != static_cast<cpu_type_t>(UINT32_MAX) && - cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE) && - !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try - // to set the CPU type or we will fail - { - size_t ocount = 0; - error.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu, &ocount), - eErrorTypePOSIX); - if (error.Fail()) - LLDB_LOG(log, "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, " - "cpu_type = {1:x}, count => {2} )", - error, cpu, ocount); - - if (error.Fail() || ocount != 1) - return error; - } - } - -#endif - - const char *tmp_argv[2]; - char *const *argv = const_cast<char *const *>( - launch_info.GetArguments().GetConstArgumentVector()); - char *const *envp = const_cast<char *const *>( - launch_info.GetEnvironmentEntries().GetConstArgumentVector()); - if (argv == NULL) { - // posix_spawn gets very unhappy if it doesn't have at least the program - // name in argv[0]. One of the side affects I have noticed is the - // environment - // variables don't make it into the child process if "argv == NULL"!!! - tmp_argv[0] = exe_path; - tmp_argv[1] = NULL; - argv = const_cast<char *const *>(tmp_argv); - } - +// The functions below implement process launching for non-Apple-based platforms #if !defined(__APPLE__) - // manage the working directory - char current_dir[PATH_MAX]; - current_dir[0] = '\0'; -#endif - - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir) { -#if defined(__APPLE__) - // Set the working directory on this thread only - if (__pthread_chdir(working_dir.GetCString()) < 0) { - if (errno == ENOENT) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - } else if (errno == ENOTDIR) { - error.SetErrorStringWithFormat("Path doesn't name a directory: %s", - working_dir.GetCString()); - } else { - error.SetErrorStringWithFormat("An unknown error occurred when " - "changing directory for process " - "execution."); - } - return error; - } -#else - if (::getcwd(current_dir, sizeof(current_dir)) == NULL) { - error.SetError(errno, eErrorTypePOSIX); - LLDB_LOG(log, "error: {0}, unable to save the current directory", error); - return error; - } - - if (::chdir(working_dir.GetCString()) == -1) { - error.SetError(errno, eErrorTypePOSIX); - LLDB_LOG(log, "error: {0}, unable to change working directory to {1}", - error, working_dir); - return error; - } -#endif - } - - ::pid_t result_pid = LLDB_INVALID_PROCESS_ID; - const size_t num_file_actions = launch_info.GetNumFileActions(); - if (num_file_actions > 0) { - posix_spawn_file_actions_t file_actions; - error.SetError(::posix_spawn_file_actions_init(&file_actions), - eErrorTypePOSIX); - if (error.Fail()) { - LLDB_LOG(log, - "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )", - error); - return error; - } - - // Make a quick class that will cleanup the posix spawn attributes in case - // we return in the middle of this function. - lldb_utility::CleanUp<posix_spawn_file_actions_t *, int> - posix_spawn_file_actions_cleanup(&file_actions, - posix_spawn_file_actions_destroy); - - for (size_t i = 0; i < num_file_actions; ++i) { - const FileAction *launch_file_action = - launch_info.GetFileActionAtIndex(i); - if (launch_file_action) { - if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, - error)) - return error; - } - } - - error.SetError( - ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), - eErrorTypePOSIX); - - if (error.Fail()) { - LLDB_LOG(log, "error: {0}, ::posix_spawnp(pid => {1}, path = '{2}', " - "file_actions = {3}, " - "attr = {4}, argv = {5}, envp = {6} )", - error, result_pid, exe_path, &file_actions, &attr, argv, envp); - if (log) { - for (int ii = 0; argv[ii]; ++ii) - LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]); - } - } - - } else { - error.SetError( - ::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), - eErrorTypePOSIX); - - if (error.Fail()) { - LLDB_LOG(log, "error: {0}, ::posix_spawnp ( pid => {1}, path = '{2}', " - "file_actions = NULL, attr = {3}, argv = {4}, envp = {5} )", - error, result_pid, exe_path, &attr, argv, envp); - if (log) { - for (int ii = 0; argv[ii]; ++ii) - LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]); - } - } - } - pid = result_pid; - - if (working_dir) { -#if defined(__APPLE__) - // No more thread specific current working directory - __pthread_fchdir(-1); -#else - if (::chdir(current_dir) == -1 && error.Success()) { - error.SetError(errno, eErrorTypePOSIX); - LLDB_LOG(log, - "error: {0}, unable to change current directory back to {1}", - error, current_dir); - } -#endif - } - - return error; -} - -bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, - Log *log, Status &error) { - if (info == NULL) - return false; - - posix_spawn_file_actions_t *file_actions = - reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions); - - switch (info->GetAction()) { - case FileAction::eFileActionNone: - error.Clear(); - break; - - case FileAction::eFileActionClose: - if (info->GetFD() == -1) - error.SetErrorString( - "invalid fd for posix_spawn_file_actions_addclose(...)"); - else { - error.SetError( - ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), - eErrorTypePOSIX); - if (error.Fail()) - LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_addclose " - "(action={1}, fd={2})", - error, file_actions, info->GetFD()); - } - break; - - case FileAction::eFileActionDuplicate: - if (info->GetFD() == -1) - error.SetErrorString( - "invalid fd for posix_spawn_file_actions_adddup2(...)"); - else if (info->GetActionArgument() == -1) - error.SetErrorString( - "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); - else { - error.SetError( - ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), - info->GetActionArgument()), - eErrorTypePOSIX); - if (error.Fail()) - LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_adddup2 " - "(action={1}, fd={2}, dup_fd={3})", - error, file_actions, info->GetFD(), info->GetActionArgument()); - } - break; - - case FileAction::eFileActionOpen: - if (info->GetFD() == -1) - error.SetErrorString( - "invalid fd in posix_spawn_file_actions_addopen(...)"); - else { - int oflag = info->GetActionArgument(); - - mode_t mode = 0; - - if (oflag & O_CREAT) - mode = 0640; - - error.SetError(::posix_spawn_file_actions_addopen( - file_actions, info->GetFD(), - info->GetPath().str().c_str(), oflag, mode), - eErrorTypePOSIX); - if (error.Fail()) - LLDB_LOG( - log, "error: {0}, posix_spawn_file_actions_addopen (action={1}, " - "fd={2}, path='{3}', oflag={4}, mode={5})", - error, file_actions, info->GetFD(), info->GetPath(), oflag, mode); - } - break; - } - return error.Success(); -} -#endif // !defined(__ANDROID__) -#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || - // defined (__GLIBC__) || defined(__NetBSD__) - -#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || \ - defined(__NetBSD__) || defined(_WIN32) -// The functions below implement process launching via posix_spawn() for Linux, -// FreeBSD and NetBSD. - Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { std::unique_ptr<ProcessLauncher> delegate_launcher; #if defined(_WIN32) delegate_launcher.reset(new ProcessLauncherWindows()); -#elif defined(__linux__) || defined(__NetBSD__) - delegate_launcher.reset(new ProcessLauncherPosixFork()); #else - delegate_launcher.reset(new ProcessLauncherPosix()); + delegate_launcher.reset(new ProcessLauncherPosixFork()); #endif MonitoringProcessLauncher launcher(std::move(delegate_launcher)); @@ -968,7 +603,7 @@ Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { return error; } -#endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) +#endif // !defined(__APPLE__) #ifndef _WIN32 void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); } @@ -988,3 +623,51 @@ const UnixSignalsSP &Host::GetUnixSignals() { UnixSignals::Create(HostInfo::GetArchitecture()); return s_unix_signals_sp; } + +#if defined(LLVM_ON_UNIX) +WaitStatus WaitStatus::Decode(int wstatus) { + if (WIFEXITED(wstatus)) + return {Exit, uint8_t(WEXITSTATUS(wstatus))}; + else if (WIFSIGNALED(wstatus)) + return {Signal, uint8_t(WTERMSIG(wstatus))}; + else if (WIFSTOPPED(wstatus)) + return {Stop, uint8_t(WSTOPSIG(wstatus))}; + llvm_unreachable("Unknown wait status"); +} +#endif + +void llvm::format_provider<WaitStatus>::format(const WaitStatus &WS, + raw_ostream &OS, + StringRef Options) { + if (Options == "g") { + char type; + switch (WS.type) { + case WaitStatus::Exit: + type = 'W'; + break; + case WaitStatus::Signal: + type = 'X'; + break; + case WaitStatus::Stop: + type = 'S'; + break; + } + OS << formatv("{0}{1:x-2}", type, WS.status); + return; + } + + assert(Options.empty()); + const char *desc; + switch(WS.type) { + case WaitStatus::Exit: + desc = "Exited with status"; + break; + case WaitStatus::Signal: + desc = "Killed by signal"; + break; + case WaitStatus::Stop: + desc = "Stopped by signal"; + break; + } + OS << desc << " " << int(WS.status); +} diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index 6f1a9f895b618..341c301dc9c54 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -32,7 +32,6 @@ using namespace lldb_private; NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid) : m_pid(pid), m_threads(), m_current_thread_id(LLDB_INVALID_THREAD_ID), m_threads_mutex(), m_state(lldb::eStateInvalid), m_state_mutex(), - m_exit_type(eExitTypeInvalid), m_exit_status(0), m_exit_description(), m_delegates_mutex(), m_delegates(), m_breakpoint_list(), m_watchpoint_list(), m_terminal_fd(-1), m_stop_id(0) {} @@ -59,46 +58,29 @@ NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr, return Status("not implemented"); } -bool NativeProcessProtocol::GetExitStatus(ExitType *exit_type, int *status, - std::string &exit_description) { - if (m_state == lldb::eStateExited) { - *exit_type = m_exit_type; - *status = m_exit_status; - exit_description = m_exit_description; - return true; - } +llvm::Optional<WaitStatus> NativeProcessProtocol::GetExitStatus() { + if (m_state == lldb::eStateExited) + return m_exit_status; - *status = 0; - return false; + return llvm::None; } -bool NativeProcessProtocol::SetExitStatus(ExitType exit_type, int status, - const char *exit_description, +bool NativeProcessProtocol::SetExitStatus(WaitStatus status, bool bNotifyStateChange) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessProtocol::%s(%d, %d, %s, %s) called", - __FUNCTION__, exit_type, status, - exit_description ? exit_description : "nullptr", - bNotifyStateChange ? "true" : "false"); + LLDB_LOG(log, "status = {0}, notify = {1}", status, bNotifyStateChange); // Exit status already set if (m_state == lldb::eStateExited) { - if (log) - log->Printf("NativeProcessProtocol::%s exit status already set to %d, " - "ignoring new set to %d", - __FUNCTION__, m_exit_status, status); + if (m_exit_status) + LLDB_LOG(log, "exit status already set to {0}", *m_exit_status); + else + LLDB_LOG(log, "state is exited, but status not set"); return false; } m_state = lldb::eStateExited; - - m_exit_type = exit_type; m_exit_status = status; - if (exit_description && exit_description[0]) - m_exit_description = exit_description; - else - m_exit_description.clear(); if (bNotifyStateChange) SynchronouslyNotifyProcessStateChanged(lldb::eStateExited); diff --git a/source/Host/macosx/Host.mm b/source/Host/macosx/Host.mm index be205f953862b..919b35624e60b 100644 --- a/source/Host/macosx/Host.mm +++ b/source/Host/macosx/Host.mm @@ -1024,6 +1024,47 @@ static Status getXPCAuthorization(ProcessLaunchInfo &launch_info) { } #endif +static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) { + short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; + + if (launch_info.GetFlags().Test(eLaunchFlagExec)) + flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag + + if (launch_info.GetFlags().Test(eLaunchFlagDebug)) + flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag + + if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR)) + flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag + + if (launch_info.GetLaunchInSeparateProcessGroup()) + flags |= POSIX_SPAWN_SETPGROUP; + +#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT +#if defined(__x86_64__) || defined(__i386__) + static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; + if (g_use_close_on_exec_flag == eLazyBoolCalculate) { + g_use_close_on_exec_flag = eLazyBoolNo; + + uint32_t major, minor, update; + if (HostInfo::GetOSVersion(major, minor, update)) { + // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or + // earlier + if (major > 10 || (major == 10 && minor > 7)) { + // Only enable for 10.8 and later OS versions + g_use_close_on_exec_flag = eLazyBoolYes; + } + } + } +#else + static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; +#endif // defined(__x86_64__) || defined(__i386__) + // Close all files exception those with file actions if this is supported. + if (g_use_close_on_exec_flag == eLazyBoolYes) + flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; +#endif // ifdef POSIX_SPAWN_CLOEXEC_DEFAULT + return flags; +} + static Status LaunchProcessXPC(const char *exe_path, ProcessLaunchInfo &launch_info, lldb::pid_t &pid) { @@ -1107,7 +1148,7 @@ static Status LaunchProcessXPC(const char *exe_path, xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey, launch_info.GetArchitecture().GetMachOCPUType()); xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, - Host::GetPosixspawnFlags(launch_info)); + GetPosixspawnFlags(launch_info)); const FileAction *file_action = launch_info.GetFileActionForFD(STDIN_FILENO); if (file_action && !file_action->GetPath().empty()) { xpc_dictionary_set_string(message, LauncherXPCServiceStdInPathKeyKey, @@ -1161,6 +1202,262 @@ static Status LaunchProcessXPC(const char *exe_path, #endif } +static bool AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, + Log *log, Status &error) { + if (info == NULL) + return false; + + posix_spawn_file_actions_t *file_actions = + reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions); + + switch (info->GetAction()) { + case FileAction::eFileActionNone: + error.Clear(); + break; + + case FileAction::eFileActionClose: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd for posix_spawn_file_actions_addclose(...)"); + else { + error.SetError( + ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), + eErrorTypePOSIX); + if (error.Fail()) + LLDB_LOG(log, + "error: {0}, posix_spawn_file_actions_addclose " + "(action={1}, fd={2})", + error, file_actions, info->GetFD()); + } + break; + + case FileAction::eFileActionDuplicate: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd for posix_spawn_file_actions_adddup2(...)"); + else if (info->GetActionArgument() == -1) + error.SetErrorString( + "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); + else { + error.SetError( + ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), + info->GetActionArgument()), + eErrorTypePOSIX); + if (error.Fail()) + LLDB_LOG(log, + "error: {0}, posix_spawn_file_actions_adddup2 " + "(action={1}, fd={2}, dup_fd={3})", + error, file_actions, info->GetFD(), info->GetActionArgument()); + } + break; + + case FileAction::eFileActionOpen: + if (info->GetFD() == -1) + error.SetErrorString( + "invalid fd in posix_spawn_file_actions_addopen(...)"); + else { + int oflag = info->GetActionArgument(); + + mode_t mode = 0; + + if (oflag & O_CREAT) + mode = 0640; + + error.SetError(::posix_spawn_file_actions_addopen( + file_actions, info->GetFD(), + info->GetPath().str().c_str(), oflag, mode), + eErrorTypePOSIX); + if (error.Fail()) + LLDB_LOG(log, + "error: {0}, posix_spawn_file_actions_addopen (action={1}, " + "fd={2}, path='{3}', oflag={4}, mode={5})", + error, file_actions, info->GetFD(), info->GetPath(), oflag, + mode); + } + break; + } + return error.Success(); +} + +static Status LaunchProcessPosixSpawn(const char *exe_path, + const ProcessLaunchInfo &launch_info, + lldb::pid_t &pid) { + Status error; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | + LIBLLDB_LOG_PROCESS)); + + posix_spawnattr_t attr; + error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX); + + if (error.Fail()) { + LLDB_LOG(log, "error: {0}, ::posix_spawnattr_init ( &attr )", error); + return error; + } + + // Make a quick class that will cleanup the posix spawn attributes in case + // we return in the middle of this function. + lldb_utility::CleanUp<posix_spawnattr_t *, int> posix_spawnattr_cleanup( + &attr, posix_spawnattr_destroy); + + sigset_t no_signals; + sigset_t all_signals; + sigemptyset(&no_signals); + sigfillset(&all_signals); + ::posix_spawnattr_setsigmask(&attr, &no_signals); + ::posix_spawnattr_setsigdefault(&attr, &all_signals); + + short flags = GetPosixspawnFlags(launch_info); + + error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX); + if (error.Fail()) { + LLDB_LOG(log, + "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )", + error, flags); + return error; + } + +// posix_spawnattr_setbinpref_np appears to be an Apple extension per: +// http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ +#if !defined(__arm__) + + // Don't set the binpref if a shell was provided. After all, that's only + // going to affect what version of the shell + // is launched, not what fork of the binary is launched. We insert "arch + // --arch <ARCH> as part of the shell invocation + // to do that job on OSX. + + if (launch_info.GetShell() == nullptr) { + // We don't need to do this for ARM, and we really shouldn't now that we + // have multiple CPU subtypes and no posix_spawnattr call that allows us + // to set which CPU subtype to launch... + const ArchSpec &arch_spec = launch_info.GetArchitecture(); + cpu_type_t cpu = arch_spec.GetMachOCPUType(); + cpu_type_t sub = arch_spec.GetMachOCPUSubType(); + if (cpu != 0 && cpu != static_cast<cpu_type_t>(UINT32_MAX) && + cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE) && + !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try + // to set the CPU type or we will fail + { + size_t ocount = 0; + error.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu, &ocount), + eErrorTypePOSIX); + if (error.Fail()) + LLDB_LOG(log, + "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, " + "cpu_type = {1:x}, count => {2} )", + error, cpu, ocount); + + if (error.Fail() || ocount != 1) + return error; + } + } +#endif // !defined(__arm__) + + const char *tmp_argv[2]; + char *const *argv = const_cast<char *const *>( + launch_info.GetArguments().GetConstArgumentVector()); + char *const *envp = const_cast<char *const *>( + launch_info.GetEnvironmentEntries().GetConstArgumentVector()); + if (argv == NULL) { + // posix_spawn gets very unhappy if it doesn't have at least the program + // name in argv[0]. One of the side affects I have noticed is the + // environment + // variables don't make it into the child process if "argv == NULL"!!! + tmp_argv[0] = exe_path; + tmp_argv[1] = NULL; + argv = const_cast<char *const *>(tmp_argv); + } + + FileSpec working_dir{launch_info.GetWorkingDirectory()}; + if (working_dir) { + // Set the working directory on this thread only + if (__pthread_chdir(working_dir.GetCString()) < 0) { + if (errno == ENOENT) { + error.SetErrorStringWithFormat("No such file or directory: %s", + working_dir.GetCString()); + } else if (errno == ENOTDIR) { + error.SetErrorStringWithFormat("Path doesn't name a directory: %s", + working_dir.GetCString()); + } else { + error.SetErrorStringWithFormat("An unknown error occurred when " + "changing directory for process " + "execution."); + } + return error; + } + } + + ::pid_t result_pid = LLDB_INVALID_PROCESS_ID; + const size_t num_file_actions = launch_info.GetNumFileActions(); + if (num_file_actions > 0) { + posix_spawn_file_actions_t file_actions; + error.SetError(::posix_spawn_file_actions_init(&file_actions), + eErrorTypePOSIX); + if (error.Fail()) { + LLDB_LOG(log, + "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )", + error); + return error; + } + + // Make a quick class that will cleanup the posix spawn attributes in case + // we return in the middle of this function. + lldb_utility::CleanUp<posix_spawn_file_actions_t *, int> + posix_spawn_file_actions_cleanup(&file_actions, + posix_spawn_file_actions_destroy); + + for (size_t i = 0; i < num_file_actions; ++i) { + const FileAction *launch_file_action = + launch_info.GetFileActionAtIndex(i); + if (launch_file_action) { + if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, + error)) + return error; + } + } + + error.SetError( + ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), + eErrorTypePOSIX); + + if (error.Fail()) { + LLDB_LOG(log, + "error: {0}, ::posix_spawnp(pid => {1}, path = '{2}', " + "file_actions = {3}, " + "attr = {4}, argv = {5}, envp = {6} )", + error, result_pid, exe_path, &file_actions, &attr, argv, envp); + if (log) { + for (int ii = 0; argv[ii]; ++ii) + LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]); + } + } + + } else { + error.SetError( + ::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), + eErrorTypePOSIX); + + if (error.Fail()) { + LLDB_LOG(log, + "error: {0}, ::posix_spawnp ( pid => {1}, path = '{2}', " + "file_actions = NULL, attr = {3}, argv = {4}, envp = {5} )", + error, result_pid, exe_path, &attr, argv, envp); + if (log) { + for (int ii = 0; argv[ii]; ++ii) + LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]); + } + } + } + pid = result_pid; + + if (working_dir) { + // No more thread specific current working directory + __pthread_fchdir(-1); + } + + return error; +} + static bool ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info) { bool result = false; diff --git a/source/Host/posix/ProcessLauncherPosix.cpp b/source/Host/posix/ProcessLauncherPosix.cpp deleted file mode 100644 index 6d07be1eec64c..0000000000000 --- a/source/Host/posix/ProcessLauncherPosix.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//===-- ProcessLauncherPosix.cpp --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/posix/ProcessLauncherPosix.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostProcess.h" - -#include "lldb/Target/ProcessLaunchInfo.h" - -#include <limits.h> - -using namespace lldb; -using namespace lldb_private; - -HostProcess -ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, - Status &error) { - lldb::pid_t pid; - char exe_path[PATH_MAX]; - - launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - - // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make - // MacOSX re-use this - // ProcessLauncher when it wants a posix_spawn launch. - error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid); - return HostProcess(pid); -} diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp index 1eace5cd24cdd..0b40c24256eff 100644 --- a/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -52,10 +52,10 @@ static void FixupEnvironment(Args &env) { static void LLVM_ATTRIBUTE_NORETURN ExitWithError(int error_fd, const char *operation) { - std::ostringstream os; - os << operation << " failed: " << strerror(errno); - write(error_fd, os.str().data(), os.str().size()); - close(error_fd); + int err = errno; + llvm::raw_fd_ostream os(error_fd, true); + os << operation << " failed: " << llvm::sys::StrError(err); + os.flush(); _exit(1); } diff --git a/source/Host/windows/Host.cpp b/source/Host/windows/Host.cpp index e1acd23d5c815..69a7c2ef4f74c 100644 --- a/source/Host/windows/Host.cpp +++ b/source/Host/windows/Host.cpp @@ -101,19 +101,6 @@ lldb::thread_t Host::GetCurrentThread() { return lldb::thread_t(::GetCurrentThread()); } -lldb::thread_key_t -Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { - return TlsAlloc(); -} - -void *Host::ThreadLocalStorageGet(lldb::thread_key_t key) { - return ::TlsGetValue(key); -} - -void Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) { - ::TlsSetValue(key, value); -} - void Host::Kill(lldb::pid_t pid, int signo) { TerminateProcess((HANDLE)pid, 1); } |