📄 sparc-tdep.c
字号:
/* * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Lawrence Berkeley Laboratory, * Berkeley, CA. The name of the University may not be used to * endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Target dependent code for a sparcstation running SunOS. * This is mostly kernel debugging support. * Common code is in sparc-tcmn.c. */#ifndef lintstatic char rcsid[] = "@(#) $Header: sparc-tdep.c,v 1.2 93/02/19 15:25:07 mccanne Exp $ (LBL)";#endif#include <stdio.h>#include "defs.h"#include "frame.h"#include "target.h"#include <machine/reg.h>#ifdef KERNELDEBUG#include "kernel.h"#include <kvm.h>#include <sys/param.h>#include <sys/dir.h>#include <sys/user.h>#include <signal.h>#include <sys/ioctl.h>#include <fcntl.h>extern int kernel_debugging;extern CORE_ADDR ksym_lookup();/* * Read the "thing" at address 'addr' into the space pointed to by P. * The length of the "thing" is determined by the type of P. * Result is non-zero if transfer fails. */#define READMEM(addr, p) \ (target_read_memory((CORE_ADDR)(addr), (char *)(p), sizeof(*(p))))#endif/* * Return the address of the saved pc in frame. */CORE_ADDRaddr_of_pc(frame) struct frame_info *frame;{ register CORE_ADDR addr; register struct rwindow *rw;#ifdef KERNELDEBUG /* * If we are kernel debugging, we must special case trap frames. * We can tell if we are a trap frame by looking at the return * address of the frame below us. If it is in locore, then * we are such a frame and we can find our saved pc in %l1. */ if (kernel_debugging && frame->next) { static CORE_ADDR locore_h, locore_t; if (locore_h == 0) { locore_h = ksym_lookup("sys_trap"); locore_t = ksym_lookup("kadb_tcode"); } rw = (struct rwindow *)frame->next->bottom; addr = read_memory_integer((CORE_ADDR)&rw->rw_in[7], 4); if (addr > locore_h && addr < locore_t) { rw = (struct rwindow *)frame->bottom; return (CORE_ADDR)&rw->rw_local[1]; } }#endif rw = (struct rwindow *)frame->bottom; return (CORE_ADDR)&rw->rw_in[7];}#ifdef KERNELDEBUG/* * The code below implements kernel debugging of crashdumps (or /dev/kmem) * or remote systems (via a serial link). For remote kernels, the remote * context does most the work, so there is very little to do -- we just * manage the kernel stack boundaries so we know where to stop a backtrace. * * The crashdump/kmem (kvm) support is a bit more grungy, but thanks to * libkvm (see kcore.c) not too bad. The main work is kvm_fetch_registers * which sucks the register state out of the current processes pcb. * There is a command that let's you set the current process -- hopefully, * to something that's blocked (in the live kernel case). *//* XXX For misc_function_vector. */#include "symtab.h"/* * Address ranges for the kernel interrupt stack (fixed) and the current * process' kernel stack (dynamic). */static CORE_ADDR intstack_top;static CORE_ADDR intstack_bottom;static CORE_ADDR kernstack_top;static CORE_ADDR kernstack_bottom;static struct proc *curproc;void set_curproc();/* * Return true if ADDR is a valid stack address according to the * current boundaries (which are determined by the currently running * user process). */intinside_kernstack(addr) CORE_ADDR addr;{ if (curproc == 0) set_curproc(); return (addr > intstack_bottom && addr < intstack_top) || (addr > kernstack_bottom && addr < kernstack_top);}/* * (re-)set the variables that make inside_kernstack() work. */voidset_kernel_boundaries(p) struct proc *p;{ CORE_ADDR kstack; if (intstack_top == 0) { intstack_top = ksym_lookup("eintstack"); intstack_bottom = ksym_lookup("intstack"); } /* * During boot, if masterprocp is still NULL the kernel * stack lives in [ubasic..ubasic+KERNSTACK). */ if (p == NULL) kstack = ksym_lookup("ubasic"); else { if (READMEM(&p->p_segu, &kstack)) error("cannot read kernel stack pointer at %x\n", &p->p_segu); } kernstack_bottom = kstack; kernstack_top = kstack + KERNSTACK;}/* * Return the current proc. masterprocp points to * current proc which points to current u area. */struct proc *fetch_curproc(){ struct proc *p; static CORE_ADDR addr; if (addr == 0) addr = ksym_lookup("masterprocp"); if (READMEM(addr, &p)) error("cannot read proc pointer at %x\n", addr); return p;}/* * Called from remote_wait, after the remote kernel has stopped. * Look up the current proc, and set up boundaries. * This is for active kernels only. */voidset_curproc(){ curproc = fetch_curproc(); set_kernel_boundaries(curproc);}/* * All code below is exclusively for support of kernel core files. *//* * Fetch registers from a crashdump or /dev/kmem. */voidkvm_fetch_registers(p) struct proc *p;{ struct user *uaddr; int i; u_long cps, reg, sp; float freg; struct rwindow win; struct pcb pcb; /* find the pcb for the current process */ if (READMEM(&p->p_uarea, &uaddr)) error("cannot u area ptr for proc at 0x%x", p); if (READMEM(&uaddr->u_pcb, &pcb)) error("cannot read pcb at 0x%x", &uaddr->u_pcb); /* * Invalidate all the registers then fill in the ones we know about. */ registers_changed(); sp = pcb.pcb_sp; supply_register(SP_REGNUM, (char *)&pcb.pcb_sp); supply_register(PC_REGNUM, (char *)&pcb.pcb_pc); /* PC came from o7. */ supply_register(15, (char *)&pcb.pcb_pc); supply_register(PS_REGNUM, (char *)&pcb.pcb_psr); /* XXX There should be a WIM_REGNUM. */ supply_register(66, (char *)&pcb.pcb_uwm); /* * Read last register window saved on stack. */ if (READMEM(sp, &win)) { printf("cannot read register window at sp=%x\n", pcb.pcb_sp); bzero((char *)&win, sizeof win); } for (i = 0; i < 8; ++i) supply_register(i + 16, &win.rw_local[i]); for (i = 0; i < 8; ++i) supply_register(i + 24, &win.rw_in[i]); /* * read the globals & outs saved on the stack (for a trap frame). */ sp += 92 + 12; /* XXX - MINFRAME + R_Y */ for (i = 1; i < 14; ++i) { u_long val; if (READMEM(sp + i*4, &val) == 0) supply_register(i, (char *)&val); } if (READMEM(pcb.pcb_cpctxp, &cps) == 0) supply_register(CPS_REGNUM, (char *)&cps);}/* * Set the process context to that of the proc structure at * system address paddr. Read in the register state. */intset_procaddr(paddr) CORE_ADDR paddr;{ struct proc proc; struct user *uaddr; if (paddr == 0) paddr = (CORE_ADDR)fetch_curproc(); if (paddr < KERNELBASE) return (1); if (READMEM(paddr, &proc)) error("cannot read proc struct at 0x%x", paddr); /* * This is REALLY STUPID. The only way to tell libkvm that we want to * change user address maps is with kvm_getu. * If the getu fails, revert to the old address. */ if (kernel_getu((u_long *)&proc) == 0) { (void)READMEM(curproc, &proc); (void)kernel_getu((u_long *)&proc); error("cannot read uarea for proc at 0x%x", paddr); return (1); } curproc = (struct proc *)paddr; set_kernel_boundaries(curproc); kvm_fetch_registers(curproc); return (0);}/* * Get the registers out of a crashdump or /dev/kmem. * XXX This somehow belongs in kcore.c. * * We just get all the registers, so we don't use regno. *//* ARGSUSED */voidkernel_core_registers(regno) int regno;{ /* * Need to find current u area to get kernel stack and pcb * where "panic" saved registers. * (libkvm also needs to know current u area to get user * address space mapping). */ (void)set_procaddr(curproc);}/* * Building in support for stepping through a longjmp is silly. * Couldn't the gdb maintainers spend their time more productively? */intget_longjmp_target(pc) CORE_ADDR *pc;{ return (0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -