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); }
public static int Parse(int helperPid, File file, Process proc, ref UserPtr stackTop) { Contract.Requires(file.GhostOwner == proc); Contract.Requires(proc.Space.GhostOwner == proc); var buf = new byte[Size]; uint pos = 0; if (file.Read(buf, ref pos) != buf.Length) return -ErrorCode.EINVAL; var eh = Read(buf); if (eh.type != ELF32Header.ELF_TYPE_EXECUTABLE || eh.ProgramHeaderOffest == 0) return -ErrorCode.ENOEXEC; proc.EntryPoint = eh.EntryPoint; ELF32ProgramHeader ph = new ELF32ProgramHeader(); var ret = FindInterpreter(file, eh, ref ph); if (ret == -ErrorCode.EINVAL) { Arch.Console.WriteLine("Malformed ELF file"); return ret; } else if (ret == 0) { var interpreterBuf = new byte[ph.FileSize]; pos = ph.offset; if (file.Read(interpreterBuf, ref pos) != interpreterBuf.Length) return -ErrorCode.EINVAL; var interpreterName = new ASCIIString(interpreterBuf); ErrorCode ec; var interpreter_inode = Arch.ArchFS.Open(helperPid, interpreterName, 0, 0, out ec); if (interpreter_inode == null) return -ErrorCode.ENOENT; var interpreter = new File(proc, interpreter_inode, FileFlags.ReadOnly, 0); /* * Parse the information of linker. * * This function will also override the entry point. */ if (Parse(helperPid, interpreter, proc, ref stackTop) != 0) return -ErrorCode.EINVAL; // So now let's copy the program header to the top of the stack, and push auxlirary vectors PushProgramHeaderAndAuxliraryVectors(proc, file, eh, ref stackTop); } return MapInSegments(file, proc, eh); }
public static ELF32ProgramHeader Read(byte[] buf) { Contract.Requires(buf.Length == Size); var r = new ELF32ProgramHeader(); r.type = Deserializer.ReadUInt(buf, 0); r.offset = Deserializer.ReadUInt(buf, sizeof(uint)); r.vaddr = Deserializer.ReadUInt(buf, sizeof(uint) * 2); r.paddr = Deserializer.ReadUInt(buf, sizeof(uint) * 3); r.FileSize = Deserializer.ReadInt(buf, sizeof(uint) * 4); r.MemorySize = Deserializer.ReadInt(buf, sizeof(uint) * 5); r.flags = Deserializer.ReadUInt(buf, sizeof(uint) * 6); r.align = Deserializer.ReadUInt(buf, sizeof(uint) * 7); 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; }
public static ELF32ProgramHeader Read(byte[] buf) { Contract.Requires(buf.Length == Size); var r = new ELF32ProgramHeader(); r.type = Deserializer.ReadUInt(buf, 0); r.offset = Deserializer.ReadUInt(buf, sizeof(uint)); r.vaddr = Deserializer.ReadUInt(buf, sizeof(uint) * 2); r.paddr = Deserializer.ReadUInt(buf, sizeof(uint) * 3); r.FileSize = Deserializer.ReadInt(buf, sizeof(uint) * 4); r.MemorySize = Deserializer.ReadInt(buf, sizeof(uint) * 5); r.flags = Deserializer.ReadUInt(buf, sizeof(uint) * 6); r.align = Deserializer.ReadUInt(buf, sizeof(uint) * 7); return r; }
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 static int Parse(int helperPid, File file, Process proc, ref UserPtr stackTop) { Contract.Requires(file.GhostOwner == proc); Contract.Requires(proc.Space.GhostOwner == proc); var buf = new byte[Size]; uint pos = 0; if (file.Read(buf, ref pos) != buf.Length) { return(-ErrorCode.EINVAL); } var eh = Read(buf); if (eh.type != ELF32Header.ELF_TYPE_EXECUTABLE || eh.ProgramHeaderOffest == 0) { return(-ErrorCode.ENOEXEC); } proc.EntryPoint = eh.EntryPoint; ELF32ProgramHeader ph = new ELF32ProgramHeader(); var ret = FindInterpreter(file, eh, ref ph); if (ret == -ErrorCode.EINVAL) { Arch.Console.WriteLine("Malformed ELF file"); return(ret); } else if (ret == 0) { var interpreterBuf = new byte[ph.FileSize]; pos = ph.offset; if (file.Read(interpreterBuf, ref pos) != interpreterBuf.Length) { return(-ErrorCode.EINVAL); } var interpreterName = new ASCIIString(interpreterBuf); ErrorCode ec; var interpreter_inode = Arch.ArchFS.Open(helperPid, interpreterName, 0, 0, out ec); if (interpreter_inode == null) { return(-ErrorCode.ENOENT); } var interpreter = new File(proc, interpreter_inode, FileFlags.ReadOnly, 0); /* * Parse the information of linker. * * This function will also override the entry point. */ if (Parse(helperPid, interpreter, proc, ref stackTop) != 0) { return(-ErrorCode.EINVAL); } // So now let's copy the program header to the top of the stack, and push auxlirary vectors PushProgramHeaderAndAuxliraryVectors(proc, file, eh, ref stackTop); } return(MapInSegments(file, proc, eh)); }
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); }