diff options
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/Makefile | 2 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/kgdb.h | 10 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/kthr.c | 59 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/main.c | 46 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/trgt.c | 116 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/trgt_alpha.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/trgt_amd64.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/trgt_i386.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/trgt_ia64.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/trgt_sparc64.c | 2 |
10 files changed, 218 insertions, 25 deletions
diff --git a/gnu/usr.bin/gdb/kgdb/Makefile b/gnu/usr.bin/gdb/kgdb/Makefile index 404b960..d688bb6 100644 --- a/gnu/usr.bin/gdb/kgdb/Makefile +++ b/gnu/usr.bin/gdb/kgdb/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= kgdb${GDB_SUFFIX} -SRCS= kthr.c main.c trgt.c trgt_${TARGET_ARCH}.c +SRCS= main.c kthr.c trgt.c trgt_${MACHINE_ARCH}.c WARNS?= 2 BULIBS= ${OBJ_BU}/libbfd/libbfd.a ${OBJ_BU}/libopcodes/libopcodes.a \ diff --git a/gnu/usr.bin/gdb/kgdb/kgdb.h b/gnu/usr.bin/gdb/kgdb/kgdb.h index eb38032..b545ebb 100644 --- a/gnu/usr.bin/gdb/kgdb/kgdb.h +++ b/gnu/usr.bin/gdb/kgdb/kgdb.h @@ -29,15 +29,19 @@ #ifndef _KGDB_H_ #define _KGDB_H_ +struct thread_info; + extern kvm_t *kvm; extern int verbose; struct kthr { struct kthr *next; + uintptr_t paddr; uintptr_t kaddr; uintptr_t kstack; uintptr_t pcb; int tid; + int pid; }; extern struct kthr *curkthr; @@ -48,8 +52,12 @@ void kgdb_trgt_store_registers(int); struct kthr *kgdb_thr_first(void); struct kthr *kgdb_thr_init(void); -struct kthr *kgdb_thr_lookup(int); +struct kthr *kgdb_thr_lookup_tid(int); +struct kthr *kgdb_thr_lookup_pid(int); +struct kthr *kgdb_thr_lookup_paddr(uintptr_t); +struct kthr *kgdb_thr_lookup_taddr(uintptr_t); struct kthr *kgdb_thr_next(struct kthr *); struct kthr *kgdb_thr_select(struct kthr *); +char *kgdb_thr_extra_thread_info(int); #endif /* _KGDB_H_ */ diff --git a/gnu/usr.bin/gdb/kgdb/kthr.c b/gnu/usr.bin/gdb/kgdb/kthr.c index 25f8d49..505605d 100644 --- a/gnu/usr.bin/gdb/kgdb/kthr.c +++ b/gnu/usr.bin/gdb/kgdb/kthr.c @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <stdlib.h> +#include <defs.h> + #include "kgdb.h" static uintptr_t dumppcb; @@ -102,19 +104,21 @@ kgdb_thr_init(void) (uintptr_t)td.td_pcb; kt->kstack = td.td_kstack; kt->tid = td.td_tid; + kt->pid = p.p_pid; + kt->paddr = paddr; first = kt; addr = (uintptr_t)TAILQ_NEXT(&td, td_plist); } paddr = (uintptr_t)LIST_NEXT(&p, p_list); } - curkthr = kgdb_thr_lookup(dumptid); + curkthr = kgdb_thr_lookup_tid(dumptid); if (curkthr == NULL) curkthr = first; return (first); } struct kthr * -kgdb_thr_lookup(int tid) +kgdb_thr_lookup_tid(int tid) { struct kthr *kt; @@ -125,6 +129,39 @@ kgdb_thr_lookup(int tid) } struct kthr * +kgdb_thr_lookup_taddr(uintptr_t taddr) +{ + struct kthr *kt; + + kt = first; + while (kt != NULL && kt->kaddr != taddr) + kt = kt->next; + return (kt); +} + +struct kthr * +kgdb_thr_lookup_pid(int pid) +{ + struct kthr *kt; + + kt = first; + while (kt != NULL && kt->pid != pid) + kt = kt->next; + return (kt); +} + +struct kthr * +kgdb_thr_lookup_paddr(uintptr_t paddr) +{ + struct kthr *kt; + + kt = first; + while (kt != NULL && kt->paddr != paddr) + kt = kt->next; + return (kt); +} + +struct kthr * kgdb_thr_next(struct kthr *kt) { return (kt->next); @@ -139,3 +176,21 @@ kgdb_thr_select(struct kthr *kt) curkthr = kt; return (pcur); } + +char * +kgdb_thr_extra_thread_info(int tid) +{ + struct kthr *kt; + struct proc *p; + static char comm[MAXCOMLEN + 1]; + + kt = kgdb_thr_lookup_tid(tid); + if (kt == NULL) + return (NULL); + p = (struct proc *)kt->paddr; + if (kvm_read(kvm, (uintptr_t)&p->p_comm[0], &comm, sizeof(comm)) != + sizeof(comm)) + return (NULL); + + return (comm); +} diff --git a/gnu/usr.bin/gdb/kgdb/main.c b/gnu/usr.bin/gdb/kgdb/main.c index 54f6a3e..3ad158b 100644 --- a/gnu/usr.bin/gdb/kgdb/main.c +++ b/gnu/usr.bin/gdb/kgdb/main.c @@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$"); #include <main.h> #include <target.h> #include <top.h> +#include <bfd.h> +#include <gdbcore.h> extern void (*init_ui_hook)(char *); @@ -166,18 +168,50 @@ out: } static void +kgdb_init_target(void) +{ + bfd *kern_bfd; + int kern_desc; + + kern_desc = open(kernel, O_RDONLY); + if (kern_desc == -1) + errx(1, "couldn't open a kernel image"); + + kern_bfd = bfd_fdopenr(kernel, gnutarget, kern_desc); + if (kern_bfd == NULL) { + close(kern_desc); + errx(1, "\"%s\": can't open to probe ABI: %s.", kernel, + bfd_errmsg (bfd_get_error ())); + } + bfd_set_cacheable(kern_bfd, 1); + + if (!bfd_check_format (kern_bfd, bfd_object)) { + bfd_close(kern_bfd); + errx(1, "\"%s\": not in executable format: %s", kernel, + bfd_errmsg(bfd_get_error())); + } + + set_gdbarch_from_file (kern_bfd); + bfd_close(kern_bfd); + + symbol_file_add_main (kernel, 0); + if (remote) + push_remote_target (remote, 0); + else + kgdb_target(); +} + +static void kgdb_interp_command_loop(void *data) { static int once = 0; if (!once) { once = 1; - symbol_file_add_main (kernel, 0); - if (remote) - push_remote_target (remote, 0); - else - kgdb_target(); - print_stack_frame(get_current_frame(), -1, 0); + kgdb_init_target(); + kgdb_target(); + print_stack_frame (get_selected_frame (), + frame_relative_level (get_selected_frame ()), 1); } command_loop(); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt.c b/gnu/usr.bin/gdb/kgdb/trgt.c index 5c889eb..93cac11 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt.c +++ b/gnu/usr.bin/gdb/kgdb/trgt.c @@ -27,22 +27,48 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/sysctl.h> +#include <sys/user.h> #include <kvm.h> -#include "kgdb.h" - #include <defs.h> +#include <command.h> #include <gdbthread.h> #include <inferior.h> +#include <regcache.h> #include <target.h> +#include "kgdb.h" + static struct target_ops kgdb_trgt_ops; +#define KERNOFF (kgdb_kernbase ()) +#define INKERNEL(x) ((x) >= KERNOFF) + +static CORE_ADDR +kgdb_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; +} + static char * -kgdb_trgt_extra_thread_info(struct thread_info *ti __unused) +kgdb_trgt_extra_thread_info(struct thread_info *ti) { - return (NULL); + return (kgdb_thr_extra_thread_info(ptid_get_tid(ti->ptid))); } static void @@ -53,16 +79,17 @@ kgdb_trgt_find_new_threads(void) static char * kgdb_trgt_pid_to_str(ptid_t ptid) { - static char buf[16]; + static char buf[33]; - snprintf(buf, sizeof(buf), "TID %d", ptid_get_pid(ptid)); + snprintf(buf, sizeof(buf), "PID %5d TID %5ld", ptid_get_pid(ptid), + ptid_get_tid(ptid)); return (buf); } static int kgdb_trgt_thread_alive(ptid_t ptid) { - return (kgdb_thr_lookup(ptid_get_pid(ptid)) != NULL); + return (kgdb_thr_lookup_tid(ptid_get_tid(ptid)) != NULL); } static int @@ -78,6 +105,71 @@ kgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write, return (kvm_write(kvm, memaddr, myaddr, len)); } +static void +kgdb_switch_to_thread(struct kthr *thr) +{ + if (thr->tid == ptid_get_tid(inferior_ptid)) + return; + + inferior_ptid = ptid_build(thr->pid, 0, thr->tid); + flush_cached_frames (); + registers_changed (); + stop_pc = read_pc (); + select_frame (get_current_frame ()); +} + +static void +kgdb_set_proc_cmd (char *arg, int from_tty) +{ + CORE_ADDR addr; + struct kthr *thr; + + if (!arg) + error_no_arg ("proc address for the new context"); + + if (kvm == NULL) + error ("no kernel core file"); + + addr = (CORE_ADDR) parse_and_eval_address (arg); + + if (!INKERNEL (addr)) { + thr = kgdb_thr_lookup_pid((int)addr); + if (thr == NULL) + error ("invalid pid"); + } else { + thr = kgdb_thr_lookup_paddr(addr); + if (thr == NULL) + error("invalid proc address"); + } + kgdb_switch_to_thread(thr); +} + +static void +kgdb_set_tid_cmd (char *arg, int from_tty) +{ + CORE_ADDR addr; + struct kthr *thr; + + if (!arg) + error_no_arg ("TID or thread address for the new context"); + + if (kvm == NULL) + error ("no kernel core file"); + + addr = (CORE_ADDR) parse_and_eval_address (arg); + + if (!INKERNEL (addr)) { + thr = kgdb_thr_lookup_tid((int)addr); + if (thr == NULL) + error ("invalid TID"); + } else { + thr = kgdb_thr_lookup_taddr(addr); + if (thr == NULL) + error("invalid thread address"); + } + kgdb_switch_to_thread(thr); +} + void kgdb_target(void) { @@ -105,8 +197,12 @@ kgdb_target(void) kt = kgdb_thr_first(); while (kt != NULL) { - ti = add_thread(ptid_build(kt->tid, 0, 0)); + ti = add_thread(ptid_build(kt->pid, 0, kt->tid)); kt = kgdb_thr_next(kt); } - inferior_ptid = ptid_build(curkthr->tid, 0, 0); + inferior_ptid = ptid_build(curkthr->pid, 0, curkthr->tid); + add_com ("proc", class_obscure, kgdb_set_proc_cmd, + "Set current process context"); + add_com ("tid", class_obscure, kgdb_set_tid_cmd, + "Set current process context"); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt_alpha.c b/gnu/usr.bin/gdb/kgdb/trgt_alpha.c index 891b0eb..336970b 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_alpha.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_alpha.c @@ -47,7 +47,7 @@ kgdb_trgt_fetch_registers(int regno __unused) struct kthr *kt; struct pcb pcb; - kt = kgdb_thr_lookup(ptid_get_pid(inferior_ptid)); + kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_amd64.c b/gnu/usr.bin/gdb/kgdb/trgt_amd64.c index e193969..0907d0d 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_amd64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_amd64.c @@ -47,7 +47,7 @@ kgdb_trgt_fetch_registers(int regno __unused) struct kthr *kt; struct pcb pcb; - kt = kgdb_thr_lookup(ptid_get_pid(inferior_ptid)); + kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_i386.c b/gnu/usr.bin/gdb/kgdb/trgt_i386.c index 36c1ed0..96dad51 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_i386.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_i386.c @@ -47,7 +47,7 @@ kgdb_trgt_fetch_registers(int regno __unused) struct kthr *kt; struct pcb pcb; - kt = kgdb_thr_lookup(ptid_get_pid(inferior_ptid)); + kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_ia64.c b/gnu/usr.bin/gdb/kgdb/trgt_ia64.c index 15609af..bfceba4 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_ia64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_ia64.c @@ -49,7 +49,7 @@ kgdb_trgt_fetch_registers(int regno __unused) struct pcb pcb; uint64_t r; - kt = kgdb_thr_lookup(ptid_get_pid(inferior_ptid)); + kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c b/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c index 81f9a86..8be716e 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c @@ -49,7 +49,7 @@ kgdb_trgt_fetch_registers(int regno __unused) struct pcb pcb; uint64_t r; - kt = kgdb_thr_lookup(ptid_get_pid(inferior_ptid)); + kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { |