Beispiel #1
0
        public virtual Thread CreateThread(ThreadStartMethod MainMethod, FOS_System.String Name)
        {
#if PROCESS_TRACE
            BasicConsole.WriteLine("Creating thread...");
#endif

            Thread newThread = new Thread(this, MainMethod, ThreadIdGenerator++, UserMode, Name);
#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding data page...");
#endif
            // Add the page to the processes memory layout
            uint threadStackVirtAddr = (uint)newThread.State->ThreadStackTop - 4092;
            uint threadStackPhysAddr = (uint)VirtMemManager.GetPhysicalAddress(newThread.State->ThreadStackTop - 4092);
            TheMemoryLayout.AddDataPage(threadStackPhysAddr, threadStackVirtAddr);
            if (ProcessManager.KernelProcess != null)
            {
                ProcessManager.KernelProcess.TheMemoryLayout.AddDataPage(threadStackPhysAddr, threadStackVirtAddr);
            }

#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding thread...");
#endif

            Threads.Add(newThread);
            if (Registered)
            {
                Scheduler.InitThread(this, newThread);
            }

            return(newThread);
        }
Beispiel #2
0
        public virtual Thread CreateThread(ThreadStartMethod MainMethod)
        {
#if PROCESS_TRACE
            BasicConsole.WriteLine("Creating thread...");
#endif
            //bool reenable = Scheduler.Enabled;
            //if (reenable)
            //{
            //    Scheduler.Disable();
            //}

            Thread newThread = new Thread(MainMethod, ThreadIdGenerator++, UserMode);
#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding data page...");
#endif
            // Add the page to the processes memory layout
            TheMemoryLayout.AddDataPage(
                (uint)VirtMemManager.GetPhysicalAddress(newThread.State->ThreadStackTop - 4092),
                (uint)newThread.State->ThreadStackTop - 4092);
            
#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding thread...");
#endif

            Threads.Add(newThread);

            //if (reenable)
            //{
            //    Scheduler.Enable();
            //}

            return newThread;
        }
Beispiel #3
0
        public virtual Thread CreateThread(ThreadStartMethod MainMethod, FOS_System.String Name)
        {
#if PROCESS_TRACE
            BasicConsole.WriteLine("Process: CreateThread: Creating thread...");
#endif
            //TODO: Wrap EnableKernelAccessToProcessMemory in try-finally blocks

            // Required so that page allocations by new Thread don't create conflicts
            ProcessManager.EnableKernelAccessToProcessMemory(this);

            Thread newThread = new Thread(this, MainMethod, ThreadIdGenerator++, UserMode, Name);
#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding data page...");
#endif
            // Add the page to the processes memory layout
            uint threadStackVirtAddr = (uint)newThread.State->ThreadStackTop - 4092;
            uint threadStackPhysAddr = (uint)VirtMemManager.GetPhysicalAddress(newThread.State->ThreadStackTop - 4092);
            TheMemoryLayout.AddDataPage(threadStackPhysAddr, threadStackVirtAddr);

            ProcessManager.DisableKernelAccessToProcessMemory(this);

#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding thread...");
#endif

            Threads.Add(newThread);

            if (Registered)
            {
                Scheduler.InitThread(this, newThread);
            }

            return(newThread);
        }
Beispiel #4
0
        public static Process CreateProcess(ThreadStartMethod MainMethod, FOS_System.String Name, bool UserMode, bool CreateHeap)
        {
#if PROCESSMANAGER_TRACE
            BasicConsole.WriteLine("Creating process object...");
#endif
            return new Process(MainMethod, ProcessIdGenerator++, Name, UserMode, CreateHeap);
        }
Beispiel #5
0
        public static Process CreateProcess(ThreadStartMethod MainMethod, FOS_System.String Name, bool UserMode, bool CreateHeap)
        {
#if PROCESSMANAGER_TRACE
            BasicConsole.WriteLine("Creating process object...");
#endif
            return(new Process(MainMethod, ProcessIdGenerator++, Name, UserMode, CreateHeap));
        }
Beispiel #6
0
        public static unsafe ThreadResponses Thread_Create(ThreadStartMethod startMethod)
        {
            uint Return1 = 0;
            uint Return2 = 0;
            uint Return3 = 0;
            uint Return4 = 0;

            Call(Kernel.Shared.SystemCalls.Thread, (uint)ThreadRequests.Create, (uint)(ObjectUtilities.GetHandle(startMethod)), 0, ref Return1, ref Return2, ref Return3, ref Return4);
            return((ThreadResponses)Return1);
        }
Beispiel #7
0
        public Process(ThreadStartMethod MainMethod, uint AnId, FOS_System.String AName, bool userMode)
        {
#if PROCESS_TRACE
            BasicConsole.WriteLine("Constructing process object...");
#endif
            Id = AnId;
            Name = AName;
            UserMode = userMode;

#if PROCESS_TRACE
            BasicConsole.WriteLine("Creating thread...");
#endif
            CreateThread(MainMethod);
        }
Beispiel #8
0
        public Process(ThreadStartMethod MainMethod, uint AnId, FOS_System.String AName, bool userMode, bool createHeap)
        {
#if PROCESS_TRACE
            BasicConsole.WriteLine("Constructing process object...");
#endif
            Id       = AnId;
            Name     = AName;
            UserMode = userMode;

#if PROCESS_TRACE
            BasicConsole.WriteLine("Creating thread...");
#endif
            CreateThread(MainMethod, "Main");

            if (createHeap)
            {
                CreateHeap();
            }
        }
Beispiel #9
0
 public static unsafe ThreadResponses Thread_Create(ThreadStartMethod startMethod)
 {
     uint Return1 = 0;
     uint Return2 = 0;
     uint Return3 = 0;
     uint Return4 = 0;
     Call(Kernel.Shared.SystemCalls.Thread, (uint)ThreadRequests.Create, (uint)(ObjectUtilities.GetHandle(startMethod)), 0, ref Return1, ref Return2, ref Return3, ref Return4);
     return (ThreadResponses)Return1;
 }
Beispiel #10
0
 public static Process CreateProcess(ThreadStartMethod MainMethod, FOS_System.String Name, bool UserMode)
 {
     return(CreateProcess(MainMethod, Name, UserMode, false));
 }
Beispiel #11
0
        public static Process LoadProcess_FromRawExe(File RawExeFile, bool UserMode)
        {
            // - Read in file contents
            // - Map enough memory for the exe file contents
            // - Copy the memory over

            //bool reenable = Scheduler.Enabled;
            //if (reenable)
            //{
            //    Scheduler.Disable();
            //}

            //TODO - Handle case of EXE being bigger than 4KiB?
            //          - Would need to map contiguous (virtual) pages.

            BasicConsole.WriteLine("Mapping free page for process...");
            byte *destMemPtr = (byte *)Hardware.VirtMemManager.MapFreePage(
                UserMode ? Hardware.VirtMem.VirtMemImpl.PageFlags.None : Hardware.VirtMem.VirtMemImpl.PageFlags.KernelOnly);

            BasicConsole.WriteLine(((FOS_System.String) "Physical address = ") + (uint)Hardware.VirtMemManager.GetPhysicalAddress(destMemPtr));
            BasicConsole.WriteLine(((FOS_System.String) "Virtual address = ") + (uint)destMemPtr);

            // Add the page to the current processes memory layout
            //  So we can access the memory while we load the process.
            //  Otherwise we will hit a page fault as soon as we try copying the memory
            //      further down.
            //  Note: The page fault will only be hit on starting a second process because
            //      the scheduler doesn't change the context when only one process is running.
            ProcessManager.CurrentProcess.TheMemoryLayout.AddDataPage(
                (uint)Hardware.VirtMemManager.GetPhysicalAddress(destMemPtr),
                (uint)destMemPtr);
            // We could have been "scheduler interrupted" just after the map but just before the
            //  add data page...
            ProcessManager.CurrentProcess.LoadMemLayout();

            //BasicConsole.WriteLine("Reading file...");
            int bytesRead = 0;

            byte[] readBuffer = new byte[4096];
            bytesRead = RawExeFile.GetStream().Read(readBuffer, 0, 4096);
            //BasicConsole.WriteLine("Copying data...");
            Utilities.MemoryUtils.MemCpy_32(destMemPtr, ((byte *)Utilities.ObjectUtilities.GetHandle(readBuffer)) + FOS_System.Array.FieldsBytesSize, (uint)bytesRead);

            //BasicConsole.WriteLine("Converting destMemPtr...");
            ThreadStartMethod mainMethod = (ThreadStartMethod)Utilities.ObjectUtilities.GetObject(destMemPtr);

            //BasicConsole.WriteLine("Getting process name...");
            FOS_System.String name = RawExeFile.Name;

            // - Create the process
            //BasicConsole.WriteLine("Creating process...");
            Process process = ProcessManager.CreateProcess(
                mainMethod, name, UserMode);

            //BasicConsole.WriteLine("Adding process' code page...");
            // Add code page to new processes memory layout
            process.TheMemoryLayout.AddCodePage((uint)Hardware.VirtMemManager.GetPhysicalAddress(destMemPtr),
                                                (uint)destMemPtr);

            //BasicConsole.WriteLine("Removing process' code page from current process...");
            //Remove from current processes memory layout
            ProcessManager.CurrentProcess.TheMemoryLayout.RemovePage((uint)destMemPtr);

            //if (reenable)
            //{
            //    Scheduler.Enable();
            //}

            return(process);
        }
Beispiel #12
0
 public static Process CreateProcess(ThreadStartMethod MainMethod, FOS_System.String Name, bool UserMode)
 {
     return CreateProcess(MainMethod, Name, UserMode, false);
 }
Beispiel #13
0
        public Thread(Process AnOwner, ThreadStartMethod StartMethod, uint AnId, bool UserMode, FOS_System.String AName)
        {
            LastActiveState = ActiveStates.NotStarted;
            Owner           = AnOwner;
#if THREAD_TRACE
            BasicConsole.WriteLine("Constructing thread object...");
#endif
            //Init thread state
            #if THREAD_TRACE
            BasicConsole.WriteLine("Allocating state memory...");
#endif
            State = (ThreadState *)FOS_System.Heap.Alloc((uint)sizeof(ThreadState), "Thread : Thread() (1)");

            // Init Id and EIP
            //  Set EIP to the first instruction of the main method
#if THREAD_TRACE
            BasicConsole.WriteLine("Setting thread info...");
#endif
            Id              = AnId;
            Name            = AName;
            State->StartEIP = (uint)Utilities.ObjectUtilities.GetHandle(StartMethod);

            // Allocate kernel memory for the kernel stack for this thread
            //  Used when this thread is preempted or does a sys call. Stack is switched to
            //  this thread-specific kernel stack
#if THREAD_TRACE
            BasicConsole.WriteLine("Allocating kernel stack...");
#endif
            State->KernelStackTop = (byte *)FOS_System.Heap.Alloc(0x1000, 4) + 0xFFC; //4KiB, 4-byte aligned

            // Allocate free memory for the user stack for this thread
            //  Used by this thread in normal execution
#if THREAD_TRACE
            BasicConsole.WriteLine("Mapping thread stack page...");
#endif
            State->UserMode       = UserMode;
            State->ThreadStackTop = (byte *)Hardware.VirtMemManager.MapFreePage(
                UserMode ? Hardware.VirtMem.VirtMemImpl.PageFlags.None :
                Hardware.VirtMem.VirtMemImpl.PageFlags.KernelOnly) + 4092;            //4 KiB, page-aligned

            // Set ESP to the top of the stack - 4 byte aligned, high address since x86 stack works
            //  downwards
#if THREAD_TRACE
            BasicConsole.WriteLine("Setting ESP...");
#endif
            State->ESP = (uint)State->ThreadStackTop;

            // TimeToRun and TimeToRunReload are set up in Scheduler.InitProcess which
            //      is called when a process is registered.

            // Init SS
            //  Stack Segment = User or Kernel space data segment selector offset
            //  Kernel data segment selector offset (offset in GDT) = 0x10 (16)
            //  User   data segment selector offset (offset in GDT) = 0x23 (32|3)
            //          User data segment selector must also be or'ed with 3 for User Privilege level
#if THREAD_TRACE
            Console.Default.WriteLine(" > > > Setting SS...");
#endif
            State->SS = UserMode ? (ushort)0x23 : (ushort)0x10;

            // Init Started
            //  Not started yet so set to false
#if THREAD_TRACE
            Console.Default.WriteLine(" > > > Setting started...");
#endif
            State->Started = false;

            // Init Exception State
            State->ExState = (ExceptionState *)FOS_System.Heap.AllocZeroed((uint)sizeof(ExceptionState), "Thread : Thread() (2)");
        }
Beispiel #14
0
        public virtual Thread CreateThread(ThreadStartMethod MainMethod, FOS_System.String Name)
        {
#if PROCESS_TRACE
            BasicConsole.WriteLine("Creating thread...");
#endif

            Thread newThread = new Thread(this, MainMethod, ThreadIdGenerator++, UserMode, Name);
#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding data page...");
#endif
            // Add the page to the processes memory layout
            uint threadStackVirtAddr = (uint)newThread.State->ThreadStackTop - 4092;
            uint threadStackPhysAddr = (uint)VirtMemManager.GetPhysicalAddress(newThread.State->ThreadStackTop - 4092);
            TheMemoryLayout.AddDataPage(threadStackPhysAddr, threadStackVirtAddr);
            if (ProcessManager.KernelProcess != null)
            {
                ProcessManager.KernelProcess.TheMemoryLayout.AddDataPage(threadStackPhysAddr, threadStackVirtAddr);
            }

#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding thread...");
#endif

            Threads.Add(newThread);
            if (Registered)
            {
                Scheduler.InitThread(this, newThread);
            }

            return newThread;
        }
Beispiel #15
0
        public void Load(bool UserMode)
        {
            bool OK = true;

            try
            {
                bool DynamicLinkingRequired = false;

                ThreadStartMethod mainMethod = (ThreadStartMethod)Utilities.ObjectUtilities.GetObject(theFile.Header.EntryPoint);
                theProcess = ProcessManager.CreateProcess(
                    mainMethod, theFile.TheFile.Name, UserMode);

                uint threadStackVirtAddr = (uint)((Thread)theProcess.Threads[0]).State->ThreadStackTop - 4092;
                uint threadStackPhysAddr = (uint)Hardware.VirtMemManager.GetPhysicalAddress(threadStackVirtAddr);
                ProcessManager.CurrentProcess.TheMemoryLayout.AddDataPage(threadStackPhysAddr, threadStackVirtAddr);

                // Load the ELF segments (i.e. the program code and data)
                BaseAddress = theFile.BaseAddress;
                LoadSegments(theFile, ref OK, ref DynamicLinkingRequired, BaseAddress);

                //BasicConsole.WriteLine();

                #region Relocations

                // Useful articles / specifications on Relocations:
                //      - Useful / practical explanation of various relocation types: http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries/#id20
                //      - Orcale : ELF Specification copy: http://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-54839.html

                if (DynamicLinkingRequired)
                {
                    Console.Default.WriteLine("Dynamic Linking");
                    BasicConsole.WriteLine("Dynamic Linking");

                    ELFDynamicSection            dynamicSection        = theFile.DynamicSection;
                    ELFDynamicSymbolTableSection dynamicSymbolsSection = theFile.DynamicSymbolsSection;

                    ELFStringTable DynamicsStringTable = new ELFStringTable(
                        dynamicSection.StrTabDynamic.Val_Ptr, dynamicSection.StrTabSizeDynamic.Val_Ptr);

                    for (uint i = 0; i < dynamicSection.Dynamics.Count; i++)
                    {
                        ELFDynamicSection.Dynamic theDyn = dynamicSection[i];

                        //BasicConsole.WriteLine("     - Dynamic : ");
                        //BasicConsole.Write("         - Tag : ");
                        //BasicConsole.WriteLine((int)theDyn.Tag);
                        //BasicConsole.Write("         - Value or Pointer : ");
                        //BasicConsole.WriteLine(theDyn.Val_Ptr);

                        if (theDyn.Tag == ELFDynamicSection.DynamicTag.Needed)
                        {
                            BasicConsole.Write("         - Needed library name : ");

                            FOS_System.String libFullPath = DynamicsStringTable[theDyn.Val_Ptr];
                            Console.Default.WriteLine(libFullPath);
                            BasicConsole.WriteLine(libFullPath);

                            FOS_System.String libFileName = (FOS_System.String)libFullPath.Split('\\').Last();
                            libFileName = (FOS_System.String)libFileName.Split('/').Last();
                            FOS_System.String libTestPath = theFile.TheFile.Parent.GetFullPath() + libFileName;
                            File sharedObjectFile         = File.Open(libTestPath);
                            if (sharedObjectFile == null)
                            {
                                Console.Default.WarningColour();
                                Console.Default.WriteLine("Failed to find needed library file!");
                                BasicConsole.WriteLine("Failed to find needed library file!");
                                Console.Default.DefaultColour();
                                OK = false;
                            }
                            else
                            {
                                Console.Default.WriteLine("Found library file. Loading library...");
                                BasicConsole.WriteLine("Found library file. Loading library...");

                                ELFSharedObject sharedObject = DynamicLinkerLoader.LoadLibrary_FromELFSO(sharedObjectFile, this);
                                SharedObjectDependencies.Add(sharedObject);

                                Console.Default.WriteLine("Library loaded.");
                                BasicConsole.WriteLine("Library loaded.");
                            }
                        }
                    }

                    Console.Default.WriteLine("Library Relocations");
                    BasicConsole.WriteLine("Library Relocations");

                    // Perform relocation / dynamic linking of all libraries
                    for (int i = 0; i < SharedObjectDependencies.Count; i++)
                    {
                        ELFSharedObject SO = (ELFSharedObject)SharedObjectDependencies[i];

                        //BasicConsole.WriteLine("Shared Object base address : " + (FOS_System.String)SO.BaseAddress);
                        //BasicConsole.WriteLine("Shared Object file base address : " + (FOS_System.String)SO.TheFile.BaseAddress);

                        List SOSections = SO.TheFile.Sections;
                        for (int j = 0; j < SOSections.Count; j++)
                        {
                            ELFSection SOSection = (ELFSection)SOSections[j];
                            if (SOSection is ELFRelocationTableSection)
                            {
                                //BasicConsole.WriteLine(" - Normal Relocation");

                                ELFRelocationTableSection relocTableSection = (ELFRelocationTableSection)SOSection;
                                ELFSymbolTableSection     symbolTable       = (ELFSymbolTableSection)SO.TheFile.Sections[relocTableSection.SymbolTableSectionIndex];
                                ELFStringTableSection     symbolNamesTable  = (ELFStringTableSection)SO.TheFile.Sections[symbolTable.StringsSectionIndex];

                                List Relocations = relocTableSection.Relocations;
                                for (int k = 0; k < Relocations.Count; k++)
                                {
                                    // Reference: http://docs.oracle.com/cd/E19683-01/817-3677/chapter6-26/index.html

                                    ELFRelocationTableSection.Relocation relocation = (ELFRelocationTableSection.Relocation)Relocations[k];
                                    if (relocation.Type == ELFRelocationTableSection.RelocationType.R_386_NONE)
                                    {
                                        continue;
                                    }

                                    uint *resolvedRelLocation               = (uint *)(SO.BaseAddress + (relocation.Offset - SO.TheFile.BaseAddress));
                                    ELFSymbolTableSection.Symbol symbol     = (ELFSymbolTableSection.Symbol)symbolTable[relocation.Symbol];
                                    FOS_System.String            symbolName = symbolNamesTable[symbol.NameIdx];

                                    //BasicConsole.WriteLine("Relocation:");
                                    ////BasicConsole.WriteLine("    > Symbol index : " + (FOS_System.String)relocation.Symbol);
                                    //BasicConsole.WriteLine("    > Type : " + (FOS_System.String)(uint)relocation.Type);
                                    //BasicConsole.WriteLine("    > Offset : " + (FOS_System.String)(uint)relocation.Offset);
                                    //BasicConsole.WriteLine(((FOS_System.String)"    > Resolved location address: ") + (uint)resolvedRelLocation);
                                    ////BasicConsole.WriteLine(((FOS_System.String)"    > Resolved location start value: ") + *resolvedRelLocation);
                                    //BasicConsole.Write("    > Symbol name : ");
                                    //BasicConsole.WriteLine(symbolName);

                                    uint newValue = 0;
                                    switch (relocation.Type)
                                    {
                                    case ELFRelocationTableSection.RelocationType.R_386_32:
                                        newValue = GetSymbolAddress(symbol, symbolName) + *resolvedRelLocation;
                                        break;

                                    case ELFRelocationTableSection.RelocationType.R_386_PC32:
                                        newValue = GetSymbolAddress(symbol, symbolName) + *resolvedRelLocation - (uint)resolvedRelLocation;
                                        break;

                                    case ELFRelocationTableSection.RelocationType.R_386_RELATIVE:
                                        newValue = SO.BaseAddress + *resolvedRelLocation;
                                        break;

                                    //TODO: Support more relocation types
                                    default:
                                        Console.Default.WarningColour();
                                        Console.Default.Write("WARNING: Unrecognised relocation type! (");
                                        Console.Default.Write_AsDecimal((uint)relocation.Type);
                                        Console.Default.WriteLine(")");
                                        Console.Default.DefaultColour();

                                        BasicConsole.Write("WARNING: Unrecognised relocation type! (");
                                        BasicConsole.Write((uint)relocation.Type);
                                        BasicConsole.WriteLine(")");
                                        break;
                                    }

                                    *resolvedRelLocation = newValue;

                                    //BasicConsole.WriteLine("    > New value: " + (FOS_System.String)(newValue));
                                    //BasicConsole.WriteLine("    > Resolved location end value: " + (FOS_System.String)(*resolvedRelLocation));
                                }
                            }
                            else if (SOSection is ELFRelocationAddendTableSection)
                            {
                                //BasicConsole.WriteLine(" - Addend Relocation");

                                ELFRelocationAddendTableSection relocTableSection = (ELFRelocationAddendTableSection)SOSection;
                                ELFSymbolTableSection           symbolTable       = (ELFSymbolTableSection)SO.TheFile.Sections[relocTableSection.SymbolTableSectionIndex];
                                ELFStringTableSection           symbolNamesTable  = (ELFStringTableSection)SO.TheFile.Sections[symbolTable.StringsSectionIndex];

                                List Relocations = relocTableSection.Relocations;
                                for (int k = 0; k < Relocations.Count; k++)
                                {
                                    ELFRelocationAddendTableSection.RelocationAddend relocation = (ELFRelocationAddendTableSection.RelocationAddend)Relocations[k];
                                    if (relocation.Type == ELFRelocationTableSection.RelocationType.R_386_NONE)
                                    {
                                        continue;
                                    }

                                    ELFSymbolTableSection.Symbol symbol     = (ELFSymbolTableSection.Symbol)symbolTable[relocation.Symbol];
                                    FOS_System.String            symbolName = symbolNamesTable[symbol.NameIdx];
                                    uint *resolvedRelLocation = (uint *)(SO.BaseAddress + (relocation.Offset - SO.TheFile.BaseAddress));

                                    //BasicConsole.WriteLine("Relocation:");
                                    ////BasicConsole.WriteLine("    > Symbol index : " + (FOS_System.String)relocation.Symbol);
                                    //BasicConsole.WriteLine("    > Type : " + (FOS_System.String)(uint)relocation.Type);
                                    //BasicConsole.WriteLine("    > Offset : " + (FOS_System.String)(uint)relocation.Offset);
                                    //BasicConsole.WriteLine(((FOS_System.String)"    > Resolved location address: ") + (uint)resolvedRelLocation);
                                    ////BasicConsole.WriteLine(((FOS_System.String)"    > Resolved location start value: ") + *resolvedRelLocation);
                                    //BasicConsole.Write("    > Symbol name : ");
                                    //BasicConsole.WriteLine(symbolName);

                                    uint newValue = 0;
                                    switch (relocation.Type)
                                    {
                                    //TODO: Support more relocation types
                                    default:
                                        Console.Default.WarningColour();
                                        Console.Default.Write("WARNING: Unrecognised relocation type! (");
                                        Console.Default.Write_AsDecimal((uint)relocation.Type);
                                        Console.Default.WriteLine(")");
                                        Console.Default.DefaultColour();

                                        BasicConsole.Write("WARNING: Unrecognised relocation type! (");
                                        BasicConsole.Write((uint)relocation.Type);
                                        BasicConsole.WriteLine(")");
                                        break;
                                    }

                                    *resolvedRelLocation = newValue;

                                    //BasicConsole.WriteLine("    > New value: " + (FOS_System.String)(newValue));
                                    //BasicConsole.WriteLine("    > Resolved location end value: " + (FOS_System.String)(*resolvedRelLocation));
                                }
                            }
                        }
                    }

                    Console.Default.WriteLine("Executable Relocations");
                    BasicConsole.WriteLine("Executable Relocations");

                    //BasicConsole.WriteLine("Executable base address : " + (FOS_System.String)BaseAddress);
                    //BasicConsole.WriteLine("Executable file base address : " + (FOS_System.String)theFile.BaseAddress);

                    // Perform dynamic linking of executable
                    List ExeSections = theFile.Sections;
                    for (int j = 0; j < ExeSections.Count; j++)
                    {
                        ELFSection ExeSection = (ELFSection)ExeSections[j];
                        if (ExeSection is ELFRelocationTableSection)
                        {
                            //BasicConsole.WriteLine(" - Normal Relocations");

                            ELFRelocationTableSection relocTableSection = (ELFRelocationTableSection)ExeSection;
                            ELFSymbolTableSection     symbolTable       = (ELFSymbolTableSection)theFile.Sections[relocTableSection.SymbolTableSectionIndex];
                            ELFStringTableSection     symbolNamesTable  = (ELFStringTableSection)theFile.Sections[symbolTable.StringsSectionIndex];

                            List Relocations = relocTableSection.Relocations;
                            for (int k = 0; k < Relocations.Count; k++)
                            {
                                ELFRelocationTableSection.Relocation relocation = (ELFRelocationTableSection.Relocation)Relocations[k];
                                if (relocation.Type == ELFRelocationTableSection.RelocationType.R_386_NONE)
                                {
                                    continue;
                                }

                                uint *resolvedRelLocation               = (uint *)(BaseAddress + (relocation.Offset - theFile.BaseAddress));
                                ELFSymbolTableSection.Symbol symbol     = (ELFSymbolTableSection.Symbol)symbolTable[relocation.Symbol];
                                FOS_System.String            symbolName = symbolNamesTable[symbol.NameIdx];

                                //BasicConsole.WriteLine("Relocation:");
                                ////BasicConsole.WriteLine("    > Symbol index : " + (FOS_System.String)relocation.Symbol);
                                //BasicConsole.WriteLine("    > Type : " + (FOS_System.String)(uint)relocation.Type);
                                //BasicConsole.WriteLine("    > Offset : " + (FOS_System.String)(uint)relocation.Offset);
                                //BasicConsole.WriteLine(((FOS_System.String)"    > Resolved location address: ") + (uint)resolvedRelLocation);
                                ////BasicConsole.WriteLine(((FOS_System.String)"    > Resolved location start value: ") + *resolvedRelLocation);
                                //BasicConsole.Write("    > Symbol name : ");
                                //BasicConsole.WriteLine(symbolName);

                                bool setFromNewValue = true;
                                uint newValue        = 0;
                                switch (relocation.Type)
                                {
                                //TODO: Support more relocation types
                                case ELFRelocationTableSection.RelocationType.R_386_JMP_SLOT:
                                    newValue = GetSymbolAddress(symbol, symbolName);
                                    break;

                                case ELFRelocationTableSection.RelocationType.R_386_COPY:
                                    // Created by the link-editor for dynamic executables to preserve a read-only text segment.
                                    // Its offset member refers to a location in a writable segment. The symbol table index
                                    // specifies a symbol that should exist both in the current object file and in a shared object.
                                    // During execution, the runtime linker copies data associated with the shared object's symbol
                                    // to the location specified by the offset.
                                    // See Copy Relocations:
                                    //      http://docs.oracle.com/cd/E19683-01/817-3677/6mj8mbtbs/index.html#chapter4-84604

                                    setFromNewValue = false;
                                    uint symbolAddress = 0;
                                    uint symbolSize    = 0;

                                    if (GetSymbolAddressAndSize(symbol, symbolName, ref symbolAddress, ref symbolSize))
                                    {
                                        byte *symbolValuePtr = (byte *)symbolAddress;

                                        //BasicConsole.Write("    > Symbol size : ");
                                        //BasicConsole.WriteLine(symbolSize);

                                        for (int i = 0; i < symbolSize; i++)
                                        {
                                            resolvedRelLocation[i] = symbolValuePtr[i];
                                        }
                                    }
                                    else
                                    {
                                        BasicConsole.WriteLine("Failed to get symbol address and size for R_386_COPY relocation!");
                                    }
                                    break;

                                default:
                                    Console.Default.WarningColour();
                                    Console.Default.Write("WARNING: Unrecognised relocation type! (");
                                    Console.Default.Write_AsDecimal((uint)relocation.Type);
                                    Console.Default.WriteLine(")");
                                    Console.Default.DefaultColour();

                                    BasicConsole.Write("WARNING: Unrecognised relocation type! (");
                                    BasicConsole.Write((uint)relocation.Type);
                                    BasicConsole.WriteLine(")");
                                    break;
                                }
                                if (setFromNewValue)
                                {
                                    *resolvedRelLocation = newValue;
                                    //BasicConsole.WriteLine("    > New value: " + (FOS_System.String)(newValue));
                                    //BasicConsole.WriteLine("    > Resolved location end value: " + (FOS_System.String)(*resolvedRelLocation));
                                }
                            }
                        }
                        else if (ExeSection is ELFRelocationAddendTableSection)
                        {
                            //BasicConsole.WriteLine(" - Addend Relocations");

                            ELFRelocationAddendTableSection relocTableSection = (ELFRelocationAddendTableSection)ExeSection;
                            ELFSymbolTableSection           symbolTable       = (ELFSymbolTableSection)theFile.Sections[relocTableSection.SymbolTableSectionIndex];
                            ELFStringTableSection           symbolNamesTable  = (ELFStringTableSection)theFile.Sections[symbolTable.StringsSectionIndex];

                            List Relocations = relocTableSection.Relocations;
                            for (int k = 0; k < Relocations.Count; k++)
                            {
                                ELFRelocationAddendTableSection.RelocationAddend relocation = (ELFRelocationAddendTableSection.RelocationAddend)Relocations[k];
                                if (relocation.Type == ELFRelocationTableSection.RelocationType.R_386_NONE)
                                {
                                    continue;
                                }

                                uint *resolvedRelLocation               = (uint *)(BaseAddress + (relocation.Offset - theFile.BaseAddress));
                                ELFSymbolTableSection.Symbol symbol     = (ELFSymbolTableSection.Symbol)symbolTable[relocation.Symbol];
                                FOS_System.String            symbolName = symbolNamesTable[symbol.NameIdx];

                                //BasicConsole.WriteLine("Relocation:");
                                ////BasicConsole.WriteLine("    > Symbol index : " + (FOS_System.String)relocation.Symbol);
                                //BasicConsole.WriteLine("    > Type : " + (FOS_System.String)(uint)relocation.Type);
                                //BasicConsole.WriteLine("    > Offset : " + (FOS_System.String)(uint)relocation.Offset);
                                //BasicConsole.WriteLine(((FOS_System.String)"    > Resolved location address: ") + (uint)resolvedRelLocation);
                                ////BasicConsole.WriteLine(((FOS_System.String)"    > Resolved location start value: ") + *resolvedRelLocation);
                                //BasicConsole.Write("    > Symbol name : ");
                                //BasicConsole.WriteLine(symbolName);

                                uint newValue = 0;
                                switch (relocation.Type)
                                {
                                //TODO: Support more relocation types
                                default:
                                    Console.Default.WarningColour();
                                    Console.Default.Write("WARNING: Unrecognised relocation type! (");
                                    Console.Default.Write_AsDecimal((uint)relocation.Type);
                                    Console.Default.WriteLine(")");
                                    Console.Default.DefaultColour();

                                    BasicConsole.Write("WARNING: Unrecognised relocation type! (");
                                    BasicConsole.Write((uint)relocation.Type);
                                    BasicConsole.WriteLine(")");
                                    break;
                                }
                                *resolvedRelLocation = newValue;
                                //BasicConsole.WriteLine("    > New value: " + (FOS_System.String)(newValue));
                                //BasicConsole.WriteLine("    > Resolved location end value: " + (FOS_System.String)(*resolvedRelLocation));
                            }
                        }
                    }

                    // TODO: Call Init functions of libraries
                }

                // Unmap processes' memory from current processes' memory
                for (int i = 0; i < SharedObjectDependencies.Count; i++)
                {
                    ELFSharedObject SO = (ELFSharedObject)SharedObjectDependencies[i];
                    uint            FileBaseAddress = SO.TheFile.BaseAddress;
                    uint            MemBaseAddress  = SO.BaseAddress;

                    List SOSegments = SO.TheFile.Segments;
                    for (int j = 0; j < SOSegments.Count; j++)
                    {
                        ELFSegment SOSegment = (ELFSegment)SOSegments[j];
                        ProcessManager.CurrentProcess.TheMemoryLayout.RemovePage(
                            (MemBaseAddress + ((uint)SOSegment.Header.VAddr - FileBaseAddress)) & 0xFFFFF000);
                    }
                }
                {
                    uint FileBaseAddress = theFile.BaseAddress;
                    uint MemBaseAddress  = BaseAddress;

                    List ExeSegments = theFile.Segments;
                    for (int j = 0; j < ExeSegments.Count; j++)
                    {
                        ELFSegment ExeSegment = (ELFSegment)ExeSegments[j];
                        ProcessManager.CurrentProcess.TheMemoryLayout.RemovePage(
                            (MemBaseAddress + ((uint)ExeSegment.Header.VAddr - FileBaseAddress)) & 0xFFFFF000);
                    }
                }

                #endregion

                ProcessManager.CurrentProcess.TheMemoryLayout.RemovePage(threadStackVirtAddr);
            }
            finally
            {
                if (!OK)
                {
                    theProcess = null;
                }
            }
        }
Beispiel #16
0
        public virtual Thread CreateThread(ThreadStartMethod MainMethod, FOS_System.String Name)
        {
#if PROCESS_TRACE
            BasicConsole.WriteLine("Process: CreateThread: Creating thread...");
#endif
            //TODO: Wrap EnableKernelAccessToProcessMemory in try-finally blocks
            
            // Required so that page allocations by new Thread don't create conflicts
            ProcessManager.EnableKernelAccessToProcessMemory(this);
        
            Thread newThread = new Thread(this, MainMethod, ThreadIdGenerator++, UserMode, Name);
#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding data page...");
#endif
            // Add the page to the processes memory layout
            uint threadStackVirtAddr = (uint)newThread.State->ThreadStackTop - 4092;
            uint threadStackPhysAddr = (uint)VirtMemManager.GetPhysicalAddress(newThread.State->ThreadStackTop - 4092);
            TheMemoryLayout.AddDataPage(threadStackPhysAddr, threadStackVirtAddr);
            
            ProcessManager.DisableKernelAccessToProcessMemory(this);
        
#if PROCESS_TRACE
            BasicConsole.WriteLine("Adding thread...");
#endif

            Threads.Add(newThread);

            if (Registered)
            {
                Scheduler.InitThread(this, newThread);
            }
            
            return newThread;
        }
Beispiel #17
0
        public Thread(Process AnOwner, ThreadStartMethod StartMethod, uint AnId, bool UserMode, FOS_System.String AName)
        {
#if THREAD_TRACE
            BasicConsole.WriteLine("Constructing thread object...");
#endif
            LastActiveState = ActiveStates.NotStarted;
            Owner = AnOwner;

            //Init thread state
            #if THREAD_TRACE
            BasicConsole.WriteLine("Allocating state memory...");
#endif
            State = (ThreadState*)FOS_System.Heap.Alloc((uint)sizeof(ThreadState), "Thread : Thread() (1)");

            // Init Id and EIP
            //  Set EIP to the first instruction of the main method
#if THREAD_TRACE
            BasicConsole.WriteLine("Setting thread info...");
#endif
            Id = AnId;
            Name = AName;
            State->StartEIP = (uint)Utilities.ObjectUtilities.GetHandle(StartMethod);

            // Allocate kernel memory for the kernel stack for this thread
            //  Used when this thread is preempted or does a sys call. Stack is switched to
            //  this thread-specific kernel stack
#if THREAD_TRACE
            BasicConsole.WriteLine("Allocating kernel stack...");
#endif
            // TODO: Allocate using virt mem manager not the heap (see ThreadStackTop below)
            State->KernelStackTop = (byte*)FOS_System.Heap.Alloc(0x1000, 4) + 0xFFC; //4KiB, 4-byte aligned
            
            // Allocate free memory for the user stack for this thread
            //  Used by this thread in normal execution
#if THREAD_TRACE
            BasicConsole.WriteLine("Mapping thread stack page...");
#endif
            State->UserMode = UserMode;
            State->ThreadStackTop = (byte*)Hardware.VirtMemManager.MapFreePage(
                UserMode ? Hardware.VirtMem.VirtMemImpl.PageFlags.None :
                           Hardware.VirtMem.VirtMemImpl.PageFlags.KernelOnly) + 4092; //4 KiB, page-aligned
            
            // Set ESP to the top of the stack - 4 byte aligned, high address since x86 stack works
            //  downwards
#if THREAD_TRACE
            BasicConsole.WriteLine("Setting ESP...");
#endif
            State->ESP = (uint)State->ThreadStackTop;

            // TimeToRun and TimeToRunReload are set up in Scheduler.InitProcess which
            //      is called when a process is registered.

            // Init SS
            //  Stack Segment = User or Kernel space data segment selector offset
            //  Kernel data segment selector offset (offset in GDT) = 0x10 (16)
            //  User   data segment selector offset (offset in GDT) = 0x23 (32|3)
            //          User data segment selector must also be or'ed with 3 for User Privilege level
#if THREAD_TRACE
            BasicConsole.WriteLine("Setting SS...");
#endif
            State->SS = UserMode ? (ushort)0x23 : (ushort)0x10;

            // Init Started
            //  Not started yet so set to false
#if THREAD_TRACE
            BasicConsole.WriteLine("Setting started...");
#endif
            State->Started = false;

#if THREAD_TRACE
            BasicConsole.WriteLine("Allocating exception state...");
#endif
            //TODO: This is currently incorrectly allocated from the current process's heap instead of the heap of the owner process
            // Init Exception State
            State->ExState = (ExceptionState*)FOS_System.Heap.AllocZeroed((uint)sizeof(ExceptionState), "Thread : Thread() (2)");

#if THREAD_TRACE
            BasicConsole.WriteLine("Done.");
#endif
        }