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