this diff takes advantage of -msave-args to allow ddb to print
arguments in stack traces on amd64.
-msave-args basically pushes the functions register arguments onto
the stack, so the code looks before (in memory) the base pointer
for them. the rest of the arguments get passed normally, ie, after
the base pointer, so ddb looks for them there.
without CTF, ddb doesnt know how many arguments there are, so this
has it blindly assume there's 6 if there's no CTF. this corresponds
to how many register arguments there could be, but it is more about
looking for enough arguments generally to be useful rather than too
few.
as per the mail about the gcc diff, ddb should now look like this:
ddb{0}> tr
Debugger(ffffff0866b9d400,7f7ffffc7000,10,ffff80002100dd00,286,8) at Debugger+0
x9
ddb_sysctl(ffff80002100ddb4,1,7f7ffffc5180,ffff80002100dde0,7f7ffffc5174,4) at d
db_sysctl+0x1c9
sys_sysctl(ffff800020fb39a0,ffff80002100de60,ffff80002100deb0,1,ca,1) at sys_sy
sctl+0x239
syscall() at syscall+0x29f
--- syscall (number 202) ---
end of kernel
end trace frame: 0x7f7ffffc731f, count: -4
0x1c5881d106ea:
ddb{0}> tr /p 0t34348
sleep_finish(ffff800020f1ebc0,1,0,118,ffffffff8194f100,ffffff0879dacc80) at sle
ep_finish+0xc2
utsleep(ffffff0879dacc80,118,ffffffff8178fea0,0,0,40) at utsleep+0x133
kqueue_scan(ffffff0879dacc80,40,1b3605246800,0,ffff800020eb6018,ffff800020f1ede
4) at kqueue_scan+0x19a
sys_kevent(ffff800020eb6018,ffff800020f1ee60,ffff800020f1eeb0,1,48,1) at sys_ke
vent+0x2c9
syscall() at syscall+0x29f
--- syscall (number 72) ---
end of kernel
end trace frame: 0x1b3605246800, count: -5
0x1b35be687b0a:
ddb{0}>
ive also tried to handle looking at registers instead of the stack
if we're at the top of the current stack. i havent tested this
though.
id like -msave-args in gcc to be in the tree for a while before
committing this. im sending it out now for feedback and review.
Index: conf/Makefile.amd64
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/Makefile.amd64,v
retrieving revision 1.75
diff -u -p -r1.75 Makefile.amd64
--- conf/Makefile.amd64 25 Jan 2017 11:15:07 -0000 1.75
+++ conf/Makefile.amd64 24 Apr 2017 21:54:32 -0000
@@ -28,7 +28,7 @@ CWARNFLAGS= -Werror -Wall -Wimplicit-fun
-Wframe-larger-than=2047
CMACHFLAGS= -mcmodel=kernel -mno-red-zone -mno-sse2 -mno-sse -mno-3dnow \
- -mno-mmx -msoft-float -fno-omit-frame-pointer
+ -mno-mmx -msoft-float -msave-args -fno-omit-frame-pointer
CMACHFLAGS+= -ffreestanding ${NOPIE_FLAGS}
.if ${IDENT:M-DNO_PROPOLICE}
CMACHFLAGS+= -fno-stack-protector
Index: amd64/db_trace.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/db_trace.c,v
retrieving revision 1.26
diff -u -p -r1.26 db_trace.c
--- amd64/db_trace.c 20 Apr 2017 12:41:43 -0000 1.26
+++ amd64/db_trace.c 24 Apr 2017 21:54:32 -0000
@@ -100,7 +100,7 @@ db_numargs(struct callframe *fp, const c
#ifdef DDBCTF
return db_ctf_func_numargs(sym);
#else
- return 0;
+ return 6;
#endif /* DDBCTF */
}
@@ -175,12 +175,21 @@ db_is_trap(const char *name)
return NONE;
}
+const unsigned long *db_reg_args[6] = {
+ (unsigned long *)&ddb_regs.tf_rdi,
+ (unsigned long *)&ddb_regs.tf_rsi,
+ (unsigned long *)&ddb_regs.tf_rdx,
+ (unsigned long *)&ddb_regs.tf_rcx,
+ (unsigned long *)&ddb_regs.tf_r8,
+ (unsigned long *)&ddb_regs.tf_r9,
+};
+
void
db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count,
char *modif, int (*pr)(const char *, ...))
{
struct callframe *frame, *lastframe;
- long *argp, *arg0;
+ unsigned long *argp, *arg0;
db_addr_t callpc;
int is_trap = 0;
boolean_t kernel_only = TRUE;
@@ -220,7 +229,8 @@ db_stack_trace_print(db_expr_t addr, boo
lastframe = 0;
while (count && frame != 0) {
int narg;
- char * name;
+ unsigned int i;
+ char * name;
db_expr_t offset;
db_sym_t sym;
@@ -229,7 +239,7 @@ db_stack_trace_print(db_expr_t addr, boo
if (lastframe == 0 && sym == NULL) {
/* Symbol not found, peek at code */
- long instr = db_get_value(callpc, 8, FALSE);
+ unsigned long instr = db_get_value(callpc, 8, FALSE);
offset = 1;
if ((instr & 0x00ffffff) == 0x00e58955 ||
@@ -239,6 +249,7 @@ db_stack_trace_print(db_expr_t addr, boo
offset = 0;
}
}
+
if (INKERNEL(callpc) && (is_trap = db_is_trap(name)) != NONE)
narg = 0;
else {
@@ -249,22 +260,37 @@ db_stack_trace_print(db_expr_t addr, boo
(*pr)("%s(", name);
if (lastframe == 0 && offset == 0 && !have_addr) {
- /*
- * We have a breakpoint before the frame is set up
- * Use %rsp instead
- */
+ /* We have a breakpoint before the frame is set up */
+ for (i = min(6, narg); i > 0; i--) {
+ (*pr)("%lx", *db_reg_args[i]);
+ if (--narg != 0)
+ (*pr)(",");
+ }
+
+ /* Use %rsp instead */
arg0 =
&((struct callframe *)(ddb_regs.tf_rsp-8))->f_arg0;
} else {
+ argp = (unsigned long *)frame;
+ for (i = min(6, narg); i > 0; i--) {
+ argp--;
+ (*pr)("%lx", db_get_value((db_addr_t)argp,
+ sizeof(*argp), FALSE));
+ if (--narg != 0)
+ (*pr)(",");
+ }
+
arg0 = &frame->f_arg0;
}
for (argp = arg0; narg > 0; ) {
- (*pr)("%lx", db_get_value((db_addr_t)argp, 8, FALSE));
+ (*pr)("%lx", db_get_value((db_addr_t)argp,
+ sizeof(*argp), FALSE));
argp++;
if (--narg != 0)
(*pr)(",");
}
+
(*pr)(") at ");
db_printsym(callpc, DB_STGY_PROC, pr);
(*pr)("\n");