/// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="X86Context"/> in which the
        /// operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the
        /// operand.</param>
        /// <exception cref="ArgumentNullException">
        /// <para><paramref name="context"/> is <see langword="null"/>.</para>
        /// -or-
        /// <para><paramref name="instr"/> is <see langword="null"/>.</para>
        /// </exception>
        internal override void Construct(X86Context context, EncodedInstruction instr)
        {
            #region Contract
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (instr == null)
            {
                throw new ArgumentNullException("instr");
            }
            #endregion

            // Let's evaluate the expression.
            ExpressionResult result = new BinaryExpression(
                expression,
                BinaryOperation.Subtract,
                new BinaryExpression(
                    new CurrentPosition(),
                    BinaryOperation.Add,
                    new Constant((long)instr.GetLength()))).Evaluate(context);

            // Determine the size of the immediate operand.
            DataSize size = RequestedSize;
            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (result.HasReference)
                {
                    // When the result has a reference, use the architecture's operand size.
                    size = context.Representation.Architecture.OperandSize;
                }
                else
                {
                    // Otherwise, use the most efficient word size.
                    size = result.Constant.GetSize();
                }
            }
            if (size >= DataSize.Bit64)
            {
                throw new AssemblerException(ExceptionStrings.OperandSizeNotEncodable);
            }
            else if (size == DataSize.None)
            {
                throw new AssemblerException(ExceptionStrings.OperandSizeNotSpecified);
            }

            // Set the parameters.
            instr.Immediate     = result;
            instr.ImmediateSize = size;
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, size);
        }
示例#2
0
        /// <summary>
        /// Constructor of task
        /// </summary>
        /// <param name="priority">The priority of the task</param>
        /// <param name="flags">The spawn flags</param>
        public Task(TaskPriority priority, SpawnFlags flags)
        {
            PID             = NextPID++;
            FileDescriptors = new FileDescriptors();

            Priority = priority;
            TimeLeft = (int)priority;

            // Check spawn flags
            if ((flags & SpawnFlags.SWAP_PID) == SpawnFlags.SWAP_PID)
            {
                int old = PID;
                PID = Tasking.CurrentTask.PID;
                Tasking.CurrentTask.PID = old;
            }

            // Other data
            GID          = Tasking.CurrentTask.GID;
            UID          = Tasking.CurrentTask.UID;
            m_launchTime = Time.FullTicks;
            Name         = "Nameless";
            CMDLine      = "";

            // Signals
            m_signalActions = new SignalAction[Signals.NSIG];

            // Context
            Context = new X86Context();

            // Filesystem related initialization if we're not a kernel task
            if ((flags & SpawnFlags.KERNEL_TASK) != SpawnFlags.KERNEL_TASK)
            {
                SetFileDescriptors(Tasking.CurrentTask.FileDescriptors.Clone());
                CurrentDirectory = String.Clone(Tasking.CurrentTask.CurrentDirectory);
            }

            // List of addresses that need to be freed
            m_usedAddresses = new List();
        }
示例#3
0
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="X86Context"/> in which the
        /// operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the
        /// operand.</param>
        /// <exception cref="ArgumentNullException">
        /// <para><paramref name="context"/> is <see langword="null"/>.</para>
        /// -or-
        /// <para><paramref name="instr"/> is <see langword="null"/>.</para>
        /// </exception>
        internal override void Construct(X86Context context, EncodedInstruction instr)
        {
            #region Contract
            if (context == null) throw new ArgumentNullException("context");
            if (instr == null) throw new ArgumentNullException("instr");
            #endregion

            // Let's evaluate the expression.
            ExpressionResult result = new BinaryExpression(
                    expression,
                    BinaryOperation.Subtract,
                    new BinaryExpression(
                        new CurrentPosition(),
                        BinaryOperation.Add,
                        new Constant((long)instr.GetLength()))).Evaluate(context);

            // Determine the size of the immediate operand.
            DataSize size = RequestedSize;
            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (result.HasReference)
                    // When the result has a reference, use the architecture's operand size.
                    size = context.Representation.Architecture.OperandSize;
                else
                    // Otherwise, use the most efficient word size.
                    size = result.Constant.GetSize();
            }
            if (size >= DataSize.Bit64) throw new AssemblerException(ExceptionStrings.OperandSizeNotEncodable);
            else if (size == DataSize.None) throw new AssemblerException(ExceptionStrings.OperandSizeNotSpecified);

            // Set the parameters.
            instr.Immediate = result;
            instr.ImmediateSize = size;
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, size);
        }
示例#4
0
        /// <summary>
        /// Executes an ELF file
        /// </summary>
        /// <param name="buffer">The buffer</param>
        /// <param name="size">The size of the ELF</param>
        /// <param name="argv">The arguments</param>
        /// <param name="flags">Spawn flags</param>
        /// <returns>The error code or PID</returns>
        public static unsafe int Execute(byte[] buffer, uint size, string[] argv, Task.SpawnFlags flags)
        {
            ELF32 *elf;

            fixed(byte *ptr = buffer)
            elf = (ELF32 *)ptr;

            if (!isValidELF(elf))
            {
                return(-(int)ErrorCode.EINVAL);
            }

            // Get program header
            ProgramHeader *programHeader = (ProgramHeader *)((int)elf + elf->PhOff);
            uint           virtAddress   = programHeader->VirtAddress;
            void *         allocated     = Heap.AlignedAlloc(0x1000, (int)size);

            // Loop through every section
            for (uint i = 0; i < elf->ShNum; i++)
            {
                SectionHeader *section = getSection(elf, i);

                // Only loadable sections
                if (section->Address == 0)
                {
                    continue;
                }

                uint offset = section->Address - virtAddress;

                // BSS
                if (section->Type == SectionHeaderType.SHT_NOBITS)
                {
                    Memory.Memclear((void *)((uint)allocated + offset), (int)section->Size);
                }
                // Copy
                else
                {
                    Memory.Memcpy((void *)((uint)allocated + offset), (void *)((uint)elf + section->Offset), (int)section->Size);
                }
            }

            // Count arguments
            int argc = 0;

            while (argv[argc] != null)
            {
                argc++;
            }

            // Make sure arguments are safe by copying them
            string[] argvClone = new string[argc + 1];
            for (int i = 0; i < argc; i++)
            {
                argvClone[i] = String.Clone(argv[i]);
            }

            // Stack
            int[] initialStack = new int[2];
            initialStack[0] = (int)Util.ObjectToVoidPtr(argvClone);
            initialStack[1] = argc;

            // Create thread
            Thread thread = new Thread();

            thread.Context.CreateNewContext((void *)elf->Entry, 2, initialStack, false);
            Heap.Free(initialStack);

            CPU.CLI();

            // Create task
            Task       newTask = new Task(TaskPriority.NORMAL, flags);
            X86Context context = (X86Context)newTask.Context;

            context.CreateNewContext(false);
            newTask.AddThread(thread);
            newTask.AddUsedAddress(allocated);

            // Task info
            newTask.Name    = argvClone[0];
            newTask.CMDLine = Array.Join(argvClone, argc, " ");
            newTask.AddUsedAddress(newTask.CMDLine);

            // Argv clone freeing
            newTask.AddUsedAddress(argvClone);
            for (int i = 0; i < argc; i++)
            {
                newTask.AddUsedAddress(argvClone[i]);
            }

            // Map memory
            Paging.PageDirectory *newDirectory = context.PageDirVirtual;
            Paging.PageFlags      pageFlags    = Paging.PageFlags.Present | Paging.PageFlags.Writable | Paging.PageFlags.UserMode;
            for (uint j = 0; j < size; j += 0x1000)
            {
                // Note: the physical memory is not always a continuous block
                Paging.MapPage(newDirectory, (int)Paging.GetPhysicalFromVirtual((void *)((int)allocated + j)), (int)(virtAddress + j), pageFlags);
            }

            // Schedule task
            Tasking.ScheduleTask(newTask);

            CPU.STI();

            return(newTask.PID);
        }