int stub_main(int arch_reason) { int ret; int gdb_signal; gdb_signal = decode_signal(arch_reason); /* Do not announce stop reply if we were detached. */ if (isattached) { send_stop_reply(gdb_signal); } /* We are now attached. */ isattached = 1; do { int cmd; char *p; while (getpkt(&pktbuf[0], sizeof(pktbuf)) < 1); p = &pktbuf[0]; cmd = *p; if ('?' == cmd) { send_stop_reply(gdb_signal); ret = 0; } else if ('c' == cmd) { ret = handle_c(p); } else if ('s' == cmd) { ret = handle_s(p); } else if ('D' == cmd) { ret = handle_D(p); if (ret & CMD_LEAVE) { isattached = 0; } } else if ('g' == cmd) { ret = handle_g(p); } else if ('G' == cmd) { ret = handle_G(p); } else if ('P' == cmd) { ret = handle_P(p); } else if ('m' == cmd) { ret = handle_m(p); } else if ('M' == cmd) { ret = handle_M(p); } else { /* * For any command not supported by the stub, an empty * response ('$#00') should be returned. */ p = ""; ret = CMD_REPLY; } if (ret & CMD_REPLY) { putpkt(p); } } while (!(ret & CMD_LEAVE)); return ret; }
void gdbstub_loop(void) { int addr; int length; char *ptr, *ptr1; void *ramaddr; unsigned long regbuf[NUMREGS]; bool reply, set; while (1) { remcomOutBuffer[0] = 0; ptr = getpacket(); if (!ptr) { gdbstub_disconnect(); return; } reply = true; switch (*ptr++) { case '?': send_stop_reply(SIGNAL_TRAP, NULL, 0); reply = false; // already done break; case 'g': /* return the value of the CPU registers */ get_registers(regbuf); ptr = remcomOutBuffer; ptr = mem2hex(regbuf, ptr, NUMREGS * sizeof(unsigned long)); break; case 'G': /* set the value of the CPU registers - return OK */ hex2mem(ptr, regbuf, NUMREGS * sizeof(unsigned long)); set_registers(regbuf); strcpy(remcomOutBuffer,"OK"); break; case 'p': /* pn Read the value of register n */ if (hexToInt(&ptr, &addr) && (size_t)addr < sizeof(regbuf)) { mem2hex(get_registers(regbuf) + addr, remcomOutBuffer, sizeof(unsigned long)); } else { strcpy(remcomOutBuffer,"E01"); } break; case 'P': /* Pn=r Write register n with value r */ ptr = strtok(ptr, "="); if (hexToInt(&ptr, &addr) && (ptr=strtok(NULL, "")) && (size_t)addr < sizeof(regbuf) // TODO hex2mem doesn't check the format && hex2mem((char*)ptr, &get_registers(regbuf)[addr], sizeof(u32)) ) { set_registers(regbuf); strcpy(remcomOutBuffer, "OK"); } else { strcpy(remcomOutBuffer,"E01"); } break; case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ /* Try to read %x,%x */ if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length)) { ramaddr = virt_mem_ptr(addr, length); if (!ramaddr || mem2hex(ramaddr, remcomOutBuffer, length)) break; strcpy(remcomOutBuffer, "E03"); } else strcpy(remcomOutBuffer,"E01"); break; case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */ /* Try to read '%x,%x:' */ if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length) && *ptr++ == ':') { ramaddr = virt_mem_ptr(addr, length); if (!ramaddr) { strcpy(remcomOutBuffer, "E03"); break; } if (range_translated((u32)ramaddr, (u32)((char *)ramaddr + length))) flush_translations(); if (hex2mem(ptr, ramaddr, length)) strcpy(remcomOutBuffer, "OK"); else strcpy(remcomOutBuffer, "E03"); } else strcpy(remcomOutBuffer, "E02"); break; case 'S': /* Ssig[;AA..AA] Step with signal at address AA..AA(optional). Same as 's' for us. */ ptr = strchr(ptr, ';'); /* skip the signal */ if (ptr) ptr++; case 's': /* s[AA..AA] Step at address AA..AA(optional) */ cpu_events |= EVENT_DEBUG_STEP; goto parse_new_pc; case 'C': /* Csig[;AA..AA] Continue with signal at address AA..AA(optional). Same as 'c' for us. */ ptr = strchr(ptr, ';'); /* skip the signal */ if (ptr) ptr++; case 'c': /* c[AA..AA] Continue at address AA..AA(optional) */ parse_new_pc: if (ptr && hexToInt(&ptr, &addr)) { arm.reg[15] = addr; } return; case 'q': if (!strcmp("Offsets", ptr)) { sprintf(remcomOutBuffer, "Text=%x;Data=%x;Bss=%x", ndls_debug_alloc_block, ndls_debug_alloc_block, ndls_debug_alloc_block); } break; case 'Z': /* 0|1|2|3|4,addr,kind */ set = true; goto z; case 'z': /* 0|1|2|3|4,addr,kind */ set = false; // kinds other than 4 aren't supported z: ptr1 = ptr++; ptr = strtok(ptr, ","); if (ptr && hexToInt(&ptr, &addr) && (ramaddr = virt_mem_ptr(addr & ~3, 4))) { u32 *flags = &RAM_FLAGS(ramaddr); switch (*ptr1) { case '0': // mem breakpoint case '1': // hw breakpoint if (set) { if (*flags & RF_CODE_TRANSLATED) flush_translations(); *flags |= RF_EXEC_BREAKPOINT; } else *flags &= ~RF_EXEC_BREAKPOINT; break; case '2': // write watchpoint case '4': // access watchpoint if (set) *flags |= RF_WRITE_BREAKPOINT; else *flags &= ~RF_WRITE_BREAKPOINT; if (*ptr1 != 4) break; case '3': // read watchpoint, access watchpoint if (set) *flags |= RF_READ_BREAKPOINT; else *flags &= ~RF_READ_BREAKPOINT; break; default: goto reply; } strcpy(remcomOutBuffer, "OK"); } else strcpy(remcomOutBuffer, "E01"); break; } /* switch */ reply: /* reply to the request */ if (reply) putpacket(remcomOutBuffer); } }