void GdbServer::gdb_out(const char *buf) { int i = strlen (buf) * 2 + 1; char hexdata [i + 1]; hexdata[0] = 'O'; hexify (hexdata + 1, (unsigned char*) buf, strlen(buf)); gdb_putpacket (hexdata, i); }
void GdbServer::gdb_putpacket_f (const char *fmt, ...) { va_list ap; char *buf; int size; va_start(ap, fmt); size = vasprintf (&buf, (const char*) fmt, ap); gdb_putpacket (buf, size); free(buf); va_end(ap); }
void GdbServer::handle_q_packet (char *packet, int len) { unsigned long addr, alen; if (!strncmp (packet, "qRcmd,", 6)) { int datalen; /* calculate size and allocate buffer for command */ datalen = (len - 6) / 2; char data [datalen + 1]; /* dehexify command */ unhexify ((unsigned char*) data, (const unsigned char*)packet + 6, datalen); data[datalen] = 0; /* add terminating null */ int c = mon.command (data); if (c < 0) gdb_putpacketz (""); else if (c == 0) gdb_putpacketz ("OK"); else gdb_putpacketz ("E"); } else if (!strncmp (packet, "qSupported", 10)) { /* Query supported protocol features */ gdb_putpacket_f ("PacketSize=%X;qXfer:memory-map:read+;qXfer:features:read+", BUF_SIZE); } else if (strncmp (packet, "qXfer:memory-map:read::", 23) == 0) { /* Read target XML memory map */ if ((!target) || (!target->xml_mem_map)) { gdb_putpacketz ("E01"); return; } handle_q_string_reply (target->xml_mem_map, packet + 23); } else if (strncmp (packet, "qXfer:features:read:target.xml:", 31) == 0) { /* Read target description */ if ((!target) || (!target->tdesc)) { gdb_putpacketz ("E01"); return; } handle_q_string_reply (target->tdesc, packet + 31); } else if (sscanf (packet, "qCRC:%08lx,%08lx", &addr, &alen) == 2) { if (!target) { gdb_putpacketz ("E01"); return; } gdb_putpacket_f ("C%lx", target->generic_crc32 (addr, alen)); } else { debug ("*** Unsupported packet: %s\n", packet); gdb_putpacket ("", 0); } }
void GdbServer::handle_q_string_reply (const char *str, const char *param) { unsigned long addr, len; if (sscanf (param, "%08lx,%08lx", &addr, &len) != 2) { gdb_putpacketz ("E01"); return; } if (addr < strlen (str)) { char reply [len+2]; reply[0] = 'm'; strncpy (reply + 1, &str [addr], len); if (len > strlen (&str [addr])) len = strlen (&str [addr]); gdb_putpacket (reply, len + 1); } else if (addr == strlen (str)) { gdb_putpacketz ("l"); } else gdb_putpacketz ("E01"); }
void gdb_main(void) { int size; bool single_step = false; char last_activity = 0; DEBUG("Entring GDB protocol main loop\n"); /* GDB protocol main loop */ while(1) { SET_IDLE_STATE(1); size = gdb_getpacket(pbuf, BUF_SIZE); SET_IDLE_STATE(0); continue_activity: switch(pbuf[0]) { /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ ERROR_IF_NO_TARGET(); uint8_t arm_regs[target_regs_size(cur_target)]; target_regs_read(cur_target, arm_regs); gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)), sizeof(arm_regs) * 2); break; } case 'm': { /* 'm addr,len': Read len bytes from addr */ uint32_t addr, len; ERROR_IF_NO_TARGET(); sscanf(pbuf, "m%" SCNx32 ",%" SCNx32, &addr, &len); DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; target_mem_read(cur_target, mem, addr, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else gdb_putpacket(hexify(pbuf, mem, len), len*2); break; } case 'G': { /* 'G XX': Write general registers */ ERROR_IF_NO_TARGET(); uint8_t arm_regs[target_regs_size(cur_target)]; unhexify(arm_regs, &pbuf[1], sizeof(arm_regs)); target_regs_write(cur_target, arm_regs); gdb_putpacketz("OK"); break; } case 'M': { /* 'M addr,len:XX': Write len bytes to addr */ uint32_t addr, len; int hex; ERROR_IF_NO_TARGET(); sscanf(pbuf, "M%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &hex); DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; unhexify(mem, pbuf + hex, len); target_mem_write(cur_target, addr, mem, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); break; } case 's': /* 's [addr]': Single step [start at addr] */ single_step = true; // Fall through to resume target case 'c': /* 'c [addr]': Continue [at addr] */ if(!cur_target) { gdb_putpacketz("X1D"); break; } target_halt_resume(cur_target, single_step); SET_RUN_STATE(1); single_step = false; // Fall through to wait for target halt case '?': { /* '?': Request reason for target halt */ /* This packet isn't documented as being mandatory, * but GDB doesn't work without it. */ uint32_t watch_addr; int sig; if(!cur_target) { /* Report "target exited" if no target */ gdb_putpacketz("W00"); break; } last_activity = pbuf[0]; /* Wait for target halt */ while(!(sig = target_halt_wait(cur_target))) { unsigned char c = gdb_if_getchar_to(0); if((c == '\x03') || (c == '\x04')) { target_halt_request(cur_target); last_activity = 's'; } } SET_RUN_STATE(0); /* Negative signal indicates we're in a syscall */ if (sig < 0) break; /* Target disappeared */ if (cur_target == NULL) { gdb_putpacket_f("X%02X", sig); break; } /* Report reason for halt */ if(target_check_hw_wp(cur_target, &watch_addr)) { /* Watchpoint hit */ gdb_putpacket_f("T%02Xwatch:%08X;", sig, watch_addr); } else { gdb_putpacket_f("T%02X", sig); } break; } case 'F': { /* Semihosting call finished */ int retcode, errcode, items; char c, *p; if (pbuf[1] == '-') p = &pbuf[2]; else p = &pbuf[1]; items = sscanf(p, "%x,%x,%c", &retcode, &errcode, &c); if (pbuf[1] == '-') retcode = -retcode; target_hostio_reply(cur_target, retcode, errcode); /* if break is requested */ if (items == 3 && c == 'C') { gdb_putpacketz("T02"); break; } pbuf[0] = last_activity; goto continue_activity; } /* Optional GDB packet support */ case '!': /* Enable Extended GDB Protocol. */ /* This doesn't do anything, we support the extended * protocol anyway, but GDB will never send us a 'R' * packet unless we answer 'OK' here. */ gdb_putpacketz("OK"); break; case 0x04: case 'D': /* GDB 'detach' command. */ if(cur_target) target_detach(cur_target); last_target = cur_target; cur_target = NULL; gdb_putpacketz("OK"); break; case 'k': /* Kill the target */ if(cur_target) { target_reset(cur_target); target_detach(cur_target); last_target = cur_target; cur_target = NULL; } break; case 'r': /* Reset the target system */ case 'R': /* Restart the target program */ if(cur_target) target_reset(cur_target); else if(last_target) { cur_target = target_attach(last_target, gdb_target_destroy_callback); target_reset(cur_target); } break; case 'X': { /* 'X addr,len:XX': Write binary data to addr */ uint32_t addr, len; int bin; ERROR_IF_NO_TARGET(); sscanf(pbuf, "X%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &bin); DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); target_mem_write(cur_target, addr, pbuf+bin, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); break; } case 'q': /* General query packet */ handle_q_packet(pbuf, size); break; case 'v': /* General query packet */ handle_v_packet(pbuf, size); break; /* These packet implement hardware break-/watchpoints */ case 'Z': /* Z type,addr,len: Set breakpoint packet */ case 'z': /* z type,addr,len: Clear breakpoint packet */ ERROR_IF_NO_TARGET(); handle_z_packet(pbuf, size); break; default: /* Packet not implemented */ DEBUG("*** Unsupported packet: %s\n", pbuf); gdb_putpacketz(""); } } }
static void handle_v_packet(char *packet, int plen) { unsigned long addr, len; int bin; static uint8_t flash_mode = 0; if (sscanf(packet, "vAttach;%08lx", &addr) == 1) { /* Attach to remote target processor */ target *t; uint32_t i; for(t = target_list, i = 1; t; t = t->next, i++) if(i == addr) { cur_target = target_attach(t, gdb_target_destroy_callback); break; } if(cur_target) gdb_putpacketz("T05"); else gdb_putpacketz("E01"); } else if (!strcmp(packet, "vRun;")) { /* Run target program. For us (embedded) this means reset. */ if(cur_target) { target_reset(cur_target); gdb_putpacketz("T05"); } else if(last_target) { cur_target = target_attach(last_target, gdb_target_destroy_callback); /* If we were able to attach to the target again */ if (cur_target) { target_reset(cur_target); gdb_putpacketz("T05"); } else gdb_putpacketz("E01"); } else gdb_putpacketz("E01"); } else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) { /* Erase Flash Memory */ DEBUG("Flash Erase %08lX %08lX\n", addr, len); if(!cur_target) { gdb_putpacketz("EFF"); return; } if(!flash_mode) { /* Reset target if first flash command! */ /* This saves us if we're interrupted in IRQ context */ target_reset(cur_target); flash_mode = 1; } if(target_flash_erase(cur_target, addr, len) == 0) gdb_putpacketz("OK"); else gdb_putpacketz("EFF"); } else if (sscanf(packet, "vFlashWrite:%08lx:%n", &addr, &bin) == 1) { /* Write Flash Memory */ len = plen - bin; DEBUG("Flash Write %08lX %08lX\n", addr, len); if(cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, len) == 0) gdb_putpacketz("OK"); else gdb_putpacketz("EFF"); } else if (!strcmp(packet, "vFlashDone")) { /* Commit flash operations. */ gdb_putpacketz(target_flash_done(cur_target) ? "EFF" : "OK"); flash_mode = 0; } else { DEBUG("*** Unsupported packet: %s\n", packet); gdb_putpacket("", 0); } }
static void handle_q_packet(char *packet, int len) { uint32_t addr, alen; if(!strncmp(packet, "qRcmd,", 6)) { char *data; int datalen; /* calculate size and allocate buffer for command */ datalen = (len - 6) / 2; data = alloca(datalen+1); /* dehexify command */ unhexify(data, packet+6, datalen); data[datalen] = 0; /* add terminating null */ int c = command_process(cur_target, data); if(c < 0) gdb_putpacketz(""); else if(c == 0) gdb_putpacketz("OK"); else gdb_putpacketz("E"); } else if (!strncmp (packet, "qSupported", 10)) { /* Query supported protocol features */ gdb_putpacket_f("PacketSize=%X;qXfer:memory-map:read+;qXfer:features:read+", BUF_SIZE); } else if (strncmp (packet, "qXfer:memory-map:read::", 23) == 0) { /* Read target XML memory map */ if((!cur_target) && last_target) { /* Attach to last target if detached. */ cur_target = target_attach(last_target, gdb_target_destroy_callback); } if (!cur_target) { gdb_putpacketz("E01"); return; } handle_q_string_reply(target_mem_map(cur_target), packet + 23); } else if (strncmp (packet, "qXfer:features:read:target.xml:", 31) == 0) { /* Read target description */ if((!cur_target) && last_target) { /* Attach to last target if detached. */ cur_target = target_attach(last_target, gdb_target_destroy_callback); } if (!cur_target) { gdb_putpacketz("E01"); return; } handle_q_string_reply(target_tdesc(cur_target), packet + 31); } else if (sscanf(packet, "qCRC:%" PRIx32 ",%" PRIx32, &addr, &alen) == 2) { if(!cur_target) { gdb_putpacketz("E01"); return; } gdb_putpacket_f("C%lx", generic_crc32(cur_target, addr, alen)); } else { DEBUG("*** Unsupported packet: %s\n", packet); gdb_putpacket("", 0); } }
uint32_t GdbServer::Up (char *pbuf, uint32_t plen) { debug ("Up::%d:\"%s\"\n", plen, pbuf); lock.lock(); size = plen; continue_activity: switch (pbuf[0]) { case 0: { // Ctrl - C debug ("GdbServer::Up Ctrl-C\n"); target->halt_request (); last_activity = 's'; break; } /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ if (!target_check ()) break; int rsize = target->get_regs_size(); debug ("RSIZE = %d\n", rsize); uint8_t arm_regs [rsize]; target->regs_read (arm_regs); /* Výstup po blocích délky max. 240 bytů byl vynucen větší déklou dat registrů * CortexM4F. Zdá se, že to funguje. */ const int chunk = 120; int block, start = 0; for (;;) { if (rsize > chunk) block = chunk; else block = rsize; char* tptr = (char*) hexify (pbuf, (const unsigned char*) arm_regs + start, block); gdb_putpacket (tptr , block * 2); start += block; rsize -= block; if (!rsize) break; } break; } case 'm': { /* 'm addr,len': Read len bytes from addr */ unsigned long addr, len; if (!target_check ()) break; sscanf ((char*)pbuf, "m%08lx,%08lx", &addr, &len); debug ("m packet: addr = %08lX, len = %08lX\n", addr, len); uint8_t mem[len]; if ( ( (addr & 3) == 0) && ( (len & 3) == 0)) target->mem_read_words ((uint32_t*) mem, addr, len); else target->mem_read_bytes (mem, addr, len); if (target->check_error ()) gdb_putpacketz ("E01"); else gdb_putpacket ((char*)hexify (pbuf, mem, len), len*2); break; } case 'G': { /* 'G XX': Write general registers */ if (!target_check ()) break; int rsize = target->get_regs_size(); uint8_t arm_regs [rsize]; unhexify (arm_regs, (unsigned char*) &pbuf[1], rsize); target->regs_write (arm_regs); gdb_putpacketz ("OK"); break; } case 'M': { /* 'M addr,len:XX': Write len bytes to addr */ unsigned long addr, len; int hex; if (!target_check ()) break; sscanf ((char*)pbuf, "M%08lx,%08lx:%n", &addr, &len, &hex); debug ("M packet: addr = %08lX, len = %08lX\n", addr, len); uint8_t mem[len]; unhexify (mem, (unsigned char*)pbuf + hex, len); if ( ( (addr & 3) == 0) && ( (len & 3) == 0)) target->mem_write_words (addr, (const uint32_t*) mem, len); else target->mem_write_bytes (addr, mem, len); if (target->check_error ()) gdb_putpacketz ("E01"); else gdb_putpacketz ("OK"); break; } case 's': /* 's [addr]': Single step [start at addr] */ single_step = true; // Fall through to resume target case 'c': /* 'c [addr]': Continue [at addr] */ if (!target) { gdb_putpacketz ("X1D"); break; } target->halt_resume (single_step); single_step = false; // Fall through to wait for target halt case '?': { /* '?': Request reason for target halt */ /* This packet isn't documented as being mandatory, * but GDB doesn't work without it. */ if (!target) { /* Report "target exited" if no target */ gdb_putpacketz ("W00"); break; } if (!target->attached) { /* Report "target exited" if no target */ gdb_putpacketz ("W00"); break; } last_activity = pbuf[0]; /* Wait for target halt */ debug("? WAIT HALT\n"); SetActive (); // timto se prepne do mainloop, kde ceka na zastaveni break; } case 'F': { /* Semihosting call finished */ int retcode, errcode, items; char c, *p; if (pbuf[1] == '-') p = (char*) &pbuf[2]; else p = (char*) &pbuf[1]; items = sscanf (p, "%x,%x,%c", &retcode, &errcode, &c); if (pbuf[1] == '-') retcode = -retcode; target->hostio_reply (retcode, errcode); /* if break is requested */ if (items == 3 && c == 'C') { gdb_putpacketz ("T02"); break; } pbuf[0] = last_activity; goto continue_activity; } /* Optional GDB packet support */ case '!': /* Enable Extended GDB Protocol. */ /* This doesn't do anything, we support the extended * protocol anyway, but GDB will never send us a 'R' * packet unless we answer 'OK' here. */ gdb_putpacketz ("OK"); break; case 0x04: // ??? debug ("CASE 4 packet ???\n"); case 'D': /* GDB 'detach' command. */ if (target) { if (target->attached) { target->detach (); target->reset (); } } gdb_putpacketz ("OK"); break; case 'k': /* Kill the target */ if (target) { target->detach (); target->reset (); } break; case 'r': /* Reset the target system */ case 'R': /* Restart the target program */ if (target && target->attach()) { target->reset (); SetActive (); } break; case 'X': { /* 'X addr,len:XX': Write binary data to addr */ unsigned long addr, len; int bin, icp; if (!target_check ()) break; sscanf ((char*)pbuf, "X%08lx,%08lx:%n", &addr, &len, &bin); // On Cortex-M0 word align param to write_words for (icp=0; icp<(int)len; icp++) pbuf[icp] = pbuf[icp + bin]; debug ("X packet: addr = %08lX, len = %08lX\n", addr, len); if ( ( (addr & 3) == 0) && ( (len & 3) == 0)) target->mem_write_words (addr, (const uint32_t*) pbuf, len); else target->mem_write_bytes (addr, (unsigned char*) pbuf, len); if (target->check_error ()) gdb_putpacketz ("E01"); else gdb_putpacketz ("OK"); break; } case 'q': /* General query packet */ handle_q_packet ((char*)pbuf, size); break; case 'v': /* General query packet */ handle_v_packet ((char*)pbuf, size); break; /* These packet implement hardware break-/watchpoints */ case 'Z': /* Z type,addr,len: Set breakpoint packet */ case 'z': /* z type,addr,len: Clear breakpoint packet */ if (!target_check ()) break; handle_z_packet ((char*)pbuf, size); break; default: /* Packet not implemented */ debug ("*** Unsupported packet: %s\n", pbuf); gdb_putpacketz (""); } lock.unlock(); //return BaseLayer::Up (pbuf, plen); return plen; }
void GdbServer::gdb_putpacketz (const char *packet) { int size = strlen (packet); gdb_putpacket (packet, size); }
void GdbServer::handle_v_packet (char *packet, int plen) { unsigned long addr, len; int bin; static uint32_t flash_mode = 0; if (sscanf (packet, "vAttach;%08lx", &addr) == 1) { /* Attach to remote target processor */ if (target && target->attach()) gdb_putpacketz ("T05"); else gdb_putpacketz ("E01"); } else if (!strcmp (packet, "vRun;")) { /* Run target program. For us (embedded) this means reset. */ if (target && target->attach()) { target->reset (); SetActive (); gdb_putpacketz ("T05"); } else gdb_putpacketz ("E01"); } else if (sscanf (packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) { /* Erase Flash Memory */ debug ("Flash Erase %08lX %08lX\n", addr, len); if (!target) { gdb_putpacketz ("EFF"); return; } if (!flash_mode) { /* Reset target if first flash command! */ /* This saves us if we're interrupted in IRQ context */ target->reset (); flash_mode = 1; } if (target->flash_erase (addr, len) == 0) gdb_putpacketz ("OK"); else gdb_putpacketz ("EFF"); } else if (sscanf (packet, "vFlashWrite:%08lx:%n", &addr, &bin) == 1) { /* Write Flash Memory */ len = plen - bin; debug ("Flash Write %08lX %08lX\n", addr, len); if (target && target->flash_write (addr, (unsigned char*) packet + bin, len) == 0) gdb_putpacketz ("OK"); else gdb_putpacketz ("EFF"); } else if (!strcmp (packet, "vFlashDone")) { /* Commit flash operations. */ gdb_putpacketz ("OK"); flash_mode = 0; } else { debug ("*** Unsupported packet: %s\n", packet); gdb_putpacket ("", 0); } }
int gdb_main_loop(struct target_controller *tc, bool in_syscall) { int size; bool single_step = false; /* GDB protocol main loop */ while(1) { SET_IDLE_STATE(1); size = gdb_getpacket(pbuf, BUF_SIZE); SET_IDLE_STATE(0); switch(pbuf[0]) { /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ ERROR_IF_NO_TARGET(); uint8_t arm_regs[target_regs_size(cur_target)]; target_regs_read(cur_target, arm_regs); gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)), sizeof(arm_regs) * 2); break; } case 'm': { /* 'm addr,len': Read len bytes from addr */ uint32_t addr, len; ERROR_IF_NO_TARGET(); sscanf(pbuf, "m%" SCNx32 ",%" SCNx32, &addr, &len); if (len > sizeof(pbuf) / 2) { gdb_putpacketz("E02"); break; } DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; if (target_mem_read(cur_target, mem, addr, len)) gdb_putpacketz("E01"); else gdb_putpacket(hexify(pbuf, mem, len), len*2); break; } case 'G': { /* 'G XX': Write general registers */ ERROR_IF_NO_TARGET(); uint8_t arm_regs[target_regs_size(cur_target)]; unhexify(arm_regs, &pbuf[1], sizeof(arm_regs)); target_regs_write(cur_target, arm_regs); gdb_putpacketz("OK"); break; } case 'M': { /* 'M addr,len:XX': Write len bytes to addr */ uint32_t addr, len; int hex; ERROR_IF_NO_TARGET(); sscanf(pbuf, "M%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &hex); if (len > (unsigned)(size - hex) / 2) { gdb_putpacketz("E02"); break; } DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; unhexify(mem, pbuf + hex, len); if (target_mem_write(cur_target, addr, mem, len)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); break; } case 's': /* 's [addr]': Single step [start at addr] */ single_step = true; /* fall through */ case 'c': /* 'c [addr]': Continue [at addr] */ if(!cur_target) { gdb_putpacketz("X1D"); break; } target_halt_resume(cur_target, single_step); SET_RUN_STATE(1); single_step = false; /* fall through */ case '?': { /* '?': Request reason for target halt */ /* This packet isn't documented as being mandatory, * but GDB doesn't work without it. */ target_addr watch; enum target_halt_reason reason; if(!cur_target) { /* Report "target exited" if no target */ gdb_putpacketz("W00"); break; } /* Wait for target halt */ while(!(reason = target_halt_poll(cur_target, &watch))) { unsigned char c = gdb_if_getchar_to(0); if((c == '\x03') || (c == '\x04')) { target_halt_request(cur_target); } } SET_RUN_STATE(0); /* Translate reason to GDB signal */ switch (reason) { case TARGET_HALT_ERROR: gdb_putpacket_f("X%02X", GDB_SIGLOST); morse("TARGET LOST.", true); break; case TARGET_HALT_REQUEST: gdb_putpacket_f("T%02X", GDB_SIGINT); break; case TARGET_HALT_WATCHPOINT: gdb_putpacket_f("T%02Xwatch:%08X;", GDB_SIGTRAP, watch); break; case TARGET_HALT_FAULT: gdb_putpacket_f("T%02X", GDB_SIGSEGV); break; default: gdb_putpacket_f("T%02X", GDB_SIGTRAP); } break; } case 'F': /* Semihosting call finished */ if (in_syscall) { return hostio_reply(tc, pbuf, size); } else { DEBUG("*** F packet when not in syscall! '%s'\n", pbuf); gdb_putpacketz(""); } break; /* Optional GDB packet support */ case '!': /* Enable Extended GDB Protocol. */ /* This doesn't do anything, we support the extended * protocol anyway, but GDB will never send us a 'R' * packet unless we answer 'OK' here. */ gdb_putpacketz("OK"); break; case 0x04: case 'D': /* GDB 'detach' command. */ if(cur_target) target_detach(cur_target); last_target = cur_target; cur_target = NULL; gdb_putpacketz("OK"); break; case 'k': /* Kill the target */ if(cur_target) { target_reset(cur_target); target_detach(cur_target); last_target = cur_target; cur_target = NULL; } break; case 'r': /* Reset the target system */ case 'R': /* Restart the target program */ if(cur_target) target_reset(cur_target); else if(last_target) { cur_target = target_attach(last_target, &gdb_controller); target_reset(cur_target); } break; case 'X': { /* 'X addr,len:XX': Write binary data to addr */ uint32_t addr, len; int bin; ERROR_IF_NO_TARGET(); sscanf(pbuf, "X%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &bin); if (len > (unsigned)(size - bin)) { gdb_putpacketz("E02"); break; } DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); if (target_mem_write(cur_target, addr, pbuf+bin, len)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); break; } case 'q': /* General query packet */ handle_q_packet(pbuf, size); break; case 'v': /* General query packet */ handle_v_packet(pbuf, size); break; /* These packet implement hardware break-/watchpoints */ case 'Z': /* Z type,addr,len: Set breakpoint packet */ case 'z': /* z type,addr,len: Clear breakpoint packet */ ERROR_IF_NO_TARGET(); handle_z_packet(pbuf, size); break; default: /* Packet not implemented */ DEBUG("*** Unsupported packet: %s\n", pbuf); gdb_putpacketz(""); } } }