Esempio n. 1
0
        private static int FindInterpreter(File file, ELF32Header eh, ref ELF32ProgramHeader ret)
        {
            var buf = new byte[ELF32ProgramHeader.Size];

            uint   pos = 0;
            ushort i   = 0;

            while (i < eh.NumOfProgramHeader)
            {
                pos = (uint)(eh.ProgramHeaderOffest + eh.ProgramHeaderSize * i);
                if (file.Read(buf, ref pos) != ELF32ProgramHeader.Size)
                {
                    return(-ErrorCode.EINVAL);
                }

                ret = ELF32ProgramHeader.Read(buf);

                if (ret.type == ELF32ProgramHeader.PT_INTERP)
                {
                    break;
                }

                ++i;
            }
            return(i == eh.NumOfProgramHeader ? -ErrorCode.ENOENT : 0);
        }
Esempio n. 2
0
        private static ELF32Header Read(byte[] buf)
        {
            var r   = new ELF32Header();
            int off = 0;

            r.ident1              = Deserializer.ReadLong(buf, off); off += sizeof(long);
            r.ident2              = Deserializer.ReadLong(buf, off); off += sizeof(long);
            r.type                = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
            r.machine             = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
            r.version             = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
            r.EntryPoint          = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
            r.ProgramHeaderOffest = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
            r.SectionHeaderOffset = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
            r.flags               = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
            r.ELFHeaderSize       = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
            r.ProgramHeaderSize   = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
            r.NumOfProgramHeader  = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
            r.SectionHeaderSize   = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
            r.NumOfSectionHeader  = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
            r.shstrndx            = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
            return(r);
        }
Esempio n. 3
0
        private static int FindInterpreter(File file, ELF32Header eh, ref ELF32ProgramHeader ret)
        {
            var buf = new byte[ELF32ProgramHeader.Size];

            uint pos = 0;
            ushort i = 0;

            while (i < eh.NumOfProgramHeader)
            {
                pos = (uint)(eh.ProgramHeaderOffest + eh.ProgramHeaderSize * i);
                if (file.Read(buf, ref pos) != ELF32ProgramHeader.Size)
                    return -ErrorCode.EINVAL;

                ret = ELF32ProgramHeader.Read(buf);

                if (ret.type == ELF32ProgramHeader.PT_INTERP)
                    break;

                ++i;
            }
            return i == eh.NumOfProgramHeader ? -ErrorCode.ENOENT : 0;
        }
Esempio n. 4
0
 private static ELF32Header Read(byte[] buf)
 {
     var r = new ELF32Header();
     int off = 0;
     r.ident1 = Deserializer.ReadLong(buf, off); off += sizeof(long);
     r.ident2 = Deserializer.ReadLong(buf, off); off += sizeof(long);
     r.type = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
     r.machine = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
     r.version = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
     r.EntryPoint = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
     r.ProgramHeaderOffest = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
     r.SectionHeaderOffset = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
     r.flags = Deserializer.ReadUInt(buf, off); off += sizeof(uint);
     r.ELFHeaderSize = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
     r.ProgramHeaderSize = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
     r.NumOfProgramHeader = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
     r.SectionHeaderSize = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
     r.NumOfSectionHeader = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
     r.shstrndx = Deserializer.ReadUShort(buf, off); off += sizeof(ushort);
     return r;
 }
Esempio n. 5
0
        private static int PushProgramHeaderAndAuxliraryVectors(Process proc, File file, ELF32Header eh, ref UserPtr stackTop)
        {
            var programHeaderLength = eh.NumOfProgramHeader * eh.ProgramHeaderSize;
            var buf = new byte[programHeaderLength];
            uint pos = eh.ProgramHeaderOffest;

            if (file.Read(buf, ref pos) != programHeaderLength)
                return -ErrorCode.ENOMEM;

            stackTop -= programHeaderLength;
            UserPtr ph_ptr = stackTop;

            if (ph_ptr.Write(proc, buf) != 0)
                return -ErrorCode.ENOMEM;

            // align
            stackTop = UserPtr.RoundDown(stackTop);

            var aux_vector = new uint[LengthOfAuxVector];
            aux_vector[0] = AT_PHDR;
            aux_vector[1] = ph_ptr.Value.ToUInt32();
            aux_vector[2] = AT_ENTRY;
            aux_vector[3] = eh.EntryPoint;
            aux_vector[4] = AT_PHNUM;
            aux_vector[5] = eh.NumOfProgramHeader;
            aux_vector[6] = 0;
            aux_vector[7] = 0;

            var auxVectorSize = sizeof(uint) * LengthOfAuxVector;
            stackTop -= auxVectorSize;

            if (stackTop.Write(proc, aux_vector) != 0)
                return -ErrorCode.ENOMEM;

            return 0;
        }
Esempio n. 6
0
        private static int MapInSegments(File file, Process proc, ELF32Header eh)
        {
            Contract.Requires(file != null && file.GhostOwner == proc);
            Contract.Requires(proc.Space.GhostOwner == proc);

            var buf = new byte[ELF32ProgramHeader.Size];

            var ph = new ELF32ProgramHeader();
            // At this point we need to map in all stuff in PT_LOAD
            for (var i = 0; i < eh.NumOfProgramHeader; ++i)
            {
                var pos = (uint)(eh.ProgramHeaderOffest + eh.ProgramHeaderSize * i);
                if (file.Read(buf, ref pos) != buf.Length)
                    return -ErrorCode.EINVAL;

                ph = ELF32ProgramHeader.Read(buf);

                var size = ph.FileSize > ph.MemorySize ? ph.FileSize : ph.MemorySize;

                if (ph.type != ELF32ProgramHeader.PT_LOAD)
                    continue;

                // Round address to page boundary

                var diff = Arch.ArchDefinition.PageOffset(ph.vaddr);
                var vaddr = new Pointer(ph.vaddr);
                var offset = ph.offset;
                var memSize = (int)Arch.ArchDefinition.PageAlign((uint)ph.MemorySize);
                var fileSize = ph.FileSize;

                if (diff < 0 || ph.offset < diff || fileSize + diff > file.inode.Size || fileSize <= 0 || memSize <= 0)
                    return -ErrorCode.EINVAL;

                vaddr -= diff;
                offset -= (uint)diff;
                fileSize += diff;

                if (fileSize > memSize)
                    fileSize = memSize;

                if (proc.Space.AddMapping(ph.ExpressOSAccessFlag, 0, file, offset, fileSize, vaddr, memSize) != 0)
                    return -ErrorCode.ENOMEM;

                // Update brk

                var segmentEnd = (vaddr + memSize).ToUInt32();
                if (segmentEnd > proc.Space.Brk)
                {
                    proc.Space.InitializeBrk(segmentEnd);
                }
            }
            return 0;
        }
Esempio n. 7
0
        private static int PushProgramHeaderAndAuxliraryVectors(Process proc, File file, ELF32Header eh, ref UserPtr stackTop)
        {
            var  programHeaderLength = eh.NumOfProgramHeader * eh.ProgramHeaderSize;
            var  buf = new byte[programHeaderLength];
            uint pos = eh.ProgramHeaderOffest;

            if (file.Read(buf, ref pos) != programHeaderLength)
            {
                return(-ErrorCode.ENOMEM);
            }

            stackTop -= programHeaderLength;
            UserPtr ph_ptr = stackTop;

            if (ph_ptr.Write(proc, buf) != 0)
            {
                return(-ErrorCode.ENOMEM);
            }

            // align
            stackTop = UserPtr.RoundDown(stackTop);

            var aux_vector = new uint[LengthOfAuxVector];

            aux_vector[0] = AT_PHDR;
            aux_vector[1] = ph_ptr.Value.ToUInt32();
            aux_vector[2] = AT_ENTRY;
            aux_vector[3] = eh.EntryPoint;
            aux_vector[4] = AT_PHNUM;
            aux_vector[5] = eh.NumOfProgramHeader;
            aux_vector[6] = 0;
            aux_vector[7] = 0;

            var auxVectorSize = sizeof(uint) * LengthOfAuxVector;

            stackTop -= auxVectorSize;

            if (stackTop.Write(proc, aux_vector) != 0)
            {
                return(-ErrorCode.ENOMEM);
            }

            return(0);
        }
Esempio n. 8
0
        private static int MapInSegments(File file, Process proc, ELF32Header eh)
        {
            Contract.Requires(file != null && file.GhostOwner == proc);
            Contract.Requires(proc.Space.GhostOwner == proc);

            var buf = new byte[ELF32ProgramHeader.Size];

            var ph = new ELF32ProgramHeader();

            // At this point we need to map in all stuff in PT_LOAD
            for (var i = 0; i < eh.NumOfProgramHeader; ++i)
            {
                var pos = (uint)(eh.ProgramHeaderOffest + eh.ProgramHeaderSize * i);
                if (file.Read(buf, ref pos) != buf.Length)
                {
                    return(-ErrorCode.EINVAL);
                }

                ph = ELF32ProgramHeader.Read(buf);

                var size = ph.FileSize > ph.MemorySize ? ph.FileSize : ph.MemorySize;

                if (ph.type != ELF32ProgramHeader.PT_LOAD)
                {
                    continue;
                }

                // Round address to page boundary

                var diff     = Arch.ArchDefinition.PageOffset(ph.vaddr);
                var vaddr    = new Pointer(ph.vaddr);
                var offset   = ph.offset;
                var memSize  = (int)Arch.ArchDefinition.PageAlign((uint)ph.MemorySize);
                var fileSize = ph.FileSize;

                if (diff < 0 || ph.offset < diff || fileSize + diff > file.inode.Size || fileSize <= 0 || memSize <= 0)
                {
                    return(-ErrorCode.EINVAL);
                }

                vaddr    -= diff;
                offset   -= (uint)diff;
                fileSize += diff;

                if (fileSize > memSize)
                {
                    fileSize = memSize;
                }

                if (proc.Space.AddMapping(ph.ExpressOSAccessFlag, 0, file, offset, fileSize, vaddr, memSize) != 0)
                {
                    return(-ErrorCode.ENOMEM);
                }

                // Update brk

                var segmentEnd = (vaddr + memSize).ToUInt32();
                if (segmentEnd > proc.Space.Brk)
                {
                    proc.Space.InitializeBrk(segmentEnd);
                }
            }
            return(0);
        }
Esempio n. 9
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);
        }