public bool WaitOnBehalf(Process aProcess, Thread aThread) { ulong identifier = ((UInt64)aProcess.Id << 32) | aThread.Id; ExclLock.Enter(); bool notLocked = count > 0; if (notLocked) { count--; } else { aThread._EnterSleep(Thread.IndefiniteSleep); WaitingThreads.Add(identifier); } ExclLock.Exit(); return(notLocked); }
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"); } }