diff options
Diffstat (limited to 'main/common/gdb.c')
-rw-r--r-- | main/common/gdb.c | 930 |
1 files changed, 467 insertions, 463 deletions
diff --git a/main/common/gdb.c b/main/common/gdb.c index 74b8b5e..7287e39 100644 --- a/main/common/gdb.c +++ b/main/common/gdb.c @@ -1,7 +1,7 @@ /************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent - * + * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the @@ -21,17 +21,17 @@ * gdb.c: * * The code in this file allows a gdb debugger on a host to connect to the - * monitor. It supports both serial and network (udp) connections. + * monitor. It supports both serial and network (udp) connections. * Note that this is only the cpu-independent portion of the GDB debug * protocol. The following commands in gdb have been verified to work * with this code: * - * - target remote com1 - * - target remote udp:135.222.140.68:1234 - * - load and c - * - info registers - * - x/16x 0xff800000 - * - print varname + * - target remote com1 + * - target remote udp:135.222.140.68:1234 + * - load and c + * - info registers + * - x/16x 0xff800000 + * - print varname * *I'm sure other commands work, but these are the ones I've tested. * @@ -53,32 +53,32 @@ #if INCLUDE_GDB -#include "gdbregs.c" /* CPU-specific register name table */ +#include "gdbregs.c" /* CPU-specific register name table */ -#define REGTBL_SIZE (sizeof(gdb_regtbl)/sizeof(char *)) +#define REGTBL_SIZE (sizeof(gdb_regtbl)/sizeof(char *)) -#define GDBERR_NOHASH 1 /* no '#' in command */ -#define GDBERR_BADCSUM 2 /* bad checksum */ -#define GDBERR_GENERR 3 /* general confusion */ -#define GDBERR_BADXFMT 4 /* unexpected 'X' command format */ -#define GDBERR_RNUMOOR 5 /* register number out of range */ -#define GDBERR_NOSPACE 6 /* buffer not big enough for response */ +#define GDBERR_NOHASH 1 /* no '#' in command */ +#define GDBERR_BADCSUM 2 /* bad checksum */ +#define GDBERR_GENERR 3 /* general confusion */ +#define GDBERR_BADXFMT 4 /* unexpected 'X' command format */ +#define GDBERR_RNUMOOR 5 /* register number out of range */ +#define GDBERR_NOSPACE 6 /* buffer not big enough for response */ /* gdbIbuf[]: * Input buffer used for storage of the incoming command from * the gdb debugger. */ #if INCLUDE_ETHERNET -static uchar gdbIbuf[512]; +static uchar gdbIbuf[512]; #endif /* gdbRbuf[]: * Response buffer used for the complete response destined * for the gdb host. */ -static uchar gdbRbuf[1024]; -static int gdbRlen; -static void (*gdbContinueFptr)(); +static uchar gdbRbuf[1024]; +static int gdbRlen; +static void (*gdbContinueFptr)(); /* gdbUdp: * Set if the gdb interaction is via UDP, else zero. @@ -91,7 +91,7 @@ static int gdbUdp; * or Mtrace... Use printf if gdb is running via UDP; else use * printf. */ -static int (*gdbTrace)(char *, ...); +static int (*gdbTrace)(char *, ...); /* gdb_response(): * Utility function used by the other response functions to format @@ -102,109 +102,111 @@ static int (*gdbTrace)(char *, ...); int gdb_response(char *line) { - uchar csum, *resp; - - csum = 0; - resp = gdbRbuf; - *resp++ = '$'; - while(*line) { - csum += *line; - *resp++ = *line++; - } - resp += sprintf((char *)resp,"#%02x",csum); - *resp = 0; - - /* If gdbUdp is clear, then we assume that the gdb host is tied - * to the target's serial port, so just use printf to send the - * response. - * If gdbUdp is set, then we assume the calling function will - * send the response (via ethernet). - */ - if (!gdbUdp) - printf((char *)gdbRbuf); - - gdbRlen = strlen((char *)gdbRbuf); - - if (gdbRlen < 128) - gdbTrace("GDB_RSP: %s\n",gdbRbuf); - else - gdbTrace("GDB_RSP: BIG\n"); - - return(gdbRlen); + uchar csum, *resp; + + csum = 0; + resp = gdbRbuf; + *resp++ = '$'; + while(*line) { + csum += *line; + *resp++ = *line++; + } + resp += sprintf((char *)resp,"#%02x",csum); + *resp = 0; + + /* If gdbUdp is clear, then we assume that the gdb host is tied + * to the target's serial port, so just use printf to send the + * response. + * If gdbUdp is set, then we assume the calling function will + * send the response (via ethernet). + */ + if(!gdbUdp) { + printf((char *)gdbRbuf); + } + + gdbRlen = strlen((char *)gdbRbuf); + + if(gdbRlen < 128) { + gdbTrace("GDB_RSP: %s\n",gdbRbuf); + } else { + gdbTrace("GDB_RSP: BIG\n"); + } + + return(gdbRlen); } int gdb_ok(void) { - return(gdb_response("OK")); + return(gdb_response("OK")); } int gdb_sig(int signal) { - char buf[8]; + char buf[8]; - sprintf(buf,"S%02d",signal); - return(gdb_response(buf)); + sprintf(buf,"S%02d",signal); + return(gdb_response(buf)); } int gdb_err(int errno) { - char buf[8]; + char buf[8]; - sprintf(buf,"E%02d",errno); - return(gdb_response(buf)); + sprintf(buf,"E%02d",errno); + return(gdb_response(buf)); } /* gdb_m(): * GDB memory read command... * Incoming command format is... * - * mADDR,LEN#CC + * mADDR,LEN#CC * * where: - * 'm' is the "memory read" request - * 'ADDR' is the address from which the data is to be read - * 'LEN' is the number of bytes to be read + * 'm' is the "memory read" request + * 'ADDR' is the address from which the data is to be read + * 'LEN' is the number of bytes to be read * */ int gdb_m(char *line) { - int len, i; - char *lp; - uchar *addr, *resp, buf[128]; - - addr = (uchar *)strtol(line+1,&lp,16); - len = (int)strtol(lp+1,0,16); - if (len) { - if (len*2 >= sizeof(buf)) { - gdb_err(GDBERR_NOSPACE); - } - else { - resp = buf; - for(i=0;i<len;i++,addr++) - resp += sprintf((char *)resp,"%02x",*addr); - gdb_response((char *)buf); - } - } - else - gdb_ok(); - return(0); + int len, i; + char *lp; + uchar *addr, *resp, buf[128]; + + addr = (uchar *)strtol(line+1,&lp,16); + len = (int)strtol(lp+1,0,16); + if(len) { + if(len*2 >= sizeof(buf)) { + gdb_err(GDBERR_NOSPACE); + } else { + resp = buf; + for(i=0; i<len; i++,addr++) { + resp += sprintf((char *)resp,"%02x",*addr); + } + gdb_response((char *)buf); + } + } else { + gdb_ok(); + } + return(0); } /* gdb_M(): * GDB memory write command... * Incoming command format is... * - * MADDR,LEN:DATA#CC + * MADDR,LEN:DATA#CC * * where: - * 'M' is the "memory read" request - * 'ADDR' is the address from which the data is to be read - * 'LEN' is the number of bytes to be read - * 'DATA' is the ascii data + * 'M' is the "memory read" request + * 'ADDR' is the address from which the data is to be read + * 'LEN' is the number of bytes to be read + * 'DATA' is the ascii data * * STATUS: This function has been tested with m68k-elf-gdb (xtools) * and appears to work ok. @@ -212,22 +214,22 @@ gdb_m(char *line) int gdb_M(char *line) { - int len, i; - char *lp; - uchar *addr, buf[3]; - - addr = (uchar *)strtol(line+1,&lp,16); - len = (int)strtol(lp+1,&lp,16); - lp++; - - buf[2] = 0; - for(i=0;i<len;i++) { - buf[0] = *lp++; - buf[1] = *lp++; - *addr++ = (uchar)strtol((char *)buf,0,16); - } - gdb_ok(); - return(0); + int len, i; + char *lp; + uchar *addr, buf[3]; + + addr = (uchar *)strtol(line+1,&lp,16); + len = (int)strtol(lp+1,&lp,16); + lp++; + + buf[2] = 0; + for(i=0; i<len; i++) { + buf[0] = *lp++; + buf[1] = *lp++; + *addr++ = (uchar)strtol((char *)buf,0,16); + } + gdb_ok(); + return(0); } /* gdb_X(): @@ -237,26 +239,26 @@ gdb_M(char *line) int gdb_X(char *line) { - int len, i; - char *lp; - uchar *addr; - - addr = (uchar *)strtol(line+1,&lp,16); - len = (int)strtol(lp+1,&lp,16); - lp++; - - for(i=0;i<len;i++) { - if ((*lp == 0x7d) && - ((*(lp+1) == 0x03) || (*(lp+1) == 0x04) || (*(lp+1) == 0x5d))) { - *addr++ = *(lp+1) | 0x20; - lp += 2; - } - else - *addr++ = *lp++; - } - - gdb_ok(); - return(0); + int len, i; + char *lp; + uchar *addr; + + addr = (uchar *)strtol(line+1,&lp,16); + len = (int)strtol(lp+1,&lp,16); + lp++; + + for(i=0; i<len; i++) { + if((*lp == 0x7d) && + ((*(lp+1) == 0x03) || (*(lp+1) == 0x04) || (*(lp+1) == 0x5d))) { + *addr++ = *(lp+1) | 0x20; + lp += 2; + } else { + *addr++ = *lp++; + } + } + + gdb_ok(); + return(0); } /* gdb_q(): @@ -266,16 +268,17 @@ gdb_X(char *line) int gdb_q(char *line) { - line++; + line++; - if (strncmp(line,"Offsets",7) == 0) - return(gdb_response("Text=0;Data=0;Bss=0")); - else - return(gdb_ok()); + if(strncmp(line,"Offsets",7) == 0) { + return(gdb_response("Text=0;Data=0;Bss=0")); + } else { + return(gdb_ok()); + } } /* gdb_g(): - * Get all registers. + * Get all registers. * GDB at the host expects to see a buffer of ASCII-coded hex values * with each register being 8-bytes (forming one 32-bit value). * The order of these registers is defined by the table included @@ -285,20 +288,21 @@ gdb_q(char *line) int gdb_g(char *line) { - int i; - ulong reg; - char *resp, buf[(REGTBL_SIZE * 8) + 1]; - - resp = buf; - for(i=0;i<REGTBL_SIZE;i++) { - if (gdb_regtbl[i] != 0) - getreg(gdb_regtbl[i],®); - else - reg = 0; - self_ecl(reg); - resp += sprintf(resp,"%08lx",reg); - } - return(gdb_response(buf)); + int i; + ulong reg; + char *resp, buf[(REGTBL_SIZE * 8) + 1]; + + resp = buf; + for(i=0; i<REGTBL_SIZE; i++) { + if(gdb_regtbl[i] != 0) { + getreg(gdb_regtbl[i],®); + } else { + reg = 0; + } + self_ecl(reg); + resp += sprintf(resp,"%08lx",reg); + } + return(gdb_response(buf)); } /* gdb_P(): @@ -307,250 +311,250 @@ gdb_g(char *line) int gdb_P(char *line) { - char *lp; - int rnum; - ulong rval; - - line++; - rnum = strtol(line,&lp,16); - if (rnum >= REGTBL_SIZE) { - gdb_err(GDBERR_RNUMOOR); - return(-1); - } - lp++; - rval = strtol(lp,0,16); - self_ecl(rval); - putreg(gdb_regtbl[rnum],rval); - - gdb_ok(); - return(0); + char *lp; + int rnum; + ulong rval; + + line++; + rnum = strtol(line,&lp,16); + if(rnum >= REGTBL_SIZE) { + gdb_err(GDBERR_RNUMOOR); + return(-1); + } + lp++; + rval = strtol(lp,0,16); + self_ecl(rval); + putreg(gdb_regtbl[rnum],rval); + + gdb_ok(); + return(0); } /* gdb_c(): * This is the function that is called as a result of the 'c' (continue) - * command. - */ + * command. + */ int gdb_c(char *line) { - ulong addr; - void (*func)(); - - line++; - if (*line == '#') - getreg(CPU_PC_REG,&addr); - else - addr = strtol(line,0,16); - - func = (void(*)())addr; - func(); - return(0); + ulong addr; + void (*func)(); + + line++; + if(*line == '#') { + getreg(CPU_PC_REG,&addr); + } else { + addr = strtol(line,0,16); + } + + func = (void(*)())addr; + func(); + return(0); } /* gdb_cmd(): - * First function called out of the monitor's command interpreter. It - * does a basic syntax verification and then passes parameters to the - * appropriate handler above. - * Incoming syntax is + * First function called out of the monitor's command interpreter. It + * does a basic syntax verification and then passes parameters to the + * appropriate handler above. + * Incoming syntax is + * + * $ CMD # CSUM (of CMD) * - * $ CMD # CSUM (of CMD) + * where: + * $ is the ascii '$' character (0x24) + * # is the ascii '#' character (0x23) + * CMD is some command line consisting of a command and arguments + * CSUM is the checksum of the characters in CMD * - * where: - * $ is the ascii '$' character (0x24) - * # is the ascii '#' character (0x23) - * CMD is some command line consisting of a command and arguments - * CSUM is the checksum of the characters in CMD + * for example: * - * for example: - * - * $m4015bc,2#5a + * $m4015bc,2#5a * - * Returns... - * 0 if command is not processed; - * 1 if command is processed; - * -1 if command is processed but has an error; + * Returns... + * 0 if command is not processed; + * 1 if command is processed; + * -1 if command is processed but has an error; * - * If this code detects an error, then send an error code back to GDB. - * According to the article, there are no defined error codes in GDB so - * we will use the following... - * 1 indicates a missing '#' at the end of the incoming cmd string. - * 2 indicates a bad checksum calculation. - * 3 indicates some command processing error. - * 4 indicates bad 'X' command parsing. + * If this code detects an error, then send an error code back to GDB. + * According to the article, there are no defined error codes in GDB so + * we will use the following... + * 1 indicates a missing '#' at the end of the incoming cmd string. + * 2 indicates a bad checksum calculation. + * 3 indicates some command processing error. + * 4 indicates bad 'X' command parsing. */ int gdb_cmd(uchar *line) { - char *comma, *colon, *cp, *bp, buf[32]; - int len, clen, err, i; - uchar mycsum, incsum; - - gdbContinueFptr = (void(*)())0; - - /* If the command is 'X', then we have to treat it "special" because - * it contains binary data... - */ - if (line[1] == 'X') { - comma = strchr((char *)line,','); - colon = strchr((char *)line,':'); - if ((comma) && (colon)) { - bp = buf; - cp = (char *)line; - while(cp <= colon) - *bp++ = *cp++; - *bp = 0; - gdbTrace("GDB_CMD: '%s'\n",buf); - } - else { - gdbTrace("GDB_CMD: 'X'\n"); - gdb_err(GDBERR_BADXFMT); /* Unexpected 'X' command format */ - } - } - else if (line[0] == 0x03) { - gdbTrace("GDB_CTRLC\n"); - gdb_sig(2); - return(1); - } - else { - gdbTrace("GDB_CMD: '%s'\n",line); - len = strlen((char *)line); - - if (line[len-3] != '#') { - gdb_err(GDBERR_NOHASH); /* Missing ending '#' */ - return(-1); - } - - clen = len - 3; - mycsum = 0; - for(i=1;i<clen;i++) - mycsum += line[i]; - - incsum = (uchar)strtol((char *)line+len-2,(char **)0,16); - if (mycsum != incsum) { - gdb_err(GDBERR_BADCSUM); /* Checksum failure */ - return(-1); - } - } - - err = 0; - line++; - switch(*line) { - case 'm': /* Memory read */ - err = gdb_m((char *)line); - break; - case 'M': /* Memory write (Ascii-coded-hex) */ - err = gdb_M((char *)line); - break; - case 'X': /* Memory write (Binary) */ - err = gdb_X((char *)line); - break; - case 's': /* Step */ - gdb_response("S05"); - break; - case 'c': /* Continue */ - gdb_c((char *)line); - break; - case '?': /* Last signal */ - gdb_response("S05"); - break; - case 'g': /* get all registers */ - gdb_g((char *)line); - break; - case 'q': /* Query */ - gdb_q((char *)line); - break; - case 'P': /* PRR=HHHHHHHH... reg*/ - gdb_P((char *)line); - break; - case 'H': /* Thread */ - gdb_ok(); - break; - case 'k': /* Quit */ - gdb_ok(); - break; - default: /* Unknown... return empty response. */ - gdb_response(""); - break; - } - if (err) { - gdb_err(GDBERR_GENERR); /* Command processing error */ - } - return(1); + char *comma, *colon, *cp, *bp, buf[32]; + int len, clen, err, i; + uchar mycsum, incsum; + + gdbContinueFptr = (void(*)())0; + + /* If the command is 'X', then we have to treat it "special" because + * it contains binary data... + */ + if(line[1] == 'X') { + comma = strchr((char *)line,','); + colon = strchr((char *)line,':'); + if((comma) && (colon)) { + bp = buf; + cp = (char *)line; + while(cp <= colon) { + *bp++ = *cp++; + } + *bp = 0; + gdbTrace("GDB_CMD: '%s'\n",buf); + } else { + gdbTrace("GDB_CMD: 'X'\n"); + gdb_err(GDBERR_BADXFMT); /* Unexpected 'X' command format */ + } + } else if(line[0] == 0x03) { + gdbTrace("GDB_CTRLC\n"); + gdb_sig(2); + return(1); + } else { + gdbTrace("GDB_CMD: '%s'\n",line); + len = strlen((char *)line); + + if(line[len-3] != '#') { + gdb_err(GDBERR_NOHASH); /* Missing ending '#' */ + return(-1); + } + + clen = len - 3; + mycsum = 0; + for(i=1; i<clen; i++) { + mycsum += line[i]; + } + + incsum = (uchar)strtol((char *)line+len-2,(char **)0,16); + if(mycsum != incsum) { + gdb_err(GDBERR_BADCSUM); /* Checksum failure */ + return(-1); + } + } + + err = 0; + line++; + switch(*line) { + case 'm': /* Memory read */ + err = gdb_m((char *)line); + break; + case 'M': /* Memory write (Ascii-coded-hex) */ + err = gdb_M((char *)line); + break; + case 'X': /* Memory write (Binary) */ + err = gdb_X((char *)line); + break; + case 's': /* Step */ + gdb_response("S05"); + break; + case 'c': /* Continue */ + gdb_c((char *)line); + break; + case '?': /* Last signal */ + gdb_response("S05"); + break; + case 'g': /* get all registers */ + gdb_g((char *)line); + break; + case 'q': /* Query */ + gdb_q((char *)line); + break; + case 'P': /* PRR=HHHHHHHH... reg*/ + gdb_P((char *)line); + break; + case 'H': /* Thread */ + gdb_ok(); + break; + case 'k': /* Quit */ + gdb_ok(); + break; + default: /* Unknown... return empty response. */ + gdb_response(""); + break; + } + if(err) { + gdb_err(GDBERR_GENERR); /* Command processing error */ + } + return(1); } /* Gdb(): * This is the command at the CLI that allows the monitor to connect * to a gdb debugger via the serial port. It currently assumes that * the console port is the same port as is being used for the gdb - * connection. Eventually this needs to be modified to provide an + * connection. Eventually this needs to be modified to provide an * option for the gdb protocol to run on some serial port other than * the console. * * The connection command in gdb to connect to via serial port (PC) * is: - * target remote com1 + * target remote com1 */ char *GdbHelp[] = { - "Enter gdb mode", - "(no options)", - 0, + "Enter gdb mode", + "(no options)", + 0, }; int Gdb(int argc, char *argv) { - int state, quit; - uchar *lp, c; - static uchar line[1024]; - - printf("Entering GDB mode, to exit manually type: '$k#00'\n"); - - lp = (uchar *)0; - quit = 0; - state = 0; - gdbUdp = 0; - gdbTrace = Mtrace; - while(!quit) { - c = getchar(); - switch(state) { - case 0: /* Wait for start of message */ - if (c == '$') { - lp = line; - *lp++ = c; - state = 1; - } - break; - case 1: - *lp++ = c; /* This is the command character */ - state = 2; - break; - case 2: - if (c == '#') { - state = 3; - *lp++ = c; - } - else { - *lp++ = c; - } - break; - case 3: - *lp++ = c; - state = 4; - break; - case 4: - *lp++ = c; - *lp = 0; - state = 0; - if (line[1] == 'k') - quit = 1; - gdb_cmd(line); - break; - default: - break; - } - } - putchar('\n'); - return(CMD_SUCCESS); + int state, quit; + uchar *lp, c; + static uchar line[1024]; + + printf("Entering GDB mode, to exit manually type: '$k#00'\n"); + + lp = (uchar *)0; + quit = 0; + state = 0; + gdbUdp = 0; + gdbTrace = Mtrace; + while(!quit) { + c = getchar(); + switch(state) { + case 0: /* Wait for start of message */ + if(c == '$') { + lp = line; + *lp++ = c; + state = 1; + } + break; + case 1: + *lp++ = c; /* This is the command character */ + state = 2; + break; + case 2: + if(c == '#') { + state = 3; + *lp++ = c; + } else { + *lp++ = c; + } + break; + case 3: + *lp++ = c; + state = 4; + break; + case 4: + *lp++ = c; + *lp = 0; + state = 0; + if(line[1] == 'k') { + quit = 1; + } + gdb_cmd(line); + break; + default: + break; + } + } + putchar('\n'); + return(CMD_SUCCESS); } #if INCLUDE_ETHERNET @@ -559,126 +563,126 @@ Gdb(int argc, char *argv) * the monitor with gdb at the udp level. The connection command in * gdb to do this is: * - * target remote udp:TARGET_IP:TARGET_PORT + * target remote udp:TARGET_IP:TARGET_PORT */ int processGDB(struct ether_header *ehdr,ushort size) { - char *gdbp; - struct ip *ihdr, *ti, *ri; - struct Udphdr *uhdr, *tu, *ru; - struct ether_header *te; - - /* If SHOW_GDB is set (via ether -vg), then we dump the trace to - * the console; otherwise, we use mtrace. - */ + char *gdbp; + struct ip *ihdr, *ti, *ri; + struct Udphdr *uhdr, *tu, *ru; + struct ether_header *te; + + /* If SHOW_GDB is set (via ether -vg), then we dump the trace to + * the console; otherwise, we use mtrace. + */ #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_GDB) - gdbTrace = printf; - else + if(EtherVerbose & SHOW_GDB) { + gdbTrace = printf; + } else #endif - gdbTrace = Mtrace; - - ihdr = (struct ip *)(ehdr + 1); - uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); - gdbp = (char *)(uhdr + 1); - size = ecs(uhdr->uh_ulen) - sizeof(struct Udphdr); - - /* Check for ACK/NAK here: - */ - if (size == 1) { - if ((*gdbp == '+') || (*gdbp == '-')) { - gdbTrace("GDB_%s\n",*gdbp == '+' ? "ACK" : "NAK"); - return(0); - } - } - - /* Copy the incoming udp payload (the gdb command) to gdbIbuf[] - * and NULL terminate it... - */ - memcpy((char *)gdbIbuf,(char *)gdbp,size); - gdbIbuf[size] = 0; - - /* Now that we've stored away the GDB command request, we - * initially respond with the GDB acknowledgement ('+')... - */ - te = EtherCopy(ehdr); - ti = (struct ip *) (te + 1); - ri = (struct ip *) (ehdr + 1); - ti->ip_vhl = ri->ip_vhl; - ti->ip_tos = ri->ip_tos; - ti->ip_len = ecs((1 + (sizeof(struct ip) + sizeof(struct Udphdr)))); - ti->ip_id = ipId(); - ti->ip_off = ri->ip_off; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr, - sizeof(struct in_addr)); - memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), - sizeof(struct in_addr)); - tu = (struct Udphdr *) (ti + 1); - ru = (struct Udphdr *) (ri + 1); - tu->uh_sport = ru->uh_dport; - tu->uh_dport = ru->uh_sport; - tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + 1)); - gdbp = (char *)(tu+1); - *gdbp = '+'; - - ipChksum(ti); /* Compute checksum of ip hdr */ - udpChksum(ti); /* Compute UDP checksum */ - - sendBuffer(sizeof(struct ether_header) + sizeof(struct ip) + - sizeof(struct Udphdr) + 1); - - /* Wrap the processing of the incoming packet with a set/clear - * of the gdbUdp flag so that the other gdb code can act - * accordingly. - */ - gdbUdp = 1; - if (gdb_cmd(gdbIbuf) == 0) { - gdbUdp = 0; - return(0); - } - gdbUdp = 0; - - /* Add 1 to the gdbRlen to include the NULL termination. - */ - gdbRlen++; - - - /* The second respons is only done if gdb_cmd returns non-zero. - * It is the response to the gdb command issued by the debugger - * on the host. - */ - te = EtherCopy(ehdr); - ti = (struct ip *) (te + 1); - ri = (struct ip *) (ehdr + 1); - ti->ip_vhl = ri->ip_vhl; - ti->ip_tos = ri->ip_tos; - ti->ip_len = ecs((gdbRlen + (sizeof(struct ip) + sizeof(struct Udphdr)))); - ti->ip_id = ipId(); - ti->ip_off = ri->ip_off; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr, - sizeof(struct in_addr)); - memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), - sizeof(struct in_addr)); - - tu = (struct Udphdr *) (ti + 1); - ru = (struct Udphdr *) (ri + 1); - tu->uh_sport = ru->uh_dport; - tu->uh_dport = ru->uh_sport; - tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + gdbRlen)); - memcpy((char *)(tu+1),(char *)gdbRbuf,gdbRlen); - - ipChksum(ti); /* Compute checksum of ip hdr */ - udpChksum(ti); /* Compute UDP checksum */ - - sendBuffer(sizeof(struct ether_header) + sizeof(struct ip) + - sizeof(struct Udphdr) + gdbRlen); - - return(1); + gdbTrace = Mtrace; + + ihdr = (struct ip *)(ehdr + 1); + uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); + gdbp = (char *)(uhdr + 1); + size = ecs(uhdr->uh_ulen) - sizeof(struct Udphdr); + + /* Check for ACK/NAK here: + */ + if(size == 1) { + if((*gdbp == '+') || (*gdbp == '-')) { + gdbTrace("GDB_%s\n",*gdbp == '+' ? "ACK" : "NAK"); + return(0); + } + } + + /* Copy the incoming udp payload (the gdb command) to gdbIbuf[] + * and NULL terminate it... + */ + memcpy((char *)gdbIbuf,(char *)gdbp,size); + gdbIbuf[size] = 0; + + /* Now that we've stored away the GDB command request, we + * initially respond with the GDB acknowledgement ('+')... + */ + te = EtherCopy(ehdr); + ti = (struct ip *)(te + 1); + ri = (struct ip *)(ehdr + 1); + ti->ip_vhl = ri->ip_vhl; + ti->ip_tos = ri->ip_tos; + ti->ip_len = ecs((1 + (sizeof(struct ip) + sizeof(struct Udphdr)))); + ti->ip_id = ipId(); + ti->ip_off = ri->ip_off; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr, + sizeof(struct in_addr)); + memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), + sizeof(struct in_addr)); + tu = (struct Udphdr *)(ti + 1); + ru = (struct Udphdr *)(ri + 1); + tu->uh_sport = ru->uh_dport; + tu->uh_dport = ru->uh_sport; + tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + 1)); + gdbp = (char *)(tu+1); + *gdbp = '+'; + + ipChksum(ti); /* Compute checksum of ip hdr */ + udpChksum(ti); /* Compute UDP checksum */ + + sendBuffer(sizeof(struct ether_header) + sizeof(struct ip) + + sizeof(struct Udphdr) + 1); + + /* Wrap the processing of the incoming packet with a set/clear + * of the gdbUdp flag so that the other gdb code can act + * accordingly. + */ + gdbUdp = 1; + if(gdb_cmd(gdbIbuf) == 0) { + gdbUdp = 0; + return(0); + } + gdbUdp = 0; + + /* Add 1 to the gdbRlen to include the NULL termination. + */ + gdbRlen++; + + + /* The second respons is only done if gdb_cmd returns non-zero. + * It is the response to the gdb command issued by the debugger + * on the host. + */ + te = EtherCopy(ehdr); + ti = (struct ip *)(te + 1); + ri = (struct ip *)(ehdr + 1); + ti->ip_vhl = ri->ip_vhl; + ti->ip_tos = ri->ip_tos; + ti->ip_len = ecs((gdbRlen + (sizeof(struct ip) + sizeof(struct Udphdr)))); + ti->ip_id = ipId(); + ti->ip_off = ri->ip_off; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr, + sizeof(struct in_addr)); + memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), + sizeof(struct in_addr)); + + tu = (struct Udphdr *)(ti + 1); + ru = (struct Udphdr *)(ri + 1); + tu->uh_sport = ru->uh_dport; + tu->uh_dport = ru->uh_sport; + tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + gdbRlen)); + memcpy((char *)(tu+1),(char *)gdbRbuf,gdbRlen); + + ipChksum(ti); /* Compute checksum of ip hdr */ + udpChksum(ti); /* Compute UDP checksum */ + + sendBuffer(sizeof(struct ether_header) + sizeof(struct ip) + + sizeof(struct Udphdr) + gdbRlen); + + return(1); } #endif |