set kdb_why to "trap" when calling kdb_trap from trap_fatal

This will allow to hook a ddb script to "kdb.enter.trap" event.
Previously there was no specific name for this event, so it could only
be handled by either "kdb.enter.unknown" or "kdb.enter.default" hooks.
Both are very unspecific.

Having a specific event is useful because the fatal trap condition is
very similar to panic but it has an additional property that the current
stack frame is the frame where the trap occurred.  So, both a register
dump and a stack bottom dump have additional information that can help
analyze the problem.

I have added the event only on architectures that have trap_fatal()
function defined.  I haven't looked at other architectures.  Their
maintainers can add support for the event later.

Sample script:
kdb.enter.trap=bt; show reg; x/aS $rsp,20; x/agx $rsp,20

Reviewed by:	kib, jhb, markj
MFC after:	11 days
Sponsored by:	Panzura
Differential Revision: https://reviews.freebsd.org/D15093
This commit is contained in:
Andriy Gapon 2018-04-19 05:06:56 +00:00
parent 807dbf2b94
commit f3f6ecb450
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=332752
4 changed files with 28 additions and 8 deletions

View File

@ -761,6 +761,9 @@ trap_fatal(frame, eva)
u_int type;
struct soft_segment_descriptor softseg;
char *msg;
#ifdef KDB
bool handled;
#endif
code = frame->tf_err;
type = frame->tf_trapno;
@ -811,9 +814,13 @@ trap_fatal(frame, eva)
curproc->p_pid, curthread->td_name);
#ifdef KDB
if (debugger_on_panic)
if (kdb_trap(type, 0, frame))
if (debugger_on_panic) {
kdb_why = KDB_WHY_TRAP;
handled = kdb_trap(type, 0, frame);
kdb_why = KDB_WHY_UNSET;
if (handled)
return;
}
#endif
printf("trap number = %d\n", type);
if (type <= MAX_TRAP_MSG)

View File

@ -879,6 +879,9 @@ trap_fatal(frame, eva)
int code, ss, esp;
u_int type;
struct soft_segment_descriptor softseg;
#ifdef KDB
bool handled;
#endif
code = frame->tf_err;
type = frame->tf_trapno;
@ -940,12 +943,13 @@ trap_fatal(frame, eva)
#ifdef KDB
if (debugger_on_panic) {
kdb_why = KDB_WHY_TRAP;
frame->tf_err = eva; /* smuggle fault address to ddb */
if (kdb_trap(type, 0, frame)) {
frame->tf_err = code; /* restore error code */
handled = kdb_trap(type, 0, frame);
frame->tf_err = code; /* restore error code */
kdb_why = KDB_WHY_UNSET;
if (handled)
return;
}
frame->tf_err = code; /* restore error code */
}
#endif
printf("trap number = %d\n", type);

View File

@ -449,11 +449,19 @@ trap(struct trapframe *frame)
static void
trap_fatal(struct trapframe *frame)
{
#ifdef KDB
bool handled;
#endif
printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR));
#ifdef KDB
if (debugger_on_panic && kdb_trap(frame->exc, 0, frame))
return;
if (debugger_on_panic) {
kdb_why = KDB_WHY_TRAP;
handled = kdb_trap(frame->exc, 0, frame);
kdb_why = KDB_WHY_UNSET;
if (handled)
return;
}
#endif
panic("%s trap", trapname(frame->exc));
}

View File

@ -101,6 +101,7 @@ extern const char * volatile kdb_why;
#define KDB_WHY_UNSET NULL /* No reason set. */
#define KDB_WHY_PANIC "panic" /* panic() was called. */
#define KDB_WHY_KASSERT "kassert" /* kassert failed. */
#define KDB_WHY_TRAP "trap" /* Fatal trap. */
#define KDB_WHY_SYSCTL "sysctl" /* Sysctl entered debugger. */
#define KDB_WHY_BOOTFLAGS "bootflags" /* Boot flags were set. */
#define KDB_WHY_WITNESS "witness" /* Witness entered debugger. */