view src/gba/remote.cpp @ 2:3549bbe597ed

adding makefile.am
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:47 -0600
parents f9f4f1b99eed
children ecd30c5e2f5a
line wrap: on
line source
1 #include <cstdlib>
2 #include <cstdio>
3 #include <cstring>
5 #ifndef WIN32
6 # include <unistd.h>
7 # include <sys/socket.h>
8 # include <netdb.h>
9 # ifdef HAVE_NETINET_IN_H
10 # include <netinet/in.h>
11 # endif // HAVE_NETINET_IN_H
12 # ifdef HAVE_ARPA_INET_H
13 # include <arpa/inet.h>
14 # else // ! HAVE_ARPA_INET_H
15 # define socklen_t int
16 # endif // ! HAVE_ARPA_INET_H
17 #else // WIN32
18 # include "../win32/stdafx.h"
19 # include <winsock.h>
20 # include <io.h>
21 # define socklen_t int
22 # define close closesocket
23 # define read _read
24 # define write _write
25 #endif // WIN32
27 #include "GBA.h"
28 #include "GBAGlobals.h"
30 extern bool debugger;
31 extern void CPUUpdateCPSR();
32 #ifdef SDL
33 extern void (*dbgMain)();
34 extern void (*dbgSignal)(int, int);
35 extern void debuggerMain();
36 extern void debuggerSignal(int, int);
37 #endif
39 int remotePort = 55555;
40 int remoteSignal = 5;
41 int remoteSocket = -1;
42 int remoteListenSocket = -1;
43 bool remoteConnected = false;
44 bool remoteResumed = false;
46 int (*remoteSendFnc)(char *, int) = NULL;
47 int (*remoteRecvFnc)(char *, int) = NULL;
48 bool (*remoteInitFnc)() = NULL;
49 void (*remoteCleanUpFnc)() = NULL;
51 #if (defined WIN32 && !defined SDL)
52 void remoteSetSockets(SOCKET l, SOCKET r)
53 {
54 remoteSocket = r;
55 remoteListenSocket = l;
56 }
58 #endif
60 int remoteTcpSend(char *data, int len)
61 {
62 return send(remoteSocket, data, len, 0);
63 }
65 int remoteTcpRecv(char *data, int len)
66 {
67 return recv(remoteSocket, data, len, 0);
68 }
70 bool remoteTcpInit()
71 {
72 if (remoteSocket == -1)
73 {
74 #ifdef WIN32
75 WSADATA wsaData;
76 int error = WSAStartup(MAKEWORD(1, 1), &wsaData);
77 #endif // WIN32
78 int s = socket(PF_INET, SOCK_STREAM, 0);
80 remoteListenSocket = s;
82 if (s < 0)
83 {
84 fprintf(stderr, "Error opening socket\n");
85 exit(-1);
86 }
87 int tmp = 1;
88 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof(tmp));
90 // char hostname[256];
91 // gethostname(hostname, 256);
93 // hostent *ent = gethostbyname(hostname);
94 // unsigned long a = *((unsigned long *)ent->h_addr);
96 sockaddr_in addr;
97 addr.sin_family = AF_INET;
98 addr.sin_port = htons(remotePort);
99 addr.sin_addr.s_addr = htonl(0);
100 int count = 0;
101 while (count < 3)
102 {
103 if (bind(s, (sockaddr *)&addr, sizeof(addr)))
104 {
105 addr.sin_port = htons(ntohs(addr.sin_port)+1);
106 }
107 else
108 break;
109 }
110 if (count == 3)
111 {
112 fprintf(stderr, "Error binding \n");
113 exit(-1);
114 }
116 fprintf(stderr, "Listening for a connection at port %d\n",
117 ntohs(addr.sin_port));
119 if (listen(s, 1))
120 {
121 fprintf(stderr, "Error listening\n");
122 exit(-1);
123 }
124 socklen_t len = sizeof(addr);
126 #ifdef WIN32
127 int flag = 0;
128 ioctlsocket(s, FIONBIO, (unsigned long *)&flag);
129 #endif // WIN32
130 int s2 = accept(s, (sockaddr *)&addr, &len);
131 if (s2 > 0)
132 {
133 fprintf(stderr, "Got a connection from %s %d\n",
134 inet_ntoa((in_addr)addr.sin_addr),
135 ntohs(addr.sin_port));
136 }
137 else
138 {
139 #ifdef WIN32
140 int error = WSAGetLastError();
141 #endif // WIN32
142 }
143 char dummy;
144 recv(s2, &dummy, 1, 0);
145 if (dummy != '+')
146 {
147 fprintf(stderr, "ACK not received\n");
148 exit(-1);
149 }
150 remoteSocket = s2;
151 // close(s);
152 }
153 return true;
154 }
156 void remoteTcpCleanUp()
157 {
158 if (remoteSocket > 0)
159 {
160 fprintf(stderr, "Closing remote socket\n");
161 close(remoteSocket);
162 remoteSocket = -1;
163 }
164 if (remoteListenSocket > 0)
165 {
166 fprintf(stderr, "Closing listen socket\n");
167 close(remoteListenSocket);
168 remoteListenSocket = -1;
169 }
170 }
172 int remotePipeSend(char *data, int len)
173 {
174 int res = write(1, data, len);
175 return res;
176 }
178 int remotePipeRecv(char *data, int len)
179 {
180 int res = read(0, data, len);
181 return res;
182 }
184 bool remotePipeInit()
185 {
186 char dummy;
187 read(0, &dummy, 1);
188 if (dummy != '+')
189 {
190 fprintf(stderr, "ACK not received\n");
191 exit(-1);
192 }
194 return true;
195 }
197 void remotePipeCleanUp()
198 {}
200 void remoteSetPort(int port)
201 {
202 remotePort = port;
203 }
205 void remoteSetProtocol(int p)
206 {
207 if (p == 0)
208 {
209 remoteSendFnc = remoteTcpSend;
210 remoteRecvFnc = remoteTcpRecv;
211 remoteInitFnc = remoteTcpInit;
212 remoteCleanUpFnc = remoteTcpCleanUp;
213 }
214 else
215 {
216 remoteSendFnc = remotePipeSend;
217 remoteRecvFnc = remotePipeRecv;
218 remoteInitFnc = remotePipeInit;
219 remoteCleanUpFnc = remotePipeCleanUp;
220 }
221 }
223 void remoteInit()
224 {
225 if (remoteInitFnc)
226 remoteInitFnc();
227 }
229 void remotePutPacket(char *packet)
230 {
231 char *hex = "0123456789abcdef";
232 char buffer[1024];
234 int count = strlen(packet);
236 unsigned char csum = 0;
238 char *p = buffer;
239 *p++ = '$';
241 for (int i = 0; i < count; i++)
242 {
243 csum += packet[i];
244 *p++ = packet[i];
245 }
246 *p++ = '#';
247 *p++ = hex[csum>>4];
248 *p++ = hex[csum & 15];
249 *p++ = 0;
250 // printf("Sending %s\n", buffer);
251 remoteSendFnc(buffer, count + 4);
253 char c = 0;
254 remoteRecvFnc(&c, 1);
255 /*
256 if(c == '+')
257 printf("ACK\n");
258 else if(c=='-')
259 printf("NACK\n");
260 */
261 }
263 void remoteOutput(char *s, u32 addr)
264 {
265 char buffer[16384];
267 char *d = buffer;
268 *d++ = 'O';
270 if (s)
271 {
272 char c = *s++;
273 while (c)
274 {
275 sprintf(d, "%02x", c);
276 d += 2;
277 c = *s++;
278 }
279 }
280 else
281 {
282 char c = debuggerReadByte(addr);
283 addr++;
284 while (c)
285 {
286 sprintf(d, "%02x", c);
287 d += 2;
288 c = debuggerReadByte(addr);
289 addr++;
290 }
291 }
292 remotePutPacket(buffer);
293 // fprintf(stderr, "Output sent %s\n", buffer);
294 }
296 void remoteSendSignal()
297 {
298 char buffer[1024];
299 sprintf(buffer, "S%02x", remoteSignal);
300 remotePutPacket(buffer);
301 }
303 void remoteSendStatus()
304 {
305 char buffer[1024];
306 sprintf(buffer, "T%02x", remoteSignal);
307 char *s = buffer;
308 s += 3;
309 for (int i = 0; i < 15; i++)
310 {
311 u32 v = reg[i].I;
312 sprintf(s, "%02x:%02x%02x%02x%02x;", i,
313 (v & 255),
314 (v >> 8) & 255,
315 (v >> 16) & 255,
316 (v >> 24) & 255);
317 s += 12;
318 }
319 u32 v = armNextPC;
320 sprintf(s, "0f:%02x%02x%02x%02x;", (v & 255),
321 (v >> 8) & 255,
322 (v >> 16) & 255,
323 (v >> 24) & 255);
324 s += 12;
325 CPUUpdateCPSR();
326 v = reg[16].I;
327 sprintf(s, "19:%02x%02x%02x%02x;", (v & 255),
328 (v >> 8) & 255,
329 (v >> 16) & 255,
330 (v >> 24) & 255);
331 s += 12;
332 *s = 0;
333 // printf("Sending %s\n", buffer);
334 remotePutPacket(buffer);
335 }
337 void remoteBinaryWrite(char *p)
338 {
339 u32 address;
340 int count;
341 sscanf(p, "%x,%x:", &address, &count);
342 // printf("Binary write for %08x %d\n", address, count);
344 p = strchr(p, ':');
345 p++;
346 for (int i = 0; i < count; i++)
347 {
348 u8 b = *p++;
349 switch (b)
350 {
351 case 0x7d:
352 b = *p++;
353 debuggerWriteByte(address, (b^0x20));
354 address++;
355 break;
356 default:
357 debuggerWriteByte(address, b);
358 address++;
359 break;
360 }
361 }
362 // printf("ROM is %08x\n", debuggerReadMemory(0x8000254));
363 remotePutPacket("OK");
364 }
366 void remoteMemoryWrite(char *p)
367 {
368 u32 address;
369 int count;
370 sscanf(p, "%x,%x:", &address, &count);
371 // printf("Memory write for %08x %d\n", address, count);
373 p = strchr(p, ':');
374 p++;
375 for (int i = 0; i < count; i++)
376 {
377 u8 v = 0;
378 char c = *p++;
379 if (c <= '9')
380 v = (c - '0') << 4;
381 else
382 v = (c + 10 - 'a') << 4;
383 c = *p++;
384 if (c <= '9')
385 v += (c - '0');
386 else
387 v += (c + 10 - 'a');
388 debuggerWriteByte(address, v);
389 address++;
390 }
391 // printf("ROM is %08x\n", debuggerReadMemory(0x8000254));
392 remotePutPacket("OK");
393 }
395 void remoteMemoryRead(char *p)
396 {
397 u32 address;
398 int count;
399 sscanf(p, "%x,%x:", &address, &count);
400 // printf("Memory read for %08x %d\n", address, count);
402 char buffer[1024];
404 char *s = buffer;
405 for (int i = 0; i < count; i++)
406 {
407 u8 b = debuggerReadByte(address);
408 sprintf(s, "%02x", b);
409 address++;
410 s += 2;
411 }
412 *s = 0;
413 remotePutPacket(buffer);
414 }
416 void remoteStepOverRange(char *p)
417 {
418 u32 address;
419 u32 final;
420 sscanf(p, "%x,%x", &address, &final);
422 remotePutPacket("OK");
424 remoteResumed = true;
425 do
426 {
427 CPULoop(1);
428 if (debugger)
429 break;
430 }
431 while (armNextPC >= address && armNextPC < final);
433 remoteResumed = false;
435 remoteSendStatus();
436 }
438 void remoteWriteWatch(char *p, bool active)
439 {
440 u32 address;
441 int count;
442 sscanf(p, ",%x,%x#", &address, &count);
444 fprintf(stderr, "Write watch for %08x %d\n", address, count);
446 if (address < 0x2000000 || address > 0x3007fff)
447 {
448 remotePutPacket("E01");
449 return;
450 }
452 if (address > 0x203ffff && address < 0x3000000)
453 {
454 remotePutPacket("E01");
455 return;
456 }
458 u32 final = address + count;
460 if (address < 0x2040000 && final > 0x2040000)
461 {
462 remotePutPacket("E01");
463 return;
464 }
465 else if (address < 0x3008000 && final > 0x3008000)
466 {
467 remotePutPacket("E01");
468 return;
469 }
471 for (int i = 0; i < count; i++)
472 {
473 if ((address >> 24) == 2)
474 freezeWorkRAM[address & 0x3ffff] = active;
475 else
476 freezeInternalRAM[address & 0x7fff] = active;
477 address++;
478 }
480 remotePutPacket("OK");
481 }
483 void remoteReadRegisters(char *p)
484 {
485 char buffer[1024];
487 char *s = buffer;
488 int i;
489 // regular registers
490 for (i = 0; i < 15; i++)
491 {
492 u32 v = reg[i].I;
493 sprintf(s, "%02x%02x%02x%02x", v & 255, (v >> 8) & 255,
494 (v >> 16) & 255, (v >> 24) & 255);
495 s += 8;
496 }
497 // PC
498 u32 pc = armNextPC;
499 sprintf(s, "%02x%02x%02x%02x", pc & 255, (pc >> 8) & 255,
500 (pc >> 16) & 255, (pc >> 24) & 255);
501 s += 8;
503 // floating point registers (24-bit)
504 for (i = 0; i < 8; i++)
505 {
506 sprintf(s, "000000000000000000000000");
507 s += 24;
508 }
510 // FP status register
511 sprintf(s, "00000000");
512 s += 8;
513 // CPSR
514 CPUUpdateCPSR();
515 u32 v = reg[16].I;
516 sprintf(s, "%02x%02x%02x%02x", v & 255, (v >> 8) & 255,
517 (v >> 16) & 255, (v >> 24) & 255);
518 s += 8;
519 *s = 0;
520 remotePutPacket(buffer);
521 }
523 void remoteWriteRegister(char *p)
524 {
525 int r;
527 sscanf(p, "%x=", &r);
529 p = strchr(p, '=');
530 p++;
532 char c = *p++;
534 u32 v = 0;
536 u8 data[4] = {0, 0, 0, 0};
538 int i = 0;
540 while (c != '#')
541 {
542 u8 b = 0;
543 if (c <= '9')
544 b = (c - '0') << 4;
545 else
546 b = (c + 10 - 'a') << 4;
547 c = *p++;
548 if (c <= '9')
549 b += (c - '0');
550 else
551 b += (c + 10 - 'a');
552 data[i++] = b;
553 c = *p++;
554 }
556 v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
558 // printf("Write register %d=%08x\n", r, v);
559 reg[r].I = v;
560 if (r == 15)
561 {
562 armNextPC = v;
563 if (armState)
564 reg[15].I = v + 4;
565 else
566 reg[15].I = v + 2;
567 }
568 remotePutPacket("OK");
569 }
571 void remoteStubMain()
572 {
573 if (!debugger)
574 return;
576 if (remoteResumed)
577 {
578 remoteSendStatus();
579 remoteResumed = false;
580 }
582 while (true)
583 {
584 char buffer[1024];
585 int res = remoteRecvFnc(buffer, 1024);
587 if (res == -1)
588 {
589 fprintf(stderr, "GDB connection lost\n");
590 #ifdef SDL
591 dbgMain = debuggerMain;
592 dbgSignal = debuggerSignal;
593 #endif
594 debugger = false;
595 break;
596 }
598 // fprintf(stderr, "Received %s\n", buffer);
599 char *p = buffer;
600 char c = *p++;
601 char pp = '+';
602 remoteSendFnc(&pp, 1);
604 if (c != '$')
605 continue;
606 c = *p++;
607 switch (c)
608 {
609 case '?':
610 remoteSendSignal();
611 break;
612 case 'D':
613 remotePutPacket("OK");
614 #ifdef SDL
615 dbgMain = debuggerMain;
616 dbgSignal = debuggerSignal;
617 #endif
618 remoteResumed = true;
619 debugger = false;
620 return;
621 case 'e':
622 remoteStepOverRange(p);
623 break;
624 case 'k':
625 remotePutPacket("OK");
626 #ifdef SDL
627 dbgMain = debuggerMain;
628 dbgSignal = debuggerSignal;
629 #endif
630 debugger = false;
631 emulating = false;
632 return;
633 case 'C':
634 remoteResumed = true;
635 debugger = false;
636 return;
637 case 'c':
638 remoteResumed = true;
639 debugger = false;
640 return;
641 case 's':
642 remoteResumed = true;
643 remoteSignal = 5;
644 CPULoop(1);
645 if (remoteResumed)
646 {
647 remoteResumed = false;
648 remoteSendStatus();
649 }
650 break;
651 case 'g':
652 remoteReadRegisters(p);
653 break;
654 case 'P':
655 remoteWriteRegister(p);
656 break;
657 case 'M':
658 remoteMemoryWrite(p);
659 break;
660 case 'm':
661 remoteMemoryRead(p);
662 break;
663 case 'X':
664 remoteBinaryWrite(p);
665 break;
666 case 'H':
667 remotePutPacket("OK");
668 break;
669 case 'q':
670 remotePutPacket("");
671 break;
672 case 'Z':
673 if (*p++ == '2')
674 {
675 remoteWriteWatch(p, true);
676 }
677 else
678 remotePutPacket("");
679 break;
680 case 'z':
681 if (*p++ == '2')
682 {
683 remoteWriteWatch(p, false);
684 }
685 else
686 remotePutPacket("");
687 break;
688 default:
689 {
690 *(strchr(p, '#') + 3) = 0;
691 fprintf(stderr, "Unknown packet %s\n", --p);
692 remotePutPacket("");
693 break;
694 }
695 }
696 }
697 }
699 void remoteStubSignal(int sig, int number)
700 {
701 remoteSignal = sig;
702 remoteResumed = false;
703 remoteSendStatus();
704 debugger = true;
705 }
707 void remoteCleanUp()
708 {
709 if (remoteCleanUpFnc)
710 remoteCleanUpFnc();
711 }