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); }
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); }
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; }
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; }
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; }
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; }
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); }
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); }
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); }