forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			109 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- ProcessLauncherAndroid.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/FileSpec.h"
 | |
| #include "lldb/Host/Host.h"
 | |
| #include "lldb/Host/HostProcess.h"
 | |
| #include "lldb/Host/android/ProcessLauncherAndroid.h"
 | |
| 
 | |
| #include "lldb/Target/ProcessLaunchInfo.h"
 | |
| 
 | |
| #include <limits.h>
 | |
| 
 | |
| using namespace lldb;
 | |
| using namespace lldb_private;
 | |
| 
 | |
| static bool
 | |
| DupDescriptor(const FileSpec &file_spec, int fd, int flags)
 | |
| {
 | |
|     int target_fd = ::open(file_spec.GetCString(), flags, 0666);
 | |
| 
 | |
|     if (target_fd == -1)
 | |
|         return false;
 | |
| 
 | |
|     if (::dup2(target_fd, fd) == -1)
 | |
|         return false;
 | |
| 
 | |
|     return (::close(target_fd) == -1) ? false : true;
 | |
| }
 | |
| 
 | |
| // 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");
 | |
| }
 | |
| 
 | |
| 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)) {
 | |
|             FileSpec file_spec = file_action->GetFileSpec();
 | |
|             if (file_spec)
 | |
|                 if (!DupDescriptor(file_spec, STDIN_FILENO, O_RDONLY))
 | |
|                     exit(-1);
 | |
|         }
 | |
| 
 | |
|         if (const lldb_private::FileAction *file_action = launch_info.GetFileActionForFD(STDOUT_FILENO)) {
 | |
|             FileSpec file_spec = file_action->GetFileSpec();
 | |
|             if (file_spec)
 | |
|                 if (!DupDescriptor(file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
 | |
|                     exit(-1);
 | |
|         }
 | |
| 
 | |
|         if (const lldb_private::FileAction *file_action = launch_info.GetFileActionForFD(STDERR_FILENO)) {
 | |
|             FileSpec file_spec = file_action->GetFileSpec();
 | |
|             if (file_spec)
 | |
|                 if (!DupDescriptor(file_spec, 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();
 | |
| 
 | |
|         FileSpec working_dir = launch_info.GetWorkingDirectory();
 | |
|         if (working_dir)
 | |
|         {
 | |
|             if (::chdir(working_dir.GetCString()) != 0)
 | |
|                 exit(-1);
 | |
|         }
 | |
| 
 | |
|         execve(argv[0],
 | |
|                const_cast<char *const *>(argv),
 | |
|                const_cast<char *const *>(envp));
 | |
|         exit(-1);
 | |
|     }
 | |
|    
 | |
|     return HostProcess(pid);
 | |
| }
 |