public static void Main() { // The serial ports should have already been initialised MsgPort = Serial.COM2; NotifPort = Serial.COM3; // This looks silly, but the host debugger is actually waiting for this // to determine the OS has connected and is ready MsgPort.Write("Debug thread :D\n"); //MsgPort.Write("Enabling...\n"); // Everything is initialised and connected, so enable the debugger Enabled = true; //MsgPort.Write("Enabled.\n"); // Note: It doesn't actually matter if the host hasn't connected // because the debugger has near-zero effective cost to the rest of the system // unless it is sent a command (unlike the old debugger, which slowed everything // down to the point of being unusable). while (!Terminating) { // Read in a line from the host FOS_System.String line = ""; char c = (char)MsgPort.Read(); while (c != '\n' && c != '\r') { line += c; c = (char)MsgPort.Read(); } // Echo the command back to the host for verification MsgPort.Write("START OF COMMAND\n"); MsgPort.Write(line); MsgPort.Write("\n"); // Filter the line line = line.Trim().ToLower(); // Split it up into relevant parts List lineParts = line.Split(' '); if (lineParts.Count > 0) { FOS_System.String cmd = (FOS_System.String)lineParts[0]; if (cmd == "ping") { MsgPort.Write("pong\n"); } else if (cmd == "help") { #region Help MsgPort.Write("Available commands:\n"); MsgPort.Write(" - ping\n"); MsgPort.Write(" - threads\n"); MsgPort.Write(" - suspend (processId) (threadId | -1 for all threads)\n"); MsgPort.Write(" - resume (processId) (threadId | -1 for all threads)\n"); MsgPort.Write(" - step (processId) (threadId | -1 for all threads)\n"); MsgPort.Write(" - ss (processId) (threadId | -1 for all threads)\n"); MsgPort.Write(" - sta (processId) (threadId | -1 for all threads) (address)\n"); MsgPort.Write(" - bps (address:hex)\n"); MsgPort.Write(" - bpc (address:hex)\n"); MsgPort.Write(" - regs (processId) (threadId)\n"); MsgPort.Write(" - memory (processId) (address:hex) (length) (units:1,2,4)\n"); #endregion } else if (cmd == "threads") { #region Threads for (int i = 0; i < ProcessManager.Processes.Count; i++) { Process AProcess = (Process)ProcessManager.Processes[i]; MsgPort.Write(" - Process : "); MsgPort.Write((FOS_System.String)AProcess.Id); MsgPort.Write(" : "); MsgPort.Write(AProcess.Name); MsgPort.Write(" : "); switch (AProcess.Priority) { case Scheduler.Priority.ZeroTimed: MsgPort.Write("Zero Timed"); break; case Scheduler.Priority.Low: MsgPort.Write("Low"); break; case Scheduler.Priority.Normal: MsgPort.Write("Normal"); break; case Scheduler.Priority.High: MsgPort.Write("High"); break; } MsgPort.Write("\n"); for (int j = 0; j < AProcess.Threads.Count; j++) { Thread AThread = (Thread)AProcess.Threads[j]; MsgPort.Write(" - Thread : "); MsgPort.Write((FOS_System.String)AThread.Id); MsgPort.Write(" : "); switch (AThread.ActiveState) { case Thread.ActiveStates.Active: MsgPort.Write("Active"); break; case Thread.ActiveStates.Inactive: MsgPort.Write("Inactive"); break; case Thread.ActiveStates.NotStarted: MsgPort.Write("Not Started"); break; case Thread.ActiveStates.Suspended: MsgPort.Write("Suspended"); break; case Thread.ActiveStates.Terminated: MsgPort.Write("Terminated"); break; } MsgPort.Write(" : "); MsgPort.Write(AThread.Name); MsgPort.Write("\n"); } } #endregion } else if (cmd == "suspend") { #region Suspend if (lineParts.Count == 3) { uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0); int ThreadId = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]); Process TheProcess = ProcessManager.GetProcessById(ProcessId); if (TheProcess != null) { if (ThreadId == -1) { for (int i = 0; i < TheProcess.Threads.Count; i++) { Thread AThread = ((Thread)TheProcess.Threads[i]); if (AThread != MainThread) { UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | AThread.Id; if (ThreadsToSuspend.IndexOf(ProcessThreadId) == -1) { ThreadsToSuspend.Add(ProcessThreadId); } AThread.Debug_Suspend = true; MsgPort.Write(" > Suspended "); MsgPort.Write(AThread.Name); MsgPort.Write(" thread\n"); } } } else { UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | (uint)ThreadId; if (ThreadsToSuspend.IndexOf(ProcessThreadId) == -1) { ThreadsToSuspend.Add(ProcessThreadId); } Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess); if (TheThread != null) { if (TheThread != MainThread) { TheThread.Debug_Suspend = true; MsgPort.Write(" > Suspended "); MsgPort.Write(TheThread.Name); MsgPort.Write(" thread\n"); } } else { MsgPort.Write("Thread not found.\n"); } } } else { MsgPort.Write("Process not found.\n"); } } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else if (cmd == "resume") { #region Resume if (lineParts.Count == 3) { uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0); int ThreadId = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]); Process TheProcess = ProcessManager.GetProcessById(ProcessId); if (TheProcess != null) { if (ThreadId == -1) { for (int i = 0; i < TheProcess.Threads.Count; i++) { Thread AThread = ((Thread)TheProcess.Threads[i]); UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | AThread.Id; ThreadsToSuspend.Remove(ProcessThreadId); AThread.Debug_Suspend = false; MsgPort.Write(" > Resumed "); MsgPort.Write(AThread.Name); MsgPort.Write(" thread\n"); } } else { UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | (uint)ThreadId; ThreadsToSuspend.Remove(ProcessThreadId); Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess); if (TheThread != null) { TheThread.Debug_Suspend = false; MsgPort.Write(" > Resumed "); MsgPort.Write(TheThread.Name); MsgPort.Write(" thread\n"); } else { MsgPort.Write("Thread not found.\n"); } } } else { MsgPort.Write("Process not found.\n"); } } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else if (cmd == "step") { #region Step if (lineParts.Count == 3) { uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0); int ThreadId = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]); Process TheProcess = ProcessManager.GetProcessById(ProcessId); if (TheProcess != null) { if (ThreadId == -1) { for (int i = 0; i < TheProcess.Threads.Count; i++) { Thread AThread = ((Thread)TheProcess.Threads[i]); if (AThread.Debug_Suspend) { AThread.Debug_Suspend = false; MsgPort.Write(" > Stepping "); MsgPort.Write(AThread.Name); MsgPort.Write(" thread\n"); } else { MsgPort.Write("Thread must be suspended first.\n"); } } } else { Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess); if (TheThread != null) { if (TheThread.Debug_Suspend) { TheThread.Debug_Suspend = false; MsgPort.Write(" > Stepping "); MsgPort.Write(TheThread.Name); MsgPort.Write(" thread\n"); } else { MsgPort.Write("Thread must be suspended first.\n"); } } else { MsgPort.Write("Thread not found.\n"); } } } else { MsgPort.Write("Process not found.\n"); } } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else if (cmd == "ss") { #region Single Step if (lineParts.Count == 3) { uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0); int ThreadId = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]); Process TheProcess = ProcessManager.GetProcessById(ProcessId); if (TheProcess != null) { if (ThreadId == -1) { for (int i = 0; i < TheProcess.Threads.Count; i++) { Thread AThread = ((Thread)TheProcess.Threads[i]); if (AThread.Debug_Suspend) { // Set trap flag (int1) AThread.EFLAGSFromInterruptStack |= 0x0100; AThread.Debug_Suspend = false; MsgPort.Write(" > Single stepping "); MsgPort.Write(AThread.Name); MsgPort.Write(" thread\n"); } else { MsgPort.Write("Thread must be suspended first.\n"); } } } else { Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess); if (TheThread != null) { if (TheThread.Debug_Suspend) { // Set trap flag (int1) TheThread.EFLAGSFromInterruptStack |= 0x0100; TheThread.Debug_Suspend = false; MsgPort.Write(" > Single stepping "); MsgPort.Write(TheThread.Name); MsgPort.Write(" thread\n"); } else { MsgPort.Write("Thread must be suspended first.\n"); } } else { MsgPort.Write("Thread not found.\n"); } } } else { MsgPort.Write("Process not found.\n"); } } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else if (cmd == "sta") { #region Step To Address if (lineParts.Count == 4) { uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0); int ThreadId = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[2]); uint Address = FOS_System.Int32.Parse_HexadecimalUnsigned((FOS_System.String)lineParts[3], 0); Process TheProcess = ProcessManager.GetProcessById(ProcessId); if (TheProcess != null) { if (ThreadId == -1) { for (int i = 0; i < TheProcess.Threads.Count; i++) { Thread AThread = ((Thread)TheProcess.Threads[i]); if (AThread.Debug_Suspend) { // Set trap flag (int1) UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | (uint)ThreadId; ThreadsToSuspendAtAddresses.Add(ProcessThreadId, Address); AThread.EFLAGSFromInterruptStack |= 0x0100; AThread.Debug_Suspend = false; MsgPort.Write(" > Single stepping "); MsgPort.Write(AThread.Name); MsgPort.Write(" thread to address "); MsgPort.Write(Address); MsgPort.Write("\n"); } else { MsgPort.Write("Thread must be suspended first.\n"); } } } else { Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess); if (TheThread != null) { if (TheThread.Debug_Suspend) { // Set trap flag (int1) UInt64 ProcessThreadId = (((UInt64)ProcessId) << 32) | (uint)ThreadId; ThreadsToSuspendAtAddresses.Add(ProcessThreadId, Address); TheThread.EFLAGSFromInterruptStack |= 0x0100; TheThread.Debug_Suspend = false; MsgPort.Write(" > Single stepping "); MsgPort.Write(TheThread.Name); MsgPort.Write(" thread to address "); MsgPort.Write(Address); MsgPort.Write("\n"); } else { MsgPort.Write("Thread must be suspended first.\n"); } } else { MsgPort.Write("Thread not found.\n"); } } } else { MsgPort.Write("Process not found.\n"); } } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else if (cmd == "bps") { #region Set Breakpoint if (lineParts.Count == 2) { uint Address = FOS_System.Int32.Parse_HexadecimalUnsigned((FOS_System.String)lineParts[1], 0); MsgPort.Write(" > Breakpoint to be set at "); MsgPort.Write(Address); MsgPort.Write("\n"); *((byte *)Address) = 0xCC; } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else if (cmd == "bpc") { #region Clear Breakpoint if (lineParts.Count == 2) { uint Address = FOS_System.Int32.Parse_HexadecimalUnsigned((FOS_System.String)lineParts[1], 0); MsgPort.Write(" > Breakpoint to be cleared at "); MsgPort.Write(Address); MsgPort.Write("\n"); *((byte *)Address) = 0x90; } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else if (cmd == "regs") { #region Registers if (lineParts.Count == 3) { uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0); uint ThreadId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[2], 0); Process TheProcess = ProcessManager.GetProcessById(ProcessId); if (TheProcess != null) { Thread TheThread = ProcessManager.GetThreadById((uint)ThreadId, TheProcess); if (TheThread != null) { if (TheThread.Debug_Suspend) { MsgPort.Write("Registers of "); MsgPort.Write(TheThread.Name); MsgPort.Write(" : \n"); MsgPort.Write(" > EAX : "); MsgPort.Write(TheThread.EAXFromInterruptStack); MsgPort.Write("\n > EBX : "); MsgPort.Write(TheThread.EBXFromInterruptStack); MsgPort.Write("\n > ECX : "); MsgPort.Write(TheThread.ECXFromInterruptStack); MsgPort.Write("\n > EDX : "); MsgPort.Write(TheThread.EDXFromInterruptStack); MsgPort.Write("\n"); MsgPort.Write("\n > ESP : "); MsgPort.Write(TheThread.ESPFromInterruptStack); MsgPort.Write("\n > EBP : "); MsgPort.Write(TheThread.EBPFromInterruptStack); MsgPort.Write("\n > EIP : "); MsgPort.Write(TheThread.EIPFromInterruptStack); MsgPort.Write("\n"); } else { MsgPort.Write("Thread must be suspended first.\n"); } } else { MsgPort.Write("Thread not found.\n"); } } else { MsgPort.Write("Process not found.\n"); } } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else if (cmd == "mem") { #region Memory if (lineParts.Count == 5) { uint ProcessId = FOS_System.Int32.Parse_DecimalUnsigned((FOS_System.String)lineParts[1], 0); Process TheProcess = ProcessManager.GetProcessById(ProcessId); if (TheProcess != null && false) { // Need access to specified process' memory //TODO: Erm... MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(TheProcess); uint Address = FOS_System.Int32.Parse_HexadecimalUnsigned((FOS_System.String)lineParts[2], 0); int length = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[3]); int units = FOS_System.Int32.Parse_DecimalSigned((FOS_System.String)lineParts[4]); MsgPort.Write(" Memory from "); MsgPort.Write(Address); MsgPort.Write(" for "); MsgPort.Write(length); MsgPort.Write(" units with "); MsgPort.Write(units); MsgPort.Write(" bytes/unit:\n"); if (units == 1) { byte *AddrPtr = (byte *)Address; for (int i = 0; i < length; i++) { MsgPort.Write((FOS_System.String)AddrPtr[i]); MsgPort.Write(" "); } } else if (units == 2) { ushort *AddrPtr = (ushort *)Address; for (int i = 0; i < length; i++) { MsgPort.Write((FOS_System.String)AddrPtr[i]); MsgPort.Write(" "); } } else if (units == 4) { uint *AddrPtr = (uint *)Address; for (int i = 0; i < length; i++) { MsgPort.Write((FOS_System.String)AddrPtr[i]); MsgPort.Write(" "); } } MsgPort.Write("\n"); //TODO: Erm... SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout); } else { MsgPort.Write("Process not found.\n"); } } else { MsgPort.Write("Incorrect arguments, see help.\n"); } #endregion } else { MsgPort.Write("Unrecognised command. (Note: Backspace not supported!)\n"); } } // Always issue end of command signal, even if something else went wrong // - Keeps the host in sync. MsgPort.Write("END OF COMMAND\n"); } }
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; } } }