diff --git a/sys/alpha/alpha/gdb_machdep.c b/sys/alpha/alpha/gdb_machdep.c new file mode 100644 index 000000000000..cbc38a8a9caf --- /dev/null +++ b/sys/alpha/alpha/gdb_machdep.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +void * +gdb_cpu_getreg(int regnum, size_t *regsz) +{ + + *regsz = gdb_cpu_regsz(regnum); + switch (regnum) { + case 9: return (&kdb_thrctx->pcb_context[0]); + case 10: return (&kdb_thrctx->pcb_context[1]); + case 11: return (&kdb_thrctx->pcb_context[2]); + case 12: return (&kdb_thrctx->pcb_context[3]); + case 13: return (&kdb_thrctx->pcb_context[4]); + case 14: return (&kdb_thrctx->pcb_context[5]); + case 15: return (&kdb_thrctx->pcb_context[6]); + case 30: return (&kdb_thrctx->pcb_hw.apcb_ksp); + case 64: return (&kdb_thrctx->pcb_context[7]); + } + return (NULL); +} + +void +gdb_cpu_setreg(int regnum, register_t val) +{ + switch (regnum) { + } +} + +int +gdb_cpu_signal(int entry, int code) +{ + switch (entry) { + case ALPHA_KENTRY_INT: + case ALPHA_KENTRY_ARITH: + return (SIGILL); /* Can this happen? */ + case ALPHA_KENTRY_MM: + switch (code) { + case ALPHA_MMCSR_INVALTRANS: + return (SIGSEGV); + case ALPHA_MMCSR_ACCESS: + case ALPHA_MMCSR_FOR: + case ALPHA_MMCSR_FOE: + case ALPHA_MMCSR_FOW: + return (SIGBUS); + } + case ALPHA_KENTRY_IF: + switch (code) { + case ALPHA_IF_CODE_BUGCHK: + case ALPHA_IF_CODE_BPT: + return (SIGTRAP); + case ALPHA_IF_CODE_GENTRAP: + case ALPHA_IF_CODE_FEN: + case ALPHA_IF_CODE_OPDEC: + return (SIGILL); + } + case ALPHA_KENTRY_UNA: + return (SIGSEGV); + case ALPHA_KENTRY_SYS: + return (SIGILL); + } + return (SIGILL); +} diff --git a/sys/alpha/include/gdb_machdep.h b/sys/alpha/include/gdb_machdep.h new file mode 100644 index 000000000000..5ca5d69f5890 --- /dev/null +++ b/sys/alpha/include/gdb_machdep.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_GDB_MACHDEP_H_ +#define _MACHINE_GDB_MACHDEP_H_ + +#define GDB_BUFSZ 600 +#define GDB_NREGS 67 +#define GDB_REG_PC 64 + +static __inline size_t +gdb_cpu_regsz(int regnum) +{ + return (sizeof(long)); +} + +static __inline int +gdb_cpu_query(void) +{ + return (0); +} + +void *gdb_cpu_getreg(int, size_t *); +void gdb_cpu_setreg(int, register_t); +int gdb_cpu_signal(int, int); + +#endif /* !_MACHINE_GDB_MACHDEP_H_ */ diff --git a/sys/amd64/amd64/gdb_machdep.c b/sys/amd64/amd64/gdb_machdep.c new file mode 100644 index 000000000000..820824b1731a --- /dev/null +++ b/sys/amd64/amd64/gdb_machdep.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +void * +gdb_cpu_getreg(int regnum, size_t *regsz) +{ + struct trapframe *tf = kdb_frame; + + *regsz = gdb_cpu_regsz(regnum); + switch (regnum) { + case 0: return (&tf->tf_rax); + case 1: return (&tf->tf_rbx); + case 2: return (&tf->tf_rcx); + case 3: return (&tf->tf_rdx); + case 4: return (&tf->tf_rsi); + case 5: return (&tf->tf_rdi); + case 6: return (&tf->tf_rbp); + case 7: return (&tf->tf_rsp); + case 8: return (&tf->tf_r8); + case 9: return (&tf->tf_r9); + case 10: return (&tf->tf_r10); + case 11: return (&tf->tf_r11); + case 12: return (&tf->tf_r12); + case 13: return (&tf->tf_r13); + case 14: return (&tf->tf_r14); + case 15: return (&tf->tf_r15); + case 16: return (&tf->tf_rip); + case 17: return (&tf->tf_rflags); + case 18: return (&tf->tf_cs); + case 19: return (&tf->tf_ss); + } + return (NULL); +} + +void +gdb_cpu_setreg(int regnum, register_t val) +{ + struct trapframe *tf = kdb_frame; + + switch (regnum) { + case GDB_REG_PC: tf->tf_rip = val; break; + } +} diff --git a/sys/amd64/include/gdb_machdep.h b/sys/amd64/include/gdb_machdep.h new file mode 100644 index 000000000000..458f2f6eb9b5 --- /dev/null +++ b/sys/amd64/include/gdb_machdep.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_GDB_MACHDEP_H_ +#define _MACHINE_GDB_MACHDEP_H_ + +#define GDB_BUFSZ 500 +#define GDB_NREGS 56 +#define GDB_REG_PC 18 + +static __inline size_t +gdb_cpu_regsz(int regnum) +{ + return ((regnum > 16 && regnum < 24) ? 4 : 8); +} + +static __inline int +gdb_cpu_signal(int type, int code __unused) +{ + return (type); +} + +static __inline int +gdb_cpu_query(void) +{ + return (0); +} + +void *gdb_cpu_getreg(int, size_t *); +void gdb_cpu_setreg(int, register_t); + +#endif /* !_MACHINE_GDB_MACHDEP_H_ */ diff --git a/sys/gdb/gdb.h b/sys/gdb/gdb.h new file mode 100644 index 000000000000..a7a54294d38e --- /dev/null +++ b/sys/gdb/gdb.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _GDB_GDB_H_ +#define _GDB_GDB_H_ + +typedef int gdb_checkc_f(void); +typedef int gdb_getc_f(void); +typedef void gdb_init_f(void); +typedef int gdb_probe_f(void); +typedef void gdb_putc_f(int); +typedef void gdb_term_f(void); + +struct gdb_dbgport { + const char *gdb_name; + gdb_checkc_f *gdb_checkc; + gdb_getc_f *gdb_getc; + gdb_init_f *gdb_init; + gdb_probe_f *gdb_probe; + gdb_putc_f *gdb_putc; + gdb_term_f *gdb_term; + int gdb_active; +}; + +#define GDB_DBGPORT(name, probe, init, term, checkc, getc, putc) \ + static struct gdb_dbgport name##_gdb_dbgport = { \ + .gdb_name = #name, \ + .gdb_checkc = checkc, \ + .gdb_getc = getc, \ + .gdb_init = init, \ + .gdb_probe = probe, \ + .gdb_putc = putc, \ + .gdb_term = term \ + }; \ + DATA_SET(gdb_dbgport_set, name##_gdb_dbgport) + +#endif /* !_GDB_GDB_H_ */ diff --git a/sys/gdb/gdb_int.h b/sys/gdb/gdb_int.h new file mode 100644 index 000000000000..1a043bdca632 --- /dev/null +++ b/sys/gdb/gdb_int.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _GDB_GDB_INT_H_ +#define _GDB_GDB_INT_H_ + +extern struct gdb_dbgport *gdb_cur; + +extern char *gdb_rxp; +extern size_t gdb_rxsz; +extern char *gdb_txp; + +int gdb_rx_begin(void); +int gdb_rx_equal(const char *); +int gdb_rx_mem(unsigned char *, size_t); +int gdb_rx_varhex(uintmax_t *); + +static __inline int +gdb_rx_char(void) +{ + int c; + + if (gdb_rxsz > 0) { + c = *gdb_rxp++; + gdb_rxsz--; + } else + c = -1; + return (c); +} + +void gdb_tx_begin(char); +int gdb_tx_end(void); +int gdb_tx_mem(const unsigned char *, size_t); +void gdb_tx_reg(int); + +static __inline void +gdb_tx_char(char c) +{ + *gdb_txp++ = c; +} + +static __inline int +gdb_tx_empty(void) +{ + gdb_tx_begin('\0'); + return (gdb_tx_end()); +} + +static __inline void +gdb_tx_hex(uintmax_t n, int sz) +{ + gdb_txp += sprintf(gdb_txp, "%0*jx", sz, n); +} + +static __inline int +gdb_tx_err(int err) +{ + gdb_tx_begin('E'); + gdb_tx_hex(err, 2); + return (gdb_tx_end()); +} + +static __inline int +gdb_tx_ok(void) +{ + gdb_tx_begin('O'); + gdb_tx_char('K'); + return (gdb_tx_end()); +} + +static __inline void +gdb_tx_str(const char *s) +{ + while (*s) + *gdb_txp++ = *s++; +} + +static __inline void +gdb_tx_varhex(uintmax_t n) +{ + gdb_txp += sprintf(gdb_txp, "%jx", n); +} + +#endif /* !_GDB_GDB_INT_H_ */ diff --git a/sys/gdb/gdb_main.c b/sys/gdb/gdb_main.c new file mode 100644 index 000000000000..025c5b89e105 --- /dev/null +++ b/sys/gdb/gdb_main.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +static dbbe_init_f gdb_init; +static dbbe_trap_f gdb_trap; + +KDB_BACKEND(gdb, gdb_init, NULL, gdb_trap); + +GDB_DBGPORT(null, NULL, NULL, NULL, NULL, NULL, NULL); +SET_DECLARE(gdb_dbgport_set, struct gdb_dbgport); + +struct gdb_dbgport *gdb_cur = NULL; + +static int +gdb_init(void) +{ + struct gdb_dbgport *dp, **iter; + int cur_pri, pri; + + gdb_cur = NULL; + cur_pri = -1; + SET_FOREACH(iter, gdb_dbgport_set) { + dp = *iter; + pri = (dp->gdb_probe != NULL) ? dp->gdb_probe() : -1; + dp->gdb_active = (pri >= 0) ? 0 : -1; + if (pri > cur_pri) { + cur_pri = pri; + gdb_cur = dp; + } + } + if (gdb_cur != NULL) { + printf("GDB: debug ports:"); + SET_FOREACH(iter, gdb_dbgport_set) { + dp = *iter; + if (dp->gdb_active == 0) + printf(" %s", dp->gdb_name); + } + printf("\n"); + } else + printf("GDB: no debug ports present\n"); + if (gdb_cur != NULL) { + gdb_cur->gdb_init(); + printf("GDB: current port: %s\n", gdb_cur->gdb_name); + } + if (gdb_cur != NULL) + cur_pri = (boothowto & RB_GDB) ? 2 : 0; + else + cur_pri = -1; + return (cur_pri); +} + +static int +gdb_trap(int type, int code) +{ + struct thread *thr_iter; + + /* + * Send a T packet. We currently do not support watchpoints (the + * awatch, rwatch or watch elements). + */ + gdb_tx_begin('T'); + gdb_tx_hex(gdb_cpu_signal(type, code), 2); + gdb_tx_varhex(GDB_REG_PC); + gdb_tx_char(':'); + gdb_tx_reg(GDB_REG_PC); + gdb_tx_char(';'); + gdb_tx_str("thread:"); + gdb_tx_varhex((long)kdb_thread->td_tid); + gdb_tx_char(';'); + gdb_tx_end(); /* XXX check error condition. */ + + thr_iter = NULL; + while (gdb_rx_begin() == 0) { + printf("GDB: got '%s'\n", gdb_rxp); + switch (gdb_rx_char()) { + case '?': /* Last signal. */ + gdb_tx_begin('S'); + gdb_tx_hex(gdb_cpu_signal(type, code), 2); + gdb_tx_end(); + break; + case 'c': { /* Continue. */ + uintmax_t addr; + if (!gdb_rx_varhex(&addr)) + gdb_cpu_setreg(GDB_REG_PC, addr); + kdb_cpu_clear_singlestep(); + return (1); + } + case 'C': { /* Continue with signal. */ + uintmax_t addr, sig; + if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' && + !gdb_rx_varhex(&addr)) + gdb_cpu_setreg(GDB_REG_PC, addr); + kdb_cpu_clear_singlestep(); + return (1); + } + case 'g': { /* Read registers. */ + size_t r; + gdb_tx_begin(0); + for (r = 0; r < GDB_NREGS; r++) + gdb_tx_reg(r); + gdb_tx_end(); + break; + } + case 'G': /* Write registers. */ + gdb_tx_err(0); + break; + case 'H': { /* Set thread. */ + intmax_t tid; + struct thread *thr; + gdb_rx_char(); + gdb_rx_varhex(&tid); + if (tid > 0) { + thr = kdb_thr_lookup(tid); + if (thr == NULL) { + gdb_tx_err(ENOENT); + break; + } + kdb_thr_select(thr); + } + gdb_tx_ok(); + break; + } + case 'k': /* Kill request. */ + kdb_cpu_clear_singlestep(); + return (1); + case 'm': { /* Read memory. */ + uintmax_t addr, size; + if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' || + gdb_rx_varhex(&size)) { + gdb_tx_err(EINVAL); + break; + } + gdb_tx_begin(0); + if (gdb_tx_mem((char *)(uintptr_t)addr, size)) + gdb_tx_end(); + else + gdb_tx_err(EIO); + break; + } + case 'M': { /* Write memory. */ + uintmax_t addr, size; + if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' || + gdb_rx_varhex(&size) || gdb_rx_char() != ':') { + gdb_tx_err(EINVAL); + break; + } + if (gdb_rx_mem((char *)(uintptr_t)addr, size) == 0) + gdb_tx_err(EIO); + else + gdb_tx_ok(); + break; + } + case 'P': { /* Write register. */ + uintmax_t reg, val; + if (gdb_rx_varhex(®) || gdb_rx_char() != '=' || + gdb_rx_varhex(&val)) { + gdb_tx_err(EINVAL); + break; + } + gdb_cpu_setreg(reg, val); + gdb_tx_ok(); + break; + } + case 'q': /* General query. */ + if (gdb_rx_equal("fThreadInfo")) { + thr_iter = kdb_thr_first(); + gdb_tx_begin('m'); + gdb_tx_hex((long)thr_iter->td_tid, 8); + gdb_tx_end(); + } else if (gdb_rx_equal("sThreadInfo")) { + if (thr_iter == NULL) { + gdb_tx_err(ENXIO); + break; + } + thr_iter = kdb_thr_next(thr_iter); + if (thr_iter != NULL) { + gdb_tx_begin('m'); + gdb_tx_hex((long)thr_iter->td_tid, 8); + gdb_tx_end(); + } else { + gdb_tx_begin('l'); + gdb_tx_end(); + } + } else if (!gdb_cpu_query()) + gdb_tx_empty(); + break; + case 's': { /* Step. */ + uintmax_t addr; + if (!gdb_rx_varhex(&addr)) + gdb_cpu_setreg(GDB_REG_PC, addr); + kdb_cpu_set_singlestep(); + return (1); + } + case 'S': { /* Step with signal. */ + uintmax_t addr, sig; + if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' && + !gdb_rx_varhex(&addr)) + gdb_cpu_setreg(GDB_REG_PC, addr); + kdb_cpu_set_singlestep(); + return (1); + } + case 'T': { /* Thread alive. */ + intmax_t tid; + gdb_rx_varhex(&tid); + if (kdb_thr_lookup(tid) != NULL) + gdb_tx_ok(); + else + gdb_tx_err(ENOENT); + break; + } + case -1: + /* Empty command. Treat as unknown command. */ + /* FALLTHROUGH */ + default: + /* Unknown command. Send empty response. */ + gdb_tx_empty(); + break; + } + } + return (0); +} diff --git a/sys/gdb/gdb_packet.c b/sys/gdb/gdb_packet.c new file mode 100644 index 000000000000..703d2e0b52db --- /dev/null +++ b/sys/gdb/gdb_packet.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +#include +#include + +static char gdb_rxbuf[GDB_BUFSZ]; +char *gdb_rxp = NULL; +size_t gdb_rxsz = 0; +static char gdb_txbuf[GDB_BUFSZ]; +char *gdb_txp = NULL; /* Used in inline functions. */ + +#define C2N(c) (((c) < 'A') ? (c) - '0' : \ + 10 + (((c) < 'a') ? (c) - 'A' : (c) - 'a')) +#define N2C(n) (((n) < 10) ? (n) + '0' : (n) + 'a' - 10) + +/* + * Functions to receive and extract from a packet. + */ + +int +gdb_rx_begin(void) +{ + int c, cksum; + + gdb_rxp = NULL; + do { + /* + * Wait for the start character, ignore all others. + * XXX needs a timeout. + */ + while ((c = gdb_cur->gdb_getc()) != '$') + ; + + /* Read until a # or end of buffer is found. */ + cksum = 0; + gdb_rxsz = 0; + while (gdb_rxsz < sizeof(gdb_rxbuf) - 1) { + c = gdb_cur->gdb_getc(); + if (c == '#') + break; + gdb_rxbuf[gdb_rxsz++] = c; + cksum += c; + } + gdb_rxbuf[gdb_rxsz] = 0; + cksum &= 0xff; + + /* Bail out on a buffer overflow. */ + if (c != '#') { + gdb_cur->gdb_putc('-'); + return (ENOSPC); + } + + c = gdb_cur->gdb_getc(); + cksum -= (C2N(c) << 4) & 0xf0; + c = gdb_cur->gdb_getc(); + cksum -= C2N(c) & 0x0f; + gdb_cur->gdb_putc((cksum == 0) ? '+' : '-'); + if (cksum != 0) + printf("GDB: packet `%s' has invalid checksum\n", + gdb_rxbuf); + } while (cksum != 0); + + gdb_rxp = gdb_rxbuf; + return (0); +} + +int +gdb_rx_equal(const char *str) +{ + int len; + + len = strlen(str); + if (len > gdb_rxsz || strncmp(str, gdb_rxp, len) != 0) + return (0); + gdb_rxp += len; + gdb_rxsz -= len; + return (1); +} + +int +gdb_rx_mem(unsigned char *addr, size_t size) +{ + void *prev; + jmp_buf jb; + int ret; + unsigned char c; + + if (size * 2 != gdb_rxsz) + return (-1); + + prev = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + while (size-- > 0) { + c = (C2N(gdb_rxp[0]) << 4) & 0xf0; + c |= C2N(gdb_rxp[1]) & 0x0f; + *addr++ = c; + gdb_rxsz -= 2; + gdb_rxp += 2; + } + } + (void)kdb_jmpbuf(prev); + return ((ret == 0) ? 1 : 0); +} + +int +gdb_rx_varhex(uintmax_t *vp) +{ + uintmax_t v; + int c, neg; + + c = gdb_rx_char(); + neg = (c == '-') ? 1 : 0; + if (neg == 1) + c = gdb_rx_char(); + if (!isxdigit(c)) { + gdb_rxp -= ((c == -1) ? 0 : 1) + neg; + gdb_rxsz += ((c == -1) ? 0 : 1) + neg; + return (-1); + } + v = 0; + do { + v <<= 4; + v += C2N(c); + c = gdb_rx_char(); + } while (isxdigit(c)); + if (c != -1) { + gdb_rxp--; + gdb_rxsz++; + } + *vp = (neg) ? -v : v; + return (0); +} + +/* + * Function to build and send a package. + */ + +void +gdb_tx_begin(char tp) +{ + + gdb_txp = gdb_txbuf; + if (tp != '\0') + gdb_tx_char(tp); +} + +int +gdb_tx_end(void) +{ + const char *p; + int runlen; + unsigned char c, cksum; + + do { + gdb_cur->gdb_putc('$'); + + cksum = 0; + p = gdb_txbuf; + while (p < gdb_txp) { + /* Send a character and start run-length encoding. */ + c = *p++; + gdb_cur->gdb_putc(c); + cksum += c; + runlen = 0; + /* Determine run-length and update checksum. */ + while (p < gdb_txp && *p == c) { + runlen++; + p++; + } + /* Emit the run-length encoded string. */ + while (runlen >= 97) { + gdb_cur->gdb_putc('*'); + cksum += '*'; + gdb_cur->gdb_putc(97+29); + cksum += 97+29; + runlen -= 97; + if (runlen > 0) { + gdb_cur->gdb_putc(c); + cksum += c; + runlen--; + } + } + if (runlen == 1) { + gdb_cur->gdb_putc(c); + cksum += c; + runlen--; + } + if (runlen == 0) + continue; + /* Don't emit '$', '#', '+' or '-'. */ + if (runlen == 7) { + gdb_cur->gdb_putc(c); + cksum += c; + runlen--; + } + if (runlen == 6 || runlen == 14 || runlen == 16) { + gdb_cur->gdb_putc(c); + cksum += c; + runlen--; + } + gdb_cur->gdb_putc('*'); + cksum += '*'; + gdb_cur->gdb_putc(runlen+29); + cksum += runlen+29; + } + + gdb_cur->gdb_putc('#'); + c = cksum >> 4; + gdb_cur->gdb_putc(N2C(c)); + c = cksum & 0x0f; + gdb_cur->gdb_putc(N2C(c)); + + c = gdb_cur->gdb_getc(); + } while (c != '+'); + + return (0); +} + +int +gdb_tx_mem(const unsigned char *addr, size_t size) +{ + void *prev; + jmp_buf jb; + int ret; + + prev = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + while (size-- > 0) { + *gdb_txp++ = N2C(*addr >> 4); + *gdb_txp++ = N2C(*addr & 0x0f); + addr++; + } + } + (void)kdb_jmpbuf(prev); + return ((ret == 0) ? 1 : 0); +} + +void +gdb_tx_reg(int regnum) +{ + unsigned char *regp; + size_t regsz; + + regp = gdb_cpu_getreg(regnum, ®sz); + if (regp == NULL) { + /* Register unavailable. */ + while (regsz--) { + gdb_tx_char('x'); + gdb_tx_char('x'); + } + } else + gdb_tx_mem(regp, regsz); +} diff --git a/sys/i386/i386/gdb_machdep.c b/sys/i386/i386/gdb_machdep.c new file mode 100644 index 000000000000..81df8d10ffdf --- /dev/null +++ b/sys/i386/i386/gdb_machdep.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +void * +gdb_cpu_getreg(int regnum, size_t *regsz) +{ + + *regsz = gdb_cpu_regsz(regnum); + switch (regnum) { + case 3: return (&kdb_thrctx->pcb_ebx); + case 4: return (&kdb_thrctx->pcb_esp); + case 5: return (&kdb_thrctx->pcb_ebp); + case 6: return (&kdb_thrctx->pcb_esi); + case 7: return (&kdb_thrctx->pcb_edi); + case 8: return (&kdb_thrctx->pcb_eip); + } + return (NULL); +} + +void +gdb_cpu_setreg(int regnum, register_t val) +{ + + switch (regnum) { + case GDB_REG_PC: kdb_thrctx->pcb_eip = val; break; + } +} + +int +gdb_cpu_signal(int type, int code) +{ + + switch (type & ~T_USER) { + case 0: return (SIGFPE); /* Divide by zero. */ + case 1: return (SIGTRAP); /* Debug exception. */ + case 3: return (SIGTRAP); /* Breakpoint. */ + case 4: return (SIGURG); /* into instr. (overflow). */ + case 5: return (SIGURG); /* bound instruction. */ + case 6: return (SIGILL); /* Invalid opcode. */ + case 7: return (SIGFPE); /* Coprocessor not present. */ + case 8: return (SIGEMT); /* Double fault. */ + case 9: return (SIGSEGV); /* Coprocessor segment overrun. */ + case 10: return (SIGTRAP); /* Invalid TSS (also single-step). */ + case 11: return (SIGSEGV); /* Segment not present. */ + case 12: return (SIGSEGV); /* Stack exception. */ + case 13: return (SIGSEGV); /* General protection. */ + case 14: return (SIGSEGV); /* Page fault. */ + case 16: return (SIGEMT); /* Coprocessor error. */ + } + return (SIGEMT); +} diff --git a/sys/i386/include/gdb_machdep.h b/sys/i386/include/gdb_machdep.h new file mode 100644 index 000000000000..c67412a292ff --- /dev/null +++ b/sys/i386/include/gdb_machdep.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_GDB_MACHDEP_H_ +#define _MACHINE_GDB_MACHDEP_H_ + +#define GDB_BUFSZ 400 +#define GDB_NREGS 14 +#define GDB_REG_PC 8 + +static __inline size_t +gdb_cpu_regsz(int regnum __unused) +{ + return (sizeof(int)); +} + +static __inline int +gdb_cpu_query(void) +{ + return (0); +} + +void *gdb_cpu_getreg(int, size_t *); +void gdb_cpu_setreg(int, register_t); +int gdb_cpu_signal(int, int); + +#endif /* !_MACHINE_GDB_MACHDEP_H_ */ diff --git a/sys/ia64/ia64/gdb_machdep.c b/sys/ia64/ia64/gdb_machdep.c new file mode 100644 index 000000000000..8cf6085c2e20 --- /dev/null +++ b/sys/ia64/ia64/gdb_machdep.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +void * +gdb_cpu_getreg(int regnum, size_t *regsz) +{ + static uint64_t synth; + uint64_t cfm; + + *regsz = gdb_cpu_regsz(regnum); + switch (regnum) { + /* Registers 0-127: general registers. */ + case 1: return (&kdb_thrctx->pcb_special.gp); + case 4: return (&kdb_thrctx->pcb_preserved.gr4); + case 5: return (&kdb_thrctx->pcb_preserved.gr5); + case 6: return (&kdb_thrctx->pcb_preserved.gr6); + case 7: return (&kdb_thrctx->pcb_preserved.gr7); + case 12: return (&kdb_thrctx->pcb_special.sp); + case 13: return (&kdb_thrctx->pcb_special.tp); + /* Registers 128-255: floating-point registers. */ + case 130: return (&kdb_thrctx->pcb_preserved_fp.fr2); + case 131: return (&kdb_thrctx->pcb_preserved_fp.fr3); + case 132: return (&kdb_thrctx->pcb_preserved_fp.fr4); + case 133: return (&kdb_thrctx->pcb_preserved_fp.fr5); + case 144: return (&kdb_thrctx->pcb_preserved_fp.fr16); + case 145: return (&kdb_thrctx->pcb_preserved_fp.fr17); + case 146: return (&kdb_thrctx->pcb_preserved_fp.fr18); + case 147: return (&kdb_thrctx->pcb_preserved_fp.fr19); + case 148: return (&kdb_thrctx->pcb_preserved_fp.fr20); + case 149: return (&kdb_thrctx->pcb_preserved_fp.fr21); + case 150: return (&kdb_thrctx->pcb_preserved_fp.fr22); + case 151: return (&kdb_thrctx->pcb_preserved_fp.fr23); + case 152: return (&kdb_thrctx->pcb_preserved_fp.fr24); + case 153: return (&kdb_thrctx->pcb_preserved_fp.fr25); + case 154: return (&kdb_thrctx->pcb_preserved_fp.fr26); + case 155: return (&kdb_thrctx->pcb_preserved_fp.fr27); + case 156: return (&kdb_thrctx->pcb_preserved_fp.fr28); + case 157: return (&kdb_thrctx->pcb_preserved_fp.fr29); + case 158: return (&kdb_thrctx->pcb_preserved_fp.fr30); + case 159: return (&kdb_thrctx->pcb_preserved_fp.fr31); + /* Registers 320-327: branch registers. */ + case 320: + if (kdb_thrctx->pcb_special.__spare == ~0UL) + return (&kdb_thrctx->pcb_special.rp); + break; + case 321: return (&kdb_thrctx->pcb_preserved.br1); + case 322: return (&kdb_thrctx->pcb_preserved.br2); + case 323: return (&kdb_thrctx->pcb_preserved.br3); + case 324: return (&kdb_thrctx->pcb_preserved.br4); + case 325: return (&kdb_thrctx->pcb_preserved.br5); + /* Registers 328-333: misc. other registers. */ + case 330: return (&kdb_thrctx->pcb_special.pr); + case 331: + if (kdb_thrctx->pcb_special.__spare == ~0UL) { + synth = kdb_thrctx->pcb_special.iip; + synth += (kdb_thrctx->pcb_special.psr >> 41) & 3; + return (&synth); + } + return (&kdb_thrctx->pcb_special.rp); + case 333: + if (kdb_thrctx->pcb_special.__spare == ~0UL) + return (&kdb_thrctx->pcb_special.cfm); + return (&kdb_thrctx->pcb_special.pfs); + /* Registers 334-461: application registers. */ + case 350: return (&kdb_thrctx->pcb_special.rsc); + case 351: /* bsp */ + case 352: /* bspstore. */ + synth = kdb_thrctx->pcb_special.bspstore; + if (kdb_thrctx->pcb_special.__spare == ~0UL) { + synth += kdb_thrctx->pcb_special.ndirty; + } else { + cfm = kdb_thrctx->pcb_special.pfs; + synth = ia64_bsp_adjust(synth, + IA64_CFM_SOF(cfm) - IA64_CFM_SOL(cfm)); + } + return (&synth); + case 353: return (&kdb_thrctx->pcb_special.rnat); + case 370: return (&kdb_thrctx->pcb_special.unat); + case 374: return (&kdb_thrctx->pcb_special.fpsr); + case 398: + if (kdb_thrctx->pcb_special.__spare == ~0UL) + return (&kdb_thrctx->pcb_special.pfs); + break; + case 399: return (&kdb_thrctx->pcb_preserved.lc); + } + return (NULL); +} + +void +gdb_cpu_setreg(int regnum, register_t val) +{ + + switch (regnum) { + case GDB_REG_PC: break; + } +} + +int +gdb_cpu_query(void) +{ +#if 0 + uint64_t bspstore, *kstack; +#endif + uintmax_t slot; + + if (!gdb_rx_equal("Part:dirty:read::")) + return (0); + + if (gdb_rx_varhex(&slot) < 0) { + gdb_tx_err(EINVAL); + return (-1); + } + + gdb_tx_err(EINVAL); + return (-1); + +#if 0 + /* slot is unsigned. No need to test for negative values. */ + if (slot >= (kdb_frame->tf_special.ndirty >> 3)) { + return (-1); + } + + /* + * If the trapframe describes a kernel entry, bspstore holds + * the address of the user backing store. Calculate the right + * kernel stack address. See also ptrace_machdep(). + */ + bspstore = kdb_frame->tf_special.bspstore; + kstack = (bspstore >= IA64_RR_BASE(5)) ? (uint64_t*)bspstore : + (uint64_t*)(kdb_thread->td_kstack + (bspstore & 0x1ffUL)); + gdb_tx_begin('\0'); + gdb_tx_mem((void*)(kstack + slot), 8); + gdb_tx_end(); + return (1); +#endif +} diff --git a/sys/ia64/include/gdb_machdep.h b/sys/ia64/include/gdb_machdep.h new file mode 100644 index 000000000000..70ff8408865e --- /dev/null +++ b/sys/ia64/include/gdb_machdep.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_GDB_MACHDEP_H_ +#define _MACHINE_GDB_MACHDEP_H_ + +#define GDB_NREGS 462 +#define GDB_REG_PC 331 + +#define GDB_BUFSZ (GDB_NREGS*16+128*16) + +static __inline size_t +gdb_cpu_regsz(int regnum) +{ + return ((regnum >= 128 && regnum < 256) ? 16 : 8); +} + +static __inline int +gdb_cpu_signal(int vector, int dummy __unused) +{ + /* Add 100 so GDB won't translate the vector into signal names. */ + return (vector + 100); +} + +void *gdb_cpu_getreg(int, size_t *); +void gdb_cpu_setreg(int, register_t); +int gdb_cpu_query(void); + +#endif /* !_MACHINE_GDB_MACHDEP_H_ */ diff --git a/sys/sparc64/include/gdb_machdep.h b/sys/sparc64/include/gdb_machdep.h new file mode 100644 index 000000000000..b30ad04b634a --- /dev/null +++ b/sys/sparc64/include/gdb_machdep.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_GDB_MACHDEP_H_ +#define _MACHINE_GDB_MACHDEP_H_ + +#define GDB_BUFSZ 600 +#define GDB_NREGS 86 +#define GDB_REG_PC 80 + +static __inline size_t +gdb_cpu_regsz(int regnum) +{ + return ((regnum >= 32 && regnum < 64) ? sizeof(float) : sizeof(long)); +} + +static __inline int +gdb_cpu_query(void) +{ + return (0); +} + +static __inline int +gdb_cpu_signal(int vector, int _) +{ + return (vector); +} + +void *gdb_cpu_getreg(int, size_t *); +void gdb_cpu_setreg(int, register_t); + +#endif /* !_MACHINE_GDB_MACHDEP_H_ */ diff --git a/sys/sparc64/sparc64/gdb_machdep.c b/sys/sparc64/sparc64/gdb_machdep.c new file mode 100644 index 000000000000..219ac13ffdb2 --- /dev/null +++ b/sys/sparc64/sparc64/gdb_machdep.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +void * +gdb_cpu_getreg(int regnum, size_t *regsz) +{ + static uint64_t synth; + + *regsz = gdb_cpu_regsz(regnum); + switch (regnum) { + /* 0-7: g0-g7 */ + /* 8-15: o0-o7 */ + case 14: + synth = kdb_thrctx->pcb_sp - CCFSZ; + return (&synth); + /* 16-23: l0-l7 */ + /* 24-31: i0-i7 */ + case 30: return (&kdb_thrctx->pcb_sp); + /* 32-63: f0-f31 */ + /* 64-79: f32-f62 (16 double FP) */ + case 80: return (&kdb_thrctx->pcb_pc); + } + return (NULL); +} + +void +gdb_cpu_setreg(int regnum, register_t val) +{ + switch (regnum) { + } +}