diff --git a/sbin/Makefile b/sbin/Makefile index 7c78a99f197f..31744644a4a7 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -15,6 +15,7 @@ SUBDIR= adjkerntz \ clri \ comcontrol \ conscontrol \ + ddb \ ${_devd} \ devfs \ dhclient \ diff --git a/sbin/ddb/Makefile b/sbin/ddb/Makefile new file mode 100644 index 000000000000..1ae724b55ee3 --- /dev/null +++ b/sbin/ddb/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +PROG= ddb +SRCS= ddb.c ddb_script.c +MAN= ddb.8 +WARNS= 3 + +.include diff --git a/sbin/ddb/ddb.8 b/sbin/ddb/ddb.8 new file mode 100644 index 000000000000..5d20d874582b --- /dev/null +++ b/sbin/ddb/ddb.8 @@ -0,0 +1,106 @@ +.\"- +.\" Copyright (c) 2007 Robert N. M. Watson +.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$ +.\" +.Dd 25 December, 2007 +.Dt DDB 8 +.Os +.Sh NAME +.Nm ddb +.Nd Configure DDB kernel debugger properties +.Sh SYNOPSIS +.Nm +.Cm script +.Ar scriptname +.Nm +.Cm script +.Ar scriptname=script +.Nm +.Cm scripts +.Nm +.Cm unscript +.Ar scriptname +.Sh DESCRIPTION +.Nm +configures certain aspects of the +.Xr DDB 4 +kernel debugger from user space that are not configured at compile-time or +easily via +.Xr sysctl 8 +MIB entries. +.Sh SCRIPTING +.Nm +can be used to configure aspects of +.Xr DDB 4 +scripting from user space; scripting support is described in more detail in +.Xr DDB 4 . +Each of the debugger commands is available from the command line: +.Bl -tag -width indent +.It Cm script Ar scriptname +Print the script named +.Ar scriptname . +.It Cm script Ar scriptname=scriptvalue +Define a script named +.Ar scriptname ; +as many scripts contain characters interpreted in special ways by the shell, +it is advisable to enclose +.Ar scriptvalue +in quotes. +.It Cm scripts +List currently defined scripts. +.It Cm unset Ar scriptname +Delete the script named +.Ar scriptname . +.El +.Sh EXAMPLES +The following example defines a script that will execute when the kernel +debugger is entered as a result of a break signal: +.Bd -literal -offset indent +ddb script kdb.enter.break="show pcpu;bt" +.Ed +.Pp +The following example will delete the script: +.Bd -literal -offset indent +ddb unscript kdb.enter.break +.Ed +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr DDB 4 , +.Xr sysctl 8 +.Sh HISTORY +.Nm +first appeared in +.Fx 8.0 . +.Sh AUTHORS +.An Robert N M Watson +.Sh BUGS +Ideally, +.Nm +would not exist, as all pertinent aspects of +.Xr DDB 4 +could be configured directly via +.Xr sysctl 8 . diff --git a/sbin/ddb/ddb.c b/sbin/ddb/ddb.c new file mode 100644 index 000000000000..9ca0d57e6732 --- /dev/null +++ b/sbin/ddb/ddb.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2007 Robert N. M. Watson + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 "ddb.h" + +void +usage(void) +{ + + fprintf(stderr, "usage:\n"); + fprintf(stderr, "ddb script scriptname\n"); + fprintf(stderr, "ddb script scriptname=script\n"); + fprintf(stderr, "ddb scripts\n"); + fprintf(stderr, "ddb unscript scriptname\n"); + exit(EX_USAGE); +} + +int +main(int argc, char *argv[]) +{ + + if (argc < 2) + usage(); + + argc -= 1; + argv += 1; + if (strcmp(argv[0], "script") == 0) + ddb_script(argc, argv); + else if (strcmp(argv[0], "scripts") == 0) + ddb_scripts(argc, argv); + else if (strcmp(argv[0], "unscript") == 0) + ddb_unscript(argc, argv); + else + usage(); + exit(EX_OK); +} diff --git a/sbin/ddb/ddb.h b/sbin/ddb/ddb.h new file mode 100644 index 000000000000..50128bd43c61 --- /dev/null +++ b/sbin/ddb/ddb.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2007 Robert N. M. Watson + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 DDB_H +#define DDB_H + +void ddb_script(int argc, char *argv[]); +void ddb_scripts(int argc, char *argv[]); +void ddb_unscript(int argc, char *argv[]); +void usage(void); + +#endif /* DDB_H */ diff --git a/sbin/ddb/ddb_script.c b/sbin/ddb/ddb_script.c new file mode 100644 index 000000000000..13829049dbea --- /dev/null +++ b/sbin/ddb/ddb_script.c @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2007 Robert N. M. Watson + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 "ddb.h" + +/* + * These commands manage DDB(4) scripts from user space. For better or worse, + * the setting and unsetting of scripts is only poorly represented using + * sysctl(8), and this interface provides a more user-friendly way to + * accomplish this management, wrapped around lower-level sysctls. For + * completeness, listing of scripts is also included. + */ + +#define SYSCTL_SCRIPT "debug.ddb.scripting.script" +#define SYSCTL_SCRIPTS "debug.ddb.scripting.scripts" +#define SYSCTL_UNSCRIPT "debug.ddb.scripting.unscript" + +/* + * Print all scripts (scriptname==NULL) or a specific script. + */ +static void +ddb_list_scripts(const char *scriptname) +{ + char *buffer, *line, *nextline; + char *line_script, *line_scriptname; + size_t buflen, len; + int ret; + +repeat: + if (sysctlbyname(SYSCTL_SCRIPTS, NULL, &buflen, NULL, 0) < 0) + err(EX_OSERR, "sysctl: %s", SYSCTL_SCRIPTS); + if (buflen == 0) + return; + buffer = malloc(buflen); + if (buffer == NULL) + err(EX_OSERR, "malloc"); + bzero(buffer, buflen); + len = buflen; + ret = sysctlbyname(SYSCTL_SCRIPTS, buffer, &len, NULL, 0); + if (ret < 0 && errno != ENOMEM) + err(EX_OSERR, "sysctl: %s", SYSCTL_SCRIPTS); + if (ret < 0) { + free(buffer); + goto repeat; + } + + /* + * We nul'd the buffer before calling sysctl(), so at worst empty. + * + * If a specific script hasn't been requested, print it all. + */ + if (scriptname == NULL) { + printf("%s", buffer); + free(buffer); + return; + } + + /* + * If a specific script has been requested, we have to parse the + * string to find it. + */ + nextline = buffer; + while ((line = strsep(&nextline, "\n")) != NULL) { + line_script = line; + line_scriptname = strsep(&line_script, "="); + if (line_script == NULL) + continue; + if (strcmp(scriptname, line_scriptname) != 0) + continue; + printf("%s\n", line_script); + break; + } + if (line == NULL) { + errno = ENOENT; + err(EX_DATAERR, "%s", scriptname); + } + free(buffer); +} + +/* + * "ddb script" can be used to either print or set a script. + */ +void +ddb_script(int argc, char *argv[]) +{ + + if (argc != 2) + usage(); + argv++; + argc--; + if (strchr(argv[0], '=') != 0) { + if (sysctlbyname(SYSCTL_SCRIPT, NULL, NULL, argv[0], + strlen(argv[0]) + 1) < 0) + err(EX_OSERR, "sysctl: %s", SYSCTL_SCRIPTS); + } else + ddb_list_scripts(argv[0]); +} + +void +ddb_scripts(int argc, char *argv[]) +{ + + if (argc != 1) + usage(); + ddb_list_scripts(NULL); +} + +void +ddb_unscript(int argc, char *argv[]) +{ + int ret; + + if (argc != 2) + usage(); + argv++; + argc--; + ret = sysctlbyname(SYSCTL_UNSCRIPT, NULL, NULL, argv[0], + strlen(argv[0]) + 1); + if (ret < 0 && errno == EINVAL) { + errno = ENOENT; + err(EX_DATAERR, "sysctl: %s", argv[0]); + } else if (ret < 0) + err(EX_OSERR, "sysctl: %s", SYSCTL_UNSCRIPT); +}