diff --git a/share/man/man4/ddb.4 b/share/man/man4/ddb.4 --- a/share/man/man4/ddb.4 +++ b/share/man/man4/ddb.4 @@ -955,14 +955,10 @@ Display the register set. If the .Cm u -modifier is specified, it displays user registers instead of -kernel registers or the currently saved one. +modifier is specified, the register contents of the thread's previous +trapframe are displayed instead. +Usually, this corresponds to the saved state from userspace. .Pp -.Sy Warning : -The support of the -.Cm u -modifier depends on the machine. -If not supported, incorrect information will be displayed. .\" .Pp .It Ic show Cm rman Ar addr diff --git a/sys/ddb/db_print.c b/sys/ddb/db_print.c --- a/sys/ddb/db_print.c +++ b/sys/ddb/db_print.c @@ -49,12 +49,32 @@ #include void -db_show_regs(db_expr_t _1, bool _2, db_expr_t _3, char *_4) +db_show_regs(db_expr_t _1, bool _2, db_expr_t _3, char *modif) { + struct trapframe *oldtf; struct db_variable *regp; db_expr_t value, offset; const char *name; + /* + * The 'u' modifier instructs us to print the previous trapframe, most + * often containing state from userspace. This is done by temporarily + * switching out kdb_frame. + * + * NB: curthread is used instead of kdb_thread, so that behaviour is + * consistent with regular `show registers`, which always prints + * curthread's trapframe. + */ + oldtf = kdb_frame; + if (modif[0] == 'u') { + if (curthread->td_frame == NULL || + curthread->td_frame == oldtf) { + db_printf("previous trapframe unavailable"); + return; + } + kdb_frame = curthread->td_frame; + } + for (regp = db_regs; regp < db_eregs; regp++) { if (!db_read_variable(regp, &value)) continue; @@ -70,4 +90,6 @@ db_printf("\n"); } db_print_loc_and_inst(PC_REGS()); + + kdb_frame = oldtf; }