diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2004-07-08 08:18:00 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2004-07-08 08:18:00 +0000 |
commit | 586e635d72877a713b4214084fdaa19d806a233a (patch) | |
tree | 982e7d38d85df68a55cd0967109eccdb9904f831 /gnu/usr.bin | |
parent | 2e13687ea23333acaa7c96208fbdbe01ed286179 (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.c | 41 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/bsd-kvm.c | 98 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/bsd-kvm.h | 7 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/i386nbsd-nat.c | 15 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/m68kbsd-nat.c | 20 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/sparcnbsd-nat.c | 7 |
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); } |