diff options
author | kan <kan@FreeBSD.org> | 2005-02-20 22:55:07 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2005-02-20 22:55:07 +0000 |
commit | 858ff332fa8011a79d62b31a443335ed8b70fe69 (patch) | |
tree | 84cd848fd72dc0dd4c8a495c04c1925cdc3accf5 /gnu | |
parent | 967bb5dcb03c116c14a8b9cef87322e766eb32f3 (diff) | |
download | FreeBSD-src-858ff332fa8011a79d62b31a443335ed8b70fe69.zip FreeBSD-src-858ff332fa8011a79d62b31a443335ed8b70fe69.tar.gz |
Attempt to make kgdb little more useful and easy to use. Properly initialize
it to recognise what ABI to use on amd64 (and possibly others) platform.
Display PID and process name as a part of the 'info threads' output, TIDs
alone are too confusing. Introduce new commmands 'tid <tid>' and 'proc <pid>'
to accompany gdb's default 'thread <thread num>' to make the task of switching
between different contexts easier.
Diffstat (limited to 'gnu')
-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)) { |