summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2004-07-10 17:47:22 +0000
committermarcel <marcel@FreeBSD.org>2004-07-10 17:47:22 +0000
commit6e0dcca8a9676834e327681abedbeca81a0907f2 (patch)
tree787a3c6916bdd82a49a07a8288119d62dd89055b /sys
parent1ff719505763720315217ca8b7eb6d6f03c49222 (diff)
downloadFreeBSD-src-6e0dcca8a9676834e327681abedbeca81a0907f2.zip
FreeBSD-src-6e0dcca8a9676834e327681abedbeca81a0907f2.tar.gz
Introduce the GDB debugger backend for the new KDB framework. The
backend improves over the old GDB support in the following ways: o Unified implementation with minimal MD code. o A simple interface for devices to register themselves as debug ports, ala consoles. o Compression by using run-length encoding. o Implements GDB threading support.
Diffstat (limited to 'sys')
-rw-r--r--sys/alpha/alpha/gdb_machdep.c101
-rw-r--r--sys/alpha/include/gdb_machdep.h52
-rw-r--r--sys/amd64/amd64/gdb_machdep.c84
-rw-r--r--sys/amd64/include/gdb_machdep.h57
-rw-r--r--sys/gdb/gdb.h62
-rw-r--r--sys/gdb/gdb_int.h109
-rw-r--r--sys/gdb/gdb_main.c261
-rw-r--r--sys/gdb/gdb_packet.c289
-rw-r--r--sys/i386/i386/gdb_machdep.c90
-rw-r--r--sys/i386/include/gdb_machdep.h52
-rw-r--r--sys/ia64/ia64/gdb_machdep.c177
-rw-r--r--sys/ia64/include/gdb_machdep.h54
-rw-r--r--sys/sparc64/include/gdb_machdep.h57
-rw-r--r--sys/sparc64/sparc64/gdb_machdep.c70
14 files changed, 1515 insertions, 0 deletions
diff --git a/sys/alpha/alpha/gdb_machdep.c b/sys/alpha/alpha/gdb_machdep.c
new file mode 100644
index 0000000..cbc38a8
--- /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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/signal.h>
+
+#include <machine/gdb_machdep.h>
+#include <machine/pcb.h>
+#include <machine/reg.h>
+
+#include <gdb/gdb.h>
+
+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 0000000..5ca5d69
--- /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 0000000..820824b
--- /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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/signal.h>
+
+#include <machine/frame.h>
+#include <machine/gdb_machdep.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/trap.h>
+
+#include <gdb/gdb.h>
+
+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 0000000..458f2f6
--- /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 0000000..a7a5429
--- /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 0000000..1a043bd
--- /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 0000000..025c5b8
--- /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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+
+#include <machine/gdb_machdep.h>
+#include <machine/kdb.h>
+
+#include <gdb/gdb.h>
+#include <gdb/gdb_int.h>
+
+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(&reg) || 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 0000000..703d2e0
--- /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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ctype.h>
+#include <sys/kdb.h>
+
+#include <machine/gdb_machdep.h>
+
+#include <gdb/gdb.h>
+#include <gdb/gdb_int.h>
+
+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, &regsz);
+ 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 0000000..81df8d1
--- /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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/signal.h>
+
+#include <machine/gdb_machdep.h>
+#include <machine/pcb.h>
+#include <machine/trap.h>
+
+#include <gdb/gdb.h>
+
+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 0000000..c67412a
--- /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 0000000..8cf6085
--- /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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/signal.h>
+
+#include <machine/gdb_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/reg.h>
+
+#include <gdb/gdb.h>
+#include <gdb/gdb_int.h>
+
+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 0000000..70ff840
--- /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 0000000..b30ad04
--- /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 0000000..219ac13
--- /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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/signal.h>
+
+#include <machine/asm.h>
+#include <machine/gdb_machdep.h>
+#include <machine/pcb.h>
+#include <machine/reg.h>
+
+#include <gdb/gdb.h>
+
+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) {
+ }
+}
OpenPOWER on IntegriCloud