00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <assert.h>
00030 #include "jtagpxa250.h"
00031 #include "gdbremote.h"
00032 #include "debug.h"
00033 #include "step.h"
00034
00035 GdbRemote::GdbRemote(JTAGpxa250 *pxa) : pxa(pxa), clientSocket(-1), running(false) {
00036 sSocket = -1;
00037 pxa->registerTargetReadyCallback(callback, this);
00038 }
00039
00040 GdbRemote::~GdbRemote() {
00041
00042
00043 if (clientSocket != -1)
00044 close_socket(clientSocket);
00045 }
00046
00047 bool GdbRemote::openPort(int port) {
00048 return tcpstartsrv(port, 1) == 0;
00049 }
00050
00051 int GdbRemote::prepareFD_SET(fd_set *set) {
00052 int max = 0;
00053
00054 if (sSocket > 0) {
00055 FD_SET(sSocket, set);
00056 max = sSocket;
00057 }
00058
00059 if (clientSocket > 0) {
00060 FD_SET(clientSocket, set);
00061 if (clientSocket > max) max = clientSocket;
00062 }
00063 return max;
00064 }
00065
00066 void GdbRemote::processFD_SET(fd_set *set) {
00067
00068 if (sSocket != -1 && FD_ISSET(sSocket, set)) {
00069 struct sockaddr_in addr;
00070 socklen_t addrLen = sizeof(addr);
00071 int sock = accept(sSocket, (struct sockaddr *) &addr, &addrLen);
00072 if (sock == -1) {
00073 perror("accept()");
00074 fprintf(stderr, "TCP connection failed.\n");
00075 } else {
00076 if (clientSocket == -1) {
00077
00078 printf("TCP connection accepted from %s\n", inet_ntoa(addr.sin_addr) );
00079 clientSocket = sock;
00080 } else {
00081 printf("TCP connection rejected from %s: already connected.\n",
00082 inet_ntoa(addr.sin_addr) );
00083 close_socket(sock);
00084 }
00085 }
00086 }
00087
00088 if (clientSocket != -1 && FD_ISSET(clientSocket, set)) {
00089 bufferLength = read(clientSocket, buffer, sizeof(buffer) - 1);
00090
00091 if ( bufferLength <= 0 ) {
00092 printf("Read error from TCP client. Closing connection.\n");
00093 close_socket(clientSocket);
00094 clientSocket = -1;
00095 } else {
00096 buffer[bufferLength] = 0;
00097 debugMessage(GDB_REMOTE_DEBUG, "<- \"%s\"\n", buffer);
00098 parse();
00099 }
00100 }
00101 }
00102
00103 void GdbRemote::printError() {
00104 geterror();
00105 }
00106
00107 void GdbRemote::parse() {
00108
00109 reset();
00110
00111
00112 pxa->pollForTX();
00113
00114 do {
00115
00116 switch (current()) {
00117 case '+': break;
00118 case '-': printf("TCP: warning: GDB refused last packet\n"); break;
00119 case '$': parsePacket(); break;
00120 case 3: pxa->extBreak(); break;
00121 default:
00122 printf("TCP: parse error (%c %d)\n", current(), current());
00123 }
00124
00125 } while(next());
00126 }
00127
00128 void GdbRemote::parsePacket() {
00129
00130 assert( current() == '$' );
00131
00132 unsigned char sum = 0;
00133
00134 unsigned char * packet = buffer + ptr;
00135 unsigned char * eopacket = (unsigned char *) index((char *)packet, '#');
00136
00137 if (!eopacket) {
00138 fprintf(stderr, "TCP error: end of packet not found.\n");
00139 ptr = bufferLength;
00140 return;
00141 }
00142
00143 int len = eopacket - packet - 1;
00144
00145 for (int i=1; i <= len; ++i) {
00146 sum += packet[i];
00147 }
00148
00149 unsigned char packetSum = strtol((char *)packet + len + 2, 0, 16);
00150
00151 if (packetSum != sum) {
00152 printf("gdb protocol checksum error (%02X, %02X)\n", sum, packetSum);
00153 message[0] = '-';
00154 write(clientSocket, message, 1);
00155 debugMessage(GDB_REMOTE_DEBUG,"-> '-'\n");
00156
00157
00158 while(current() != '#') next();
00159 ptr += 2;
00160 } else {
00161
00162 message[0] = '+';
00163 write(clientSocket, message, 1);
00164 debugMessage(GDB_REMOTE_DEBUG,"-> '+'\n");
00165
00166 next();
00167 parseValidPacket();
00168 }
00169 }
00170
00171 unsigned char GdbRemote::toAsciiHex(unsigned int v) {
00172 unsigned char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
00173 return hexChars[v&0x0F];
00174 }
00175
00176 void GdbRemote::sendPacket() {
00177 unsigned char sum = 0;
00178 int len = strlen(message) + 4;
00179 unsigned char *sendBuff = (unsigned char *) alloca(len + 1);
00180 unsigned char *p = sendBuff;
00181
00182 *(p++) = '$';
00183
00184 for (int i=0; message[i]; ++i) {
00185 *(p++) = message[i];
00186 sum += message[i];
00187 }
00188 *(p++) = '#';
00189 *(p++) = toAsciiHex(sum >> 4);
00190 *(p++) = toAsciiHex(sum & 0x0F);
00191 *p = 0;
00192 write(clientSocket, sendBuff, len);
00193 debugMessage(GDB_REMOTE_DEBUG,"-> '%s'\n", sendBuff);
00194 }
00195
00196 void GdbRemote::hexPrintWord(unsigned char *str, unsigned int val) {
00197
00198 for (int i=0; i<4; ++i) {
00199 str[i*2] = toAsciiHex(val >> ((i*8)+4));
00200 str[i*2+1] = toAsciiHex(val>>(i*8));
00201 }
00202 }
00203
00204 unsigned char GdbRemote::asciiToHex(unsigned char c) {
00205 if (c >= 'a' && c <= 'f')
00206 return c - 'a' + 0xA;
00207 if (c >= '0' && c <= '9')
00208 return c - '0';
00209 if (c >= 'A' && c <= 'F')
00210 return c - 'A' + 0xA;
00211 return 0;
00212 }
00213
00214 unsigned int GdbRemote::parseHexByte() {
00215 unsigned char h, l, c;
00216
00217 h = asciiToHex(c=current());
00218
00219 if (c!='#')
00220 next();
00221
00222 l = asciiToHex(c=current());
00223
00224 if (c!='#')
00225 next();
00226
00227 return (h << 4) + l;
00228 }
00229
00231 unsigned int GdbRemote::parseHexWord() {
00232 unsigned int r=0;
00233
00234 for (int i=0; i < 4; ++i) {
00235 r += parseHexByte() << (i*8);
00236 }
00237 return r;
00238 }
00239
00240 void GdbRemote::callback(void *p) {
00241 GdbRemote *t = (GdbRemote *) p;
00242
00243 if (t->running) {
00244 jelie_cancel_bpt();
00245 t->lastSignal();
00246 }
00247
00248 t->running = false;
00249 }
00250
00251 void GdbRemote::query() {
00252 next();
00253
00254 if (memcmp(buffer + ptr, "Offsets", 7) == 0) {
00255 sprintf(message, "Text=%x;Data=%x;Bss=%x", 0,0,0);
00256 sendPacket();
00257 return;
00258 }
00259
00260
00261 message[0] = 0;
00262 sendPacket();
00263 }
00264
00265 void GdbRemote::lastSignal() {
00266 sprintf(message, "T05");
00267 sendPacket();
00268 }
00269
00270 void GdbRemote::setThread() {
00271 sprintf(message, "OK");
00272 sendPacket();
00273 }
00274
00275 void GdbRemote::getRegisters() {
00276 message[0] = 0;
00277 char *p = message;
00278 unsigned int i;
00279 for (i =0; i<16; ++i) {
00280 hexPrintWord((unsigned char *)p, pxa->getSavePlace(i));
00281 p += 8;
00282 }
00283 for (i=0; i< ((96 * 8 + 32) / 8); ++i) {
00284 sprintf(p, "00");
00285 p+=2;
00286 }
00287 hexPrintWord((unsigned char *)p, pxa->getSavePlace(16));
00288 p[8]=0;
00289 sendPacket();
00290 }
00291
00292 void GdbRemote::setRegisters() {
00293 unsigned i;
00294
00295
00296 next();
00297
00298 for (i=0; i<16; ++i) {
00299 pxa->setSavePlace(i, parseHexWord());
00300 }
00301
00302
00303 for (i=0; i< ((96 * 8 + 32)/8); ++i)
00304 next();
00305
00306 pxa->setSavePlace(16, parseHexWord());
00307
00308 sprintf(message, "OK");
00309 sendPacket();
00310 }
00311
00312 void GdbRemote::readMem() {
00313
00314
00315 next();
00316
00317 unsigned char *nextStr;
00318 unsigned int addr, len, unaligned;
00319
00320 addr = strtoul((char *)buffer + ptr, (char **) &nextStr, 16);
00321 unaligned = addr & 0x3;
00322 addr = addr & (~0x3);
00323 len = unaligned + strtoul((char *)nextStr + 1, 0, 16);
00324
00325 if ((len) & 0x3) len = (len & ~0x3) + 4;
00326
00327 if (2*len >= GDB_REMOTE_BUFFER_SIZE) {
00328 fprintf(stderr, "gdb remote: send buffer size too small to send %d bytes of memory !\n",
00329 len);
00330 }
00331
00332 unsigned int *data = (unsigned int *) alloca(len);
00333 pxa->getData(addr, len / 4, data);
00334 nextStr = (unsigned char *)message;
00335
00336
00337 for (unsigned int j= unaligned; j<4; j++) {
00338 unsigned int byte = data[0] >> (j*8);
00339 nextStr[0] = toAsciiHex(byte >> 4);
00340 nextStr[1] = toAsciiHex(byte);
00341 nextStr+=2;
00342 }
00343
00344
00345 for (unsigned int i=1; i < len/4; ++i) {
00346 hexPrintWord(nextStr, data[i]);
00347 nextStr+=8;
00348 }
00349
00350
00351 nextStr[0] = 0;
00352
00353 sendPacket();
00354 }
00355
00356 void GdbRemote::writeMem() {
00357
00358
00359 next();
00360
00361 unsigned char *nextStr;
00362 unsigned int addr, len;
00363
00364
00365 addr = strtoul((char *)buffer + ptr, (char **)&nextStr, 16);
00366
00367
00368 unsigned int unaligned = addr & 0x3;
00369 addr = addr & (~0x3);
00370 len = unaligned + strtoul((char *)nextStr+1, (char **)&nextStr, 16);
00371
00372 ptr = nextStr - buffer;
00373 next();
00374
00375 unsigned int *data = (unsigned int *) alloca(len + 4);
00376
00377
00378
00379 if (unaligned) {
00380 pxa->getData(addr, 1, data);
00381 pxa->pollForTX();
00382 }
00383
00384
00385 if ((len & 0x3) && len > 4) {
00386 pxa->getData(addr + (len/4), 1, data + (len/4));
00387 pxa->pollForTX();
00388 }
00389
00390
00391 for (unsigned int i=unaligned; i<len; i++) {
00392 unsigned int w = i/4;
00393 unsigned int b = i & 0x3;
00394
00395
00396 data[w] = (data[w] & ~(0xFF<<(b*8))) | (parseHexByte() << (b*8));
00397 }
00398
00399
00400 if (len == 4 && data[0] == 0xe7ffdefe)
00401 data[0] = BKPT_0_INSTR;
00402
00403 pxa->putData(addr, (len / 4) + (len&0x3 ? 1 : 0), data);
00404
00405 sprintf(message, "OK");
00406 sendPacket();
00407 }
00408
00409 void GdbRemote::resumeExec() {
00410
00411
00412 unsigned int instr;
00413 pxa->getData(pxa->getSavePlace(15), 1, &instr);
00414 pxa->pollForTX();
00415
00416 if ((instr & 0xFFF000F0) == BKPT_0_INSTR)
00417 pxa->setSavePlace(15, pxa->getSavePlace(15) + 4);
00418
00419
00420 running= true;
00421 pxa->continueCmd();
00422 }
00423
00424 void GdbRemote::cont() {
00425
00426 next();
00427
00428 if (current() != '#') {
00429 unsigned int addr;
00430
00431
00432 addr = strtoul((char *)buffer + ptr, 0, 16);
00433 pxa->setSavePlace(15, addr);
00434 }
00435
00436
00437 pxa->setCp15DebugRegister(0, JTAGpxa250::IBCR1);
00438 pxa->pollForTX();
00439
00440 resumeExec();
00441 }
00442
00443 void GdbRemote::step() {
00444 next();
00445
00446 if (current() != '#') {
00447 unsigned int addr;
00448
00449
00450 addr = strtoul((char *)buffer + ptr, 0, 16);
00451 pxa->setSavePlace(15, addr);
00452 }
00453 pxa->setCp15DebugRegister(0, JTAGpxa250::IBCR1);
00454 pxa->pollForTX();
00455
00456 jelie_set_bpt();
00457 resumeExec();
00458 }
00459
00460
00461 void GdbRemote::insertBreakWatch() {
00462
00463
00464 next();
00465 if (current() == '1') {
00466 next();
00467 next();
00468 unsigned int addr = strtoul((char *)buffer + ptr, 0, 16);
00469 for (int hb=0; hb<2; hb++) {
00470 if (hardBreak[hb] == 0) {
00471 pxa->setCp15DebugRegister(addr | 1,
00472 hb==0 ? JTAGpxa250::IBCR0 : JTAGpxa250::IBCR1);
00473 hardBreak[hb] = addr;
00474 sprintf(message, "OK");
00475 sendPacket();
00476 return;
00477 }
00478 }
00479
00480 sprintf(message, "E01");
00481 sendPacket();
00482 return;
00483 }
00484
00485
00486 message[0] = 0;
00487 sendPacket();
00488 }
00489
00490 void GdbRemote::removeBreakWatch() {
00491 next();
00492
00493 if (current() == '1') {
00494
00495 next();
00496 next();
00497 unsigned int addr = strtoul((char *)buffer + ptr, 0, 16);
00498 for (int hb=0; hb<2; hb++) {
00499 if (hardBreak[hb] == addr) {
00500 hardBreak[hb] = 0;
00501 pxa->setCp15DebugRegister(0,
00502 hb==0 ? JTAGpxa250::IBCR0 : JTAGpxa250::IBCR1);
00503 sprintf(message, "OK");
00504 sendPacket();
00505 return;
00506 }
00507
00508 sprintf(message, "E02");
00509 sendPacket();
00510 return;
00511 }
00512 }
00513
00514 message[0] = 0;
00515 sendPacket();
00516 }
00517
00518 void GdbRemote::parseValidPacket() {
00519 int startOfPacket = ptr;
00520
00521 switch (current()) {
00522 case 'H': setThread(); break;
00523 case 'q': query(); break;
00524 case '?': lastSignal(); break;
00525 case 'g': getRegisters(); break;
00526 case 'G': setRegisters(); break;
00527 case 'm': readMem(); break;
00528 case 'M': writeMem(); break;
00529 case 'c': cont(); break;
00530 case 'Z': insertBreakWatch(); break;
00531 case 'z': removeBreakWatch(); break;
00532 case 's': step();break;
00533 default:
00534 printf("gdb command %c not understood.\n", current());
00535 message[0] = 0;
00536 sendPacket();
00537 }
00538
00539
00540 ptr = startOfPacket;
00541 while(current() != '#') next();
00542 next();
00543 next();
00544 }