17#include "llvm/Support/Errno.h"
20#include <sys/ptrace.h>
28#include <android/api-level.h>
29#define PT_TRACE_ME PTRACE_TRACEME
32#if defined(__ANDROID_API__) && __ANDROID_API__ < 15
33#include <linux/personality.h>
34#elif defined(__linux__)
35#include <sys/personality.h>
46 int r = write(error_fd, str, strlen(str));
50[[noreturn]]
static void ExitWithError(
int error_fd,
const char *operation) {
61 const unsigned long personality_get_current = 0xffffffff;
62 int value = personality(personality_get_current);
66 value = personality(ADDR_NO_RANDOMIZE | value);
72static void DupDescriptor(
int error_fd,
const char *file,
int fd,
int flags) {
81 if (::dup2(target_fd, fd) == -1)
88struct ForkFileAction {
97struct ForkLaunchInfo {
100 bool separate_process_group;
106 std::vector<ForkFileAction> actions;
108 bool has_action(
int fd)
const {
109 for (
const ForkFileAction &action : actions) {
118[[noreturn]]
static void ChildFunc(
int error_fd,
const ForkLaunchInfo &info) {
119 if (info.separate_process_group) {
120 if (setpgid(0, 0) != 0)
124 for (
const ForkFileAction &action : info.actions) {
125 switch (action.action) {
127 if (close(action.fd) != 0)
131 if (dup2(action.fd, action.arg) == -1)
135 DupDescriptor(error_fd, action.path.c_str(), action.fd, action.arg);
143 if (!info.wd.empty() && 0 != ::chdir(info.wd.c_str()))
146 if (info.disable_aslr)
152 if (sigemptyset(&set) != 0 ||
153 pthread_sigmask(SIG_SETMASK, &set,
nullptr) != 0)
158 if (setgid(getgid()) != 0)
168 const llvm::StringRef proc_fd_path =
"/proc/self/fd";
171 ec = llvm::sys::fs::is_directory(proc_fd_path, result);
173 std::vector<int> files_to_close;
175 for (llvm::sys::fs::directory_iterator iter(proc_fd_path, ec), file_end;
176 iter != file_end && !ec; iter.increment(ec)) {
177 int fd = std::stoi(iter->path().substr(proc_fd_path.size() + 1));
181 if (fd > 2 && !info.has_action(fd) && fd != error_fd)
182 files_to_close.push_back(fd);
184 for (
int file_to_close : files_to_close)
185 close(file_to_close);
188 int max_fd = sysconf(_SC_OPEN_MAX);
189 for (
int fd = 3; fd < max_fd; ++fd)
190 if (!info.has_action(fd) && fd != error_fd)
196 if (ptrace64(PT_TRACE_ME, 0, 0, 0,
nullptr) == -1)
198 if (ptrace(PT_TRACE_ME, 0,
nullptr, 0) == -1)
204 execve(info.argv[0],
const_cast<char *
const *
>(info.argv), info.envp);
206#if defined(__linux__)
207 if (errno == ETXTBSY) {
217 execve(info.argv[0],
const_cast<char *
const *
>(info.argv), info.envp);
228ForkFileAction::ForkFileAction(
const FileAction &act)
229 : action(act.GetAction()), fd(act.GetFD()), path(act.GetPath().str()),
230 arg(act.GetActionArgument()) {}
232static std::vector<ForkFileAction>
234 std::vector<ForkFileAction> result;
245 env.try_emplace(
"PATH",
"/system/bin");
251 : separate_process_group(
252 info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)),
253 debug(info.GetFlags().Test(eLaunchFlagDebug)),
254 disable_aslr(info.GetFlags().Test(eLaunchFlagDisableASLR)),
255 wd(info.GetWorkingDirectory().GetPath()),
256 argv(info.GetArguments().GetConstArgumentVector()),
265 const bool child_processes_inherit =
false;
270 const ForkLaunchInfo fork_launch_info(launch_info);
276 "Fork failed with error message: {0}", llvm::sys::StrError());
288 llvm::SmallString<0> buf;
293 buf.resize_for_overwrite(pos + 100);
295 buf.begin() + pos, buf.size() - pos);
305 llvm::sys::RetryAfterSignal(-1, waitpid, pid,
nullptr, 0);
static llvm::raw_ostream & error(Stream &strm)
static void ExitWithError(int error_fd, const char *operation)
static void DisableASLR(int error_fd)
static std::vector< ForkFileAction > MakeForkActions(const ProcessLaunchInfo &info)
static Environment::Envp FixupEnvironment(Environment env)
static void DupDescriptor(int error_fd, const char *file, int fd, int flags)
static void write_string(int error_fd, const char *str)
static void ChildFunc(int error_fd, const ForkLaunchInfo &info)
int Open(const char *path, int flags, int mode=0600)
Wraps ::open in a platform-independent way.
static FileSystem & Instance()
A posix-based implementation of Pipe, a class that abtracts unix style pipes.
int GetReadFileDescriptor() const override
void CloseWriteFileDescriptor() override
int ReleaseWriteFileDescriptor() override
void CloseReadFileDescriptor() override
Status CreateNew(bool child_process_inherit) override
const FileAction * GetFileActionAtIndex(size_t idx) const
size_t GetNumFileActions() const
HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Status &error) override
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.