summaryrefslogtreecommitdiffstats
path: root/sys/gdb
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2004-12-01 06:40:35 +0000
committermarcel <marcel@FreeBSD.org>2004-12-01 06:40:35 +0000
commitc106bd9120d0e0d75dc9a28f87686d6b6d18ae8c (patch)
tree62c9a95681df36f1242efe2fd847059217302039 /sys/gdb
parentff42094303dbb28e905ab1bee9975ca994fea668 (diff)
downloadFreeBSD-src-c106bd9120d0e0d75dc9a28f87686d6b6d18ae8c.zip
FreeBSD-src-c106bd9120d0e0d75dc9a28f87686d6b6d18ae8c.tar.gz
Change gdb_cpu_setreg() to not take the value to which to set the
specified register, but a pointer to the in-memory representation of that value. The reason for this is twofold: 1. Not all registers can be represented by a register_t. In particular FP registers fall in that category. Passing the new register value by reference instead of by value makes this point moot. 2. When we receive a G or P packet, both are for writing a register, the packet will have the register value in target-byte order and in the memory representation (modulo the fact that bytes are sent as 2 printable hexadecimal numbers of course). We only need to decode the packet to have a pointer to the register value. This change fixes the bug of extracting the register value of the P packet as a hexadecimal number instead of as a bit array. The quick (and dirty) fix to bswap the register value in gdb_cpu_setreg() as it has been added on i386 and amd64 can therefore be removed and has in fact been that. Tested on: alpha, amd64, i386, ia64, sparc64
Diffstat (limited to 'sys/gdb')
-rw-r--r--sys/gdb/gdb_main.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/sys/gdb/gdb_main.c b/sys/gdb/gdb_main.c
index 0eed036..bed693a 100644
--- a/sys/gdb/gdb_main.c
+++ b/sys/gdb/gdb_main.c
@@ -120,16 +120,22 @@ gdb_trap(int type, int code)
break;
case 'c': { /* Continue. */
uintmax_t addr;
- if (!gdb_rx_varhex(&addr))
- gdb_cpu_setreg(GDB_REG_PC, addr);
+ register_t pc;
+ if (!gdb_rx_varhex(&addr)) {
+ pc = addr;
+ gdb_cpu_setreg(GDB_REG_PC, &pc);
+ }
kdb_cpu_clear_singlestep();
return (1);
}
case 'C': { /* Continue with signal. */
uintmax_t addr, sig;
+ register_t pc;
if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' &&
- !gdb_rx_varhex(&addr))
- gdb_cpu_setreg(GDB_REG_PC, addr);
+ !gdb_rx_varhex(&addr)) {
+ pc = addr;
+ gdb_cpu_setreg(GDB_REG_PC, &pc);
+ }
kdb_cpu_clear_singlestep();
return (1);
}
@@ -191,9 +197,11 @@ gdb_trap(int type, int code)
break;
}
case 'P': { /* Write register. */
- uintmax_t reg, val;
+ char *val;
+ uintmax_t reg;
+ val = gdb_rxp;
if (gdb_rx_varhex(&reg) || gdb_rx_char() != '=' ||
- gdb_rx_varhex(&val)) {
+ !gdb_rx_mem(val, gdb_cpu_regsz(reg))) {
gdb_tx_err(EINVAL);
break;
}
@@ -226,16 +234,22 @@ gdb_trap(int type, int code)
break;
case 's': { /* Step. */
uintmax_t addr;
- if (!gdb_rx_varhex(&addr))
- gdb_cpu_setreg(GDB_REG_PC, addr);
+ register_t pc;
+ if (!gdb_rx_varhex(&addr)) {
+ pc = addr;
+ gdb_cpu_setreg(GDB_REG_PC, &pc);
+ }
kdb_cpu_set_singlestep();
return (1);
}
case 'S': { /* Step with signal. */
uintmax_t addr, sig;
+ register_t pc;
if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' &&
- !gdb_rx_varhex(&addr))
- gdb_cpu_setreg(GDB_REG_PC, addr);
+ !gdb_rx_varhex(&addr)) {
+ pc = addr;
+ gdb_cpu_setreg(GDB_REG_PC, &pc);
+ }
kdb_cpu_set_singlestep();
return (1);
}
OpenPOWER on IntegriCloud