diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 2004-05-13 04:28:38 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 2004-05-13 04:28:38 +0000 |
commit | b6267d7a4b10e4fa51ae0240b39a73b9302db924 (patch) | |
tree | aa2f1fbdfd373ad82fbcf3698efc705cafcd3e34 /devel/gdb66/files/patch-kvm-fbsd.c | |
parent | Revert previous commit now that it has been tagged for 4.10-RELEASE. (diff) |
Update to the 2004-05-11 snapshot.
Also enable kgdb and thread support!
This is missing IA64 support, and the AMD64 kgdb support is hokey and needs
a few more bits filled in.
Diffstat (limited to 'devel/gdb66/files/patch-kvm-fbsd.c')
-rw-r--r-- | devel/gdb66/files/patch-kvm-fbsd.c | 759 |
1 files changed, 0 insertions, 759 deletions
diff --git a/devel/gdb66/files/patch-kvm-fbsd.c b/devel/gdb66/files/patch-kvm-fbsd.c deleted file mode 100644 index 7259fd149bed..000000000000 --- a/devel/gdb66/files/patch-kvm-fbsd.c +++ /dev/null @@ -1,759 +0,0 @@ ---- gdb/kvm-fbsd.c Fri Jan 3 08:57:23 2003 -+++ gdb/kvm-fbsd.c Fri Jan 3 08:57:20 2003 -@@ -0,0 +1,756 @@ -+/* 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. -+ -+This program is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2 of the License, or -+(at your option) any later version. -+ -+This program is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+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. -+*/ -+ -+/* $FreeBSD: /tmp/pcvs/ports/devel/gdb66/files/Attic/patch-kvm-fbsd.c,v 1.5 2003-04-08 08:37:55 jake Exp $ */ -+ -+/* -+ * 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 <kvm.h> -+#include <sys/sysctl.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" -+#include "symfile.h" -+#include "objfiles.h" -+#include "command.h" -+#include "bfd.h" -+#include "target.h" -+#include "gdbcore.h" -+#include "regcache.h" -+ -+#if __FreeBSD_version >= 500032 -+static void -+kcore_files_info (struct target_ops *); -+ -+static void -+kcore_close (int); -+ -+static void -+get_kcore_registers (int); -+ -+static int -+xfer_mem (CORE_ADDR, char *, int, int, struct mem_attrib *, -+ struct target_ops *); -+ -+static int -+xfer_umem (CORE_ADDR, char *, int, int); -+ -+static char *core_file; -+static kvm_t *core_kd; -+static struct pcb cur_pcb; -+static struct kinfo_proc *cur_proc; -+ -+static struct target_ops kcore_ops; -+ -+int kernel_debugging; -+int kernel_writablecore; -+ -+/* 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)))) -+ -+static CORE_ADDR -+ksym_kernbase (void) -+{ -+ static CORE_ADDR kernbase; -+ struct minimal_symbol *sym; -+ -+ if (kernbase == 0) -+ { -+ sym = lookup_minimal_symbol ("kernbase", NULL, NULL); -+ if (sym == NULL) { -+ kernbase = KERNBASE; -+ } else { -+ kernbase = SYMBOL_VALUE_ADDRESS (sym); -+ } -+ } -+ return kernbase; -+} -+ -+#define KERNOFF (ksym_kernbase ()) -+#define INKERNEL(x) ((x) >= KERNOFF) -+ -+CORE_ADDR -+ksym_lookup(const char *name) -+{ -+ struct minimal_symbol *sym; -+ -+ sym = lookup_minimal_symbol (name, NULL, NULL); -+ if (sym == NULL) -+ error ("kernel symbol `%s' not found.", name); -+ -+ return SYMBOL_VALUE_ADDRESS (sym); -+} -+ -+/* 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); -+ -+ /* 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); -+ } -+ } -+ -+ /* 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. */ -+ -+ 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; -+ } -+ } -+ -+ /* 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 ((CORE_ADDR)val); -+} -+ -+/* Set the current context to that of the PCB struct at the system address -+ passed. */ -+ -+static int -+set_context (CORE_ADDR addr) -+{ -+ CORE_ADDR procaddr = 0; -+ -+ if (kvread (addr, &cur_pcb)) -+ error ("cannot read pcb at %#x", addr); -+ -+ /* Fetch all registers from core file. */ -+ target_fetch_registers (-1); -+ -+ /* 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 ()); -+ return (0); -+} -+ -+/* Discard all vestiges of any previous core file and mark data and stack -+ spaces as empty. */ -+ -+/* ARGSUSED */ -+static void -+kcore_close (int quitting) -+{ -+ -+ inferior_ptid = null_ptid; /* Avoid confusion from thread stuff. */ -+ -+ if (core_kd) -+ { -+ kvm_close (core_kd); -+ free (core_file); -+ core_file = NULL; -+ core_kd = NULL; -+ } -+} -+ -+/* This routine opens and sets up the core file bfd. */ -+ -+static void -+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; -+ -+ target_preopen (from_tty); -+ -+ /* 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 ("No core file specified."); -+ return; -+ } -+ -+ filename = tilde_expand (filename); -+ if (filename[0] != '/') -+ { -+ cp = concat (current_directory, "/", filename, NULL); -+ free (filename); -+ filename = cp; -+ } -+ -+ old_chain = make_cleanup (free, 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. */ -+ -+ discard_cleanups (old_chain); /* Don't free filename any more. */ -+ core_file = filename; -+ unpush_target (&kcore_ops); -+ ontop = !push_target (&kcore_ops); -+ -+ /* 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) -+ { -+ -+ for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++) -+ if (!isascii (*cp) || (!isprint (*cp) && !isspace (*cp))) -+ *cp = '?'; -+ *cp = '\0'; -+ if (buf[0] != '\0') -+ printf_filtered ("panic: %s\n", buf); -+ } -+ -+ /* 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); -+ 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); -+ return; -+ } -+ -+ /* 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 (char *args, int from_tty) -+{ -+ if (args) -+ error ("Too many arguments"); -+ unpush_target (&kcore_ops); -+ reinit_frame_cache (); -+ if (from_tty) -+ printf_filtered ("No kernel core file now.\n"); -+} -+ -+#ifdef __alpha__ -+ -+#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) -+{ -+ -+ /* 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 (); -+} -+ -+ -+CORE_ADDR -+fbsd_kern_frame_saved_pc (struct frame_info *fi) -+{ -+ 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 (void) -+{ -+ static CORE_ADDR maxuseraddr; -+ struct minimal_symbol *sym; -+ -+ if (maxuseraddr == 0) -+ { -+ sym = lookup_minimal_symbol ("PTmap", NULL, NULL); -+ if (sym == NULL) { -+ maxuseraddr = VM_MAXUSER_ADDRESS; -+ } else { -+ maxuseraddr = SYMBOL_VALUE_ADDRESS (sym); -+ } -+ } -+ return maxuseraddr; -+} -+ -+ -+/* 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" -+ -+/* 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 }; -+ -+CORE_ADDR -+fbsd_kern_frame_saved_pc (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 || -+ strcmp (SYMBOL_NAME (sym), KSYM_OLDSYSCALL) == 0) -+ frametype = tf_syscall; -+ } -+ -+ switch (frametype) -+ { -+ default: -+ 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 -+ } -+} -+ -+static void -+fetch_kcore_registers (struct pcb *pcb) -+{ -+ int i; -+ int noreg; -+ -+ /* 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); -+ -+ /* XXX 80387 registers? */ -+} -+ -+#endif /* __i386__ */ -+ -+#ifdef __sparc64__ -+ -+#define SPARC_INTREG_SIZE 8 -+ -+static void -+fetch_kcore_registers (struct pcb *pcbp) -+{ -+ static struct frame top; -+ CORE_ADDR f_addr; -+ int i; -+ -+ /* 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 do something with the floating-point registers? -+ */ -+ supply_register (SP_REGNUM, &pcbp->pcb_sp); -+ supply_register (PC_REGNUM, &pcbp->pcb_pc); -+ f_addr = extract_address (&pcbp->pcb_sp, SPARC_INTREG_SIZE); -+ /* Load the previous frame by hand (XXX) and supply it. */ -+ read_memory (f_addr + SPOFF, (char *)&top, sizeof (top)); -+ for (i = 0; i < 8; i++) -+ supply_register (i + L0_REGNUM, &top.fr_local[i]); -+ for (i = 0; i < 8; i++) -+ supply_register (i + I0_REGNUM, &top.fr_in[i]); -+} -+ -+CORE_ADDR -+fbsd_kern_frame_saved_pc (struct frame_info *fi) -+{ -+ struct minimal_symbol *sym; -+ CORE_ADDR frame, pc_addr, pc; -+ char *buf; -+ -+ buf = alloca (MAX_REGISTER_RAW_SIZE); -+ /* XXX: duplicates fi->extra_info->bottom. */ -+ frame = (fi->next != NULL) ? fi->next->frame : read_sp (); -+ pc_addr = frame + offsetof (struct frame, fr_in[7]); -+ -+#define READ_PC(pc, a, b) do { \ -+ read_memory (a, b, SPARC_INTREG_SIZE); \ -+ pc = extract_address (b, SPARC_INTREG_SIZE); \ -+} while (0) -+ -+ READ_PC (pc, pc_addr, buf); -+ -+ sym = lookup_minimal_symbol_by_pc (pc); -+ if (sym != NULL) -+ { -+ if (strncmp (SYMBOL_NAME (sym), "tl0_", 4) == 0 || -+ strcmp (SYMBOL_NAME (sym), "btext") == 0 || -+ strcmp (SYMBOL_NAME (sym), "mp_startup") == 0 || -+ strcmp (SYMBOL_NAME (sym), "fork_trampoline") == 0) -+ { -+ /* -+ * Ugly kluge: user space addresses aren't separated from kernel -+ * ones by range; if encountering a trap from user space, just -+ * return a 0 to stop the trace. -+ * Do the same for entry points of kernel processes to avoid -+ * printing garbage. -+ */ -+ pc = 0; -+ } -+ if (strncmp (SYMBOL_NAME (sym), "tl1_", 4) == 0) -+ { -+ pc_addr = fi->frame + sizeof (struct frame) + -+ offsetof (struct trapframe, tf_tpc); -+ READ_PC (pc, pc_addr, buf); -+ } -+ } -+ return (pc); -+} -+ -+#endif /* __sparc64__ */ -+ -+/* 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. */ -+ -+/* We just get all the registers, so we don't use regno. */ -+ -+/* ARGSUSED */ -+static void -+get_kcore_registers (int regno) -+{ -+ -+ /* 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... */ -+ -+ /* Zero out register set then fill in the ones we know about. */ -+ fetch_kcore_registers (&cur_pcb); -+} -+ -+static void -+kcore_files_info (t) -+ struct target_ops *t; -+{ -+ 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 -+ignore (CORE_ADDR addr, char *contents) -+{ -+ return 0; -+} -+ -+static int -+xfer_kmem (CORE_ADDR memaddr, char *myaddr, int len, int write, -+ struct mem_attrib *attrib, struct target_ops *target) -+{ -+ int n; -+ -+ -+ if (!INKERNEL (memaddr)) -+ return xfer_umem (memaddr, myaddr, len, write); -+ -+ if (core_kd == NULL) -+ return 0; -+ -+ if (write) -+ n = kvm_write (core_kd, memaddr, myaddr, len); -+ else -+ 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 int -+xfer_umem (CORE_ADDR memaddr, char *myaddr, int len, int write /* ignored */) -+{ -+ int n = 0; -+ -+ if (cur_proc == 0) -+ { -+ error ("---Can't read userspace from dump, or kernel process---\n"); -+ return 0; -+ } -+ -+ if (write) -+ error ("kvm_uwrite unimplemented\n"); -+ else -+ n = kvm_uread (core_kd, cur_proc, memaddr, myaddr, len) ; -+ -+ if (n < 0) -+ return 0; -+ -+ return n; -+} -+ -+static void -+set_proc_cmd (char *arg, int from_tty) -+{ -+ CORE_ADDR addr, pid_addr, first_td; -+ void *val; -+ struct kinfo_proc *kp; -+ int cnt; -+ pid_t pid; -+ -+ if (!arg) -+ error_no_arg ("proc address for the new context"); -+ -+ if (core_kd == NULL) -+ error ("no kernel core file"); -+ -+ addr = (CORE_ADDR) parse_and_eval_address (arg); -+ -+ if (!INKERNEL (addr)) -+ { -+ 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 -+ { -+ /* 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"); -+ } -+ -+ /* 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"); -+ -+ /* Read the PCB address in thread structure. */ -+ addr = first_td + offsetof (struct thread, td_pcb); -+ if (kvread (addr, &val)) -+ error("cannot read pcb ptr"); -+ -+ /* Read the PCB address in proc structure. */ -+ if (set_context ((CORE_ADDR) val)) -+ error ("invalid proc address"); -+} -+#else -+int kernel_debugging = 0; -+int kernel_writablecore = 0; -+ -+CORE_ADDR -+fbsd_kern_frame_saved_pc (struct frame_info *fi) -+{ -+ return 0; -+} -+#endif -+ -+void -+_initialize_kcorelow (void) -+{ -+#if __FreeBSD_version >= 500032 -+ kcore_ops.to_shortname = "kcore"; -+ kcore_ops.to_longname = "Kernel core dump file"; -+ kcore_ops.to_doc = -+ "Use a core file as a target. Specify the filename of the core file."; -+ kcore_ops.to_open = kcore_open; -+ kcore_ops.to_close = kcore_close; -+ 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 = 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; -+ kcore_ops.to_has_memory = 1; -+ kcore_ops.to_has_stack = 1; -+ kcore_ops.to_has_registers = 1; -+ kcore_ops.to_magic = OPS_MAGIC; -+ -+ add_target (&kcore_ops); -+ add_com ("proc", class_obscure, set_proc_cmd, "Set current process context"); -+#endif -+} |