rlm@1: #include rlm@1: #include rlm@1: #include rlm@22: #include rlm@1: rlm@1: #ifndef WIN32 rlm@1: # include rlm@1: # include rlm@1: # include rlm@1: # ifdef HAVE_NETINET_IN_H rlm@1: # include rlm@1: # endif // HAVE_NETINET_IN_H rlm@1: # ifdef HAVE_ARPA_INET_H rlm@1: # include rlm@1: # else // ! HAVE_ARPA_INET_H rlm@1: # define socklen_t int rlm@1: # endif // ! HAVE_ARPA_INET_H rlm@1: #else // WIN32 rlm@1: # include "../win32/stdafx.h" rlm@1: # include rlm@1: # include rlm@1: # define socklen_t int rlm@1: # define close closesocket rlm@1: # define read _read rlm@1: # define write _write rlm@1: #endif // WIN32 rlm@1: rlm@1: #include "GBA.h" rlm@1: #include "GBAGlobals.h" rlm@1: rlm@1: extern bool debugger; rlm@1: extern void CPUUpdateCPSR(); rlm@1: #ifdef SDL rlm@1: extern void (*dbgMain)(); rlm@1: extern void (*dbgSignal)(int, int); rlm@1: extern void debuggerMain(); rlm@1: extern void debuggerSignal(int, int); rlm@1: #endif rlm@1: rlm@1: int remotePort = 55555; rlm@1: int remoteSignal = 5; rlm@1: int remoteSocket = -1; rlm@1: int remoteListenSocket = -1; rlm@1: bool remoteConnected = false; rlm@1: bool remoteResumed = false; rlm@1: rlm@1: int (*remoteSendFnc)(char *, int) = NULL; rlm@1: int (*remoteRecvFnc)(char *, int) = NULL; rlm@1: bool (*remoteInitFnc)() = NULL; rlm@1: void (*remoteCleanUpFnc)() = NULL; rlm@1: rlm@1: #if (defined WIN32 && !defined SDL) rlm@1: void remoteSetSockets(SOCKET l, SOCKET r) rlm@1: { rlm@22: remoteSocket = r; rlm@22: remoteListenSocket = l; rlm@1: } rlm@1: rlm@1: #endif rlm@1: rlm@1: int remoteTcpSend(char *data, int len) rlm@1: { rlm@22: return send(remoteSocket, data, len, 0); rlm@1: } rlm@1: rlm@1: int remoteTcpRecv(char *data, int len) rlm@1: { rlm@22: return recv(remoteSocket, data, len, 0); rlm@1: } rlm@1: rlm@1: bool remoteTcpInit() rlm@1: { rlm@22: if (remoteSocket == -1) rlm@22: { rlm@20: #ifdef WIN32 rlm@22: WSADATA wsaData; rlm@22: int error = WSAStartup(MAKEWORD(1, 1), &wsaData); rlm@20: #endif // WIN32 rlm@22: int s = socket(PF_INET, SOCK_STREAM, 0); rlm@20: rlm@22: remoteListenSocket = s; rlm@20: rlm@22: if (s < 0) rlm@22: { rlm@22: fprintf(stderr, "Error opening socket\n"); rlm@22: exit(-1); rlm@22: } rlm@22: int tmp = 1; rlm@22: setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof(tmp)); rlm@20: rlm@22: // char hostname[256]; rlm@22: // gethostname(hostname, 256); rlm@20: rlm@22: // hostent *ent = gethostbyname(hostname); rlm@22: // unsigned long a = *((unsigned long *)ent->h_addr); rlm@20: rlm@22: sockaddr_in addr; rlm@22: addr.sin_family = AF_INET; rlm@22: addr.sin_port = htons(remotePort); rlm@22: addr.sin_addr.s_addr = htonl(0); rlm@22: int count = 0; rlm@22: while (count < 3) rlm@22: { rlm@22: if (bind(s, (sockaddr *)&addr, sizeof(addr))) rlm@22: { rlm@22: addr.sin_port = htons(ntohs(addr.sin_port)+1); rlm@22: } rlm@22: else rlm@22: break; rlm@22: } rlm@22: if (count == 3) rlm@22: { rlm@22: fprintf(stderr, "Error binding \n"); rlm@22: exit(-1); rlm@22: } rlm@20: rlm@22: fprintf(stderr, "Listening for a connection at port %d\n", rlm@22: ntohs(addr.sin_port)); rlm@20: rlm@22: if (listen(s, 1)) rlm@22: { rlm@22: fprintf(stderr, "Error listening\n"); rlm@22: exit(-1); rlm@22: } rlm@22: socklen_t len = sizeof(addr); rlm@20: rlm@20: #ifdef WIN32 rlm@22: int flag = 0; rlm@22: ioctlsocket(s, FIONBIO, (unsigned long *)&flag); rlm@20: #endif // WIN32 rlm@22: int s2 = accept(s, (sockaddr *)&addr, &len); rlm@22: if (s2 > 0) rlm@22: { rlm@22: fprintf(stderr, "Got a connection from %s %d\n", rlm@22: inet_ntoa((in_addr)addr.sin_addr), rlm@22: ntohs(addr.sin_port)); rlm@22: } rlm@22: else rlm@22: { rlm@22: #ifdef WIN32 rlm@22: int error = WSAGetLastError(); rlm@22: #endif // WIN32 rlm@22: } rlm@22: char dummy; rlm@22: recv(s2, &dummy, 1, 0); rlm@22: if (dummy != '+') rlm@22: { rlm@22: fprintf(stderr, "ACK not received\n"); rlm@22: exit(-1); rlm@22: } rlm@22: remoteSocket = s2; rlm@22: // close(s); rlm@20: } rlm@22: return true; rlm@1: } rlm@1: rlm@1: void remoteTcpCleanUp() rlm@1: { rlm@22: if (remoteSocket > 0) rlm@22: { rlm@22: fprintf(stderr, "Closing remote socket\n"); rlm@22: close(remoteSocket); rlm@22: remoteSocket = -1; rlm@22: } rlm@22: if (remoteListenSocket > 0) rlm@22: { rlm@22: fprintf(stderr, "Closing listen socket\n"); rlm@22: close(remoteListenSocket); rlm@22: remoteListenSocket = -1; rlm@22: } rlm@1: } rlm@1: rlm@1: int remotePipeSend(char *data, int len) rlm@1: { rlm@22: int res = write(1, data, len); rlm@22: return res; rlm@1: } rlm@1: rlm@1: int remotePipeRecv(char *data, int len) rlm@1: { rlm@22: int res = read(0, data, len); rlm@22: return res; rlm@1: } rlm@1: rlm@1: bool remotePipeInit() rlm@1: { rlm@22: char dummy; rlm@22: read(0, &dummy, 1); rlm@22: if (dummy != '+') rlm@22: { rlm@22: fprintf(stderr, "ACK not received\n"); rlm@22: exit(-1); rlm@22: } rlm@1: rlm@22: return true; rlm@1: } rlm@1: rlm@1: void remotePipeCleanUp() rlm@1: {} rlm@1: rlm@1: void remoteSetPort(int port) rlm@1: { rlm@22: remotePort = port; rlm@1: } rlm@1: rlm@1: void remoteSetProtocol(int p) rlm@1: { rlm@22: if (p == 0) rlm@22: { rlm@22: remoteSendFnc = remoteTcpSend; rlm@22: remoteRecvFnc = remoteTcpRecv; rlm@22: remoteInitFnc = remoteTcpInit; rlm@22: remoteCleanUpFnc = remoteTcpCleanUp; rlm@22: } rlm@22: else rlm@22: { rlm@22: remoteSendFnc = remotePipeSend; rlm@22: remoteRecvFnc = remotePipeRecv; rlm@22: remoteInitFnc = remotePipeInit; rlm@22: remoteCleanUpFnc = remotePipeCleanUp; rlm@22: } rlm@1: } rlm@1: rlm@1: void remoteInit() rlm@1: { rlm@22: if (remoteInitFnc) rlm@22: remoteInitFnc(); rlm@1: } rlm@1: rlm@1: void remotePutPacket(char *packet) rlm@1: { rlm@22: char *hex = "0123456789abcdef"; rlm@22: char buffer[1024]; rlm@1: rlm@22: int count = strlen(packet); rlm@1: rlm@22: unsigned char csum = 0; rlm@1: rlm@22: char *p = buffer; rlm@22: *p++ = '$'; rlm@1: rlm@22: for (int i = 0; i < count; i++) rlm@22: { rlm@22: csum += packet[i]; rlm@22: *p++ = packet[i]; rlm@22: } rlm@22: *p++ = '#'; rlm@22: *p++ = hex[csum>>4]; rlm@22: *p++ = hex[csum & 15]; rlm@22: *p++ = 0; rlm@22: // printf("Sending %s\n", buffer); rlm@22: remoteSendFnc(buffer, count + 4); rlm@1: rlm@22: char c = 0; rlm@22: remoteRecvFnc(&c, 1); rlm@22: /* rlm@22: if(c == '+') rlm@22: printf("ACK\n"); rlm@22: else if(c=='-') rlm@22: printf("NACK\n"); rlm@22: */ rlm@1: } rlm@1: rlm@1: void remoteOutput(char *s, u32 addr) rlm@1: { rlm@22: char buffer[16384]; rlm@1: rlm@22: char *d = buffer; rlm@22: *d++ = 'O'; rlm@1: rlm@22: if (s) rlm@1: { rlm@22: char c = *s++; rlm@22: while (c) rlm@22: { rlm@22: sprintf(d, "%02x", c); rlm@22: d += 2; rlm@22: c = *s++; rlm@22: } rlm@1: } rlm@22: else rlm@1: { rlm@22: char c = debuggerReadByte(addr); rlm@22: addr++; rlm@22: while (c) rlm@22: { rlm@22: sprintf(d, "%02x", c); rlm@22: d += 2; rlm@22: c = debuggerReadByte(addr); rlm@22: addr++; rlm@22: } rlm@1: } rlm@22: remotePutPacket(buffer); rlm@22: // fprintf(stderr, "Output sent %s\n", buffer); rlm@1: } rlm@1: rlm@1: void remoteSendSignal() rlm@1: { rlm@22: char buffer[1024]; rlm@22: sprintf(buffer, "S%02x", remoteSignal); rlm@22: remotePutPacket(buffer); rlm@1: } rlm@1: rlm@1: void remoteSendStatus() rlm@1: { rlm@22: char buffer[1024]; rlm@22: sprintf(buffer, "T%02x", remoteSignal); rlm@22: char *s = buffer; rlm@22: s += 3; rlm@22: for (int i = 0; i < 15; i++) rlm@22: { rlm@22: u32 v = reg[i].I; rlm@22: sprintf(s, "%02x:%02x%02x%02x%02x;", i, rlm@22: (v & 255), rlm@22: (v >> 8) & 255, rlm@22: (v >> 16) & 255, rlm@22: (v >> 24) & 255); rlm@22: s += 12; rlm@22: } rlm@22: u32 v = armNextPC; rlm@22: sprintf(s, "0f:%02x%02x%02x%02x;", (v & 255), rlm@22: (v >> 8) & 255, rlm@22: (v >> 16) & 255, rlm@22: (v >> 24) & 255); rlm@22: s += 12; rlm@22: CPUUpdateCPSR(); rlm@22: v = reg[16].I; rlm@22: sprintf(s, "19:%02x%02x%02x%02x;", (v & 255), rlm@22: (v >> 8) & 255, rlm@22: (v >> 16) & 255, rlm@22: (v >> 24) & 255); rlm@22: s += 12; rlm@22: *s = 0; rlm@22: // printf("Sending %s\n", buffer); rlm@22: remotePutPacket(buffer); rlm@1: } rlm@1: rlm@1: void remoteBinaryWrite(char *p) rlm@1: { rlm@22: u32 address; rlm@22: int count; rlm@22: sscanf(p, "%x,%x:", &address, &count); rlm@22: // printf("Binary write for %08x %d\n", address, count); rlm@1: rlm@22: p = strchr(p, ':'); rlm@22: p++; rlm@22: for (int i = 0; i < count; i++) rlm@1: { rlm@22: u8 b = *p++; rlm@22: switch (b) rlm@22: { rlm@22: case 0x7d: rlm@22: b = *p++; rlm@22: debuggerWriteByte(address, (b^0x20)); rlm@22: address++; rlm@22: break; rlm@22: default: rlm@22: debuggerWriteByte(address, b); rlm@22: address++; rlm@22: break; rlm@22: } rlm@1: } rlm@22: // printf("ROM is %08x\n", debuggerReadMemory(0x8000254)); rlm@22: remotePutPacket("OK"); rlm@1: } rlm@1: rlm@1: void remoteMemoryWrite(char *p) rlm@1: { rlm@22: u32 address; rlm@22: int count; rlm@22: sscanf(p, "%x,%x:", &address, &count); rlm@22: // printf("Memory write for %08x %d\n", address, count); rlm@1: rlm@22: p = strchr(p, ':'); rlm@22: p++; rlm@22: for (int i = 0; i < count; i++) rlm@22: { rlm@22: u8 v = 0; rlm@22: char c = *p++; rlm@22: if (c <= '9') rlm@22: v = (c - '0') << 4; rlm@22: else rlm@22: v = (c + 10 - 'a') << 4; rlm@22: c = *p++; rlm@22: if (c <= '9') rlm@22: v += (c - '0'); rlm@22: else rlm@22: v += (c + 10 - 'a'); rlm@22: debuggerWriteByte(address, v); rlm@22: address++; rlm@22: } rlm@22: // printf("ROM is %08x\n", debuggerReadMemory(0x8000254)); rlm@22: remotePutPacket("OK"); rlm@1: } rlm@1: rlm@1: void remoteMemoryRead(char *p) rlm@1: { rlm@22: u32 address; rlm@22: int count; rlm@22: sscanf(p, "%x,%x:", &address, &count); rlm@22: // printf("Memory read for %08x %d\n", address, count); rlm@1: rlm@22: char buffer[1024]; rlm@1: rlm@22: char *s = buffer; rlm@22: for (int i = 0; i < count; i++) rlm@22: { rlm@22: u8 b = debuggerReadByte(address); rlm@22: sprintf(s, "%02x", b); rlm@22: address++; rlm@22: s += 2; rlm@22: } rlm@22: *s = 0; rlm@22: remotePutPacket(buffer); rlm@1: } rlm@1: rlm@1: void remoteStepOverRange(char *p) rlm@1: { rlm@22: u32 address; rlm@22: u32 final; rlm@22: sscanf(p, "%x,%x", &address, &final); rlm@1: rlm@22: remotePutPacket("OK"); rlm@1: rlm@22: remoteResumed = true; rlm@22: do rlm@22: { rlm@22: CPULoop(1); rlm@22: if (debugger) rlm@22: break; rlm@22: } rlm@22: while (armNextPC >= address && armNextPC < final); rlm@1: rlm@22: remoteResumed = false; rlm@1: rlm@22: remoteSendStatus(); rlm@1: } rlm@1: rlm@1: void remoteWriteWatch(char *p, bool active) rlm@1: { rlm@22: u32 address; rlm@22: int count; rlm@22: sscanf(p, ",%x,%x#", &address, &count); rlm@1: rlm@22: fprintf(stderr, "Write watch for %08x %d\n", address, count); rlm@1: rlm@22: if (address < 0x2000000 || address > 0x3007fff) rlm@22: { rlm@22: remotePutPacket("E01"); rlm@22: return; rlm@22: } rlm@1: rlm@22: if (address > 0x203ffff && address < 0x3000000) rlm@22: { rlm@22: remotePutPacket("E01"); rlm@22: return; rlm@22: } rlm@1: rlm@22: u32 final = address + count; rlm@1: rlm@22: if (address < 0x2040000 && final > 0x2040000) rlm@22: { rlm@22: remotePutPacket("E01"); rlm@22: return; rlm@22: } rlm@22: else if (address < 0x3008000 && final > 0x3008000) rlm@22: { rlm@22: remotePutPacket("E01"); rlm@22: return; rlm@22: } rlm@1: rlm@22: for (int i = 0; i < count; i++) rlm@22: { rlm@22: if ((address >> 24) == 2) rlm@22: freezeWorkRAM[address & 0x3ffff] = active; rlm@22: else rlm@22: freezeInternalRAM[address & 0x7fff] = active; rlm@22: address++; rlm@22: } rlm@1: rlm@22: remotePutPacket("OK"); rlm@1: } rlm@1: rlm@1: void remoteReadRegisters(char *p) rlm@1: { rlm@22: char buffer[1024]; rlm@1: rlm@22: char *s = buffer; rlm@22: int i; rlm@22: // regular registers rlm@22: for (i = 0; i < 15; i++) rlm@22: { rlm@22: u32 v = reg[i].I; rlm@22: sprintf(s, "%02x%02x%02x%02x", v & 255, (v >> 8) & 255, rlm@22: (v >> 16) & 255, (v >> 24) & 255); rlm@22: s += 8; rlm@22: } rlm@22: // PC rlm@22: u32 pc = armNextPC; rlm@22: sprintf(s, "%02x%02x%02x%02x", pc & 255, (pc >> 8) & 255, rlm@22: (pc >> 16) & 255, (pc >> 24) & 255); rlm@22: s += 8; rlm@1: rlm@22: // floating point registers (24-bit) rlm@22: for (i = 0; i < 8; i++) rlm@22: { rlm@22: sprintf(s, "000000000000000000000000"); rlm@22: s += 24; rlm@22: } rlm@1: rlm@22: // FP status register rlm@22: sprintf(s, "00000000"); rlm@22: s += 8; rlm@22: // CPSR rlm@22: CPUUpdateCPSR(); rlm@22: u32 v = reg[16].I; rlm@22: sprintf(s, "%02x%02x%02x%02x", v & 255, (v >> 8) & 255, rlm@22: (v >> 16) & 255, (v >> 24) & 255); rlm@22: s += 8; rlm@22: *s = 0; rlm@22: remotePutPacket(buffer); rlm@1: } rlm@1: rlm@1: void remoteWriteRegister(char *p) rlm@1: { rlm@22: int r; rlm@1: rlm@22: sscanf(p, "%x=", &r); rlm@1: rlm@22: p = strchr(p, '='); rlm@22: p++; rlm@1: rlm@22: char c = *p++; rlm@1: rlm@22: u32 v = 0; rlm@1: rlm@22: u8 data[4] = {0, 0, 0, 0}; rlm@1: rlm@22: int i = 0; rlm@1: rlm@22: while (c != '#') rlm@22: { rlm@22: u8 b = 0; rlm@22: if (c <= '9') rlm@22: b = (c - '0') << 4; rlm@22: else rlm@22: b = (c + 10 - 'a') << 4; rlm@22: c = *p++; rlm@22: if (c <= '9') rlm@22: b += (c - '0'); rlm@22: else rlm@22: b += (c + 10 - 'a'); rlm@22: data[i++] = b; rlm@22: c = *p++; rlm@22: } rlm@1: rlm@22: v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); rlm@1: rlm@22: // printf("Write register %d=%08x\n", r, v); rlm@22: reg[r].I = v; rlm@22: if (r == 15) rlm@22: { rlm@22: armNextPC = v; rlm@22: if (armState) rlm@22: reg[15].I = v + 4; rlm@22: else rlm@22: reg[15].I = v + 2; rlm@22: } rlm@22: remotePutPacket("OK"); rlm@1: } rlm@1: rlm@1: void remoteStubMain() rlm@1: { rlm@22: if (!debugger) rlm@22: return; rlm@1: rlm@22: if (remoteResumed) rlm@1: { rlm@22: remoteSendStatus(); rlm@22: remoteResumed = false; rlm@1: } rlm@1: rlm@22: while (true) rlm@22: { rlm@22: char buffer[1024]; rlm@22: int res = remoteRecvFnc(buffer, 1024); rlm@20: rlm@22: if (res == -1) rlm@22: { rlm@22: fprintf(stderr, "GDB connection lost\n"); rlm@1: #ifdef SDL rlm@22: dbgMain = debuggerMain; rlm@22: dbgSignal = debuggerSignal; rlm@1: #endif rlm@22: debugger = false; rlm@22: break; rlm@22: } rlm@22: rlm@22: // fprintf(stderr, "Received %s\n", buffer); rlm@22: char *p = buffer; rlm@22: char c = *p++; rlm@22: char pp = '+'; rlm@22: remoteSendFnc(&pp, 1); rlm@22: rlm@22: if (c != '$') rlm@22: continue; rlm@22: c = *p++; rlm@22: switch (c) rlm@22: { rlm@22: case '?': rlm@22: remoteSendSignal(); rlm@22: break; rlm@22: case 'D': rlm@22: remotePutPacket("OK"); rlm@1: #ifdef SDL rlm@22: dbgMain = debuggerMain; rlm@22: dbgSignal = debuggerSignal; rlm@1: #endif rlm@22: remoteResumed = true; rlm@22: debugger = false; rlm@22: return; rlm@22: case 'e': rlm@22: remoteStepOverRange(p); rlm@22: break; rlm@22: case 'k': rlm@22: remotePutPacket("OK"); rlm@22: #ifdef SDL rlm@22: dbgMain = debuggerMain; rlm@22: dbgSignal = debuggerSignal; rlm@22: #endif rlm@22: debugger = false; rlm@22: emulating = false; rlm@22: return; rlm@22: case 'C': rlm@22: remoteResumed = true; rlm@22: debugger = false; rlm@22: return; rlm@22: case 'c': rlm@22: remoteResumed = true; rlm@22: debugger = false; rlm@22: return; rlm@22: case 's': rlm@22: remoteResumed = true; rlm@22: remoteSignal = 5; rlm@22: CPULoop(1); rlm@22: if (remoteResumed) rlm@22: { rlm@22: remoteResumed = false; rlm@22: remoteSendStatus(); rlm@22: } rlm@22: break; rlm@22: case 'g': rlm@22: remoteReadRegisters(p); rlm@22: break; rlm@22: case 'P': rlm@22: remoteWriteRegister(p); rlm@22: break; rlm@22: case 'M': rlm@22: remoteMemoryWrite(p); rlm@22: break; rlm@22: case 'm': rlm@22: remoteMemoryRead(p); rlm@22: break; rlm@22: case 'X': rlm@22: remoteBinaryWrite(p); rlm@22: break; rlm@22: case 'H': rlm@22: remotePutPacket("OK"); rlm@22: break; rlm@22: case 'q': rlm@22: remotePutPacket(""); rlm@22: break; rlm@22: case 'Z': rlm@22: if (*p++ == '2') rlm@22: { rlm@22: remoteWriteWatch(p, true); rlm@22: } rlm@22: else rlm@22: remotePutPacket(""); rlm@22: break; rlm@22: case 'z': rlm@22: if (*p++ == '2') rlm@22: { rlm@22: remoteWriteWatch(p, false); rlm@22: } rlm@22: else rlm@22: remotePutPacket(""); rlm@22: break; rlm@22: default: rlm@22: { rlm@22: *(strchr(p, '#') + 3) = 0; rlm@22: fprintf(stderr, "Unknown packet %s\n", --p); rlm@22: remotePutPacket(""); rlm@22: break; rlm@22: } rlm@22: } rlm@1: } rlm@1: } rlm@1: rlm@1: void remoteStubSignal(int sig, int number) rlm@1: { rlm@22: remoteSignal = sig; rlm@22: remoteResumed = false; rlm@22: remoteSendStatus(); rlm@22: debugger = true; rlm@1: } rlm@1: rlm@1: void remoteCleanUp() rlm@1: { rlm@22: if (remoteCleanUpFnc) rlm@22: remoteCleanUpFnc(); rlm@1: } rlm@1: