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