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