/// <summary> /// Attempts to get descriptors of the outpoints of the specified class and subclass. /// </summary> /// <param name="CallerProcess">The process which owns the memory containing the <paramref cref="request"/>.</param> /// <param name="Class">The class of outpoint to search for.</param> /// <param name="Subclass">The subclass of outpoint to search for.</param> /// <param name="request">A pointer to the request structure (Also used to store the result(s)).</param> /// <returns>True if the request was successful. Otherwise, false.</returns> public static bool GetPipeOutpoints(Process CallerProcess, PipeClasses Class, PipeSubclasses Subclass, PipeOutpointsRequest *request) { // Validate inputs & get caller process if (CallerProcess == null) { return(false); } // Merge memory layouts // so we can access the request structure MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(CallerProcess); bool OK = true; // More validate inputs // - Check request exists (should've been pre-allocated by caller) // - Check request->Outpoints exists (should've been pre-allocated by caller) // - Check request->MaxDescriptors was set correctly if (request == null) { // Should have been pre-allocated by the calling thread (/process) OK = false; } else if (request->Outpoints == null) { // Should have been pre-allocated by the calling thread (/process) OK = false; } else if (request->MaxDescriptors == 0) { // Not technically an error but let's not waste time processing 0 descriptors OK = true; } if (OK) { // Search for all outpoints of correct class and subclass int maxDescriptors = request->MaxDescriptors; for (int i = 0, j = 0; i < PipeOutpoints.Count && j < maxDescriptors; i++) { PipeOutpoint anOutpoint = (PipeOutpoint)PipeOutpoints[i]; if (anOutpoint.Class == Class && anOutpoint.Subclass == Subclass && (anOutpoint.MaxConnections == PipeConstants.UnlimitedConnections || anOutpoint.NumConnections < anOutpoint.MaxConnections)) { // Set the resultant values request->Outpoints[j++].ProcessId = anOutpoint.ProcessId; } } } SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout); return(OK); }
public static unsafe SystemCallResults HandleDeferredSystemCall( Process CallerProcess, Thread CallerThread, SystemCallNumbers syscallNumber, uint Param1, uint Param2, uint Param3, ref uint Return2, ref uint Return3, ref uint Return4) { SystemCallResults result = SystemCallResults.Unhandled; switch (syscallNumber) { case SystemCallNumbers.StartThread: //BasicConsole.WriteLine("DSC: Start Thread"); Return2 = CallerProcess.CreateThread((ThreadStartMethod)Utilities.ObjectUtilities.GetObject((void *)Param1), "[From sys call]").Id; //BasicConsole.WriteLine("DSC: Start Thread - done."); result = SystemCallResults.OK; break; case SystemCallNumbers.RegisterPipeOutpoint: { //BasicConsole.WriteLine("DSC: Register Pipe Outpoint"); Pipes.PipeOutpoint outpoint; bool registered = Pipes.PipeManager.RegisterPipeOutpoint(CallerProcess.Id, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, (int)Param3, out outpoint); if (registered) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } //BasicConsole.WriteLine("DSC: Register Pipe Outpoint - done."); } break; case SystemCallNumbers.GetNumPipeOutpoints: { //BasicConsole.WriteLine("DSC: Get Num Pipe Outpoints"); int numOutpoints; bool obtained = Pipes.PipeManager.GetNumPipeOutpoints((Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, out numOutpoints); if (obtained) { result = SystemCallResults.OK; Return2 = (uint)numOutpoints; } else { result = SystemCallResults.Fail; } //BasicConsole.WriteLine("DSC: Get Num Pipe Outpoints - done"); } break; case SystemCallNumbers.GetPipeOutpoints: { //BasicConsole.WriteLine("DSC: Get Pipe Outpoints"); bool obtained = Pipes.PipeManager.GetPipeOutpoints(CallerProcess, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, (Pipes.PipeOutpointsRequest *)Param3); if (obtained) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } //BasicConsole.WriteLine("DSC: Get Pipe Outpoints - done"); } break; case SystemCallNumbers.CreatePipe: { //BasicConsole.WriteLine("DSC: Create Pipe"); bool created = Pipes.PipeManager.CreatePipe(CallerProcess.Id, Param1, (Pipes.CreatePipeRequest *)Param2); if (created) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } //BasicConsole.WriteLine("DSC: Create Pipe - done"); } break; case SystemCallNumbers.WaitOnPipeCreate: { //BasicConsole.WriteLine("DSC: Wait On Pipe Create"); bool waiting = Pipes.PipeManager.WaitOnPipeCreate(CallerProcess.Id, CallerThread.Id, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2); if (waiting) { result = SystemCallResults.Deferred; } else { result = SystemCallResults.Fail; } //BasicConsole.WriteLine("DSC: Wait On Pipe Create - done"); } break; case SystemCallNumbers.ReadPipe: { //BasicConsole.WriteLine("DSC: Read Pipe"); // Need access to calling process' memory to be able to set values in request structure(s) MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(CallerProcess); Pipes.ReadPipeRequest * RequestPtr = (Pipes.ReadPipeRequest *)Param1; Pipes.PipeManager.RWResults RWResult = Pipes.PipeManager.ReadPipe(RequestPtr->PipeId, RequestPtr->Blocking, CallerProcess, CallerThread); if (RWResult == Pipes.PipeManager.RWResults.Error) { result = SystemCallResults.Fail; } else { // Returning Deferred state from here will leave the caller thread // in whatever state ReadPipe decided it should be in. result = SystemCallResults.Deferred; } SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout); //BasicConsole.WriteLine("DSC: Read Pipe - done"); } break; case SystemCallNumbers.WritePipe: { //BasicConsole.WriteLine("DSC: Write Pipe"); // Need access to calling process' memory to be able to set values in request structure(s) MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(CallerProcess); Pipes.WritePipeRequest * RequestPtr = (Pipes.WritePipeRequest *)Param1; Pipes.PipeManager.RWResults RWResult = Pipes.PipeManager.WritePipe(RequestPtr->PipeId, RequestPtr->Blocking, CallerProcess, CallerThread); if (RWResult == Pipes.PipeManager.RWResults.Error) { result = SystemCallResults.Fail; } else { // Returning Deferred state from here will leave the caller thread // in whatever state WritePipe decided it should be in. result = SystemCallResults.Deferred; } SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout); //BasicConsole.WriteLine("DSC: Write Pipe - done"); } break; default: BasicConsole.WriteLine("DSC: Unrecognised call number."); BasicConsole.WriteLine((uint)syscallNumber); break; } return(result); }
/// <summary> /// Attempts to write to the specified pipe. /// </summary> /// <remarks> /// Note that this function is non-blocking. It will, however, block a system caller thread by simply not returning it from /// the deferred system call. /// </remarks> /// <param name="PipeId">The Id of the pipe to write.</param> /// <param name="Blocking">Whether the write should be blocking or non-blocking.</param> /// <param name="CallerProcess">The process which made the call.</param> /// <param name="CallerThread">The thread which made the call.</param> /// <returns>See descriptions on <see cref="PipeManager.RWResults"/> values.</returns> public static RWResults WritePipe(int PipeId, bool Blocking, Process CallerProcess, Thread CallerThread) { #if PIPES_TRACE BasicConsole.WriteLine("WritePipe: Validating inputs"); #endif // Validate inputs // - Check pipe exists Pipe pipe = GetPipe(PipeId); if (pipe == null) { return(RWResults.Error); } #if PIPES_TRACE BasicConsole.WriteLine("WritePipe: Checking caller allowed to write"); #endif // Check the caller is allowed to access the pipe if (!AllowedToWritePipe(pipe, CallerProcess.Id)) { return(RWResults.Error); } #if PIPES_TRACE BasicConsole.WriteLine("WritePipe: Getting out process"); #endif // Get outpoint process Process OutProcess = ProcessManager.GetProcessById(pipe.Outpoint.ProcessId); if (OutProcess == null) { return(RWResults.Error); } #if PIPES_TRACE BasicConsole.WriteLine("WritePipe: Getting in process"); #endif // Get inpoint process Process InProcess = ProcessManager.GetProcessById(pipe.Inpoint.ProcessId); if (InProcess == null) { return(RWResults.Error); } #if PIPES_TRACE BasicConsole.WriteLine("WritePipe: Merging memory layouts"); #endif // Merge memory layouts of in process (out process should already have been done by caller) // so we can access the request structure(s) and buffers MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(InProcess); #if PIPES_TRACE BasicConsole.WriteLine("WritePipe: Adding caller to write queue"); #endif // Add caller thread to the write queue WritePipeRequest *Request = (WritePipeRequest *)CallerThread.Param1; pipe.QueueToWrite(CallerThread.Id, Request->Length); // Set up initial failure return value CallerThread.Return1 = (uint)SystemCallResults.Fail; #if PIPES_TRACE BasicConsole.WriteLine("WritePipe: Processing pipe queue"); #endif // Process the pipe queue ProcessPipeQueue(pipe, OutProcess, InProcess); #if PIPES_TRACE BasicConsole.WriteLine("WritePipe: Unmerging memory layouts"); #endif // Unmerge memory layouts SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout); bool Completed = !pipe.AreThreadsWaitingToWrite(); if (!Blocking) { if (!Completed) { uint temp; bool removed = pipe.RemoveLastToWrite(out temp); if (!removed || temp != CallerThread.Id) { BasicConsole.WriteLine("PipeManager: Error! Async write failed and then removing last from queue resulted in thread Id mismatch!"); } CallerThread.Return1 = (uint)SystemCallResults.Fail; CallerThread._Wake(); } } return(Completed ? RWResults.Complete : RWResults.Queued); }
/// <summary> /// Attempts to create a new pipe. /// </summary> /// <param name="InProcessId">The Id of the target process which owns the inpoint.</param> /// <param name="OutProcessId">The Id of the target process which owns the outpoint.</param> /// <param name="request">A pointer to the request structure (Also used to store the result).</param> /// <returns>True if the request was successful. Otherwise, false.</returns> public static bool CreatePipe(uint InProcessId, uint OutProcessId, CreatePipeRequest *request) { // Validate inputs // - Check out process exists // - Check in process exists // - Check request isn't null (should've been pre-allocated) Process InProcess = ProcessManager.GetProcessById(InProcessId); if (InProcess == null) { return(false); } else if (ProcessManager.GetProcessById(OutProcessId) == null) { return(false); } else if (request == null) { return(false); } // Merge memory layouts // so we can access the request structure MemoryLayout OriginalMemoryLayout = SystemCallsHelpers.EnableAccessToMemoryOfProcess(InProcess); bool OK = true; // Find the outpoint PipeOutpoint outpoint = GetOutpoint(OutProcessId, request->Class, request->Subclass); // Check that we actually found the outpoint if (outpoint == null) { OK = false; } if (OK) { // Check there are sufficient connections available if (outpoint.NumConnections >= outpoint.MaxConnections && outpoint.MaxConnections != PipeConstants.UnlimitedConnections) { OK = false; } if (OK) { // Create new inpoint PipeInpoint inpoint = new PipeInpoint(InProcessId, request->Class, request->Subclass); // Create new pipe Pipe pipe = new Pipe(PipeIdGenerator++, outpoint, inpoint, request->BufferSize); // Add new pipe to list of pipes Pipes.Add(pipe); // Increment number of connections to the outpoint outpoint.NumConnections++; // Set result information request->Result.Id = pipe.Id; // Wake any threads (/processes) which were waiting on a pipe to be created WakeWaitingThreads(outpoint, pipe.Id); } } SystemCallsHelpers.DisableAccessToMemoryOfProcess(OriginalMemoryLayout); return(OK); }
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("\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(" : "); if (AThread.Debug_Suspend) { MsgPort.Write("Suspended"); } else if (AThread.TimeToSleep == -1) { MsgPort.Write("Waiting "); } else if (AThread.TimeToSleep > 0) { MsgPort.Write("Sleeping "); } else { MsgPort.Write("Running "); } 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((FOS_System.String)TheThread.EAXFromInterruptStack); MsgPort.Write("\n > EBX : "); MsgPort.Write((FOS_System.String)TheThread.EBXFromInterruptStack); MsgPort.Write("\n > ECX : "); MsgPort.Write((FOS_System.String)TheThread.ECXFromInterruptStack); MsgPort.Write("\n > EDX : "); MsgPort.Write((FOS_System.String)TheThread.EDXFromInterruptStack); MsgPort.Write("\n"); MsgPort.Write("\n > ESP : "); MsgPort.Write((FOS_System.String)TheThread.ESPFromInterruptStack); MsgPort.Write("\n > EBP : "); MsgPort.Write((FOS_System.String)TheThread.EBPFromInterruptStack); MsgPort.Write("\n > EIP : "); MsgPort.Write((FOS_System.String)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) { // Need access to specified process' memory 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"); 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"); } }