static void gdb_vmm_wr_all_sysregs(uint8_t *data, size_t len) { debug(GDBSTUB_CMD, "need to implement write all system registers\n"); data = data; len = len; gdb_unsupported(); }
static void gdb_cmd_rm_brk(uint8_t *data, size_t len) { uint64_t type; size_t size; offset_t addr; int rc; if(!__gdb_setup_brk_op(data, len, &type, &size, &addr)) return; switch(type) { case GDB_BRK_TYPE_MEM: rc = dbg_soft_del(addr); break; case GDB_BRK_TYPE_HRD_X: case GDB_BRK_TYPE_HRD_W: case GDB_BRK_TYPE_HRD_RW: rc = dbg_hard_brk_del(addr, type-1, size-1); break; default: gdb_unsupported(); return; } if(rc == DBG_BRK_OK) { gdb_ok(); return; } gdb_err_mem(); }
static void gdb_cmd_wr_mem(uint8_t *data, size_t len) { offset_t addr; loc_t bytes; size_t size, lbytes, can, i; uint8_t store[128]; if(!__gdb_setup_mem_op(data, len, &addr, &size, &bytes)) return; debug(GDBSTUB_CMD, "write mem: addr 0x%X size %D\n", addr, size); lbytes = (size_t)data + len - bytes.linear; if(lbytes/2 != size) { debug(GDBSTUB_CMD, "gdb cmd_wr_mem missing bytes\n"); gdb_unsupported(); } while(size) { can = min(size, sizeof(store)); for(i=0 ; i<can ; i++, bytes.u16++) { if(!__hex_to_uint8(bytes.u8, &store[i])) { debug(GDBSTUB_CMD, "gdb cmd_wr_mem invalid byte\n"); gdb_unsupported(); } } if(!gdb_mem_write(addr, store, can)) { debug(GDBSTUB_CMD, "access failure\n"); gdb_err_mem(); return; } addr += can; size -= can; } gdb_ok(); }
static size_t gdb_consume_packet(uint8_t *data, size_t len) { size_t done; debug(GDBSTUB_PKT, "consume (%D): [", len); #ifdef CONFIG_GDBSTUB_PKT_DBG debug_write(data, len); debug_write((uint8_t*)"]\n", 2); #endif while(len) { switch(*data) { case GDB_ACK_BYTE: if(!gdb_enabled()) { debug(GDBSTUB_PKT, "gdb connect\n"); gdb_enable(); } done = 1; break; case GDB_PKT_BYTE: done = gdb_parse_packet(data, len); if(!done) goto __end; break; case GDB_INT_BYTE: done = 1; debug(GDBSTUB_PKT, "interrupt sequence requested\n"); gdb_interrupt_sequence(); break; case GDB_NAK_BYTE: done = 1; gdb_ack(); break; default: done = 1; debug(GDBSTUB_PKT, "gdb_stub unsupported '\\x%x' (sz %D)\n", *data, len); gdb_unsupported(); break; } len -= done; data += done; } __end: return len; }
/* ** Command packets */ static void gdb_cmd_query(uint8_t *data, size_t len) { uint8_t qry = *data; data++; len--; switch(qry) { case GDB_QUERY_THREAD: gdb_query_thread(); return; } debug(GDBSTUB_CMD, "query unsupported\n"); gdb_unsupported(); return; }
static void gdb_cmd_thread(uint8_t *data) { switch(*data) { case 'g': case 'c': /* ignore thread-id */ debug(GDBSTUB_CMD, "gdb ok for thread\n"); gdb_ok(); break; default : debug(GDBSTUB_CMD, "thread unsupported\n"); gdb_unsupported(); break; } }
void gdb_cmd_vmm(uint8_t *data, size_t len) { uint8_t idx = *data - 0x80; data++; len--; if(idx <= sizeof(gdb_vmm_handlers)/sizeof(gdb_vmm_hdl_t)) { debug(GDBSTUB_CMD, "gdb_vmm handler call %d\n", idx); gdb_vmm_handlers[idx](data, len); return; } debug(GDBSTUB_CMD, "vmm cmd unsupported\n"); gdb_unsupported(); }
void gdb_process_packet(uint8_t *data, size_t len) { uint8_t cmd = *data; data++; len--; debug(GDBSTUB_CMD, "parsing cmd %c\n", cmd); switch(cmd) { case GDB_CMD_R_MEM: return gdb_cmd_rd_mem(data, len); case GDB_CMD_W_MEM: return gdb_cmd_wr_mem(data, len); case GDB_CMD_R_REG: return gdb_cmd_rd_reg(data, len); case GDB_CMD_W_REG: return gdb_cmd_wr_reg(data, len); case GDB_CMD_S_BRK: return gdb_cmd_st_brk(data, len); case GDB_CMD_R_BRK: return gdb_cmd_rm_brk(data, len); case GDB_CMD_R_GPR: return gdb_cmd_rd_gpr(); case GDB_CMD_W_GPR: return gdb_cmd_wr_gpr(data, len); case GDB_CMD_CONT: return gdb_cmd_cont(data, len); case GDB_CMD_STEP: return gdb_cmd_step(data, len); case GDB_CMD_THREAD: return gdb_cmd_thread(data); case GDB_CMD_STOP_REASON: return gdb_cmd_stop_reason(); case GDB_CMD_VMM: return gdb_cmd_vmm(data, len); case GDB_CMD_QUERY: return gdb_cmd_query(data, len); case GDB_CMD_KILL: return gdb_cmd_kill(); case GDB_CMD_DETACH: return gdb_cmd_detach(); } debug(GDBSTUB_CMD, "cmd unsupported\n"); gdb_unsupported(); }
static void gdb_cmd_rd_mem(uint8_t *data, size_t len) { offset_t addr; size_t size, need, i; uint8_t store[128]; if(!__gdb_setup_mem_op(data, len, &addr, &size, 0)) return; debug(GDBSTUB_CMD, "read mem: addr 0x%X size %D\n", addr, size); if(size > ((GDB_ANSWER_SZ - GDB_ACKPKT_SZ)/2)) { debug(GDBSTUB_CMD, "gdb buffer too small for cmd_rd_mem\n"); gdb_unsupported(); } while(size) { need = min(size, sizeof(store)); if(!gdb_mem_read(addr, store, need)) { debug(GDBSTUB_CMD, "access failure\n"); gdb_err_mem(); return; } for(i=0 ; i<need ; i++) gdb_add_byte(store[i]); addr += need; size -= need; } gdb_send_packet(); }
void gdb_send_packet() { uint8_t *pkt; size_t sz; if(!gdb_acked()) { debug(GDBSTUB_PKT, "adding ACK byte\n"); pkt = &gdb_answer[0]; sz = gdb_buffer.sz + GDB_ACKPKT_SZ; } else { debug(GDBSTUB_PKT, "already ACKed\n"); pkt = &gdb_answer[1]; gdb_set_ack(0); sz = gdb_buffer.sz + GDB_PKT_SZ; } if(gdb_buffer.sz > (GDB_ANSWER_SZ - GDB_ACKPKT_SZ)) { debug(GDBSTUB_PKT, "can not send pkt with 0x%X bytes\n", gdb_buffer.sz); gdb_unsupported(); return; } gdb_answer[gdb_buffer.sz + 2] = GDB_END_BYTE; gdb_checksum(gdb_buffer.data.u8, gdb_buffer.sz, &gdb_answer[gdb_buffer.sz+3]); gdb_io_write(pkt, sz); debug(GDBSTUB_PKT, "gdb sent (%D): [", sz); #ifdef CONFIG_GDBSTUB_PKT_DBG debug_write(pkt, sz); debug_write((uint8_t*)"]\n", 2); #endif }
static void gdb_cmd_wr_gpr(uint8_t __unused__ *data, size_t __unused__ len) { debug(GDBSTUB_CMD, "need to implement write all general purpose registers"); gdb_unsupported(); }
int __gdb_setup_reg(uint64_t idx, raw64_t **reg, size_t *size, uint8_t sys, uint8_t #ifdef CONFIG_ARCH_AMD __unused__ #endif wr) { loc_t loc; offset_t *cache; if(sys) { debug(GDBSTUB_PKT, "reg_sys_op\n"); *size = sizeof(uint64_t); if(idx >= 22) goto __fail; cache = (offset_t*)info->vm.cpu.insn_cache; goto __sys; } if(cpu_addr_sz() == 64) { *size = sizeof(uint64_t); if(idx < 16) goto __gpr; else if(idx < 24) idx -= 8; else goto __fail; } else { /* XXX: gdb seems to wait for 32 bits regs at least */ *size = sizeof(uint32_t); if(idx < 8) goto __gpr; else if(idx >= 16) goto __fail; } switch(idx) { case 8: loc.u64 = &__rip.raw; __cond_access(wr,__rip); goto __win; case 9: loc.u64 = &__rflags.raw; __cond_access(wr,__rflags); goto __win; case 10: loc.u16 = &__cs.selector.raw;__cond_access(wr,__cs.selector); goto __win16; case 11: loc.u16 = &__ss.selector.raw;__cond_access(wr,__ss.selector); goto __win16; case 12: loc.u16 = &__ds.selector.raw;__cond_access(wr,__ds.selector); goto __win16; case 13: loc.u16 = &__es.selector.raw;__cond_access(wr,__es.selector); goto __win16; case 14: loc.u16 = &__fs.selector.raw;__cond_access(wr,__fs.selector); goto __win16; case 15: loc.u16 = &__gs.selector.raw;__cond_access(wr,__gs.selector); goto __win16; } __sys: switch(idx) { case 0: loc.u64 = &__cr0.raw; __cond_access(wr,__cr0); goto __win; case 1: loc.u64 = &__cr2.raw; __cond_access(wr,__cr2); goto __win; case 2: loc.u64 = &__cr3.raw; __cond_access(wr,__cr3); goto __win; case 3: loc.u64 = &__cr4.raw; __cond_access(wr,__cr4); goto __win; case 4: *cache = get_dr0(); loc.addr = (void*)cache; goto __win; case 5: *cache = get_dr1(); loc.addr = (void*)cache; goto __win; case 6: *cache = get_dr2(); loc.addr = (void*)cache; goto __win; case 7: *cache = get_dr3(); loc.addr = (void*)cache; goto __win; case 8: loc.u64 = &__dr6.raw; __cond_access(wr,__dr6); goto __win; case 9: loc.u64 = &__dr7.raw; __cond_access(wr,__dr7); goto __win; case 10: loc.u64 = &__dbgctl.raw; __cond_access(wr,__dbgctl); goto __win; case 11: loc.u64 = &__efer.raw; /*__cond_access(wr,__efer);*/ goto __win; case 12: loc.u64 = &__cs.base.raw; __cond_access(wr,__cs.base); goto __win; case 13: loc.u64 = &__ss.base.raw; __cond_access(wr,__ss.base); goto __win; case 14: loc.u64 = &__ds.base.raw; __cond_access(wr,__ds.base); goto __win; case 15: loc.u64 = &__es.base.raw; __cond_access(wr,__es.base); goto __win; case 16: loc.u64 = &__fs.base.raw; __cond_access(wr,__fs.base); goto __win; case 17: loc.u64 = &__gs.base.raw; __cond_access(wr,__gs.base); goto __win; case 18: loc.u64 = &__gdtr.base.raw; __cond_access(wr,__gdtr.base); goto __win; case 19: loc.u64 = &__idtr.base.raw; __cond_access(wr,__idtr.base); goto __win; case 20: loc.u64 = &__ldtr.base.raw; __cond_access(wr,__ldtr.base); goto __win; case 21: loc.u64 = &__tr.base.raw; __cond_access(wr,__tr.base); goto __win; } __gpr: loc.u64 = &info->vm.cpu.gpr->raw[GPR64_RAX - idx].raw; goto __win; __win16: *size = sizeof(uint16_t); __win: debug(GDBSTUB_PKT, "reg_op win on %d\n", idx); *reg = (raw64_t*)loc.u64; return 1; __fail: debug(GDBSTUB_PKT, "reg_op failed on %d\n", idx); gdb_unsupported(); return 0; }