diff options
Diffstat (limited to 'source/Host/common/Host.cpp')
| -rw-r--r-- | source/Host/common/Host.cpp | 423 | 
1 files changed, 53 insertions, 370 deletions
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); +}  | 
