Main Page | Modules | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages | Examples

ac_gdb.cpp

Go to the documentation of this file.
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 /* Register Access ***********************************************************/
00124 
00131 void AC_GDB::reg_read(char *ib, char *ob) {
00132   int i;
00133   ob[ 0 ] = '\0';
00134   char fmt[ 5 ] = "";
00135 
00136   /* 1 byte is represented in hexadecimal by 2 chars */
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 ++; /* skip G */
00156 
00157   /* 1 byte is represented in hexadecimal by 2 chars */
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 /* Memory Access *************************************************************/
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     /* Data is wrong! */
00191     strncpy( ob, "E01", GDB_BUFFERSIZE );
00192   else {
00193     int offset;
00194     ib ++; /* next char after ':' */
00195 
00196     /* be sure to not read outside in_buffer */
00197     offset = ib - ib_h;
00198     if ( ( ( bytes << 1 ) + 1 + offset ) >= GDB_BUFFERSIZE )
00199       /* [ offset | hex bytes repr...    | \0 ] <= GDB_BUFFERSIZE */
00200       bytes = ( ( GDB_BUFFERSIZE - offset ) >> 1 ) - 1;
00201 
00202     /* 1 byte is represented by 2 letters */
00203     bytes <<= 1;
00204     for ( i = 0; i < bytes; i += 2 )
00205       {
00206         if ( ib[ i ] == 0 )
00207           strncpy( ob, "E03", GDB_BUFFERSIZE); /* end of string ('\0'),
00208                                                   this is an error! */
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     /* Data is wrong! */
00232     strncpy( ob, "E01", GDB_BUFFERSIZE );
00233   else {
00234     /* be sure there is enough room for returning string + '\0' */
00235     if ( ( ( bytes << 1 ) + 1 ) >= GDB_BUFFERSIZE )
00236       /* Read just bytes that fit the buffer */
00237       bytes = ( GDB_BUFFERSIZE >> 1 ) - 1;
00238 
00239     for ( i = 0; i < bytes; i ++ )
00240       {
00241         b = proc->mem_read( address );
00242 
00243         /* represent the byte nibbles */
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 /* Execution Control *********************************************************/
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 /* Break & Watch Point *******************************************************/
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     /* Data is wrong! */
00327     strncpy( ob, "E01", GDB_BUFFERSIZE );
00328   else {
00329     switch ( type ) {
00330     case 0:
00331       /* memory breakpoint */
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       /* hardware breakpoint */
00340       ob[ 0 ] = 0; /* FIXME --- not yet supported */
00341       break;
00342 
00343     case 2:
00344       /* write watchpoint */
00345       ob[ 0 ] = 0; /* FIXME --- not yet supported */
00346       break;
00347 
00348     case 3:
00349       /* read watchpoint */
00350       ob[ 0 ] = 0; /* FIXME --- not yet supported */
00351       break;
00352 
00353     case 4:
00354       /* access watchpoint */
00355       ob[ 0 ] = 0; /* FIXME --- not yet supported */
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     /* Data is wrong! */
00373     strncpy( ob, "E01", GDB_BUFFERSIZE );
00374   else {
00375     switch ( type )
00376       {
00377       case 0:
00378         /* memory breakpoint */
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         /* hardware breakpoint */
00387         ob[ 0 ] = 0; /* FIXME --- not yet supported */
00388         break;
00389 
00390       case 2:
00391         /* write watchpoint */
00392         ob[ 0 ] = 0; /* FIXME --- not yet supported */
00393         break;
00394 
00395       case 3:
00396         /* read watchpoint */
00397         ob[ 0 ] = 0; /* FIXME --- not yet supported */
00398         break;
00399 
00400       case 4:
00401         /* access watchpoint */
00402         ob[ 0 ] = 0; /* FIXME --- not yet supported */
00403         break;
00404       }
00405   }
00406 }
00407 
00408 
00409 
00410 
00411 
00412 /* GDB Specific Functions: ***************************************************/
00413 
00417 void AC_GDB::connect() {
00418   struct sockaddr_in cliAddr, servAddr;
00419   int sd;
00420 
00421   /* Create Socket */
00422   if ( (sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
00423     perror("Cannot Open Socket");
00424     exit(-1);
00425   }
00426 
00427   /* Bind To Server Port */
00428   servAddr.sin_family = AF_INET;
00429   servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00430   servAddr.sin_port = htons(this->port);
00431 
00432   { /* reuse address */
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   /* Listen for a connection */
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  * Process break point.                                                        *
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       /* "?": Return the reason simulator halted */
00505       snprintf( out_buffer, GDB_BUFFERSIZE, "S%02x", SIGTRAP );
00506       break;
00507 
00508     case 'g':
00509       /* "g": return the value of the CPU registers as hex data or ENN */
00510       reg_read( in_buffer, out_buffer );
00511       break;
00512 
00513     case 'G':
00514       /* "G": set the value of the CPU registers. */
00515       reg_write( in_buffer, out_buffer );
00516       break;
00517 
00518     case 'm':
00519       /* "mAA..AA,LLLL": Read LLLL bytes at address AA..AA as hex data or ENN*/
00520       mem_read( in_buffer, out_buffer );
00521       break;
00522 
00523     case 'M':
00524       /* "MAA..AA,LLLL:": Write LLLL bytes at address AA.AA return OK */
00525       mem_write( in_buffer, out_buffer );
00526       break;
00527 
00528     case 'c':
00529       /* "cAA..AA": continue at address AA..AA or same address if no AA..AA*/
00530       continue_execution( in_buffer, out_buffer );
00531       return;
00532 
00533     case 's':
00534       /* "sAA..AA": resume at address AA..AA or same address if no AA..AA */
00535       stepmode( in_buffer, out_buffer );
00536       return;
00537 
00538     case 0x03:
00539       /* Control-C: return control to gdb */
00540       cc( in_buffer, out_buffer );
00541       comm_putpacket( out_buffer );
00542       return;
00543 
00544     case 'k' :
00545       /* "k": kill */
00546       ac_stop();
00547       break;
00548 
00549     case 'Z':
00550       /* "ZT,AA..AA,LLLL": Insert breakpoint or watchpoint */
00551       break_insert( in_buffer, out_buffer );
00552       break;
00553 
00554     case 'z':
00555       /* "zT,AA..AA,LLLL": Remove breakpoint or watchpoint */
00556       break_remove( in_buffer, out_buffer );
00557       break;
00558 
00559     default:
00560       out_buffer[0] = 0; /* Null response */
00561     }
00562 
00563     comm_putpacket(out_buffer);
00564   }
00565 }
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 /* Helper Functions: *********************************************************/
00576 
00577 /* Copyright notice:
00578  *
00579  *              Most of this code was taken from: arch/mips/kernel/gdb-stub.c
00580  *
00581  * Original copyright:
00582  *
00583  *      Originally written by Glenn Engel, Lake Stevens Instrument Division
00584  *
00585  *      Contributed by HP Systems
00586  *
00587  *      Modified for SPARC by Stu Grossman, Cygnus Support.
00588  *
00589  *      Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
00590  *      Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
00591  *
00592  *      Copyright (C) 1995 Andreas Busse
00593  *
00594  *      Copyright (C) 2003 MontaVista Software Inc.
00595  *      Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
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      * wait around for the start character,
00631      * ignore all other characters
00632      */
00633     while ( ( ch = ( comm_getchar() & 0x7f ) ) != '$' );
00634 
00635     checksum = 0;
00636     xmitcsum = 255;
00637     count = 0;
00638 
00639     /*
00640      * now, read until a # or end of buffer is found
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( '-' ); /* failed checksum */
00664         else {
00665           comm_putchar( '+' ); /* successful transfer */
00666 
00667           /*
00668            * if a sequence char is present,
00669            * reply the sequence ID
00670            */
00671           if ( buffer[ 2 ] == ':' )
00672             {
00673               comm_putchar( buffer[0] );
00674               comm_putchar( buffer[1] );
00675 
00676               /*
00677                * remove sequence chars from buffer
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    * $<packet info>#<checksum>.
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 }

Generated on Thu Jun 24 08:30:05 2004 for ArchC by doxygen 1.3.4