예제 #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);
        }
예제 #2
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);
        }
예제 #3
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);
        }
예제 #4
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;
        }
예제 #5
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;
 }
예제 #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;
        }
예제 #7
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));
        }
예제 #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);
        }