Example #1
0
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.empty()) {
      result.AppendErrorWithFormat(
          "%s takes a log channel and one or more log types.\n",
          m_cmd_name.c_str());
      return false;
    }

    Log::Callbacks log_callbacks;

    const std::string channel = args.GetArgumentAtIndex(0);
    args.Shift(); // Shift off the channel
    if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) {
      log_callbacks.disable(args.GetConstArgumentVector(),
                            &result.GetErrorStream());
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else if (channel == "all") {
      Log::DisableAllLogChannels(&result.GetErrorStream());
    } else {
      LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel.data()));
      if (log_channel_sp) {
        log_channel_sp->Disable(args.GetConstArgumentVector(),
                                &result.GetErrorStream());
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
      } else
        result.AppendErrorWithFormat("Invalid log channel '%s'.\n",
                                     channel.data());
    }
    return result.Succeeded();
  }
Example #2
0
 virtual bool
 DoExecute (Args& args,
          CommandReturnObject &result)
 {
     if (args.GetArgumentCount() < 2)
     {
         result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str());
     }
     else
     {
         std::string channel(args.GetArgumentAtIndex(0));
         args.Shift ();  // Shift off the channel
         char log_file[PATH_MAX];
         if (m_options.log_file)
             m_options.log_file.GetPath(log_file, sizeof(log_file));
         else
             log_file[0] = '\0';
         bool success = m_interpreter.GetDebugger().EnableLog (channel.c_str(), 
                                                               args.GetConstArgumentVector(), 
                                                               log_file, 
                                                               m_options.log_options, 
                                                               result.GetErrorStream());
         if (success)
             result.SetStatus (eReturnStatusSuccessFinishNoResult);
         else
             result.SetStatus (eReturnStatusFailed);
     }    
     return result.Succeeded();
 }
HostProcess
ProcessLauncherAndroid::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
{
    // TODO: Handle other launch parameters specified in launc_info

    char exe_path[PATH_MAX];
    launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));

    lldb::pid_t pid = ::fork();
    if (pid == static_cast<lldb::pid_t>(-1))
    {
        // Fork failed
        error.SetErrorStringWithFormat("Fork failed with error message: %s", strerror(errno));
        return HostProcess(LLDB_INVALID_PROCESS_ID);
    }
    else if (pid == 0)
    {
        if (const lldb_private::FileAction *file_action = launch_info.GetFileActionForFD(STDIN_FILENO)) {
            const char* path = file_action->GetPath();
            if (path && ::strlen(path))
                if (!DupDescriptor(path, STDIN_FILENO, O_RDONLY))
                    exit(-1);
        }

        if (const lldb_private::FileAction *file_action = launch_info.GetFileActionForFD(STDOUT_FILENO)) {
            const char* path = file_action->GetPath();
            if (path && ::strlen(path))
                if (!DupDescriptor(path, STDOUT_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
                    exit(-1);
        }

        if (const lldb_private::FileAction *file_action = launch_info.GetFileActionForFD(STDERR_FILENO)) {
            const char* path = file_action->GetPath();
            if (path && ::strlen(path))
                if (!DupDescriptor(path, STDERR_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
                    exit(-1);
        }

        // Child process
        const char **argv = launch_info.GetArguments().GetConstArgumentVector();

        Args env = launch_info.GetEnvironmentEntries();
        FixupEnvironment(env);
        const char **envp = env.GetConstArgumentVector();

        const char *working_dir = launch_info.GetWorkingDirectory();
        if (working_dir != nullptr && working_dir[0])
        {
            if (::chdir(working_dir) != 0)
                exit(-1);
        }

        execve(argv[0],
               const_cast<char *const *>(argv),
               const_cast<char *const *>(envp));
        exit(-1);
    }
   
    return HostProcess(pid);
}
// If there is no PATH variable specified inside the environment then set the path to /system/bin.
// It is required because the default path used by execve() is wrong on android.
static void
FixupEnvironment(Args& env)
{
    static const char* path = "PATH=";
    static const int path_len = ::strlen(path);
    for (const char** args = env.GetConstArgumentVector(); *args; ++args)
        if (::strncmp(path, *args, path_len) == 0)
            return;
    env.AppendArgument("PATH=/system/bin");
}
Example #5
0
static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd,
                                              const ProcessLaunchInfo &info) {
  // First, make sure we disable all logging. If we are logging to stdout, our
  // logs can be
  // mistaken for inferior output.
  Log::DisableAllLogChannels(nullptr);

  // Do not inherit setgid powers.
  if (setgid(getgid()) != 0)
    ExitWithError(error_fd, "setgid");

  if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) {
    if (setpgid(0, 0) != 0)
      ExitWithError(error_fd, "setpgid");
  }

  for (size_t i = 0; i < info.GetNumFileActions(); ++i) {
    const FileAction &action = *info.GetFileActionAtIndex(i);
    switch (action.GetAction()) {
    case FileAction::eFileActionClose:
      if (close(action.GetFD()) != 0)
        ExitWithError(error_fd, "close");
      break;
    case FileAction::eFileActionDuplicate:
      if (dup2(action.GetFD(), action.GetActionArgument()) == -1)
        ExitWithError(error_fd, "dup2");
      break;
    case FileAction::eFileActionOpen:
      DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(),
                    action.GetActionArgument());
      break;
    case FileAction::eFileActionNone:
      break;
    }
  }

  const char **argv = info.GetArguments().GetConstArgumentVector();

  // Change working directory
  if (info.GetWorkingDirectory() &&
      0 != ::chdir(info.GetWorkingDirectory().GetCString()))
    ExitWithError(error_fd, "chdir");

  // Disable ASLR if requested.
  if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) {
    const unsigned long personality_get_current = 0xffffffff;
    int value = personality(personality_get_current);
    if (value == -1)
      ExitWithError(error_fd, "personality get");

    value = personality(ADDR_NO_RANDOMIZE | value);
    if (value == -1)
      ExitWithError(error_fd, "personality set");
  }

  Args env = info.GetEnvironmentEntries();
  FixupEnvironment(env);
  const char **envp = env.GetConstArgumentVector();

  // Clear the signal mask to prevent the child from being affected by
  // any masking done by the parent.
  sigset_t set;
  if (sigemptyset(&set) != 0 ||
      pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0)
    ExitWithError(error_fd, "pthread_sigmask");

  if (info.GetFlags().Test(eLaunchFlagDebug)) {
    // HACK:
    // Close everything besides stdin, stdout, and stderr that has no file
    // action to avoid leaking. Only do this when debugging, as elsewhere we
    // actually rely on
    // passing open descriptors to child processes.
    for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd)
      if (!info.GetFileActionForFD(fd) && fd != error_fd)
        close(fd);

    // Start tracing this child that is about to exec.
    if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1)
      ExitWithError(error_fd, "ptrace");
  }

  // Execute.  We should never return...
  execve(argv[0], const_cast<char *const *>(argv),
         const_cast<char *const *>(envp));

  if (errno == ETXTBSY) {
    // On android M and earlier we can get this error because the adb deamon can
    // hold a write
    // handle on the executable even after it has finished uploading it. This
    // state lasts
    // only a short time and happens only when there are many concurrent adb
    // commands being
    // issued, such as when running the test suite. (The file remains open when
    // someone does
    // an "adb shell" command in the fork() child before it has had a chance to
    // exec.) Since
    // this state should clear up quickly, wait a while and then give it one
    // more go.
    usleep(50000);
    execve(argv[0], const_cast<char *const *>(argv),
           const_cast<char *const *>(envp));
  }

  // ...unless exec fails.  In which case we definitely need to end the child
  // here.
  ExitWithError(error_fd, "execve");
}