summaryrefslogtreecommitdiff
path: root/source/Host
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-26 20:33:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-26 20:33:56 +0000
commitfdea456ad833fbab0d3a296a58250950f11a498c (patch)
tree3db481072633e348326ee97c01d69518ed66b145 /source/Host
parent4befb1f96d641a958548654b2c3b674f0ce8404c (diff)
Notes
Diffstat (limited to 'source/Host')
-rw-r--r--source/Host/CMakeLists.txt6
-rw-r--r--source/Host/common/Host.cpp423
-rw-r--r--source/Host/common/NativeProcessProtocol.cpp38
-rw-r--r--source/Host/macosx/Host.mm299
-rw-r--r--source/Host/posix/ProcessLauncherPosix.cpp34
-rw-r--r--source/Host/posix/ProcessLauncherPosixFork.cpp8
-rw-r--r--source/Host/windows/Host.cpp13
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);
}