diff options
author | jhb <jhb@FreeBSD.org> | 2001-04-09 21:43:45 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-04-09 21:43:45 +0000 |
commit | cd92f5e07a06ee13792a974210d5111b5cee25aa (patch) | |
tree | 85ea84b307d7ea9546eac0416d43b95f3fbdfac0 /sys/amd64 | |
parent | 179a4916c8446b0872d547329066e18c2164af70 (diff) | |
download | FreeBSD-src-cd92f5e07a06ee13792a974210d5111b5cee25aa.zip FreeBSD-src-cd92f5e07a06ee13792a974210d5111b5cee25aa.tar.gz |
- One can now specify the decimal pid of a process to trace as a parameter.
Since pid's are not in the kernel address space, this doesn't conflict
with the funcionality of specifying an arbitrary frame pointer to the
trace command.
- If the first function of a backtrace maps to fork_trampoline, then this
is a newly fork'd process that has not been executed yet, so just print
out the first frame and then return for that case.
- Lower the default count from 65535 to 1024. ddb doesn't trace into
userland, and if the stack gets hosed and starts looping it's less
annoying.
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/amd64/db_trace.c | 98 |
1 files changed, 73 insertions, 25 deletions
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c index 682a644..af02d94 100644 --- a/sys/amd64/amd64/db_trace.c +++ b/sys/amd64/amd64/db_trace.c @@ -28,6 +28,9 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/linker_set.h> +#include <sys/proc.h> +#include <sys/user.h> #include <machine/cpu.h> @@ -240,15 +243,51 @@ db_stack_trace_cmd(addr, have_addr, count, modif) int *argp; db_addr_t callpc; boolean_t first; + struct pcb *pcb; + struct proc *p; + pid_t pid; if (count == -1) - count = 65535; + count = 1024; if (!have_addr) { frame = (struct i386_frame *)ddb_regs.tf_ebp; if (frame == NULL) frame = (struct i386_frame *)(ddb_regs.tf_esp - 4); callpc = (db_addr_t)ddb_regs.tf_eip; + } else if (!INKERNEL(addr)) { + pid = (addr % 16) + ((addr >> 4) % 16) * 10 + + ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 + + ((addr >> 16) % 16) * 10000; + /* + * The pcb for curproc is not valid at this point, + * so fall back to the default case. + */ + if (pid == curproc->p_pid) { + frame = (struct i386_frame *)ddb_regs.tf_ebp; + if (frame == NULL) + frame = (struct i386_frame *) + (ddb_regs.tf_esp - 4); + callpc = (db_addr_t)ddb_regs.tf_eip; + } else { + + /* sx_slock(&allproc_lock); */ + LIST_FOREACH(p, &allproc, p_list) { + if (p->p_pid == pid) + break; + } + /* sx_sunlock(&allproc_lock); */ + if (p == NULL) { + db_printf("pid %d not found\n", pid); + return; + } + pcb = &p->p_addr->u_pcb; + frame = (struct i386_frame *)pcb->pcb_ebp; + if (frame == NULL) + frame = (struct i386_frame *) + (pcb->pcb_esp - 4); + callpc = (db_addr_t)pcb->pcb_eip; + } } else { frame = (struct i386_frame *)addr; callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE); @@ -279,33 +318,42 @@ db_stack_trace_cmd(addr, have_addr, count, modif) * db_nextframe() works because the `next' pc is special). */ actframe = frame; - if (first && !have_addr) { - int instr; - - instr = db_get_value(callpc, 4, FALSE); - if ((instr & 0x00ffffff) == 0x00e58955) { - /* pushl %ebp; movl %esp, %ebp */ - actframe = (struct i386_frame *) - (ddb_regs.tf_esp - 4); - } else if ((instr & 0x0000ffff) == 0x0000e589) { - /* movl %esp, %ebp */ - actframe = (struct i386_frame *) - ddb_regs.tf_esp; - if (ddb_regs.tf_ebp == 0) { - /* Fake the caller's frame better. */ - frame = actframe; + if (first) { + if (!have_addr) { + int instr; + + instr = db_get_value(callpc, 4, FALSE); + if ((instr & 0x00ffffff) == 0x00e58955) { + /* pushl %ebp; movl %esp, %ebp */ + actframe = (struct i386_frame *) + (ddb_regs.tf_esp - 4); + } else if ((instr & 0x0000ffff) == 0x0000e589) { + /* movl %esp, %ebp */ + actframe = (struct i386_frame *) + ddb_regs.tf_esp; + if (ddb_regs.tf_ebp == 0) { + /* Fake caller's frame better. */ + frame = actframe; + } + } else if ((instr & 0x000000ff) == 0x000000c3) { + /* ret */ + actframe = (struct i386_frame *) + (ddb_regs.tf_esp - 4); + } else if (offset == 0) { + /* Probably a symbol in assembler code. */ + actframe = (struct i386_frame *) + (ddb_regs.tf_esp - 4); } - } else if ((instr & 0x000000ff) == 0x000000c3) { - /* ret */ - actframe = (struct i386_frame *) - (ddb_regs.tf_esp - 4); - } else if (offset == 0) { - /* Probably a symbol in assembler code. */ - actframe = (struct i386_frame *) - (ddb_regs.tf_esp - 4); + } else if (!strcmp(name, "fork_trampoline")) { + /* + * Don't try to walk back on a stack for a + * process that hasn't actually been run yet. + */ + db_print_stack_entry(name, 0, 0, 0, callpc); + break; } + first = FALSE; } - first = FALSE; argp = &actframe->f_arg0; narg = MAXNARG; |