Example #1
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);
        }
Example #2
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);
        }
Example #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;
        }
Example #4
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;
        }
Example #5
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;
        }
Example #6
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));
        }
Example #7
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);
        }