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); }
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; }
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); }
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); }
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)); }
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); }
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); }
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(); } }
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; }
public static Process CreateProcess(ThreadStartMethod MainMethod, FOS_System.String Name, bool UserMode) { return(CreateProcess(MainMethod, Name, UserMode, false)); }
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); }
public static Process CreateProcess(ThreadStartMethod MainMethod, FOS_System.String Name, bool UserMode) { return CreateProcess(MainMethod, Name, UserMode, false); }
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)"); }
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; }
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; } } }
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; }
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 }