public static int Clone(Thread current, uint flags, UserPtr newsp, UserPtr parent_tidptr, UserPtr child_tidptr, ref Arch.ExceptionRegisters pt_regs) { // Only support pthread_create right now if (flags != (CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED)) { return(-ErrorCode.EINVAL); } var proc = current.Parent; var thr = Thread.Create(proc); if (thr == null) { Arch.Console.WriteLine("Failed to create thread"); return(-ErrorCode.EINVAL); } // Start the main thread // Skipping the int $0x80 thr.Start(new Pointer(pt_regs.ip + 2), newsp.Value); // There's no need to set eax for thr as they are zero by default.. return(thr.Tid); }
public const uint CLONE_IO = 0x80000000; /* Clone io context */ // // We do sync read for this one, since it's simpler.. // public static Process CreateProcess(ASCIIString path, ASCIIString[] argv, ASCIIString[] envp, AndroidApplicationInfo appInfo) { var proc = new Process(path, appInfo); Utils.Assert(!proc.Space.impl._value.isInvalid); uint addr; int workspace_fd; uint workspace_size; proc.helperPid = Arch.IPCStubs.linux_sys_take_helper(out addr, out workspace_fd, out workspace_size); if (proc.helperPid < 0) { Arch.Console.WriteLine("CreateProcess: cannot get helper"); return(null); } proc.ShadowBinderVMStart = addr; ErrorCode ec; var inode = Arch.ArchFS.Open(proc.helperPid, path, 0, 0, out ec); if (inode == null) { Arch.Console.WriteLine("CreateProcess: cannot open file"); return(null); } var stack_top = new UserPtr(INITIAL_STACK_LOCATION); // 4M Initial stack var stack_size = 4096 * Arch.ArchDefinition.PageSize; proc.Space.AddStackMapping(stack_top, stack_size); stack_top += stack_size; var augmented_envp = CreateEnvpArrayWithWorkspace(envp, proc, workspace_fd, workspace_size); var envp_ptr = PushCharArray(proc, augmented_envp, ref stack_top); if (envp_ptr == null) { Arch.Console.WriteLine("CreateProcess: Push envp failed"); return(null); } var argv_ptr = PushCharArray(proc, argv, ref stack_top); if (argv_ptr == null) { Arch.Console.WriteLine("CreateProcess: Push argv failed"); return(null); } stack_top = UserPtr.RoundDown(stack_top); // Parse the ELF file, which might push additional info on to the stack // (i.e., aux vectors when the ELF is dynamically linked) var file = new File(proc, inode, FileFlags.ReadWrite, 0); int ret = ELF32Header.Parse(proc.helperPid, file, proc, ref stack_top); if (ret != 0) { Arch.Console.WriteLine("CreateProcess: Parse ELF file failed"); return(null); } //%esp The stack contains the arguments and environment: // 0(%esp) argc // 4(%esp) argv[0] // ... // (4*argc)(%esp) NULL // (4*(argc+1))(%esp) envp[0] // ... // NULL if (PushArgumentPointers(proc, envp_ptr, ref stack_top) != 0) { return(null); } if (PushArgumentPointers(proc, argv_ptr, ref stack_top) != 0) { return(null); } if (PushInt(proc, argv_ptr.Length, ref stack_top) != 0) { return(null); } // Stdio var file_stdout = File.CreateStdout(proc); Contract.Assume(proc.Files.IsAvailableFd(Process.STDOUT_FD)); proc.InstallFd(Process.STDOUT_FD, file_stdout); var file_stderr = File.CreateStdout(proc); Contract.Assume(proc.Files.IsAvailableFd(Process.STDERR_FD)); proc.InstallFd(Process.STDERR_FD, file_stderr); var mainThread = Thread.Create(proc); if (appInfo != null) { var p = appInfo.ToParcel(); Globals.LinuxIPCBuffer.CopyFrom(0, p); Arch.IPCStubs.WriteAppInfo(proc.helperPid, p.Length); } // Start the main thread mainThread.Start(new Pointer(proc.EntryPoint), stack_top.Value); return(proc); }