From owner-p4-projects@FreeBSD.ORG Sun Mar 14 00:15:00 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id B9F8116A4D0; Sun, 14 Mar 2004 00:15:00 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8D62D16A4CE for ; Sun, 14 Mar 2004 00:15:00 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8163943D3F for ; Sun, 14 Mar 2004 00:15:00 -0800 (PST) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.10/8.12.10) with ESMTP id i2E8F0Ge030763 for ; Sun, 14 Mar 2004 00:15:00 -0800 (PST) (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.10/8.12.10/Submit) id i2E8F079030752 for perforce@freebsd.org; Sun, 14 Mar 2004 00:15:00 -0800 (PST) (envelope-from marcel@freebsd.org) Date: Sun, 14 Mar 2004 00:15:00 -0800 (PST) Message-Id: <200403140815.i2E8F079030752@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar To: Perforce Change Reviews Subject: PERFORCE change 48960 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 14 Mar 2004 08:15:01 -0000 http://perforce.freebsd.org/chv.cgi?CH=48960 Change 48960 by marcel@marcel_nfs on 2004/03/14 00:14:43 The beginnings of a new gdb backend. The meat is machine independent and shared by all platforms. The machine dependent bits mostly relate to registers and will have the necessary callbacks. The backend will support threads if all goes well. That way one can easily list all kernel threads in gdb and print backtraces and dump registers for them. While on the subject, implement support for a debug port on sparc64. Since there's no facility for specifying a debug port in the OF, we need to use environment variables. On sparc64, one needs to set debug_port to some OF device name or predefined alias (e.g set debug_port=ttyb). Affected files ... .. //depot/projects/gdb/sys/conf/files#7 edit .. //depot/projects/gdb/sys/conf/files.i386#5 edit .. //depot/projects/gdb/sys/dev/uart/uart_cpu_sparc64.c#2 edit .. //depot/projects/gdb/sys/gdb/gdb.h#4 edit .. //depot/projects/gdb/sys/gdb/gdb_int.h#1 add .. //depot/projects/gdb/sys/gdb/gdb_main.c#3 edit .. //depot/projects/gdb/sys/gdb/gdb_packet.c#1 add .. //depot/projects/gdb/sys/i386/i386/gdb_machdep.c#1 add .. //depot/projects/gdb/sys/i386/i386/i386-gdbstub.c#2 delete .. //depot/projects/gdb/sys/i386/include/gdb_machdep.h#1 add Differences ... ==== //depot/projects/gdb/sys/conf/files#7 (text+ko) ==== @@ -956,7 +956,8 @@ fs/unionfs/union_subr.c optional unionfs fs/unionfs/union_vfsops.c optional unionfs fs/unionfs/union_vnops.c optional unionfs -gdb/gdb_main.c optional gdb +gdb/gdb_main.c optional gdb +gdb/gdb_packet.c optional gdb geom/bde/g_bde.c optional geom_bde geom/bde/g_bde_crypt.c optional geom_bde geom/bde/g_bde_lock.c optional geom_bde ==== //depot/projects/gdb/sys/conf/files.i386#5 (text+ko) ==== @@ -204,8 +204,8 @@ i386/i386/elan-mmcr.c optional cpu_soekris i386/i386/elf_machdep.c standard i386/i386/exception.s standard +i386/i386/gdb_machdep.c optional gdb i386/i386/geode.c optional cpu_geode -i386/i386/i386-gdbstub.c optional gdb i386/i386/i686_mem.c standard i386/i386/identcpu.c standard i386/i386/in_cksum.c optional inet ==== //depot/projects/gdb/sys/dev/uart/uart_cpu_sparc64.c#2 (text+ko) ==== @@ -39,8 +39,6 @@ #include #include -static phandle_t uart_cpu_getdev_keyboard(phandle_t root); - static struct bus_space_tag bst_store[3]; static int @@ -67,21 +65,83 @@ return ((b1->bsh == b2->bsh) ? 1 : 0); } +/* + * Get the address of the UART that is selected as the console, if the + * console is an UART of course. Note that we enforce that both stdin and + * stdout are selected. For weird configurations, use ofw_console(4). + * Note that the currently active console (i.e. /chosen/stdout and + * /chosen/stdin) may not be the same as the device selected in the + * environment (ie /options/output-device and /options/input-device) because + * the user may have changed the environment. In that case I would assume + * that the user expects that FreeBSD uses the new console setting. There's + * no choice, really. + */ static phandle_t -uart_cpu_getdev_keyboard(phandle_t root) +uart_cpu_getdev_console(phandle_t options, char *dev, size_t devsz) +{ + char buf[32]; + phandle_t input; + + if (OF_getprop(options, "input-device", dev, devsz) == -1) + return (-1); + if ((input = OF_finddevice(dev)) == -1) + return (-1); + if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) + return (-1); + if (strcmp(buf, "serial") != 0) + return (-1); + if (OF_getprop(options, "output-device", buf, sizeof(buf)) == -1) + return (-1); + if (OF_finddevice(buf) != input) + return (-1); + return (input); +} + +/* + * Get the address of the UART that's selected as the debug port. Since + * there's no place for this in the OF, we use the kernel environment. + * The environment variable is "debug_port" and its value is the device + * name (or an alias) known by the OF. + */ +static phandle_t +uart_cpu_getdev_dbgport(phandle_t options, char *dev, size_t devsz) +{ + char buf[32]; + phandle_t input; + + if (!getenv_string("debug_port", dev, devsz)) + return (-1); + if ((input = OF_finddevice(dev)) == -1) + return (-1); + if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) + return (-1); + if (strcmp(buf, "serial") != 0) + return (-1); + /* Rudimentary sanity check: the debug port cannot be the console. */ + if (OF_getprop(options, "input-device", buf, sizeof(buf)) == -1) + return (-1); + if (OF_finddevice(buf) == input) + return (-1); + return (input); +} + +static phandle_t +uart_cpu_getdev_keyboard(phandle_t root, char *dev, size_t devsz) { - phandle_t child; - phandle_t node; char buf[32]; + phandle_t child, node; - for (child = OF_child(root); child != 0 && child != -1; - child = OF_peer(child)) { + child = OF_child(root); + while (child != 0 && child != -1) { if (OF_getprop(child, "device_type", buf, sizeof(buf)) != -1 && !strcmp(buf, "serial") && - OF_getprop(child, "keyboard", buf, sizeof(buf)) != -1) + OF_getprop(child, "keyboard", buf, sizeof(buf)) != -1) { + OF_getprop(child, "name", dev, devsz); return (child); - if ((node = uart_cpu_getdev_keyboard(child)) != -1) + } + if ((node = uart_cpu_getdev_keyboard(child, dev, devsz)) != -1) return (node); + child = OF_peer(child); } return (-1); } @@ -90,47 +150,29 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) { char buf[32], dev[32], compat[32]; - phandle_t input, options, output; + phandle_t input, options; bus_addr_t addr; int baud, bits, error, space, stop; char flag, par; - /* - * Get the address of the UART that is selected as the console, if - * the console is an UART of course. Note that we enforce that both - * stdin and stdout are selected. For weird configurations, use - * ofw_console(4). - * Note that the currently active console (ie /chosen/stdout and - * /chosen/stdin) may not be the same as the device selected in the - * environment (ie /options/output-device and /options/input-device) - * because the user may have changed the environment. In that case - * I would assume that the user expects that FreeBSD uses the new - * console setting. There's choice choice, really. - */ - if ((options = OF_finddevice("/options")) == -1) - return (ENXIO); - if (devtype == UART_DEV_CONSOLE) { - if (OF_getprop(options, "input-device", dev, sizeof(dev)) == -1) - return (ENXIO); - if ((input = OF_finddevice(dev)) == -1) - return (ENXIO); - if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) - return (ENXIO); - if (strcmp(buf, "serial")) - return (ENODEV); - if (OF_getprop(options, "output-device", buf, sizeof(buf)) - == -1) - return (ENXIO); - if ((output = OF_finddevice(buf)) == -1) - return (ENXIO); - if (input != output) - return (ENXIO); - } else if (devtype == UART_DEV_KEYBOARD) { - if ((input = uart_cpu_getdev_keyboard(OF_peer(0))) == -1) - return (ENXIO); - } else - return (ENODEV); - + if ((options = OF_finddevice("/options")) == -1) + return (ENXIO); + switch (devtype) { + case UART_DEV_CONSOLE: + input = uart_cpu_getdev_console(options, dev, sizeof(dev)); + break; + case UART_DEV_DBGPORT: + input = uart_cpu_getdev_dbgport(options, dev, sizeof(dev)); + break; + case UART_DEV_KEYBOARD: + input = uart_cpu_getdev_keyboard(OF_peer(0), dev, sizeof(dev)); + break; + default: + input = -1; + break; + } + if (input == -1) + return (ENXIO); error = OF_decode_addr(input, &space, &addr); if (error) return (error); ==== //depot/projects/gdb/sys/gdb/gdb.h#4 (text+ko) ==== @@ -59,6 +59,10 @@ }; \ DATA_SET(gdb_dbgport_set, name##_gdb_dbgport) -extern struct gdb_dbgport *gdb_cur; +struct trapframe; + +int gdb_cpu_regsz(int); +uintmax_t gdb_cpu_regval(int, struct trapframe *); +int gdb_cpu_signal(int, int); #endif /* !_GDB_GDB_H_ */ ==== //depot/projects/gdb/sys/gdb/gdb_main.c#3 (text+ko) ==== @@ -31,8 +31,12 @@ #include #include #include +#include + +#include #include +#include static dbbe_init_f gdb_init; static dbbe_trap_f gdb_trap; @@ -42,7 +46,7 @@ GDB_DBGPORT(null, NULL, NULL, NULL, NULL, NULL, NULL); SET_DECLARE(gdb_dbgport_set, struct gdb_dbgport); -static struct gdb_dbgport *gdb_cur = NULL; +struct gdb_dbgport *gdb_cur = NULL; static int gdb_init(void) @@ -81,5 +85,30 @@ static int gdb_trap(int type, int code, struct trapframe *tf) { + const char *p; + + /* + * 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_reg(GDB_REG_PC, tf); + gdb_tx_char(';'); + gdb_tx_reg(GDB_REG_FP, tf); + gdb_tx_char(';'); + gdb_tx_reg(GDB_REG_SP, tf); + gdb_tx_char(';'); + gdb_tx_str("thread:"); + gdb_tx_varhex((uintptr_t)curthread); + gdb_tx_end(); /* XXX check error condition. */ + + while (gdb_rx_begin() == 0) { + p = gdb_rxp; + switch (gdb_rx_char()) { + case 'c': /* continue */ + return (1); + } + } return (0); }