00001
00089 #include "ac_gdb.H"
00090
00091
00102 AC_GDB::AC_GDB(AC_GDB_Interface* proc, int port) {
00103 this->connected = 0;
00104 this->step = 0;
00105 this->first_time = 1;
00106 this->proc = proc;
00107 this->bps= new Breakpoints( BREAKPOINTS );
00108 this->set_port( port );
00109 this->disable();
00110 }
00111
00112
00116 AC_GDB::~AC_GDB() {
00117 delete bps;
00118 debug( "AC_GDB: connection closed!" );
00119 }
00120
00121
00122
00123
00124
00131 void AC_GDB::reg_read(char *ib, char *ob) {
00132 int i;
00133 ob[ 0 ] = '\0';
00134 char fmt[ 5 ] = "";
00135
00136
00137 snprintf( fmt, 5, "%%%02dx", sizeof( ac_word ) * 2 );
00138
00139 for ( i = 0; i < proc->nRegs(); i ++ )
00140 sprintf( ob + strlen( ob ), fmt, proc->reg_read( i ) );
00141 }
00142
00143
00150 void AC_GDB::reg_write(char *ib, char *ob) {
00151 ac_word aux;
00152 int i, ss;
00153 char fmt[ 5 ] = "";
00154
00155 ib ++;
00156
00157
00158 ss = sizeof( ac_word ) * 2;
00159 snprintf( fmt, 5, "%%%02dx", ss );
00160
00161 for ( i = 0; i < 32; i ++) {
00162 sscanf( ib, fmt, &aux );
00163 proc->reg_write( i, aux );
00164 ib += ss;
00165 }
00166
00167 strncpy( ob, "OK", GDB_BUFFERSIZE );
00168 }
00169
00170
00171
00172
00173
00180 void AC_GDB::mem_write( char *ib, char *ob ) {
00181 unsigned i, r;
00182 unsigned address, bytes;
00183 char *ib_h = ib;
00184
00185 r = sscanf( ib, "M%x,%x:", &address, &bytes );
00186
00187 ib = strchr( ib, ':' );
00188
00189 if ( ( ! ib ) || ( r != 2 ) )
00190
00191 strncpy( ob, "E01", GDB_BUFFERSIZE );
00192 else {
00193 int offset;
00194 ib ++;
00195
00196
00197 offset = ib - ib_h;
00198 if ( ( ( bytes << 1 ) + 1 + offset ) >= GDB_BUFFERSIZE )
00199
00200 bytes = ( ( GDB_BUFFERSIZE - offset ) >> 1 ) - 1;
00201
00202
00203 bytes <<= 1;
00204 for ( i = 0; i < bytes; i += 2 )
00205 {
00206 if ( ib[ i ] == 0 )
00207 strncpy( ob, "E03", GDB_BUFFERSIZE);
00208
00209
00210 proc->mem_write( address,
00211 ( hex( ib[ i ] ) << 4 ) + hex( ib[ i + 1 ] ) );
00212 address ++;
00213 }
00214 strncpy( ob, "OK", GDB_BUFFERSIZE );
00215 }
00216 }
00217
00218
00225 void AC_GDB::mem_read( char *ib, char *ob ) {
00226 unsigned i;
00227 unsigned char b;
00228 unsigned address = 0, bytes = 0;
00229
00230 if ( sscanf( ib, "m%x,%x", &address, &bytes ) != 2 )
00231
00232 strncpy( ob, "E01", GDB_BUFFERSIZE );
00233 else {
00234
00235 if ( ( ( bytes << 1 ) + 1 ) >= GDB_BUFFERSIZE )
00236
00237 bytes = ( GDB_BUFFERSIZE >> 1 ) - 1;
00238
00239 for ( i = 0; i < bytes; i ++ )
00240 {
00241 b = proc->mem_read( address );
00242
00243
00244 ob[ i * 2 ] = hexchars[ b >> 4 ];
00245 ob[ i * 2 + 1 ] = hexchars[ b & 0xF ];
00246
00247 address ++;
00248 }
00249
00250 ob[ i * 2 ] = '\0';
00251 }
00252 }
00253
00254
00255
00256
00257
00258
00259
00266 void AC_GDB::continue_execution( char *ib, char *ob ) {
00267 unsigned address;
00268
00269 if ( sscanf( ib, "c%x", &address ) == 1 )
00270 ac_resources::ac_pc = address;
00271 step = 0;
00272 }
00273
00274
00281 void AC_GDB::stepmode( char *ib, char *ob ) {
00282 unsigned address;
00283 if ( sscanf( ib, "s%x", &address ) == 1 )
00284 ac_resources::ac_pc = address;
00285
00286 step = 1;
00287 }
00288
00289
00296 void AC_GDB::cc( char *ib, char *ob ) {
00297 snprintf( ob, GDB_BUFFERSIZE, "S%02x", SIGINT );
00298 step = 1;
00299 }
00300
00301
00307 void AC_GDB::exit(int ac_exit_status) {
00308 if ( disabled ) return;
00309 snprintf( out_buffer, GDB_BUFFERSIZE, "W%02x", ac_exit_status );
00310 comm_putpacket(out_buffer);
00311 }
00312
00313
00314
00315
00322 void AC_GDB::break_insert( char *ib, char *ob ) {
00323 int type, address, length;
00324
00325 if ( sscanf( ib, "Z%x,%x,%x", &type, &address, &length ) != 3 )
00326
00327 strncpy( ob, "E01", GDB_BUFFERSIZE );
00328 else {
00329 switch ( type ) {
00330 case 0:
00331
00332 if ( bps->add( address ) == 0 )
00333 strncpy( ob, "OK", GDB_BUFFERSIZE );
00334 else
00335 strncpy( ob, "E00", GDB_BUFFERSIZE );
00336 break;
00337
00338 case 1:
00339
00340 ob[ 0 ] = 0;
00341 break;
00342
00343 case 2:
00344
00345 ob[ 0 ] = 0;
00346 break;
00347
00348 case 3:
00349
00350 ob[ 0 ] = 0;
00351 break;
00352
00353 case 4:
00354
00355 ob[ 0 ] = 0;
00356 break;
00357 }
00358 }
00359 }
00360
00361
00368 void AC_GDB::break_remove( char *ib, char *ob ) {
00369 int type, address, length;
00370
00371 if ( sscanf( ib, "z%x,%x,%x", &type, &address, &length ) != 3 )
00372
00373 strncpy( ob, "E01", GDB_BUFFERSIZE );
00374 else {
00375 switch ( type )
00376 {
00377 case 0:
00378
00379 if ( bps->remove( address ) == 0 )
00380 strncpy( ob, "OK", GDB_BUFFERSIZE );
00381 else
00382 strncpy( ob, "E00", GDB_BUFFERSIZE );
00383 break;
00384
00385 case 1:
00386
00387 ob[ 0 ] = 0;
00388 break;
00389
00390 case 2:
00391
00392 ob[ 0 ] = 0;
00393 break;
00394
00395 case 3:
00396
00397 ob[ 0 ] = 0;
00398 break;
00399
00400 case 4:
00401
00402 ob[ 0 ] = 0;
00403 break;
00404 }
00405 }
00406 }
00407
00408
00409
00410
00411
00412
00413
00417 void AC_GDB::connect() {
00418 struct sockaddr_in cliAddr, servAddr;
00419 int sd;
00420
00421
00422 if ( (sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
00423 perror("Cannot Open Socket");
00424 exit(-1);
00425 }
00426
00427
00428 servAddr.sin_family = AF_INET;
00429 servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00430 servAddr.sin_port = htons(this->port);
00431
00432 {
00433 int yes=1;
00434 if ( setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
00435 perror( "setsockopt" );
00436 exit(-1);
00437 }
00438 }
00439
00440 printf("AC_GDB: binding to port %d\n", this->port);
00441 if(bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) {
00442 perror("bind");
00443 exit(-1);
00444 }
00445
00446 listen(sd,5);
00447
00448
00449 {
00450 socklen_t cliLen;
00451 cliLen = sizeof(cliAddr);
00452
00453 if ((this->sd = accept(sd, (struct sockaddr *) &cliAddr, &cliLen)) < 0 ) {
00454 perror("accept");
00455 exit(-1);
00456 }
00457 }
00458
00459 connected = 1;
00460 }
00461
00462
00463
00464
00465
00466
00475 bool AC_GDB::stop(unsigned int decoded_pc) {
00476 if ( disabled ) return false;
00477
00478 if ( first_time || step || bps->exists(decoded_pc))
00479 return true;
00480 return false;
00481 }
00482
00483
00487 void AC_GDB::process_bp() {
00488 if ( disabled ) return;
00489 first_time=0;
00490
00491 snprintf( out_buffer, GDB_BUFFERSIZE, "S%02x", SIGTRAP );
00492 comm_putpacket(out_buffer);
00493
00494 if ( ! connected ) return;
00495
00496 while (1) {
00497
00498 out_buffer[0] = 0;
00499
00500 comm_getpacket(in_buffer);
00501
00502 switch (in_buffer[0]) {
00503 case '?':
00504
00505 snprintf( out_buffer, GDB_BUFFERSIZE, "S%02x", SIGTRAP );
00506 break;
00507
00508 case 'g':
00509
00510 reg_read( in_buffer, out_buffer );
00511 break;
00512
00513 case 'G':
00514
00515 reg_write( in_buffer, out_buffer );
00516 break;
00517
00518 case 'm':
00519
00520 mem_read( in_buffer, out_buffer );
00521 break;
00522
00523 case 'M':
00524
00525 mem_write( in_buffer, out_buffer );
00526 break;
00527
00528 case 'c':
00529
00530 continue_execution( in_buffer, out_buffer );
00531 return;
00532
00533 case 's':
00534
00535 stepmode( in_buffer, out_buffer );
00536 return;
00537
00538 case 0x03:
00539
00540 cc( in_buffer, out_buffer );
00541 comm_putpacket( out_buffer );
00542 return;
00543
00544 case 'k' :
00545
00546 ac_stop();
00547 break;
00548
00549 case 'Z':
00550
00551 break_insert( in_buffer, out_buffer );
00552 break;
00553
00554 case 'z':
00555
00556 break_remove( in_buffer, out_buffer );
00557 break;
00558
00559 default:
00560 out_buffer[0] = 0;
00561 }
00562
00563 comm_putpacket(out_buffer);
00564 }
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00605 int AC_GDB::hex(unsigned char ch)
00606 {
00607 if (ch >= 'a' && ch <= 'f')
00608 return ch-'a'+10;
00609 if (ch >= '0' && ch <= '9')
00610 return ch-'0';
00611 if (ch >= 'A' && ch <= 'F')
00612 return ch-'A'+10;
00613 return -1;
00614 }
00615
00621 void AC_GDB::comm_getpacket (char *buffer) {
00622 unsigned char checksum;
00623 unsigned char xmitcsum;
00624 int i;
00625 int count;
00626 unsigned char ch;
00627
00628 do {
00629
00630
00631
00632
00633 while ( ( ch = ( comm_getchar() & 0x7f ) ) != '$' );
00634
00635 checksum = 0;
00636 xmitcsum = 255;
00637 count = 0;
00638
00639
00640
00641
00642 while ( count < GDB_BUFFERSIZE )
00643 {
00644 ch = comm_getchar();
00645 if ( ch == '#' )
00646 break;
00647 checksum = checksum + ch;
00648 buffer[ count ] = ch;
00649 count = count + 1;
00650 }
00651
00652 if ( count >= GDB_BUFFERSIZE )
00653 continue;
00654
00655 buffer[ count ] = 0;
00656
00657 if ( ch == '#' )
00658 {
00659 xmitcsum = hex( comm_getchar() & 0x7f ) << 4;
00660 xmitcsum |= hex( comm_getchar() & 0x7f );
00661
00662 if ( checksum != xmitcsum )
00663 comm_putchar( '-' );
00664 else {
00665 comm_putchar( '+' );
00666
00667
00668
00669
00670
00671 if ( buffer[ 2 ] == ':' )
00672 {
00673 comm_putchar( buffer[0] );
00674 comm_putchar( buffer[1] );
00675
00676
00677
00678
00679 count = strlen( buffer );
00680 for ( i = 3; i <= count; i ++ )
00681 buffer[ i - 3] = buffer[ i ];
00682 }
00683 }
00684 }
00685 }
00686 while ( checksum != xmitcsum );
00687
00688 debug("received packet:" << buffer);
00689 }
00690
00691
00692
00698 void AC_GDB::comm_putpacket(const char *buffer) {
00699 unsigned char checksum;
00700 int count;
00701 unsigned char ch;
00702
00703 debug(" out packet:" << buffer << endl);
00704
00705
00706
00707
00708
00709 do
00710 {
00711 comm_putchar( '$' );
00712 checksum = 0;
00713 count = 0;
00714
00715 while ( ( ch = buffer[ count ] ) != 0 )
00716 {
00717 if ( ! ( comm_putchar( ch ) ) )
00718 return;
00719 checksum += ch;
00720 count += 1;
00721 }
00722
00723 comm_putchar( '#' );
00724 comm_putchar( hexchars[ checksum >> 4 ] );
00725 comm_putchar( hexchars[ checksum & 0xf ] );
00726
00727 }
00728 while ( ( comm_getchar() & 0x7f) != '+' );
00729 }
00730
00731
00737 int AC_GDB::comm_putchar(const char c) {
00738 return write( sd, &c, 1 );
00739 }
00740
00741
00747 char AC_GDB::comm_getchar() {
00748 char c;
00749 read( sd, &c, 1 );
00750 return(c);
00751 }
00752
00753
00754
00758 void AC_GDB::disable() {
00759 this->disabled = 1;
00760 }
00761
00765 void AC_GDB::enable() {
00766 this->disabled = 0;
00767 }
00768
00769
00770
00776 int AC_GDB::is_disabled() {
00777 return (int) this->disabled;
00778 }
00779
00780
00781
00787 void AC_GDB::set_port( int port ) {
00788 this->port = port;
00789 }
00790
00796 int AC_GDB::get_port() {
00797 return this->port;
00798 }