diff options
author | Mark Peek <mp@FreeBSD.org> | 2002-10-13 21:22:39 +0000 |
---|---|---|
committer | Mark Peek <mp@FreeBSD.org> | 2002-10-13 21:22:39 +0000 |
commit | 838ce26f5fda580254c3b64f81e5d676a688d714 (patch) | |
tree | 6f9a248ee4c5dba60973a912c14049cf643cf7a8 /devel/gdb66/files/patch-kvm-fbsd.c | |
parent | - Use MASTER_SITE_SUBDIR. (diff) |
Patches to get FreeBSD changes working with gdb-5.3.
Diffstat (limited to 'devel/gdb66/files/patch-kvm-fbsd.c')
-rw-r--r-- | devel/gdb66/files/patch-kvm-fbsd.c | 1209 |
1 files changed, 419 insertions, 790 deletions
diff --git a/devel/gdb66/files/patch-kvm-fbsd.c b/devel/gdb66/files/patch-kvm-fbsd.c index e5a83f189cfb..0bee0da4b20c 100644 --- a/devel/gdb66/files/patch-kvm-fbsd.c +++ b/devel/gdb66/files/patch-kvm-fbsd.c @@ -1,8 +1,9 @@ ---- gdb/kvm-fbsd.c Mon Jun 3 11:32:24 2002 -+++ gdb/kvm-fbsd.c Mon Jun 3 11:30:35 2002 -@@ -0,0 +1,1055 @@ -+/* Live and postmortem kernel debugging functions for FreeBSD. -+ Copyright 1996 Free Software Foundation, Inc. +--- gdb/kvm-fbsd.c Wed Dec 31 16:00:00 1969 ++++ gdb/kvm-fbsd.c Sun Oct 13 13:57:00 2002 +@@ -0,0 +1,684 @@ ++/* Kernel core dump functions below target vector, for GDB. ++ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995 ++ Free Software Foundation, Inc. + +This file is part of GDB. + @@ -18,22 +19,38 @@ + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software -+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++*/ + -+/* $FreeBSD: /tmp/pcvs/ports/devel/gdb66/files/Attic/patch-kvm-fbsd.c,v 1.1 2002-06-06 03:56:34 mp Exp $ */ ++/* $FreeBSD: /tmp/pcvs/ports/devel/gdb66/files/Attic/patch-kvm-fbsd.c,v 1.2 2002-10-13 21:22:39 mp Exp $ */ + -+#include "defs.h" ++/* ++ * This works like "remote" but, you use it like this: ++ * target kcore /dev/mem ++ * or ++ * target kcore /var/crash/host/core.0 ++ * ++ * This way makes it easy to short-circut the whole bfd monster, ++ * and direct the inferior stuff to our libkvm implementation. ++ * ++ */ + ++#include <sys/param.h> ++#include <sys/time.h> ++#include <sys/proc.h> ++#include <sys/user.h> +#include <ctype.h> +#include <errno.h> +#include <signal.h> +#include <fcntl.h> -+#include <paths.h> ++#include <kvm.h> +#include <sys/sysctl.h> -+#include <sys/param.h> -+#include <sys/time.h> -+#include <sys/proc.h> -+#include <sys/user.h> ++#include <paths.h> ++#include <readline/tilde.h> ++#include <machine/frame.h> ++ ++#include "defs.h" ++#include "gdb_string.h" +#include "frame.h" /* required by inferior.h */ +#include "inferior.h" +#include "symtab.h" @@ -43,254 +60,199 @@ +#include "bfd.h" +#include "target.h" +#include "gdbcore.h" -+#include <sys/stat.h> -+#include <unistd.h> -+#include <vm/vm.h> -+#include <vm/vm_param.h> -+ -+#include <machine/vmparam.h> -+#include <machine/pcb.h> -+#include <machine/tss.h> -+#include <machine/frame.h> -+ -+#if __FreeBSD_version >= 500032 && defined(i386) -+#define _KERNEL -+#include <sys/pcpu.h> -+#undef _KERNEL -+ -+static void kcore_files_info PARAMS ((struct target_ops *)); -+ -+static void kcore_close PARAMS ((int)); -+ -+static void get_kcore_registers PARAMS ((int)); ++#include "regcache.h" + -+static int kcore_xfer_kmem PARAMS ((CORE_ADDR, char *, int, int, struct mem_attrib *attrib, struct target_ops *)); -+ -+static int xfer_umem PARAMS ((CORE_ADDR, char *, int, int)); -+ -+static CORE_ADDR ksym_lookup PARAMS ((const char *)); -+ -+static int read_pcb PARAMS ((int, CORE_ADDR)); -+ -+static struct proc * curProc PARAMS ((void)); -+ -+static int set_proc_context PARAMS ((CORE_ADDR paddr)); -+ -+static void kcore_open PARAMS ((char *filename, int from_tty)); -+ -+static void kcore_detach PARAMS ((char *args, int from_tty)); -+ -+static void set_proc_cmd PARAMS ((char *arg, int from_tty)); -+ -+static void set_cpu_cmd PARAMS ((char *arg, int from_tty)); ++static void ++kcore_files_info (struct target_ops *); + -+static CORE_ADDR kvtophys PARAMS ((int, CORE_ADDR)); ++static void ++kcore_close (int); + -+static int physrd PARAMS ((int, u_int, char*, int)); ++static void ++get_kcore_registers (int); + -+static int kvm_open PARAMS ((const char *efile, char *cfile, char *sfile, -+ int perm, char *errout)); ++static int ++xfer_mem (CORE_ADDR, char *, int, int, struct mem_attrib *, ++ struct target_ops *); + -+static int kvm_close PARAMS ((int fd)); ++static int ++xfer_umem (CORE_ADDR, char *, int, int); + -+static int kvm_write PARAMS ((int core_kd, CORE_ADDR memaddr, -+ char *myaddr, int len)); ++static char *core_file; ++static kvm_t *core_kd; ++static struct pcb cur_pcb; ++static struct kinfo_proc *cur_proc; + -+static int kvm_read PARAMS ((int core_kd, CORE_ADDR memaddr, -+ char *myaddr, int len)); ++static struct target_ops kcore_ops; + -+static int kvm_uread PARAMS ((int core_kd, struct proc *p, -+ CORE_ADDR memaddr, char *myaddr, -+ int len)); ++int kernel_debugging; ++int kernel_writablecore; + -+static int kernel_core_file_hook PARAMS ((int fd, CORE_ADDR addr, -+ char *buf, int len)); ++/* Read the "thing" at kernel address 'addr' into the space pointed to ++ by point. The length of the "thing" is determined by the type of p. ++ Result is non-zero if transfer fails. */ + -+static CORE_ADDR kvm_getpcpu PARAMS ((int cfd, int cpuid)); ++#define kvread(addr, p) \ ++ (target_read_memory ((CORE_ADDR) (addr), (char *) (p), sizeof (*(p)))) + -+static struct kinfo_proc * kvm_getprocs PARAMS ((int cfd, int op, -+ CORE_ADDR proc, int *cnt)); ++static CORE_ADDR ++ksym_kernbase (void) ++{ ++ static CORE_ADDR kernbase; ++ struct minimal_symbol *sym; + -+extern struct target_ops kcore_ops; /* Forward decl */ ++ if (kernbase == 0) ++ { ++ sym = lookup_minimal_symbol ("kernbase", NULL, NULL); ++ if (sym == NULL) { ++ kernbase = KERNBASE; ++ } else { ++ kernbase = SYMBOL_VALUE_ADDRESS (sym); ++ } ++ } ++ return kernbase; ++} + -+/* Non-zero means we are debugging a kernel core file */ -+int kernel_debugging = 0; -+int kernel_writablecore = 0; ++#define KERNOFF (ksym_kernbase ()) ++#define INKERNEL(x) ((x) >= KERNOFF) + -+static char *core_file; -+static int core_kd = -1; -+static struct proc *cur_proc; -+static CORE_ADDR kernel_start; ++CORE_ADDR ++ksym_lookup(const char *name) ++{ ++ struct minimal_symbol *sym; + -+static CORE_ADDR pcpu; -+#define PCPU_OFFSET(name) \ -+ offsetof(struct pcpu, pc_ ## name) ++ sym = lookup_minimal_symbol (name, NULL, NULL); ++ if (sym == NULL) ++ error ("kernel symbol `%s' not found.", name); + -+/* -+ * Symbol names of kernel entry points. Use special frames. -+ */ -+#define KSYM_TRAP "calltrap" -+#define KSYM_INTR "Xintr" -+#define KSYM_FASTINTR "Xfastintr" -+#define KSYM_SYSCALL "Xsyscall" ++ return SYMBOL_VALUE_ADDRESS (sym); ++} + -+/* -+ * Read the "thing" at kernel address 'addr' into the space pointed to -+ * by point. The length of the "thing" is determined by the type of p. -+ * Result is non-zero if transfer fails. -+ */ -+#define kvread(addr, p) \ -+ (target_read_memory ((CORE_ADDR)(addr), (char *)(p), sizeof(*(p)))) ++/* Provide the address of an initial PCB to use. ++ If this is a crash dump, try for "dumppcb". ++ If no "dumppcb" or it's /dev/mem, use proc0. ++ Return the core address of the PCB we found. */ + ++static CORE_ADDR ++initial_pcb (void) ++{ ++ struct minimal_symbol *sym; ++ CORE_ADDR addr; ++ void *val; + ++ /* Make sure things are open... */ ++ if (!core_kd || !core_file) ++ return (0); + -+/* -+ * The following is FreeBSD-specific hackery to decode special frames -+ * and elide the assembly-language stub. This could be made faster by -+ * defining a frame_type field in the machine-dependent frame information, -+ * but we don't think that's too important right now. -+ */ -+enum frametype { tf_normal, tf_trap, tf_interrupt, tf_syscall }; ++ /* If this is NOT /dev/mem try for dumppcb. */ ++ if (strncmp (core_file, _PATH_DEV, sizeof _PATH_DEV - 1)) ++ { ++ sym = lookup_minimal_symbol ("dumppcb", NULL, NULL); ++ if (sym != NULL) ++ { ++ addr = SYMBOL_VALUE_ADDRESS (sym); ++ return (addr); ++ } ++ } + -+CORE_ADDR -+fbsd_kern_frame_saved_pc (fr) -+struct frame_info *fr; -+{ -+ struct minimal_symbol *sym; -+ CORE_ADDR this_saved_pc; -+ enum frametype frametype; -+ -+ this_saved_pc = read_memory_integer (fr->frame + 4, 4); -+ sym = lookup_minimal_symbol_by_pc (this_saved_pc); -+ frametype = tf_normal; -+ if (sym != NULL) { -+ if (strcmp (SYMBOL_NAME(sym), KSYM_TRAP) == 0) -+ frametype = tf_trap; -+ else if (strncmp (SYMBOL_NAME(sym), KSYM_INTR, -+ strlen(KSYM_INTR)) == 0 || strncmp (SYMBOL_NAME(sym), -+ KSYM_FASTINTR, strlen(KSYM_FASTINTR)) == 0) -+ frametype = tf_interrupt; -+ else if (strcmp (SYMBOL_NAME(sym), KSYM_SYSCALL) == 0) -+ frametype = tf_syscall; -+ } -+ -+ switch (frametype) { -+ case tf_normal: -+ return (this_saved_pc); -+ -+#define oEIP offsetof(struct trapframe, tf_eip) -+ -+ case tf_trap: -+ return (read_memory_integer (fr->frame + 8 + oEIP, 4)); -+ -+ case tf_interrupt: -+ return (read_memory_integer (fr->frame + 12 + oEIP, 4)); -+ -+ case tf_syscall: -+ return (read_memory_integer (fr->frame + 8 + oEIP, 4)); -+#undef oEIP -+ } -+} ++ /* OK, just use thread0's pcb. Note that curproc might ++ not exist, and if it does, it will point to gdb. ++ Therefore, just use proc0 and let the user set ++ some other context if they care about it. */ + -+static CORE_ADDR -+ksym_lookup (name) -+const char *name; -+{ -+ struct minimal_symbol *sym; ++ addr = ksym_lookup ("thread0"); ++ if (kvread (addr, &val)) ++ { ++ error ("cannot read thread0 pointer at %x\n", addr); ++ val = 0; ++ } ++ else ++ { ++ /* Read the PCB address in thread structure. */ ++ addr += offsetof (struct thread, td_pcb); ++ if (kvread (addr, &val)) ++ { ++ error ("cannot read thread0->td_pcb pointer at %x\n", addr); ++ val = 0; ++ } ++ } + -+ sym = lookup_minimal_symbol (name, NULL, NULL); -+ if (sym == NULL) -+ error ("kernel symbol `%s' not found.", name); ++ /* thread0 is wholly in the kernel and cur_proc is only used for ++ reading user mem, so no point in setting this up. */ ++ cur_proc = 0; + -+ return SYMBOL_VALUE_ADDRESS (sym); ++ return ((CORE_ADDR)val); +} + -+static struct proc * -+curProc () -+{ -+ struct proc *p; -+ struct thread *td; -+ CORE_ADDR addr = pcpu + PCPU_OFFSET (curthread); -+ -+ if (kvread (addr, &td)) -+ error ("cannot read thread pointer at %x\n", addr); -+ addr = (CORE_ADDR)td + offsetof(struct thread, td_proc); -+ if (kvread (addr, &p)) -+ error ("cannot read proc pointer at %x\n", addr); -+ return p; -+} ++/* Set the current context to that of the PCB struct at the system address ++ passed. */ + -+/* -+ * Set the process context to that of the proc structure at -+ * system address paddr. -+ */ +static int -+set_proc_context (paddr) -+ CORE_ADDR paddr; ++set_context (CORE_ADDR addr) +{ -+ struct proc p; ++ CORE_ADDR procaddr = 0; + -+ if (paddr < kernel_start) -+ return (1); -+ -+ cur_proc = (struct proc *)paddr; -+#ifdef notyet -+ set_kernel_boundaries (cur_proc); -+#endif ++ if (kvread (addr, &cur_pcb)) ++ error ("cannot read pcb at %#x", addr); + -+ /* Fetch all registers from core file */ ++ /* Fetch all registers from core file. */ + target_fetch_registers (-1); + -+ /* Now, set up the frame cache, and print the top of stack */ ++ /* Now, set up the frame cache, and print the top of stack. */ + flush_cached_frames (); + set_current_frame (create_new_frame (read_fp (), read_pc ())); -+ select_frame (get_current_frame (), 0); ++ select_frame (get_current_frame ()); + return (0); +} + -+/* Discard all vestiges of any previous core file -+ and mark data and stack spaces as empty. */ ++/* Discard all vestiges of any previous core file and mark data and stack ++ spaces as empty. */ + +/* ARGSUSED */ +static void -+kcore_close (quitting) -+ int quitting; ++kcore_close (int quitting) +{ -+ inferior_ptid = null_ptid; /* Avoid confusion from thread stuff */ ++ ++ inferior_ptid = null_ptid; /* Avoid confusion from thread stuff. */ + + if (core_kd) + { + kvm_close (core_kd); + free (core_file); + core_file = NULL; -+ core_kd = -1; ++ core_kd = NULL; + } +} + -+/* This routine opens and sets up the core file bfd */ ++/* This routine opens and sets up the core file bfd. */ + +static void -+kcore_open (filename, from_tty) -+ char *filename; -+ int from_tty; ++kcore_open (char *filename /* the core file */, int from_tty) +{ ++ kvm_t *kd; + const char *p; + struct cleanup *old_chain; + char buf[256], *cp; + int ontop; + CORE_ADDR addr; -+ struct pcb pcb; + + target_preopen (from_tty); + -+ unpush_target (&kcore_ops); ++ /* The exec file is required for symbols. */ ++ if (exec_bfd == NULL) ++ error ("No kernel exec file specified"); ++ ++ if (core_kd) ++ { ++ error ("No core file specified." ++ " (Use `detach' to stop debugging a core file.)"); ++ return; ++ } + + if (!filename) + { -+ /*error (core_kd?*/ -+ error ( (core_kd >= 0)? -+ "No core file specified. (Use `detach' to stop debugging a core file.)" -+ : "No core file specified."); ++ error ("No core file specified."); ++ return; + } + + filename = tilde_expand (filename); @@ -303,76 +265,66 @@ + + old_chain = make_cleanup (free, filename); + -+ /* -+ * gdb doesn't really do anything if the exec-file couldn't -+ * be opened (in that case exec_bfd is NULL). Usually that's -+ * no big deal, but kvm_open needs the exec-file's name, -+ * which results in dereferencing a NULL pointer, a real NO-NO ! -+ * So, check here if the open of the exec-file succeeded. -+ */ -+ if (exec_bfd == NULL) /* the open failed */ -+ error ("kgdb could not open the exec-file, please check the name you used !"); -+ -+ core_kd = kvm_open (exec_bfd->filename, filename, NULL, -+ kernel_writablecore? O_RDWR : O_RDONLY, "kgdb: "); -+ if (core_kd < 0) -+ perror_with_name (filename); ++ kd = kvm_open (bfd_get_filename(exec_bfd), filename, NULL, ++ kernel_writablecore ? O_RDWR: O_RDONLY, 0); ++ if (kd == NULL) ++ { ++ perror_with_name (filename); ++ return; ++ } + -+ /* Looks semi-reasonable. Toss the old core file and work on the new. */ ++ /* Looks semi-reasonable. Toss the old core file and work on the new. */ + -+ discard_cleanups (old_chain); /* Don't free filename any more */ ++ discard_cleanups (old_chain); /* Don't free filename any more. */ + core_file = filename; ++ unpush_target (&kcore_ops); + ontop = !push_target (&kcore_ops); + -+ kernel_start = bfd_get_start_address (exec_bfd); /* XXX */ ++ /* Note unpush_target (above) calls kcore_close. */ ++ core_kd = kd; + -+ /* print out the panic string if there is one */ -+ if (kvread (ksym_lookup ("panicstr"), &addr) == 0 -+ && addr != 0 -+ && target_read_memory (addr, buf, sizeof (buf)) == 0) ++ /* Print out the panic string if there is one. */ ++ if (kvread (ksym_lookup ("panicstr"), &addr) == 0 && ++ addr != 0 && ++ target_read_memory (addr, buf, sizeof(buf)) == 0) + { -+ for (cp = buf; cp < &buf[sizeof (buf)] && *cp; cp++) ++ ++ for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++) + if (!isascii (*cp) || (!isprint (*cp) && !isspace (*cp))) + *cp = '?'; + *cp = '\0'; + if (buf[0] != '\0') -+ printf ("panicstr: %s\n", buf); ++ printf_filtered ("panic: %s\n", buf); + } + -+ /* Print all the panic messages if possible. */ ++ /* Print all the panic messages if possible. */ + if (symfile_objfile != NULL) + { + printf ("panic messages:\n---\n"); + snprintf (buf, sizeof buf, -+ "/sbin/dmesg -N %s -M %s | \ -+ /usr/bin/awk '/^(panic:|Fatal trap) / { printing = 1 } \ -+ { if (printing) print $0 }'", -+ symfile_objfile->name, filename); -+ fflush(stdout); ++ "/sbin/dmesg -N %s -M %s | \ ++ /usr/bin/awk '/^(panic:|Fatal trap) / { printing = 1 } \ ++ { if (printing) print $0 }'", ++ symfile_objfile->name, filename); ++ fflush (stdout); + system (buf); + printf ("---\n"); + } + + if (!ontop) + { -+ warning ("you won't be able to access this core file until you terminate\n\ -+your %s; do ``info files''", target_longname); ++ warning ("you won't be able to access this core file until you terminate\n" ++ "your %s; do ``info files''", target_longname); + return; + } + -+ /* we may need this later */ -+ cur_proc = (struct proc *)curProc (); -+ /* Now, set up the frame cache, and print the top of stack */ -+ flush_cached_frames (); -+ set_current_frame (create_new_frame (read_fp (), read_pc ())); -+ select_frame (get_current_frame (), 0); -+ print_stack_frame (selected_frame, selected_frame_level, 1); ++ /* Now, set up process context, and print the top of stack. */ ++ (void)set_context (initial_pcb()); ++ print_stack_frame (selected_frame, frame_relative_level(selected_frame), 1); +} + +static void -+kcore_detach (args, from_tty) -+ char *args; -+ int from_tty; ++kcore_detach (char *args, int from_tty) +{ + if (args) + error ("Too many arguments"); @@ -382,39 +334,70 @@ + printf_filtered ("No kernel core file now.\n"); +} + -+/* Get the registers out of a core file. This is the machine- -+ independent part. Fetch_core_registers is the machine-dependent -+ part, typically implemented in the xm-file for each architecture. */ ++#ifdef __alpha__ + -+/* We just get all the registers, so we don't use regno. */ -+/* ARGSUSED */ -+static void -+get_kcore_registers (regno) -+ int regno; ++#include "alpha/tm-alpha.h" ++#include "alpha-tdep.h" ++ ++#ifndef S0_REGNUM ++#define S0_REGNUM (ALPHA_T7_REGNUM+1) ++#endif ++ ++fetch_kcore_registers (struct pcb *pcbp) +{ -+ struct pcb *pcbaddr; -+ struct thread *mainthread; -+ -+ /* find the pcb for the current process */ -+ if (cur_proc == NULL) -+ error ("get_kcore_registers no proc"); -+ if (kvread (&TAILQ_FIRST(&cur_proc->p_threads), &mainthread)) /* XXXKSE */ -+ error ("cannot read main thread for proc at %#x", cur_proc); -+ if (kvread (&mainthread->td_pcb, &pcbaddr)) /* XXXKSE */ -+ error ("cannot read pcb pointer for proc at %#x", cur_proc); -+ if (read_pcb (core_kd, (CORE_ADDR)pcbaddr) < 0) -+ error ("cannot read pcb at %#x", pcbaddr); ++ ++ /* First clear out any garbage. */ ++ memset (registers, '\0', REGISTER_BYTES); ++ ++ /* SP */ ++ *(long *) ®isters[REGISTER_BYTE (SP_REGNUM)] = ++ pcbp->pcb_hw.apcb_ksp; ++ ++ /* S0 through S6 */ ++ memcpy (®isters[REGISTER_BYTE (S0_REGNUM)], ++ &pcbp->pcb_context[0], 7 * sizeof (long)); ++ ++ /* PC */ ++ *(long *) ®isters[REGISTER_BYTE (PC_REGNUM)] = ++ pcbp->pcb_context[7]; ++ ++ registers_fetched (); +} + -+static void -+kcore_files_info (t) -+ struct target_ops *t; ++ ++CORE_ADDR ++fbsd_kern_frame_saved_pc (struct frame_info *fi) +{ -+ printf ("\t`%s'\n", core_file); ++ struct minimal_symbol *sym; ++ CORE_ADDR this_saved_pc; ++ ++ this_saved_pc = FRAME_SAVED_PC(fi); ++ ++ sym = lookup_minimal_symbol_by_pc (this_saved_pc); ++ ++ if (sym != NULL && ++ (strcmp (SYMBOL_NAME (sym), "XentArith") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentIF") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentInt") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentMM") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentSys") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentUna") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentRestart") == 0)) ++ { ++ return (read_memory_integer (fi->frame + 32 * 8, 8)); ++ } ++ else ++ { ++ return (this_saved_pc); ++ } +} + ++#endif /* __alpha__ */ ++ ++#ifdef __i386__ ++ +static CORE_ADDR -+ksym_maxuseraddr() ++ksym_maxuseraddr (void) +{ + static CORE_ADDR maxuseraddr; + struct minimal_symbol *sym; @@ -431,608 +414,256 @@ + return maxuseraddr; +} + -+static int -+kcore_xfer_kmem (memaddr, myaddr, len, write, attrib, target) -+ CORE_ADDR memaddr; -+ char *myaddr; -+ int len; -+ int write; -+ struct mem_attrib *attrib; -+ struct target_ops *target; -+{ -+ int ns; -+ int nu; + -+ if (memaddr >= ksym_maxuseraddr()) -+ nu = 0; -+ else -+ { -+ nu = xfer_umem (memaddr, myaddr, len, write); -+ if (nu <= 0) -+ return (0); -+ if (nu == len) -+ return (nu); -+ memaddr += nu; -+ if (memaddr != ksym_maxuseraddr()) -+ return (nu); -+ myaddr += nu; -+ len -= nu; -+ } -+ -+ ns = (write ? kvm_write : kvm_read) (core_kd, memaddr, myaddr, len); -+ if (ns < 0) -+ ns = 0; -+ -+ return (nu + ns); -+} -+ -+static int -+xfer_umem (memaddr, myaddr, len, write) -+ CORE_ADDR memaddr; -+ char *myaddr; -+ int len; -+ int write; /* ignored */ -+{ -+ int n; -+ struct proc proc; -+ -+ if (cur_proc == NULL || kvread (cur_proc, &proc)) -+ error ("cannot read proc at %#x", cur_proc); -+ n = kvm_uread (core_kd, &proc, memaddr, myaddr, len) ; ++/* Symbol names of kernel entry points. Use special frames. */ ++#define KSYM_TRAP "calltrap" ++#define KSYM_INTR "Xintr" ++#define KSYM_FASTINTR "Xfastintr" ++#define KSYM_OLDSYSCALL "Xlcall_syscall" ++#define KSYM_SYSCALL "Xint0x80_syscall" + -+ if (n < 0) -+ return 0; -+ return n; -+} ++/* The following is FreeBSD-specific hackery to decode special frames ++ and elide the assembly-language stub. This could be made faster by ++ defining a frame_type field in the machine-dependent frame information, ++ but we don't think that's too important right now. */ ++enum frametype { tf_normal, tf_trap, tf_interrupt, tf_syscall }; + -+static CORE_ADDR -+ksym_kernbase() ++CORE_ADDR ++fbsd_kern_frame_saved_pc (struct frame_info *fr) +{ -+ static CORE_ADDR kernbase; + struct minimal_symbol *sym; ++ CORE_ADDR this_saved_pc; ++ enum frametype frametype; + -+ if (kernbase == 0) ++ this_saved_pc = read_memory_integer (fr->frame + 4, 4); ++ sym = lookup_minimal_symbol_by_pc (this_saved_pc); ++ frametype = tf_normal; ++ if (sym != NULL) + { -+ sym = lookup_minimal_symbol ("kernbase", NULL, NULL); -+ if (sym == NULL) { -+ kernbase = KERNBASE; -+ } else { -+ kernbase = SYMBOL_VALUE_ADDRESS (sym); -+ } ++ if (strcmp (SYMBOL_NAME (sym), KSYM_TRAP) == 0) ++ frametype = tf_trap; ++ else ++ if (strncmp (SYMBOL_NAME (sym), KSYM_INTR, ++ strlen (KSYM_INTR)) == 0 || strncmp (SYMBOL_NAME(sym), ++ KSYM_FASTINTR, strlen (KSYM_FASTINTR)) == 0) ++ frametype = tf_interrupt; ++ else ++ if (strcmp (SYMBOL_NAME (sym), KSYM_SYSCALL) == 0 || ++ strcmp (SYMBOL_NAME (sym), KSYM_OLDSYSCALL) == 0) ++ frametype = tf_syscall; + } -+ return kernbase; -+} + -+#define KERNOFF (ksym_kernbase()) -+#define INKERNEL(x) ((x) >= KERNOFF) ++ switch (frametype) ++ { ++ default: ++ case tf_normal: ++ return (this_saved_pc); ++#define oEIP offsetof (struct trapframe, tf_eip) + -+static CORE_ADDR sbr; -+static CORE_ADDR curpcb; -+static int found_pcb; -+static int devmem; -+static int kfd; -+static struct pcb pcb; ++ case tf_trap: ++ return (read_memory_integer (fr->frame + 8 + oEIP, 4)); + -+static void -+set_proc_cmd (arg, from_tty) -+ char *arg; -+ int from_tty; -+{ -+ CORE_ADDR paddr; -+ struct kinfo_proc *kp; -+ int cnt = 0; ++ case tf_interrupt: ++ return (read_memory_integer (fr->frame + 12 + oEIP, 4)); + -+ if (!arg) -+ error_no_arg ("proc address for new current process"); -+ if (!kernel_debugging) -+ error ("not debugging kernel"); -+ -+ paddr = (CORE_ADDR)parse_and_eval_address (arg); -+ /* assume it's a proc pointer if it's in the kernel */ -+ if (paddr >= kernel_start) { -+ if (set_proc_context(paddr)) -+ error("invalid proc address"); -+ } else { -+ kp = kvm_getprocs(core_kd, KERN_PROC_PID, paddr, &cnt); -+ if (!cnt) -+ error("invalid pid"); -+ if (set_proc_context((CORE_ADDR)kp->ki_paddr)) -+ error("invalid proc address"); -+ } ++ case tf_syscall: ++ return (read_memory_integer (fr->frame + 8 + oEIP, 4)); ++#undef oEIP ++ } +} + +static void -+set_cpu_cmd (arg, from_tty) -+ char *arg; -+ int from_tty; ++fetch_kcore_registers (struct pcb *pcb) +{ -+ CORE_ADDR paddr; -+ CORE_ADDR pcaddr; -+ struct kinfo_proc *kp; -+ int cpu, cfd; ++ int i; ++ int noreg; + -+ if (!arg) -+ error_no_arg ("cpu number"); -+ if (!kernel_debugging) -+ error ("not debugging kernel"); ++ /* Get the register values out of the sys pcb and store them where ++ `read_register' will find them. */ ++ /* ++ * XXX many registers aren't available. ++ * XXX for the non-core case, the registers are stale - they are for ++ * the last context switch to the debugger. ++ * XXX gcc's register numbers aren't all #defined in tm-i386.h. ++ */ ++ noreg = 0; ++ for (i = 0; i < 3; ++i) /* eax,ecx,edx */ ++ supply_register (i, (char *)&noreg); + -+ cfd = core_kd; -+ cpu = (int)parse_and_eval_address (arg); -+ if ((pcaddr = kvm_getpcpu (cfd, cpu)) == NULL) -+ error ("cpu number out of range"); ++ supply_register (3, (char *) &pcb->pcb_ebx); ++ supply_register (SP_REGNUM, (char *) &pcb->pcb_esp); ++ supply_register (FP_REGNUM, (char *) &pcb->pcb_ebp); ++ supply_register (6, (char *) &pcb->pcb_esi); ++ supply_register (7, (char *) &pcb->pcb_edi); ++ supply_register (PC_REGNUM, (char *) &pcb->pcb_eip); + -+ pcpu = pcaddr; -+ curpcb = kvtophys(cfd, pcpu + PCPU_OFFSET (curpcb)); -+ physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb); ++ for (i = 9; i < 14; ++i) /* eflags, cs, ss, ds, es, fs */ ++ supply_register (i, (char *) &noreg); ++ supply_register (15, (char *) &pcb->pcb_gs); + -+ if (!devmem) -+ paddr = ksym_lookup ("dumppcb") - KERNOFF; -+ else -+ paddr = kvtophys (cfd, curpcb); -+ read_pcb (cfd, paddr); -+ printf ("initial pcb at %lx\n", (unsigned long)paddr); ++ /* XXX 80387 registers? */ ++} + -+ if ((cur_proc = curProc())) -+ target_fetch_registers (-1); ++#endif /* __i386__ */ + -+ /* Now, set up the frame cache, and print the top of stack */ -+ flush_cached_frames (); -+ set_current_frame (create_new_frame (read_fp (), read_pc ())); -+ select_frame (get_current_frame (), 0); -+ print_stack_frame (selected_frame, selected_frame_level, 1); -+} ++#ifdef __sparc64__ + -+/* substitutes for the stuff in libkvm which doesn't work */ -+/* most of this was taken from the old kgdb */ ++/* ++#include "sparc/tm-sp64.h" ++*/ + -+/* we don't need all this stuff, but the call should look the same */ ++fetch_kcore_registers (struct pcb *pcbp) ++{ ++} + -+static int -+kvm_open (efile, cfile, sfile, perm, errout) -+ const char *efile; -+ char *cfile; -+ char *sfile; /* makes this kvm_open more compatible to the one in libkvm */ -+ int perm; -+ char *errout; /* makes this kvm_open more compatible to the one in libkvm */ ++ ++CORE_ADDR ++fbsd_kern_frame_saved_pc (struct frame_info *fi) +{ -+ struct stat stb; -+ int cfd; -+ CORE_ADDR paddr; ++ return NULL; ++} + -+ if ((cfd = open (cfile, perm, 0)) < 0) -+ return (cfd); ++#endif /* __sparc64__ */ + -+ if ((pcpu = kvm_getpcpu (cfd, 0)) == NULL) -+ return (-1); ++/* Get the registers out of a core file. This is the machine- ++ independent part. Fetch_core_registers is the machine-dependent ++ part, typically implemented in the xm-file for each architecture. */ + -+ fstat (cfd, &stb); -+ if ((stb.st_mode & S_IFMT) == S_IFCHR -+ && stb.st_rdev == makedev (2, 0)) -+ { -+ devmem = 1; -+ kfd = open (_PATH_KMEM, perm, 0); -+ } ++/* We just get all the registers, so we don't use regno. */ + -+ physrd (cfd, ksym_lookup ("IdlePTD") - KERNOFF, (char*)&sbr, sizeof sbr); -+ printf ("IdlePTD at phsyical address 0x%08lx\n", (unsigned long)sbr); -+ curpcb = kvtophys(cfd, pcpu + PCPU_OFFSET (curpcb)); -+ physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb); ++/* ARGSUSED */ ++static void ++get_kcore_registers (int regno) ++{ + -+ found_pcb = 1; /* for vtophys */ -+ if (!devmem) -+ paddr = ksym_lookup ("dumppcb") - KERNOFF; -+ else -+ paddr = kvtophys (cfd, curpcb); -+ read_pcb (cfd, paddr); -+ printf ("initial pcb at physical address 0x%08lx\n", (unsigned long)paddr); ++ /* XXX - Only read the pcb when set_context() is called. ++ When looking at a live kernel this may be a problem, ++ but the user can do another "proc" or "pcb" command to ++ grab a new copy of the pcb... */ + -+ return (cfd); ++ /* Zero out register set then fill in the ones we know about. */ ++ fetch_kcore_registers (&cur_pcb); +} + -+static int -+kvm_close (fd) -+ int fd; ++static void ++kcore_files_info (t) ++ struct target_ops *t; +{ -+ return (close (fd)); ++ printf_filtered ("\t`%s'\n", core_file); +} ++ ++/* If mourn is being called in all the right places, this could be say ++ `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */ + +static int -+kvm_write (core_kd, memaddr, myaddr, len) -+ int core_kd; -+ CORE_ADDR memaddr; -+ char *myaddr; ++ignore (CORE_ADDR addr, char *contents) +{ -+ int cc; -+ -+ if (devmem) -+ { -+ if (kfd > 0) -+ { -+ /* -+ * Just like kvm_read, only we write. -+ */ -+ errno = 0; -+ if (lseek (kfd, (off_t)memaddr, 0) < 0 -+ && errno != 0) -+ { -+ error ("kvm_write:invalid address (%x)", memaddr); -+ return (0); -+ } -+ cc = write (kfd, myaddr, len); -+ if (cc < 0) -+ { -+ error ("kvm_write:write failed"); -+ return (0); -+ } -+ else if (cc < len) -+ error ("kvm_write:short write"); -+ return (cc); -+ } -+ else -+ return (0); -+ } -+ else -+ { -+ printf ("kvm_write not implemented for dead kernels\n"); -+ return (0); -+ } -+ /* NOTREACHED */ ++ return 0; +} + +static int -+kvm_read (core_kd, memaddr, myaddr, len) -+ int core_kd; -+ CORE_ADDR memaddr; -+ char *myaddr; ++xfer_kmem (CORE_ADDR memaddr, char *myaddr, int len, int write, ++ struct mem_attrib *attrib, struct target_ops *target) +{ -+ return (kernel_core_file_hook (core_kd, memaddr, myaddr, len)); -+} ++ int n; + -+static int -+kvm_uread (core_kd, p, memaddr, myaddr, len) -+ int core_kd; -+ register struct proc *p; -+ CORE_ADDR memaddr; -+ char *myaddr; -+ int len; -+{ -+ register char *cp; -+ char procfile[MAXPATHLEN]; -+ ssize_t amount; -+ int fd; + -+ if (devmem) -+ { -+ sprintf (procfile, "/proc/%d/mem", p->p_pid); -+ fd = open (procfile, O_RDONLY, 0); -+ if (fd < 0) -+ { -+ error ("cannot open %s", procfile); -+ close (fd); -+ return (0); -+ } ++ if (!INKERNEL (memaddr)) ++ return xfer_umem (memaddr, myaddr, len, write); + -+ cp = myaddr; -+ while (len > 0) -+ { -+ errno = 0; -+ if (lseek (fd, (off_t)memaddr, 0) == -1 && errno != 0) -+ { -+ error ("invalid address (%x) in %s", memaddr, procfile); -+ break; -+ } -+ amount = read (fd, cp, len); -+ if (amount < 0) -+ { -+ error ("error reading %s", procfile); -+ break; -+ } -+ if (amount == 0) -+ { -+ error ("EOF reading %s", procfile); -+ break; -+ } -+ cp += amount; -+ memaddr += amount; -+ len -= amount; -+ } ++ if (core_kd == NULL) ++ return 0; + -+ close (fd); -+ return ((ssize_t) (cp - myaddr)); -+ } ++ if (write) ++ n = kvm_write (core_kd, memaddr, myaddr, len); + else -+ return (kernel_core_file_hook (core_kd, memaddr, myaddr, len)); ++ n = kvm_read (core_kd, memaddr, myaddr, len) ; ++ if (n < 0) { ++ fprintf_unfiltered (gdb_stderr, "can not access 0x%x, %s\n", ++ memaddr, kvm_geterr (core_kd)); ++ n = 0; ++ } ++ ++ return n; +} + -+static struct kinfo_proc kp; + -+/* -+ * try to do what kvm_proclist in libkvm would do -+ */ +static int -+kvm_proclist (cfd, pid, p, cnt) -+int cfd, pid, *cnt; -+struct proc *p; ++xfer_umem (CORE_ADDR memaddr, char *myaddr, int len, int write /* ignored */) +{ -+ struct proc lp; -+ -+ for (; p != NULL; p = LIST_NEXT(&lp, p_list)) { -+ if (!kvm_read(cfd, (CORE_ADDR)p, (char *)&lp, sizeof (lp))) -+ return (0); -+ if (lp.p_pid != pid) -+ continue; -+ kp.ki_paddr = p; -+ *cnt = 1; -+ return (1); -+ } -+ *cnt = 0; -+ return (0); -+} ++ int n = 0; + -+/* -+ * try to do what kvm_deadprocs in libkvm would do -+ */ -+static struct kinfo_proc * -+kvm_deadprocs (cfd, pid, cnt) -+int cfd, pid, *cnt; -+{ -+ CORE_ADDR allproc, zombproc; -+ struct proc *p; -+ -+ allproc = ksym_lookup("allproc"); -+ if (kvm_read(cfd, allproc, (char *)&p, sizeof (p)) == 0) -+ return (NULL); -+ kvm_proclist (cfd, pid, p, cnt); -+ if (!*cnt) { -+ zombproc = ksym_lookup("zombproc"); -+ if (kvm_read(cfd, zombproc, (char *)&p, sizeof (p)) == 0) -+ return (NULL); -+ kvm_proclist (cfd, pid, p, cnt); -+ } -+ return (&kp); -+} -+ -+static CORE_ADDR -+kvm_getpcpu (cfd, cpuid) -+int cfd, cpuid; -+{ -+ SLIST_HEAD(, pcpu) pcpu_head; -+ struct pcpu lpc; -+ struct pcpu *pc; -+ -+ physrd (cfd, ksym_lookup ("cpuhead") - KERNOFF, (char*)&pcpu_head, -+ sizeof pcpu_head); -+ pc = SLIST_FIRST (&pcpu_head); -+ for (; pc != NULL; pc = SLIST_NEXT (&lpc, pc_allcpu)) ++ if (cur_proc == 0) + { -+ kvm_read (cfd, (CORE_ADDR)pc, (char*)&lpc, sizeof lpc); -+ if (lpc.pc_cpuid == cpuid) -+ break; ++ error ("---Can't read userspace from dump, or kernel process---\n"); ++ return 0; + } + -+ return ((CORE_ADDR)pc); -+} ++ if (write) ++ error ("kvm_uwrite unimplemented\n"); ++ else ++ n = kvm_uread (core_kd, cur_proc, memaddr, myaddr, len) ; + -+/* -+ * try to do what kvm_getprocs in libkvm would do -+ */ -+static struct kinfo_proc * -+kvm_getprocs (cfd, op, proc, cnt) -+int cfd, op, *cnt; -+CORE_ADDR proc; -+{ -+ int mib[4], size; -+ -+ *cnt = 0; -+ /* assume it's a pid */ -+ if (devmem) { /* "live" kernel, use sysctl */ -+ mib[0] = CTL_KERN; -+ mib[1] = KERN_PROC; -+ mib[2] = KERN_PROC_PID; -+ mib[3] = (int)proc; -+ size = sizeof (kp); -+ if (sysctl (mib, 4, &kp, &size, NULL, 0) < 0) { -+ perror("sysctl"); -+ *cnt = 0; -+ return (NULL); -+ } -+ if (!size) -+ *cnt = 0; -+ else -+ *cnt = 1; -+ return (&kp); -+ } else -+ return (kvm_deadprocs (cfd, (int)proc, cnt)); -+} ++ if (n < 0) ++ return 0; + -+static int -+physrd (cfd, addr, dat, len) -+ int cfd; -+ u_int addr; -+ char *dat; -+ int len; -+{ -+ if (lseek (cfd, (off_t)addr, L_SET) == -1) -+ return (-1); -+ return (read (cfd, dat, len)); ++ return n; +} + -+static CORE_ADDR -+kvtophys (fd, addr) -+ int fd; -+ CORE_ADDR addr; ++static void ++set_proc_cmd (char *arg, int from_tty) +{ -+ CORE_ADDR v; -+ unsigned int pte; -+ static CORE_ADDR PTD = -1; -+ CORE_ADDR current_ptd; -+ -+ /* -+ * We may no longer have a linear system page table... -+ * -+ * Here's the scoop. IdlePTD contains the physical address -+ * of a page table directory that always maps the kernel. -+ * IdlePTD is in memory that is mapped 1-to-1, so we can -+ * find it easily given its 'virtual' address from ksym_lookup(). -+ * For hysterical reasons, the value of IdlePTD is stored in sbr. -+ * -+ * To look up a kernel address, we first convert it to a 1st-level -+ * address and look it up in IdlePTD. This gives us the physical -+ * address of a page table page; we extract the 2nd-level part of -+ * VA and read the 2nd-level pte. Finally, we add the offset part -+ * of the VA into the physical address from the pte and return it. -+ * -+ * User addresses are a little more complicated. If we don't have -+ * a current PCB from read_pcb(), we use PTD, which is the (fixed) -+ * virtual address of the current ptd. Since it's NOT in 1-to-1 -+ * kernel space, we must look it up using IdlePTD. If we do have -+ * a pcb, we get the ptd from pcb_ptd. -+ */ ++ CORE_ADDR addr, pid_addr, first_td; ++ void *val; ++ struct kinfo_proc *kp; ++ int cnt; ++ pid_t pid; + -+ if (INKERNEL (addr)) -+ current_ptd = sbr; -+ else if (found_pcb == 0) -+ { -+ if (PTD == -1) -+ PTD = kvtophys (fd, ksym_lookup ("PTD")); -+ current_ptd = PTD; -+ } -+ else -+ current_ptd = pcb.pcb_cr3; ++ if (!arg) ++ error_no_arg ("proc address for the new context"); + -+ /* -+ * Read the first-level page table (ptd). -+ */ -+ v = current_ptd + ( (unsigned)addr >> PDRSHIFT) * sizeof pte; -+ if (physrd (fd, v, (char *)&pte, sizeof pte) < 0 || (pte&PG_V) == 0) -+ return (~0); ++ if (core_kd == NULL) ++ error ("no kernel core file"); + -+ if (pte & PG_PS) ++ addr = (CORE_ADDR) parse_and_eval_address (arg); ++ ++ if (!INKERNEL (addr)) + { -+ /* -+ * No second-level page table; ptd describes one 4MB page. -+ * (We assume that the kernel wouldn't set PG_PS without enabling -+ * it cr0, and that the kernel doesn't support 36-bit physical -+ * addresses). -+ */ -+#define PAGE4M_MASK (NBPDR - 1) -+#define PG_FRAME4M (~PAGE4M_MASK) -+ addr = (pte & PG_FRAME4M) + (addr & PAGE4M_MASK); ++ kp = kvm_getprocs (core_kd, KERN_PROC_PID, addr, &cnt); ++ if (!cnt) ++ error ("invalid pid"); ++ addr = (CORE_ADDR)kp->ki_paddr; ++ cur_proc = kp; + } + else + { -+ /* -+ * Read the second-level page table. -+ */ -+ v = (pte&PG_FRAME) + ((addr >> PAGE_SHIFT)&(NPTEPG-1)) * sizeof pte; -+ if (physrd (fd, v, (char *) &pte, sizeof (pte)) < 0 || (pte&PG_V) == 0) -+ return (~0); -+ -+ addr = (pte & PG_FRAME) + (addr & PAGE_MASK); -+ } -+#if 0 -+ printf ("vtophys (%x) -> %x\n", oldaddr, addr); -+#endif -+ return (addr); -+} -+ -+static int -+read_pcb (fd, uaddr) -+ int fd; -+ CORE_ADDR uaddr; -+{ -+ int i; -+ int noreg; -+ CORE_ADDR nuaddr = uaddr; -+ -+ /* need this for the `proc' command to work */ -+ if (INKERNEL(uaddr)) -+ nuaddr = kvtophys(fd, uaddr); -+ -+ if (physrd (fd, nuaddr, (char *)&pcb, sizeof pcb) < 0) -+ { -+ error ("cannot read pcb at %x\n", uaddr); -+ return (-1); ++ /* Update cur_proc. */ ++ pid_addr = addr + offsetof (struct proc, p_pid); ++ if (kvread (pid_addr, &pid)) ++ error ("cannot read pid ptr"); ++ cur_proc = kvm_getprocs (core_kd, KERN_PROC_PID, pid, &cnt); ++ if (!cnt) ++ error("invalid pid"); + } + -+ /* -+ * get the register values out of the sys pcb and -+ * store them where `read_register' will find them. -+ */ -+ /* -+ * XXX many registers aren't available. -+ * XXX for the non-core case, the registers are stale - they are for -+ * the last context switch to the debugger. -+ * XXX gcc's register numbers aren't all #defined in tm-i386.h. -+ */ -+ noreg = 0; -+ for (i = 0; i < 3; ++i) /* eax,ecx,edx */ -+ supply_register (i, (char *)&noreg); -+ supply_register (3, (char *)&pcb.pcb_ebx); -+ supply_register (SP_REGNUM, (char *)&pcb.pcb_esp); -+ supply_register (FP_REGNUM, (char *)&pcb.pcb_ebp); -+ supply_register (6, (char *)&pcb.pcb_esi); -+ supply_register (7, (char *)&pcb.pcb_edi); -+ supply_register (PC_REGNUM, (char *)&pcb.pcb_eip); -+ for (i = 9; i < 14; ++i) /* eflags, cs, ss, ds, es, fs */ -+ supply_register (i, (char *)&noreg); -+ supply_register (15, (char *)&pcb.pcb_gs); ++ /* Find the first thread in the process. XXXKSE */ ++ addr += offsetof (struct proc, p_threads.tqh_first); ++ if (kvread (addr, &first_td)) ++ error ("cannot read thread ptr"); + -+ /* XXX 80387 registers? */ -+} -+ -+/* -+ * read len bytes from kernel virtual address 'addr' into local -+ * buffer 'buf'. Return numbert of bytes if read ok, 0 otherwise. On read -+ * errors, portion of buffer not read is zeroed. -+ */ -+ -+static int -+kernel_core_file_hook (fd, addr, buf, len) -+ int fd; -+ CORE_ADDR addr; -+ char *buf; -+ int len; -+{ -+ int i; -+ CORE_ADDR paddr; -+ register char *cp; -+ int cc; ++ /* Read the PCB address in thread structure. */ ++ addr = first_td + offsetof (struct thread, td_pcb); ++ if (kvread (addr, &val)) ++ error("cannot read pcb ptr"); + -+ cp = buf; -+ -+ while (len > 0) -+ { -+ paddr = kvtophys (fd, addr); -+ if (paddr == ~0) -+ { -+ memset (buf, '\000', len); -+ break; -+ } -+ /* we can't read across a page boundary */ -+ i = min (len, PAGE_SIZE - (addr & PAGE_MASK)); -+ if ( (cc = physrd (fd, paddr, cp, i)) <= 0) -+ { -+ memset (cp, '\000', len); -+ return (cp - buf); -+ } -+ cp += cc; -+ addr += cc; -+ len -= cc; -+ } -+ return (cp - buf); ++ /* Read the PCB address in proc structure. */ ++ if (set_context ((CORE_ADDR) val)) ++ error ("invalid proc address"); +} + -+static struct target_ops kcore_ops; -+ -+#else -+int kernel_debugging = 0; -+#endif -+ +void -+_initialize_kcorelow() ++_initialize_kcorelow (void) +{ -+#if __FreeBSD_version >= 500032 && defined(i386) + kcore_ops.to_shortname = "kcore"; + kcore_ops.to_longname = "Kernel core dump file"; + kcore_ops.to_doc = @@ -1042,7 +673,7 @@ + kcore_ops.to_attach = find_default_attach; + kcore_ops.to_detach = kcore_detach; + kcore_ops.to_fetch_registers = get_kcore_registers; -+ kcore_ops.to_xfer_memory = kcore_xfer_kmem; ++ kcore_ops.to_xfer_memory = xfer_kmem; + kcore_ops.to_files_info = kcore_files_info; + kcore_ops.to_create_inferior = find_default_create_inferior; + kcore_ops.to_stratum = kcore_stratum; @@ -1053,6 +684,4 @@ + + add_target (&kcore_ops); + add_com ("proc", class_obscure, set_proc_cmd, "Set current process context"); -+ add_com ("cpu", class_obscure, set_cpu_cmd, "Set current cpu"); -+#endif +} |