string WriteRegisters(GDBPacket packet) { string regsData = packet.GetCommandParameters()[0]; for (int i = 0, pos = 0; i < RegistersCount; i++) { int currentRegisterLength = GetRegisterSize(i) == RegisterSize.Word ? 4 : 2; SetRegister(i, regsData.Substring(pos, currentRegisterLength)); pos += currentRegisterLength; } return StandartAnswers.OK; }
string SetRegister(GDBPacket packet) { string[] parameters = packet.GetCommandParameters()[0].Split(new char[] { '=' }); if (SetRegister(Convert.ToInt32(parameters[0], 16), parameters[1])) return StandartAnswers.OK; else return StandartAnswers.Error; }
string WriteMemory(GDBPacket packet) { string[] parameters = packet.GetCommandParameters(); ushort addr = Convert.ToUInt16(parameters[0], 16); int length = Convert.ToUInt16(parameters[1], 16); if (length > 0) { for (int i = 0; i < length; i++) emulator.CPU.WRMEM((ushort)(addr + i), (byte)Convert.ToUInt16(parameters[2].Substring(i * 2, 2), 16)); } else return StandartAnswers.Error; return StandartAnswers.OK; }
string ReadRegisters(GDBPacket packet) { return String.Join("", Enumerable.Range(0, RegistersCount - 1).Select(i => GetRegisterAsHex(i)).ToArray()); }
string SetBreakpoint(GDBPacket packet) { string[] parameters = packet.GetCommandParameters(); Breakpoint.BreakpointType type = Breakpoint.GetBreakpointType(int.Parse(parameters[0])); ushort addr = Convert.ToUInt16(parameters[1], 16); if (type == Breakpoint.BreakpointType.Execution) emulator.AddBreakpoint(new ZXMAK2.Entities.Breakpoint(addr)); else jtagDevice.AddBreakpoint(type, addr); return StandartAnswers.OK; }
string GetTargetHaltedReason(GDBPacket packet) { return StandartAnswers.HaltedReason; }
string ReadMemory(GDBPacket packet) { string[] parameters = packet.GetCommandParameters(); var addr = Convert.ToUInt16(parameters[0], 16); var length = Convert.ToUInt16(parameters[1]); string result = ""; if (length > 0) { for (int i = 0; i < length; i++) result += emulator.CPU.RDMEM((ushort)(addr + i)).ToLowEndianHexString(); return result; } else return StandartAnswers.Error; }
string GetRegister(GDBPacket packet) { return GetRegisterAsHex(Convert.ToInt32(packet.GetCommandParameters()[0], 16)); }
string GeneralQueryResponse(GDBPacket packet) { string command = packet.GetCommandParameters()[0]; if (command.StartsWith("Supported")) return "PacketSize=4000"; if (command.StartsWith("C")) return StandartAnswers.Empty; if (command.StartsWith("Attached")) return "1"; if (command.StartsWith("TStatus")) return StandartAnswers.Empty; if (command.StartsWith("Offset")) return StandartAnswers.Error; return StandartAnswers.OK; }
string ExecutionRequest(GDBPacket packet) { string command = packet.GetCommandParameters()[0]; if (command.StartsWith("Cont?")) return ""; if (command.StartsWith("Cont")) { } return StandartAnswers.Empty; }
public string ParseRequest(GDBPacket packet, out bool isSignal) { string result = StandartAnswers.Empty; isSignal = false; // ctrl+c is SIGINT if (packet.GetBytes()[0] == 0x03) { emulator.DoStop(); result = StandartAnswers.Interrupt; isSignal = true; } switch(packet.CommandName) { case '\0': // Command is empty ("+" in 99.99% cases) return null; case 'q': result = GeneralQueryResponse(packet); break; case 'Q': result = GeneralQueryResponse(packet); break; case '?': result = GetTargetHaltedReason(packet); break; case '!': // extended connection break; case 'g': // read registers result = ReadRegisters(packet); break; case 'G': // write registers result = WriteRegisters(packet); break; case 'm': // read memory result = ReadMemory(packet);break; case 'M': // write memory result = WriteMemory(packet);break; case 'X': // write memory binary // Not implemented yet, client shoul use M instead //result = StandartAnswers.OK; break; case 'p': // get single register result = GetRegister(packet);break; case 'P': // set single register result = SetRegister(packet); break; case 'v': // some requests, mainly vCont result = ExecutionRequest(packet);break; case 's': //stepi emulator.CPU.ExecCycle(); result = "T05"; break; case 'z': // remove bp result = RemoveBreakpoint(packet); break; case 'Z': // insert bp result = SetBreakpoint(packet); break; case 'k': // Kill the target break; case 'H': // set thread result = StandartAnswers.OK; // we do not have threads, so ignoring this command is OK break; case 'c': // continue emulator.DoRun(); result = null; break; case 'D': // Detach from client emulator.DoRun(); result = StandartAnswers.OK; break; } if (result == null) return "+"; else return FormatResponse(result); }
private void GDBClientConnected(object client) { TcpClient tcpClient = (TcpClient)client; NetworkStream clientStream = tcpClient.GetStream(); GDBSession session = new GDBSession(emulator, jtagDevice); byte[] message = new byte[0x1000]; int bytesRead; // log = new StreamWriter("c:\\temp\\log.txt"); // log.AutoFlush = true; emulator.DoStop(); while (true) { bytesRead = 0; try { bytesRead = clientStream.Read(message, 0, 4096); } catch { //a socket error has occured break; } if (bytesRead == 0) { //the client has disconnected from the server break; } if (bytesRead > 0) { GDBPacket packet = new GDBPacket(message, bytesRead); if (log) LogAgent.Info("--> " + packet.ToString()); bool isSignal; string response = session.ParseRequest(packet, out isSignal); if (response != null) { if (isSignal) SendGlobal(response); else SendResponse(clientStream, response); } } } tcpClient.Close (); }