MFp4 @178364:
Implement an optional delay to the ddb reset/reboot command. This allows textdumps to be run automatically with unattended reboots after a resonable timeout, while still permitting an administrator to break into debugger if attached to the console at the time of the event for further debugging. Cap the maximum delay at 1 week to avoid highly accidental results, and default to 15s in case of problems parsing the timeout value. Move hex2dec helper function from db_thread.c to db_command.c to make it generally available and prefix it with a "db_" to avoid namespace collisions. Reviewed by: rwatson MFC after: 4 weeks
This commit is contained in:
parent
3abaa08643
commit
0f59fbc3d6
@ -60,7 +60,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 29, 2008
|
||||
.Dd May 24, 2010
|
||||
.Dt DDB 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -1092,9 +1092,13 @@ for a list of signals.
|
||||
Note that the arguments are reversed relative to
|
||||
.Xr kill 2 .
|
||||
.Pp
|
||||
.It Ic reboot
|
||||
.It Ic reset
|
||||
.It Ic reboot Op Ar seconds
|
||||
.It Ic reset Op Ar seconds
|
||||
Hard reset the system.
|
||||
If the optional argument
|
||||
.Ar seconds
|
||||
is given, the debugger will wait for this long, at most a week,
|
||||
before rebooting.
|
||||
.Pp
|
||||
.It Ic help
|
||||
Print a short summary of the available commands and command
|
||||
|
@ -661,13 +661,42 @@ db_kill(dummy1, dummy2, dummy3, dummy4)
|
||||
#undef DB_ERROR
|
||||
}
|
||||
|
||||
/*
|
||||
* Reboot. In case there is an additional argument, take it as delay in
|
||||
* seconds. Default to 15s if we cannot parse it and make sure we will
|
||||
* never wait longer than 1 week. Some code is similar to
|
||||
* kern_shutdown.c:shutdown_panic().
|
||||
*/
|
||||
#ifndef DB_RESET_MAXDELAY
|
||||
#define DB_RESET_MAXDELAY (3600 * 24 * 7)
|
||||
#endif
|
||||
|
||||
static void
|
||||
db_reset(dummy1, dummy2, dummy3, dummy4)
|
||||
db_expr_t dummy1;
|
||||
boolean_t dummy2;
|
||||
db_expr_t dummy3;
|
||||
char * dummy4;
|
||||
db_reset(db_expr_t addr, boolean_t have_addr, db_expr_t count __unused,
|
||||
char *modif __unused)
|
||||
{
|
||||
int delay, loop;
|
||||
|
||||
if (have_addr) {
|
||||
delay = (int)db_hex2dec(addr);
|
||||
|
||||
/* If we parse to fail, use 15s. */
|
||||
if (delay == -1)
|
||||
delay = 15;
|
||||
|
||||
/* Cap at one week. */
|
||||
if ((uintmax_t)delay > (uintmax_t)DB_RESET_MAXDELAY)
|
||||
delay = DB_RESET_MAXDELAY;
|
||||
|
||||
db_printf("Automatic reboot in %d seconds - "
|
||||
"press a key on the console to abort\n", delay);
|
||||
for (loop = delay * 10; loop > 0; --loop) {
|
||||
DELAY(1000 * 100); /* 1/10th second */
|
||||
/* Did user type a key? */
|
||||
if (cncheckc() != -1)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cpu_reset();
|
||||
}
|
||||
@ -771,3 +800,28 @@ db_stack_trace_all(db_expr_t dummy, boolean_t dummy2, db_expr_t dummy3,
|
||||
kdb_jmpbuf(prev_jb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the parsed expression value from the command line that was parsed
|
||||
* as a hexadecimal value and convert it as if the expression was parsed
|
||||
* as a decimal value. Returns -1 if the expression was not a valid
|
||||
* decimal value.
|
||||
*/
|
||||
db_expr_t
|
||||
db_hex2dec(db_expr_t expr)
|
||||
{
|
||||
uintptr_t x, y;
|
||||
db_expr_t val;
|
||||
|
||||
y = 1;
|
||||
val = 0;
|
||||
x = expr;
|
||||
while (x != 0) {
|
||||
if (x % 16 > 9)
|
||||
return (-1);
|
||||
val += (x % 16) * (y);
|
||||
x >>= 4;
|
||||
y *= 10;
|
||||
}
|
||||
return (val);
|
||||
}
|
||||
|
@ -33,6 +33,12 @@
|
||||
* Author: David B. Golub, Carnegie Mellon University
|
||||
* Date: 7/90
|
||||
*/
|
||||
|
||||
/*
|
||||
* Helper functions.
|
||||
*/
|
||||
db_expr_t db_hex2dec(db_expr_t expr);
|
||||
|
||||
/*
|
||||
* Command loop declarations.
|
||||
*/
|
||||
|
@ -38,8 +38,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <ddb/db_command.h>
|
||||
#include <ddb/db_sym.h>
|
||||
|
||||
static db_expr_t hex2dec(db_expr_t expr);
|
||||
|
||||
void
|
||||
db_print_thread(void)
|
||||
{
|
||||
@ -107,31 +105,6 @@ db_show_threads(db_expr_t addr, boolean_t hasaddr, db_expr_t cnt, char *mod)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the parsed expression value from the command line that was parsed
|
||||
* as a hexadecimal value and convert it as if the expression was parsed
|
||||
* as a decimal value. Returns -1 if the expression was not a valid
|
||||
* decimal value.
|
||||
*/
|
||||
static db_expr_t
|
||||
hex2dec(db_expr_t expr)
|
||||
{
|
||||
uintptr_t x, y;
|
||||
db_expr_t val;
|
||||
|
||||
y = 1;
|
||||
val = 0;
|
||||
x = expr;
|
||||
while (x != 0) {
|
||||
if (x % 16 > 9)
|
||||
return (-1);
|
||||
val += (x % 16) * (y);
|
||||
x >>= 4;
|
||||
y *= 10;
|
||||
}
|
||||
return (val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a thread based on a db expression address. We assume that the
|
||||
* address was parsed in hexadecimal. We reparse the address in decimal
|
||||
@ -151,7 +124,7 @@ db_lookup_thread(db_expr_t addr, boolean_t check_pid)
|
||||
* If the parsed address was not a valid decimal expression,
|
||||
* assume it is a thread pointer.
|
||||
*/
|
||||
decaddr = hex2dec(addr);
|
||||
decaddr = db_hex2dec(addr);
|
||||
if (decaddr == -1)
|
||||
return ((struct thread *)addr);
|
||||
|
||||
@ -183,7 +156,7 @@ db_lookup_proc(db_expr_t addr)
|
||||
db_expr_t decaddr;
|
||||
struct proc *p;
|
||||
|
||||
decaddr = hex2dec(addr);
|
||||
decaddr = db_hex2dec(addr);
|
||||
if (decaddr != -1) {
|
||||
FOREACH_PROC_IN_SYSTEM(p) {
|
||||
if (p->p_pid == decaddr)
|
||||
|
Loading…
Reference in New Issue
Block a user