Date: Tue, 6 Jul 2004 01:12:30 GMT From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 56562 for review Message-ID: <200407060112.i661CUuV098199@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=56562 Change 56562 by marcel@marcel_nfs on 2004/07/06 01:11:30 Implement makectx() on ia64. Tested and working. This gave some complications: unwinding based on the PCB was based on the fact that savectx() was called and thus that the context we cared about was that of the previous function (i.e. the caller. As such, the PC was taken from the return address and the frame state was the previous one. When constructing a PCB from a trapframe, the context we care about is the one that was interrupted. Worse, we cannot simply store the IP and CFM as RP and PFS in the context because that messes up unwinding when those registers actually contain live values. So, a yedi trick was called for: there's a spare field in the pcb_special structure that is explicitly cleared by savectx(). I must have had foresight. When we create the PCB from the trapframe, we write ~0 in that field. From there on we extract the values from the PCB based on that value: when 0 - it's a PCB created by savectx() and we use RP & PFS. Otherwise it's actually a trapframe in disguise and we use IIP & CFM. I haven't given the spare field a name, but it isn't actually spare anymore. This has to sink in first... Affected files ... .. //depot/projects/gdb/sys/ia64/ia64/machdep.c#9 edit .. //depot/projects/gdb/sys/ia64/ia64/unwind.c#6 edit .. //depot/projects/gdb/sys/ia64/include/db_machdep.h#5 edit Differences ... ==== //depot/projects/gdb/sys/ia64/ia64/machdep.c#9 (text+ko) ==== @@ -1017,6 +1017,23 @@ } #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) { ==== //depot/projects/gdb/sys/ia64/ia64/unwind.c#6 (text+ko) ==== @@ -310,7 +310,7 @@ int unw_create_from_frame(struct unw_regstate *rs, struct trapframe *tf) { - uint64_t bsp; + uint64_t bsp, ip; int uwxerr; rs->frame = tf; @@ -326,9 +326,10 @@ bsp = tf->tf_special.bspstore + tf->tf_special.ndirty; bsp = ia64_bsp_adjust(bsp, -IA64_CFM_SOF(tf->tf_special.cfm)); + ip = tf->tf_special.iip + ((tf->tf_special.isr >> 41) & 3); - uwxerr = uwx_init_context(rs->env, tf->tf_special.iip, - tf->tf_special.sp, bsp, tf->tf_special.cfm); + uwxerr = uwx_init_context(rs->env, ip, tf->tf_special.sp, bsp, + tf->tf_special.cfm); return ((uwxerr) ? EINVAL : 0); /* XXX */ } @@ -336,7 +337,7 @@ int unw_create_from_pcb(struct unw_regstate *rs, struct pcb *pcb) { - uint64_t bsp, cfm; + uint64_t bsp, cfm, ip; int uwxerr; rs->frame = NULL; @@ -351,11 +352,16 @@ return (EINVAL); /* XXX */ bsp = pcb->pcb_special.bspstore; - cfm = pcb->pcb_special.pfs; + if (pcb->pcb_special.__spare == ~0UL) { + ip = pcb->pcb_special.iip + ((pcb->pcb_special.isr >> 41) & 3); + cfm = pcb->pcb_special.cfm; + bsp += pcb->pcb_special.ndirty; + } else { + ip = pcb->pcb_special.rp; + cfm = pcb->pcb_special.pfs; + } bsp = ia64_bsp_adjust(bsp, -IA64_CFM_SOL(cfm)); - - uwxerr = uwx_init_context(rs->env, pcb->pcb_special.rp, - pcb->pcb_special.sp, bsp, pcb->pcb_special.pfs); + uwxerr = uwx_init_context(rs->env, ip, pcb->pcb_special.sp, bsp, cfm); return ((uwxerr) ? EINVAL : 0); /* XXX */ } ==== //depot/projects/gdb/sys/ia64/include/db_machdep.h#5 (text+ko) ==== @@ -44,7 +44,9 @@ typedef vm_offset_t db_addr_t; /* address - unsigned */ typedef long db_expr_t; /* expression - signed */ -#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_special.rp) +#define PC_REGS() ((kdb_thrctx->pcb_special.__spare == 0) ? \ + kdb_thrctx->pcb_special.rp : \ + kdb_thrctx->pcb_special.iip + ((kdb_thrctx->pcb_special.psr>>41) & 3)) #define BKPT_WRITE(addr, storage) db_bkpt_write(addr, storage) #define BKPT_CLEAR(addr, storage) db_bkpt_clear(addr, storage) @@ -71,6 +73,4 @@ #define branch_taken(ins, pc, regs) pc -#define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4))) - #endif /* _MACHINE_DB_MACHDEP_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407060112.i661CUuV098199>