diff options
author | marcel <marcel@FreeBSD.org> | 2004-07-10 19:56:00 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2004-07-10 19:56:00 +0000 |
commit | 006d404cf77cb76437589bef7e0e1bb57c7bd79d (patch) | |
tree | ef114b5aee4601f2523b9d10bcaef23b379b7b6a | |
parent | 8a7d828338d290e43e0ba04946b945be561589c7 (diff) | |
download | FreeBSD-src-006d404cf77cb76437589bef7e0e1bb57c7bd79d.zip FreeBSD-src-006d404cf77cb76437589bef7e0e1bb57c7bd79d.tar.gz |
Implement makectx(). The makectx() function is used by KDB to create
a PCB from a trapframe for purposes of unwinding the stack. The PCB
is used as the thread context and all but the thread that entered the
debugger has a valid PCB.
This function can also be used to create a context for the threads
running on the CPUs that have been stopped when the debugger got
entered. This however is not done at the time of this commit.
-rw-r--r-- | sys/alpha/alpha/machdep.c | 23 | ||||
-rw-r--r-- | sys/alpha/include/pcb.h | 1 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 21 | ||||
-rw-r--r-- | sys/amd64/include/pcb.h | 3 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 19 | ||||
-rw-r--r-- | sys/i386/include/pcb.h | 3 | ||||
-rw-r--r-- | sys/ia64/ia64/machdep.c | 17 | ||||
-rw-r--r-- | sys/ia64/include/pcb.h | 6 | ||||
-rw-r--r-- | sys/sparc64/include/pcb.h | 1 | ||||
-rw-r--r-- | sys/sparc64/sparc64/machdep.c | 15 |
10 files changed, 108 insertions, 1 deletions
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index 005e56e..82c856d 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -1989,6 +1989,29 @@ alpha_pa_access(vm_offset_t pa) #endif } +/* + * Construct a PCB from a trapframe. This is called from kdb_trap() where + * we want to start a backtrace from the function that caused us to enter + * the debugger. We have the context in the trapframe, but base the trace + * on the PCB. The PCB doesn't have to be perfect, as long as it contains + * enough for a backtrace. + */ +void +makectx(struct trapframe *tf, struct pcb *pcb) +{ + + pcb->pcb_context[0] = tf->tf_regs[FRAME_S0]; + pcb->pcb_context[1] = tf->tf_regs[FRAME_S1]; + pcb->pcb_context[2] = tf->tf_regs[FRAME_S2]; + pcb->pcb_context[3] = tf->tf_regs[FRAME_S3]; + pcb->pcb_context[4] = tf->tf_regs[FRAME_S4]; + pcb->pcb_context[5] = tf->tf_regs[FRAME_S5]; + pcb->pcb_context[6] = tf->tf_regs[FRAME_S6]; + pcb->pcb_context[7] = tf->tf_regs[FRAME_PC]; + pcb->pcb_context[8] = tf->tf_regs[FRAME_PS]; + pcb->pcb_hw.apcb_ksp = tf->tf_regs[FRAME_SP]; +} + int fill_regs(td, regs) struct thread *td; diff --git a/sys/alpha/include/pcb.h b/sys/alpha/include/pcb.h index 982e97b..4375ef2 100644 --- a/sys/alpha/include/pcb.h +++ b/sys/alpha/include/pcb.h @@ -58,6 +58,7 @@ struct pcb { }; #ifdef _KERNEL +void makectx(struct trapframe *, struct pcb *); void savectx(struct pcb *); #endif diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 2d0fd66..8a107ab 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1265,6 +1265,27 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) pcpu->pc_acpi_id = 0xffffffff; } +/* + * Construct a PCB from a trapframe. This is called from kdb_trap() where + * we want to start a backtrace from the function that caused us to enter + * the debugger. We have the context in the trapframe, but base the trace + * on the PCB. The PCB doesn't have to be perfect, as long as it contains + * enough for a backtrace. + */ +void +makectx(struct trapframe *tf, struct pcb *pcb) +{ + + pcb->pcb_r12 = tf->tf_r12; + pcb->pcb_r13 = tf->tf_r13; + pcb->pcb_r14 = tf->tf_r14; + pcb->pcb_r15 = tf->tf_r15; + pcb->pcb_rbp = tf->tf_rbp; + pcb->pcb_rbx = tf->tf_rbx; + pcb->pcb_rip = tf->tf_rip; + pcb->pcb_rsp = (ISPL(tf->tf_cs)) ? tf->tf_rsp : (long)(tf + 1) - 8; +} + int ptrace_set_pc(struct thread *td, unsigned long addr) { diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h index 73d8aa5..305b7ff 100644 --- a/sys/amd64/include/pcb.h +++ b/sys/amd64/include/pcb.h @@ -78,6 +78,9 @@ struct pcb { }; #ifdef _KERNEL +struct trapframe; + +void makectx(struct trapframe *, struct pcb *); void savectx(struct pcb *); #endif diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 9fbc6f9..b1b388c 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -2206,6 +2206,25 @@ f00f_hack(void *unused) } #endif /* defined(I586_CPU) && !NO_F00F_HACK */ +/* + * Construct a PCB from a trapframe. This is called from kdb_trap() where + * we want to start a backtrace from the function that caused us to enter + * the debugger. We have the context in the trapframe, but base the trace + * on the PCB. The PCB doesn't have to be perfect, as long as it contains + * enough for a backtrace. + */ +void +makectx(struct trapframe *tf, struct pcb *pcb) +{ + + pcb->pcb_edi = tf->tf_edi; + pcb->pcb_esi = tf->tf_esi; + pcb->pcb_ebp = tf->tf_ebp; + pcb->pcb_ebx = tf->tf_ebx; + pcb->pcb_eip = tf->tf_eip; + pcb->pcb_esp = (ISPL(tf->tf_cs)) ? tf->tf_esp : (int)(tf + 1) - 8; +} + int ptrace_set_pc(struct thread *td, u_long addr) { diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h index c88823a..3f32340 100644 --- a/sys/i386/include/pcb.h +++ b/sys/i386/include/pcb.h @@ -74,6 +74,9 @@ struct pcb { }; #ifdef _KERNEL +struct trapframe; + +void makectx(struct trapframe *, struct pcb *); void savectx(struct pcb *); #endif diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index ca75d2c..5c39d05 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -1017,6 +1017,23 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) } #endif +/* + * Construct a PCB from a trapframe. This is called from kdb_trap() where + * we want to start a backtrace from the function that caused us to enter + * the debugger. We have the context in the trapframe, but base the trace + * on the PCB. The PCB doesn't have to be perfect, as long as it contains + * enough for a backtrace. + */ +void +makectx(struct trapframe *tf, struct pcb *pcb) +{ + + pcb->pcb_special = tf->tf_special; + pcb->pcb_special.__spare = ~0UL; /* XXX see unwind.c */ + save_callee_saved(&pcb->pcb_preserved); + save_callee_saved_fp(&pcb->pcb_preserved_fp); +} + int get_mcontext(struct thread *td, mcontext_t *mc, int flags) { diff --git a/sys/ia64/include/pcb.h b/sys/ia64/include/pcb.h index 23d7e50..d018127 100644 --- a/sys/ia64/include/pcb.h +++ b/sys/ia64/include/pcb.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003 Doug Rabson + * Copyright (c) 2003,2004 Marcel Moolenaar * Copyright (c) 2000 Doug Rabson * All rights reserved. * @@ -59,6 +59,10 @@ struct pcb { #ifdef _KERNEL #define savectx(p) swapctx(p, NULL) + +struct trapframe; + +void makectx(struct trapframe *, struct pcb *); void restorectx(struct pcb *) __dead2; int swapctx(struct pcb *old, struct pcb *new); diff --git a/sys/sparc64/include/pcb.h b/sys/sparc64/include/pcb.h index 38578d2..1f1e8dc 100644 --- a/sys/sparc64/include/pcb.h +++ b/sys/sparc64/include/pcb.h @@ -49,6 +49,7 @@ struct pcb { } __aligned(64); #ifdef _KERNEL +void makectx(struct trapframe *, struct pcb *); int savectx(struct pcb *pcb); #endif diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 3db2dd8..2bc8329 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -564,6 +564,21 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) } #endif +/* + * Construct a PCB from a trapframe. This is called from kdb_trap() where + * we want to start a backtrace from the function that caused us to enter + * the debugger. We have the context in the trapframe, but base the trace + * on the PCB. The PCB doesn't have to be perfect, as long as it contains + * enough for a backtrace. + */ +void +makectx(struct trapframe *tf, struct pcb *pcb) +{ + + pcb->pcb_pc = tf->tf_tpc; + pcb->pcb_sp = tf->tf_sp; +} + int get_mcontext(struct thread *td, mcontext_t *mc, int flags) { |