summaryrefslogtreecommitdiff
path: root/gnu/usr.bin
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2004-07-08 08:18:00 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2004-07-08 08:18:00 +0000
commit586e635d72877a713b4214084fdaa19d806a233a (patch)
tree982e7d38d85df68a55cd0967109eccdb9904f831 /gnu/usr.bin
parent2e13687ea23333acaa7c96208fbdbe01ed286179 (diff)
Sync libkvm interface with FSF repository. This adds new "kvm proc" and
"kvm pcb" commands. ok deraadt@
Diffstat (limited to 'gnu/usr.bin')
-rw-r--r--gnu/usr.bin/binutils/gdb/amd64obsd-nat.c41
-rw-r--r--gnu/usr.bin/binutils/gdb/bsd-kvm.c98
-rw-r--r--gnu/usr.bin/binutils/gdb/bsd-kvm.h7
-rw-r--r--gnu/usr.bin/binutils/gdb/i386nbsd-nat.c15
-rw-r--r--gnu/usr.bin/binutils/gdb/m68kbsd-nat.c20
-rw-r--r--gnu/usr.bin/binutils/gdb/sparcnbsd-nat.c7
6 files changed, 162 insertions, 26 deletions
diff --git a/gnu/usr.bin/binutils/gdb/amd64obsd-nat.c b/gnu/usr.bin/binutils/gdb/amd64obsd-nat.c
index ccca6c38d5e..0f9b5efac7f 100644
--- a/gnu/usr.bin/binutils/gdb/amd64obsd-nat.c
+++ b/gnu/usr.bin/binutils/gdb/amd64obsd-nat.c
@@ -66,8 +66,8 @@ static int amd64obsd32_r_reg_offset[] =
#include "bsd-kvm.h"
-int
-bsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb)
+static int
+amd64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
{
struct switchframe sf;
int regnum;
@@ -91,22 +91,38 @@ bsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb)
Together with %rsp in the pcb, this accounts for all callee-saved
registers specified by the psABI. From this information we
reconstruct the register state as it would look when we just
- returned from cpu_switch(). */
+ returned from cpu_switch().
+
+ For core dumps the pcb is saved by savectx(). In that case the
+ stack frame only contains the return address, and there is no way
+ to recover the other registers. */
/* The stack pointer shouldn't be zero. */
if (pcb->pcb_rsp == 0)
return 0;
+ /* Read the stack frame, and check its validity. */
read_memory (pcb->pcb_rsp, (char *) &sf, sizeof sf);
- pcb->pcb_rsp += sizeof (struct switchframe);
- regcache_raw_supply (regcache, 12, &sf.sf_r12);
- regcache_raw_supply (regcache, 13, &sf.sf_r13);
- regcache_raw_supply (regcache, 14, &sf.sf_r14);
- regcache_raw_supply (regcache, 15, &sf.sf_r15);
+ if (sf.sf_rbp == pcb->pcb_rbp)
+ {
+ /* Yes, we have a frame that matches cpu_switch(). */
+ pcb->pcb_rsp += sizeof (struct switchframe);
+ regcache_raw_supply (regcache, 12, &sf.sf_r12);
+ regcache_raw_supply (regcache, 13, &sf.sf_r13);
+ regcache_raw_supply (regcache, 14, &sf.sf_r14);
+ regcache_raw_supply (regcache, 15, &sf.sf_r15);
+ regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &sf.sf_rbx);
+ regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &sf.sf_rip);
+ }
+ else
+ {
+ /* No, the pcb must have been last updated by savectx(). */
+ pcb->pcb_rsp += 8;
+ regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &sf);
+ }
+
regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp);
- regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &sf.sf_rbp);
- regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &sf.sf_rbx);
- regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &sf.sf_rip);
+ regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp);
return 1;
}
@@ -121,4 +137,7 @@ _initialize_amd64obsd_nat (void)
amd64_native_gregset32_reg_offset = amd64obsd32_r_reg_offset;
amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64obsd32_r_reg_offset);
amd64_native_gregset64_reg_offset = amd64obsd_r_reg_offset;
+
+ /* Support debugging kernel virtual memory images. */
+ bsd_kvm_add_target (amd64obsd_supply_pcb);
}
diff --git a/gnu/usr.bin/binutils/gdb/bsd-kvm.c b/gnu/usr.bin/binutils/gdb/bsd-kvm.c
index b8ef075b831..79ab09505f6 100644
--- a/gnu/usr.bin/binutils/gdb/bsd-kvm.c
+++ b/gnu/usr.bin/binutils/gdb/bsd-kvm.c
@@ -20,9 +20,12 @@
Boston, MA 02111-1307, USA. */
#include "defs.h"
+#include "cli/cli-cmds.h"
+#include "command.h"
#include "frame.h"
#include "regcache.h"
#include "target.h"
+#include "value.h"
#include "gdb_assert.h"
#include <fcntl.h>
@@ -30,6 +33,7 @@
#include <nlist.h>
#include "readline/readline.h"
#include <sys/param.h>
+#include <sys/proc.h>
#include <sys/user.h>
#include "bsd-kvm.h"
@@ -40,6 +44,10 @@ kvm_t *core_kd;
/* Address of process control block. */
struct pcb *bsd_kvm_paddr;
+/* Pointer to architecture-specific function that reconstructs the
+ register state from PCB and supplies it to REGCACHE. */
+int (*bsd_kvm_supply_pcb)(struct regcache *regcache, struct pcb *pcb);
+
/* Target ops for libkvm interface. */
struct target_ops bsd_kvm_ops;
@@ -104,6 +112,8 @@ bsd_kvm_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
return -1;
}
+/* Fetch process control block at address PADDR. */
+
static int
bsd_kvm_fetch_pcb (struct pcb *paddr)
{
@@ -122,7 +132,10 @@ bsd_kvm_fetch_registers (int regnum)
struct nlist nl[2];
if (bsd_kvm_paddr)
- bsd_kvm_fetch_pcb (bsd_kvm_paddr);
+ {
+ bsd_kvm_fetch_pcb (bsd_kvm_paddr);
+ return;
+ }
/* On dumping core, BSD kernels store the faulting context (PCB)
in the variable "dumppcb". */
@@ -179,8 +192,8 @@ bsd_kvm_fetch_registers (int regnum)
struct pcb *paddr;
/* Found thread0. */
- nl[1].n_value += offsetof (struct thread, td_pcb);
- if (kvm_read (core_kd, nl[1].n_value, &paddr, sizeof paddr) == -1)
+ nl[0].n_value += offsetof (struct thread, td_pcb);
+ if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
error ("%s", kvm_geterr (core_kd));
bsd_kvm_fetch_pcb (paddr);
@@ -190,13 +203,77 @@ bsd_kvm_fetch_registers (int regnum)
error ("Cannot find a valid PCB");
}
+
+
+/* Kernel memory interface commands. */
+struct cmd_list_element *bsd_kvm_cmdlist;
+
+static void
+bsd_kvm_cmd (char *arg, int fromtty)
+{
+ /* ??? Should this become an alias for "target kvm"? */
+}
+
+#ifndef HAVE_STRUCT_THREAD_TD_PCB
+
+static void
+bsd_kvm_proc_cmd (char *arg, int fromtty)
+{
+ CORE_ADDR addr;
+
+ if (arg == NULL)
+ error_no_arg ("proc address");
+
+ if (core_kd == NULL)
+ error ("No kernel memory image.");
+
+ addr = parse_and_eval_address (arg);
+ addr += offsetof (struct proc, p_addr);
+
+ if (kvm_read (core_kd, addr, &bsd_kvm_paddr, sizeof bsd_kvm_paddr) == -1)
+ error ("%s", kvm_geterr (core_kd));
+
+ target_fetch_registers (-1);
+
+ flush_cached_frames ();
+ select_frame (get_current_frame ());
+ print_stack_frame (get_selected_frame (), -1, 1);
+}
+
+#endif
+
+static void
+bsd_kvm_pcb_cmd (char *arg, int fromtty)
+{
+ if (arg == NULL)
+ error_no_arg ("pcb address");
+
+ if (core_kd == NULL)
+ error ("No kernel memory image.");
+
+ bsd_kvm_paddr = (struct pcb *) parse_and_eval_address (arg);
+
+ target_fetch_registers (-1);
+
+ flush_cached_frames ();
+ select_frame (get_current_frame ());
+ print_stack_frame (get_selected_frame (), -1, 1);
+}
+
+/* Add the libkvm interface to the list of all possible targets and
+ register CUPPLY_PCB as the architecture-specific process control
+ block interpreter. */
void
-_initialize_bsd_kvm (void)
+bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *))
{
+ gdb_assert (bsd_kvm_supply_pcb == NULL);
+ bsd_kvm_supply_pcb = supply_pcb;
+
bsd_kvm_ops.to_shortname = "kvm";
bsd_kvm_ops.to_longname = "Kernel memory interface";
- bsd_kvm_ops.to_doc = "XXX";
+ bsd_kvm_ops.to_doc = "Use a kernel virtual memory image as a target.\n\
+Optionally specify the filename of a core dump.";
bsd_kvm_ops.to_open = bsd_kvm_open;
bsd_kvm_ops.to_close = bsd_kvm_close;
bsd_kvm_ops.to_fetch_registers = bsd_kvm_fetch_registers;
@@ -208,4 +285,15 @@ _initialize_bsd_kvm (void)
bsd_kvm_ops.to_magic = OPS_MAGIC;
add_target (&bsd_kvm_ops);
+
+ add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, "\
+Generic command for manipulating the kernel memory interface.",
+ &bsd_kvm_cmdlist, "kvm ", 0, &cmdlist);
+
+#ifndef HAVE_STRUCT_THREAD_TD_PCB
+ add_cmd ("proc", class_obscure, bsd_kvm_proc_cmd,
+ "Set current context from proc address", &bsd_kvm_cmdlist);
+#endif
+ add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd,
+ "Set current context from pcb address", &bsd_kvm_cmdlist);
}
diff --git a/gnu/usr.bin/binutils/gdb/bsd-kvm.h b/gnu/usr.bin/binutils/gdb/bsd-kvm.h
index 129a2f20c72..0660776cf43 100644
--- a/gnu/usr.bin/binutils/gdb/bsd-kvm.h
+++ b/gnu/usr.bin/binutils/gdb/bsd-kvm.h
@@ -25,6 +25,11 @@
struct pcb;
struct regcache;
-extern int bsd_kvm_supply_pcb (struct regcache *regache, struct pcb *pcb);
+/* Add the libkvm interface to the list of all possible targets and
+ register CUPPLY_PCB as the architecture-specific process control
+ block interpreter. */
+
+extern void
+ bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *));
#endif /* bsd-kvm.h */
diff --git a/gnu/usr.bin/binutils/gdb/i386nbsd-nat.c b/gnu/usr.bin/binutils/gdb/i386nbsd-nat.c
index 816241e613e..92da7e18dcd 100644
--- a/gnu/usr.bin/binutils/gdb/i386nbsd-nat.c
+++ b/gnu/usr.bin/binutils/gdb/i386nbsd-nat.c
@@ -33,8 +33,8 @@
#include "bsd-kvm.h"
-int
-bsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb)
+static int
+i386nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
{
struct switchframe sf;
@@ -69,3 +69,14 @@ bsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
+
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_i386nbsd_nat (void);
+
+void
+_initialize_i386nbsd_nat (void)
+{
+ /* Support debugging kernel virtual memory images. */
+ bsd_kvm_add_target (i386nbsd_supply_pcb);
+}
diff --git a/gnu/usr.bin/binutils/gdb/m68kbsd-nat.c b/gnu/usr.bin/binutils/gdb/m68kbsd-nat.c
index 8954a164189..285c149428d 100644
--- a/gnu/usr.bin/binutils/gdb/m68kbsd-nat.c
+++ b/gnu/usr.bin/binutils/gdb/m68kbsd-nat.c
@@ -81,7 +81,7 @@ m68kbsd_collect_gregset (const struct regcache *regcache,
for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++)
{
if (regnum == -1 || regnum == i)
- regcache_raw_collect (regcache, regnum, regs + i * 4);
+ regcache_raw_collect (regcache, i, regs + i * 4);
}
}
@@ -98,8 +98,7 @@ m68kbsd_collect_fpregset (struct regcache *regcache,
for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++)
{
if (regnum == -1 || regnum == i)
- regcache_raw_collect (regcache, regnum,
- regs + m68kbsd_fpreg_offset (i));
+ regcache_raw_collect (regcache, i, regs + m68kbsd_fpreg_offset (i));
}
}
@@ -186,8 +185,8 @@ store_inferior_registers (int regnum)
#define PCB_REGS_SP 11
#endif
-int
-bsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb)
+static int
+m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
{
int regnum, tmp;
int i = 0;
@@ -216,3 +215,14 @@ bsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
+
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_m68kbsd_nat (void);
+
+void
+_initialize_m68kbsd_nat (void)
+{
+ /* Support debugging kernel virtual memory images. */
+ bsd_kvm_add_target (m68kbsd_supply_pcb);
+}
diff --git a/gnu/usr.bin/binutils/gdb/sparcnbsd-nat.c b/gnu/usr.bin/binutils/gdb/sparcnbsd-nat.c
index 88941712439..01089eeef32 100644
--- a/gnu/usr.bin/binutils/gdb/sparcnbsd-nat.c
+++ b/gnu/usr.bin/binutils/gdb/sparcnbsd-nat.c
@@ -33,8 +33,8 @@
#include "bsd-kvm.h"
-int
-bsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb)
+static int
+sparc32nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
{
/* The following is true for NetBSD 1.6.2:
@@ -65,4 +65,7 @@ void
_initialize_sparcnbsd_nat (void)
{
sparc_gregset = &sparc32nbsd_gregset;
+
+ /* Support debugging kernel virtual memory images. */
+ bsd_kvm_add_target (sparc32nbsd_supply_pcb);
}