Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }