diff --git a/gnu/usr.bin/gdb/kgdb/kgdb.h b/gnu/usr.bin/gdb/kgdb/kgdb.h index e828f56bbc7b..1a32d8a125ab 100644 --- a/gnu/usr.bin/gdb/kgdb/kgdb.h +++ b/gnu/usr.bin/gdb/kgdb/kgdb.h @@ -1,76 +1,78 @@ /* * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _KGDB_H_ #define _KGDB_H_ struct thread_info; extern kvm_t *kvm; struct kthr { struct kthr *next; uintptr_t paddr; uintptr_t kaddr; uintptr_t kstack; uintptr_t pcb; int tid; int pid; u_char cpu; }; extern struct kthr *curkthr; void initialize_kld_target(void); void initialize_kgdb_target(void); void kgdb_dmesg(void); +CORE_ADDR kgdb_trgt_core_pcb(u_int); +CORE_ADDR kgdb_trgt_stop_pcb(u_int, u_int); void kgdb_trgt_new_objfile(struct objfile *); void kgdb_trgt_fetch_registers(int); void kgdb_trgt_store_registers(int); void kld_init(void); void kld_new_objfile(struct objfile *); frame_unwind_sniffer_ftype kgdb_trgt_trapframe_sniffer; struct kthr *kgdb_thr_first(void); struct kthr *kgdb_thr_init(void); 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); CORE_ADDR kgdb_lookup(const char *sym); CORE_ADDR kgdb_parse_1(const char *, int); #define kgdb_parse(exp) kgdb_parse_1((exp), 0) #define kgdb_parse_quiet(exp) kgdb_parse_1((exp), 1) #endif /* _KGDB_H_ */ diff --git a/gnu/usr.bin/gdb/kgdb/kthr.c b/gnu/usr.bin/gdb/kgdb/kthr.c index b12d07c28e2c..713b93b6895a 100644 --- a/gnu/usr.bin/gdb/kgdb/kthr.c +++ b/gnu/usr.bin/gdb/kgdb/kthr.c @@ -1,257 +1,252 @@ /* * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" -#include static CORE_ADDR dumppcb; static int dumptid; -static CORE_ADDR stoppcbs; static cpuset_t stopped_cpus; static struct kthr *first; struct kthr *curkthr; CORE_ADDR kgdb_lookup(const char *sym) { CORE_ADDR addr; char *name; asprintf(&name, "&%s", sym); addr = kgdb_parse(name); free(name); return (addr); } struct kthr * kgdb_thr_first(void) { return (first); } static void kgdb_thr_add_procs(uintptr_t paddr) { struct proc p; struct thread td; struct kthr *kt; CORE_ADDR addr; while (paddr != 0) { if (kvm_read(kvm, paddr, &p, sizeof(p)) != sizeof(p)) { warnx("kvm_read: %s", kvm_geterr(kvm)); break; } addr = (uintptr_t)TAILQ_FIRST(&p.p_threads); while (addr != 0) { if (kvm_read(kvm, addr, &td, sizeof(td)) != sizeof(td)) { warnx("kvm_read: %s", kvm_geterr(kvm)); break; } kt = malloc(sizeof(*kt)); kt->next = first; kt->kaddr = addr; if (td.td_tid == dumptid) kt->pcb = dumppcb; - else if (td.td_state == TDS_RUNNING && stoppcbs != 0 && + else if (td.td_state == TDS_RUNNING && CPU_ISSET(td.td_oncpu, &stopped_cpus)) - kt->pcb = (uintptr_t)stoppcbs + - sizeof(struct pcb) * td.td_oncpu; + kt->pcb = kgdb_trgt_core_pcb(td.td_oncpu); else kt->pcb = (uintptr_t)td.td_pcb; kt->kstack = td.td_kstack; kt->tid = td.td_tid; kt->pid = p.p_pid; kt->paddr = paddr; kt->cpu = td.td_oncpu; first = kt; addr = (uintptr_t)TAILQ_NEXT(&td, td_plist); } paddr = (uintptr_t)LIST_NEXT(&p, p_list); } } struct kthr * kgdb_thr_init(void) { long cpusetsize; struct kthr *kt; CORE_ADDR addr; uintptr_t paddr; while (first != NULL) { kt = first; first = kt->next; free(kt); } addr = kgdb_lookup("allproc"); if (addr == 0) return (NULL); kvm_read(kvm, addr, &paddr, sizeof(paddr)); dumppcb = kgdb_lookup("dumppcb"); if (dumppcb == 0) return (NULL); addr = kgdb_lookup("dumptid"); if (addr != 0) kvm_read(kvm, addr, &dumptid, sizeof(dumptid)); else dumptid = -1; addr = kgdb_lookup("stopped_cpus"); CPU_ZERO(&stopped_cpus); cpusetsize = sysconf(_SC_CPUSET_SIZE); if (cpusetsize != -1 && (u_long)cpusetsize <= sizeof(cpuset_t) && addr != 0) kvm_read(kvm, addr, &stopped_cpus, cpusetsize); - stoppcbs = kgdb_lookup("stoppcbs"); - kgdb_thr_add_procs(paddr); addr = kgdb_lookup("zombproc"); if (addr != 0) { kvm_read(kvm, addr, &paddr, sizeof(paddr)); kgdb_thr_add_procs(paddr); } curkthr = kgdb_thr_lookup_tid(dumptid); if (curkthr == NULL) curkthr = first; return (first); } struct kthr * kgdb_thr_lookup_tid(int tid) { struct kthr *kt; kt = first; while (kt != NULL && kt->tid != tid) kt = kt->next; return (kt); } 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); } struct kthr * kgdb_thr_select(struct kthr *kt) { struct kthr *pcur; pcur = curkthr; curkthr = kt; return (pcur); } char * kgdb_thr_extra_thread_info(int tid) { char comm[MAXCOMLEN + 1]; char td_name[MAXCOMLEN + 1]; struct kthr *kt; struct proc *p; struct thread *t; static char buf[64]; kt = kgdb_thr_lookup_tid(tid); if (kt == NULL) return (NULL); snprintf(buf, sizeof(buf), "PID=%d", kt->pid); p = (struct proc *)kt->paddr; if (kvm_read(kvm, (uintptr_t)&p->p_comm[0], &comm, sizeof(comm)) != sizeof(comm)) return (buf); strlcat(buf, ": ", sizeof(buf)); strlcat(buf, comm, sizeof(buf)); t = (struct thread *)kt->kaddr; if (kvm_read(kvm, (uintptr_t)&t->td_name[0], &td_name, sizeof(td_name)) == sizeof(td_name) && strcmp(comm, td_name) != 0) { strlcat(buf, "/", sizeof(buf)); strlcat(buf, td_name, sizeof(buf)); } return (buf); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt.c b/gnu/usr.bin/gdb/kgdb/trgt.c index 14449b93af38..85065ccc383a 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt.c +++ b/gnu/usr.bin/gdb/kgdb/trgt.c @@ -1,354 +1,371 @@ /* * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" +static CORE_ADDR stoppcbs; + static void kgdb_core_cleanup(void *); static char *vmcore; static struct target_ops kgdb_trgt_ops; kvm_t *kvm; static char kvm_err[_POSIX2_LINE_MAX]; #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 void kgdb_trgt_open(char *filename, int from_tty) { struct cleanup *old_chain; struct thread_info *ti; struct kthr *kt; kvm_t *nkvm; char *temp; int ontop; target_preopen (from_tty); if (!filename) error ("No vmcore file specified."); if (!exec_bfd) error ("Can't open a vmcore without a kernel"); filename = tilde_expand (filename); if (filename[0] != '/') { temp = concat (current_directory, "/", filename, NULL); xfree(filename); filename = temp; } old_chain = make_cleanup (xfree, filename); nkvm = kvm_openfiles(bfd_get_filename(exec_bfd), filename, NULL, write_files ? O_RDWR : O_RDONLY, kvm_err); if (nkvm == NULL) error ("Failed to open vmcore: %s", kvm_err); /* Don't free the filename now and close any previous vmcore. */ discard_cleanups(old_chain); unpush_target(&kgdb_trgt_ops); kvm = nkvm; vmcore = filename; old_chain = make_cleanup(kgdb_core_cleanup, NULL); ontop = !push_target (&kgdb_trgt_ops); discard_cleanups (old_chain); kgdb_dmesg(); init_thread_list(); kt = kgdb_thr_init(); while (kt != NULL) { ti = add_thread(pid_to_ptid(kt->tid)); kt = kgdb_thr_next(kt); } if (curkthr != 0) inferior_ptid = pid_to_ptid(curkthr->tid); if (ontop) { /* XXX: fetch registers? */ kld_init(); flush_cached_frames(); select_frame (get_current_frame()); print_stack_frame(get_selected_frame(), frame_relative_level(get_selected_frame()), 1); } else warning( "you won't be able to access this vmcore until you terminate\n\ your %s; do ``info files''", target_longname); } static void kgdb_trgt_close(int quitting) { if (kvm != NULL) { inferior_ptid = null_ptid; CLEAR_SOLIB(); if (kvm_close(kvm) != 0) warning("cannot close \"%s\": %s", vmcore, kvm_geterr(kvm)); kvm = NULL; xfree(vmcore); vmcore = NULL; if (kgdb_trgt_ops.to_sections) { xfree(kgdb_trgt_ops.to_sections); kgdb_trgt_ops.to_sections = NULL; kgdb_trgt_ops.to_sections_end = NULL; } } } static void kgdb_core_cleanup(void *arg) { kgdb_trgt_close(0); } static void kgdb_trgt_detach(char *args, int from_tty) { if (args) error ("Too many arguments"); unpush_target(&kgdb_trgt_ops); reinit_frame_cache(); if (from_tty) printf_filtered("No vmcore file now.\n"); } static char * kgdb_trgt_extra_thread_info(struct thread_info *ti) { return (kgdb_thr_extra_thread_info(ptid_get_pid(ti->ptid))); } static void kgdb_trgt_files_info(struct target_ops *target) { printf_filtered ("\t`%s', ", vmcore); wrap_here (" "); printf_filtered ("file type %s.\n", "FreeBSD kernel vmcore"); } static void kgdb_trgt_find_new_threads(void) { struct target_ops *tb; if (kvm != NULL) return; tb = find_target_beneath(&kgdb_trgt_ops); if (tb->to_find_new_threads != NULL) tb->to_find_new_threads(); } static char * kgdb_trgt_pid_to_str(ptid_t ptid) { static char buf[33]; snprintf(buf, sizeof(buf), "Thread %d", ptid_get_pid(ptid)); return (buf); } static int kgdb_trgt_thread_alive(ptid_t ptid) { return (kgdb_thr_lookup_tid(ptid_get_pid(ptid)) != NULL); } static int kgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write, struct mem_attrib *attrib, struct target_ops *target) { struct target_ops *tb; if (kvm != NULL) { if (len == 0) return (0); if (!write) return (kvm_read(kvm, memaddr, myaddr, len)); else return (kvm_write(kvm, memaddr, myaddr, len)); } tb = find_target_beneath(target); return (tb->to_xfer_memory(memaddr, myaddr, len, write, attrib, tb)); } static int kgdb_trgt_ignore_breakpoints(CORE_ADDR addr, char *contents) { return 0; } static void kgdb_switch_to_thread(int tid) { char buf[16]; int thread_id; thread_id = pid_to_thread_id(pid_to_ptid(tid)); if (thread_id == 0) error ("invalid tid"); snprintf(buf, sizeof(buf), "%d", thread_id); gdb_thread_select(uiout, buf); } 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 ("only supported for core file target"); 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->tid); } 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"); addr = (CORE_ADDR) parse_and_eval_address (arg); if (kvm != NULL && INKERNEL (addr)) { thr = kgdb_thr_lookup_taddr(addr); if (thr == NULL) error("invalid thread address"); addr = thr->tid; } kgdb_switch_to_thread(addr); } int fbsdcoreops_suppress_target = 1; void initialize_kgdb_target(void) { kgdb_trgt_ops.to_magic = OPS_MAGIC; kgdb_trgt_ops.to_shortname = "kernel"; kgdb_trgt_ops.to_longname = "kernel core dump file"; kgdb_trgt_ops.to_doc = "Use a vmcore file as a target. Specify the filename of the vmcore file."; kgdb_trgt_ops.to_stratum = core_stratum; kgdb_trgt_ops.to_has_memory = 1; kgdb_trgt_ops.to_has_registers = 1; kgdb_trgt_ops.to_has_stack = 1; kgdb_trgt_ops.to_open = kgdb_trgt_open; kgdb_trgt_ops.to_close = kgdb_trgt_close; kgdb_trgt_ops.to_attach = find_default_attach; kgdb_trgt_ops.to_detach = kgdb_trgt_detach; kgdb_trgt_ops.to_extra_thread_info = kgdb_trgt_extra_thread_info; kgdb_trgt_ops.to_fetch_registers = kgdb_trgt_fetch_registers; kgdb_trgt_ops.to_files_info = kgdb_trgt_files_info; kgdb_trgt_ops.to_find_new_threads = kgdb_trgt_find_new_threads; kgdb_trgt_ops.to_pid_to_str = kgdb_trgt_pid_to_str; kgdb_trgt_ops.to_store_registers = kgdb_trgt_store_registers; kgdb_trgt_ops.to_thread_alive = kgdb_trgt_thread_alive; kgdb_trgt_ops.to_xfer_memory = kgdb_trgt_xfer_memory; kgdb_trgt_ops.to_insert_breakpoint = kgdb_trgt_ignore_breakpoints; kgdb_trgt_ops.to_remove_breakpoint = kgdb_trgt_ignore_breakpoints; add_target(&kgdb_trgt_ops); add_com ("proc", class_obscure, kgdb_set_proc_cmd, "Set current process context"); add_com ("tid", class_obscure, kgdb_set_tid_cmd, "Set current thread context"); } + +CORE_ADDR +kgdb_trgt_stop_pcb(u_int cpuid, u_int pcbsz) +{ + static int once = 0; + + if (stoppcbs == 0 && !once) { + once = 1; + stoppcbs = kgdb_lookup("stoppcbs"); + } + if (stoppcbs == 0) + return 0; + + return (stoppcbs + pcbsz * cpuid); +} diff --git a/gnu/usr.bin/gdb/kgdb/trgt_amd64.c b/gnu/usr.bin/gdb/kgdb/trgt_amd64.c index cdab77538af5..cb13d7172a6c 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_amd64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_amd64.c @@ -1,192 +1,198 @@ /* * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } supply_register(AMD64_RBX_REGNUM, (char *)&pcb.pcb_rbx); supply_register(AMD64_RBP_REGNUM, (char *)&pcb.pcb_rbp); supply_register(AMD64_RSP_REGNUM, (char *)&pcb.pcb_rsp); supply_register(AMD64_R8_REGNUM + 4, (char *)&pcb.pcb_r12); supply_register(AMD64_R8_REGNUM + 5, (char *)&pcb.pcb_r13); supply_register(AMD64_R8_REGNUM + 6, (char *)&pcb.pcb_r14); supply_register(AMD64_R15_REGNUM, (char *)&pcb.pcb_r15); supply_register(AMD64_RIP_REGNUM, (char *)&pcb.pcb_rip); amd64_supply_fxsave(current_regcache, -1, (struct fpusave *)(&pcb + 1)); } void kgdb_trgt_store_registers(int regno __unused) { fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); } void kgdb_trgt_new_objfile(struct objfile *objfile) { } struct kgdb_frame_cache { CORE_ADDR pc; CORE_ADDR sp; }; static int kgdb_trgt_frame_offset[20] = { offsetof(struct trapframe, tf_rax), offsetof(struct trapframe, tf_rbx), offsetof(struct trapframe, tf_rcx), offsetof(struct trapframe, tf_rdx), offsetof(struct trapframe, tf_rsi), offsetof(struct trapframe, tf_rdi), offsetof(struct trapframe, tf_rbp), offsetof(struct trapframe, tf_rsp), offsetof(struct trapframe, tf_r8), offsetof(struct trapframe, tf_r9), offsetof(struct trapframe, tf_r10), offsetof(struct trapframe, tf_r11), offsetof(struct trapframe, tf_r12), offsetof(struct trapframe, tf_r13), offsetof(struct trapframe, tf_r14), offsetof(struct trapframe, tf_r15), offsetof(struct trapframe, tf_rip), offsetof(struct trapframe, tf_rflags), offsetof(struct trapframe, tf_cs), offsetof(struct trapframe, tf_ss) }; static struct kgdb_frame_cache * kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); *this_cache = cache; cache->pc = frame_func_unwind(next_frame); frame_unwind_register(next_frame, SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, SP_REGNUM)); } return (cache); } static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_frame_cache *cache; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *this_id = frame_id_build(cache->sp, cache->pc); } static void kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { char dummy_valuep[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; int ofs, regsz; regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; ofs = (regnum >= AMD64_RAX_REGNUM && regnum <= AMD64_EFLAGS_REGNUM + 2) ? kgdb_trgt_frame_offset[regnum] : -1; if (ofs == -1) return; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *addrp = cache->sp + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { UNKNOWN_FRAME, &kgdb_trgt_trapframe_this_id, &kgdb_trgt_trapframe_prev_register }; const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { char *pname; CORE_ADDR pc; pc = frame_pc_unwind(next_frame); pname = NULL; find_pc_partial_function(pc, &pname, NULL, NULL); if (pname == NULL) return (NULL); if (strcmp(pname, "calltrap") == 0 || strcmp(pname, "nmi_calltrap") == 0 || (pname[0] == 'X' && pname[1] != '_')) return (&kgdb_trgt_trapframe_unwind); /* printf("%s: %lx =%s\n", __func__, pc, pname); */ return (NULL); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt_arm.c b/gnu/usr.bin/gdb/kgdb/trgt_arm.c index f2e292e5735d..ca18ae3696ab 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_arm.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_arm.c @@ -1,237 +1,243 @@ /* * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #ifndef CROSS_DEBUGGER #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { #ifndef CROSS_DEBUGGER struct kthr *kt; struct pcb pcb; int i, reg; kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } for (i = ARM_A1_REGNUM + 8; i <= ARM_SP_REGNUM; i++) { supply_register(i, (char *)&pcb.un_32.pcb32_r8 + (i - (ARM_A1_REGNUM + 8 )) * 4); } if (pcb.un_32.pcb32_sp != 0) { for (i = 0; i < 4; i++) { if (kvm_read(kvm, pcb.un_32.pcb32_sp + (i) * 4, ®, 4) != 4) { warnx("kvm_read: %s", kvm_geterr(kvm)); break; } supply_register(ARM_A1_REGNUM + 4 + i, (char *)®); } if (kvm_read(kvm, pcb.un_32.pcb32_sp + 4 * 4, ®, 4) != 4) warnx("kvm_read :%s", kvm_geterr(kvm)); else supply_register(ARM_PC_REGNUM, (char *)®); } #endif } void kgdb_trgt_store_registers(int regno __unused) { fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); } void kgdb_trgt_new_objfile(struct objfile *objfile) { } #ifndef CROSS_DEBUGGER struct kgdb_frame_cache { CORE_ADDR fp; CORE_ADDR sp; }; static int kgdb_trgt_frame_offset[26] = { offsetof(struct trapframe, tf_r0), offsetof(struct trapframe, tf_r1), offsetof(struct trapframe, tf_r2), offsetof(struct trapframe, tf_r3), offsetof(struct trapframe, tf_r4), offsetof(struct trapframe, tf_r5), offsetof(struct trapframe, tf_r6), offsetof(struct trapframe, tf_r7), offsetof(struct trapframe, tf_r8), offsetof(struct trapframe, tf_r9), offsetof(struct trapframe, tf_r10), offsetof(struct trapframe, tf_r11), offsetof(struct trapframe, tf_r12), offsetof(struct trapframe, tf_svc_sp), offsetof(struct trapframe, tf_svc_lr), offsetof(struct trapframe, tf_pc), -1, -1, -1, -1, -1, -1, -1, -1, -1, offsetof(struct trapframe, tf_spsr) }; static struct kgdb_frame_cache * kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); *this_cache = cache; frame_unwind_register(next_frame, ARM_SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, ARM_SP_REGNUM)); frame_unwind_register(next_frame, ARM_FP_REGNUM, buf); cache->fp = extract_unsigned_integer(buf, register_size(current_gdbarch, ARM_FP_REGNUM)); } return (cache); } static int is_undef; static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_frame_cache *cache; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *this_id = frame_id_build(cache->fp, 0); } static void kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { char dummy_valuep[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; int ofs, regsz; int is_undefined = 0; regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; ofs = (regnum >= 0 && regnum <= ARM_PS_REGNUM) ? kgdb_trgt_frame_offset[regnum] : -1; if (ofs == -1) return; cache = kgdb_trgt_frame_cache(next_frame, this_cache); if (is_undef && (regnum == ARM_SP_REGNUM || regnum == ARM_PC_REGNUM)) { *addrp = cache->sp + offsetof(struct trapframe, tf_spsr); target_read_memory(*addrp, valuep, regsz); is_undefined = 1; ofs = kgdb_trgt_frame_offset[ARM_SP_REGNUM]; } *addrp = cache->sp + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); if (is_undefined) { *addrp = *(unsigned int *)valuep + (regnum == ARM_SP_REGNUM ? 0 : 8); target_read_memory(*addrp, valuep, regsz); } } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { UNKNOWN_FRAME, &kgdb_trgt_trapframe_this_id, &kgdb_trgt_trapframe_prev_register }; #endif const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { #ifndef CROSS_DEBUGGER char *pname; CORE_ADDR pc; pc = frame_pc_unwind(next_frame); pname = NULL; find_pc_partial_function(pc, &pname, NULL, NULL); if (pname == NULL) { is_undef = 0; return (NULL); } if (!strcmp(pname, "undefinedinstruction")) is_undef = 1; if (strcmp(pname, "Laddress_exception_entry") == 0 || strcmp(pname, "undefined_entry") == 0 || strcmp(pname, "exception_exit") == 0 || strcmp(pname, "Laddress_exception_msg") == 0 || strcmp(pname, "irq_entry") == 0) return (&kgdb_trgt_trapframe_unwind); if (!strcmp(pname, "undefinedinstruction")) is_undef = 1; else is_undef = 0; #endif return (NULL); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt_i386.c b/gnu/usr.bin/gdb/kgdb/trgt_i386.c index aba8b6586340..02c99182fcfc 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_i386.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_i386.c @@ -1,381 +1,387 @@ /* * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" static int ofs_fix; +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } supply_register(I386_EBX_REGNUM, (char *)&pcb.pcb_ebx); supply_register(I386_ESP_REGNUM, (char *)&pcb.pcb_esp); supply_register(I386_EBP_REGNUM, (char *)&pcb.pcb_ebp); supply_register(I386_ESI_REGNUM, (char *)&pcb.pcb_esi); supply_register(I386_EDI_REGNUM, (char *)&pcb.pcb_edi); supply_register(I386_EIP_REGNUM, (char *)&pcb.pcb_eip); } void kgdb_trgt_store_registers(int regno __unused) { fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); } void kgdb_trgt_new_objfile(struct objfile *objfile) { /* * In revision 1.117 of i386/i386/exception.S trap handlers * were changed to pass trapframes by reference rather than * by value. Detect this by seeing if the first instruction * at the 'calltrap' label is a "push %esp" which has the * opcode 0x54. */ if (kgdb_parse("((char *)calltrap)[0]") == 0x54) ofs_fix = 4; else ofs_fix = 0; } struct kgdb_tss_cache { CORE_ADDR pc; CORE_ADDR sp; CORE_ADDR tss; }; static int kgdb_trgt_tss_offset[15] = { offsetof(struct i386tss, tss_eax), offsetof(struct i386tss, tss_ecx), offsetof(struct i386tss, tss_edx), offsetof(struct i386tss, tss_ebx), offsetof(struct i386tss, tss_esp), offsetof(struct i386tss, tss_ebp), offsetof(struct i386tss, tss_esi), offsetof(struct i386tss, tss_edi), offsetof(struct i386tss, tss_eip), offsetof(struct i386tss, tss_eflags), offsetof(struct i386tss, tss_cs), offsetof(struct i386tss, tss_ss), offsetof(struct i386tss, tss_ds), offsetof(struct i386tss, tss_es), offsetof(struct i386tss, tss_fs) }; /* * If the current thread is executing on a CPU, fetch the common_tss * for that CPU. * * This is painful because 'struct pcpu' is variant sized, so we can't * use it. Instead, we lookup the GDT selector for this CPU and * extract the base of the TSS from there. */ static CORE_ADDR kgdb_trgt_fetch_tss(void) { struct kthr *kt; struct segment_descriptor sd; uintptr_t addr, cpu0prvpage, tss; kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL || kt->cpu == NOCPU) return (0); addr = kgdb_lookup("gdt"); if (addr == 0) return (0); addr += (kt->cpu * NGDT + GPROC0_SEL) * sizeof(sd); if (kvm_read(kvm, addr, &sd, sizeof(sd)) != sizeof(sd)) { warnx("kvm_read: %s", kvm_geterr(kvm)); return (0); } if (sd.sd_type != SDT_SYS386BSY) { warnx("descriptor is not a busy TSS"); return (0); } tss = sd.sd_hibase << 24 | sd.sd_lobase; /* * In SMP kernels, the TSS is stored as part of the per-CPU * data. On older kernels, the CPU0's private page * is stored at an address that isn't mapped in minidumps. * However, the data is mapped at the alternate cpu0prvpage * address. Thus, if the TSS is at the invalid address, * change it to be relative to cpu0prvpage instead. */ if (trunc_page(tss) == 0xffc00000) { addr = kgdb_lookup("cpu0prvpage"); if (addr == 0) return (0); if (kvm_read(kvm, addr, &cpu0prvpage, sizeof(cpu0prvpage)) != sizeof(cpu0prvpage)) { warnx("kvm_read: %s", kvm_geterr(kvm)); return (0); } tss = cpu0prvpage + (tss & PAGE_MASK); } return ((CORE_ADDR)tss); } static struct kgdb_tss_cache * kgdb_trgt_tss_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_tss_cache *cache; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_tss_cache); *this_cache = cache; cache->pc = frame_func_unwind(next_frame); frame_unwind_register(next_frame, SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, SP_REGNUM)); cache->tss = kgdb_trgt_fetch_tss(); } return (cache); } static void kgdb_trgt_dblfault_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_tss_cache *cache; cache = kgdb_trgt_tss_cache(next_frame, this_cache); *this_id = frame_id_build(cache->sp, cache->pc); } static void kgdb_trgt_dblfault_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { char dummy_valuep[MAX_REGISTER_SIZE]; struct kgdb_tss_cache *cache; int ofs, regsz; regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; ofs = (regnum >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) ? kgdb_trgt_tss_offset[regnum] : -1; if (ofs == -1) return; cache = kgdb_trgt_tss_cache(next_frame, this_cache); if (cache->tss == 0) return; *addrp = cache->tss + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_dblfault_unwind = { UNKNOWN_FRAME, &kgdb_trgt_dblfault_this_id, &kgdb_trgt_dblfault_prev_register }; struct kgdb_frame_cache { int frame_type; CORE_ADDR pc; CORE_ADDR sp; }; #define FT_NORMAL 1 #define FT_INTRFRAME 2 #define FT_INTRTRAPFRAME 3 #define FT_TIMERFRAME 4 static int kgdb_trgt_frame_offset[15] = { offsetof(struct trapframe, tf_eax), offsetof(struct trapframe, tf_ecx), offsetof(struct trapframe, tf_edx), offsetof(struct trapframe, tf_ebx), offsetof(struct trapframe, tf_esp), offsetof(struct trapframe, tf_ebp), offsetof(struct trapframe, tf_esi), offsetof(struct trapframe, tf_edi), offsetof(struct trapframe, tf_eip), offsetof(struct trapframe, tf_eflags), offsetof(struct trapframe, tf_cs), offsetof(struct trapframe, tf_ss), offsetof(struct trapframe, tf_ds), offsetof(struct trapframe, tf_es), offsetof(struct trapframe, tf_fs) }; static struct kgdb_frame_cache * kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; char *pname; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); *this_cache = cache; cache->pc = frame_func_unwind(next_frame); find_pc_partial_function(cache->pc, &pname, NULL, NULL); if (pname[0] != 'X') cache->frame_type = FT_NORMAL; else if (strcmp(pname, "Xtimerint") == 0) cache->frame_type = FT_TIMERFRAME; else if (strcmp(pname, "Xcpustop") == 0 || strcmp(pname, "Xrendezvous") == 0 || strcmp(pname, "Xipi_intr_bitmap_handler") == 0 || strcmp(pname, "Xlazypmap") == 0) cache->frame_type = FT_INTRTRAPFRAME; else cache->frame_type = FT_INTRFRAME; frame_unwind_register(next_frame, SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, SP_REGNUM)); } return (cache); } static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_frame_cache *cache; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *this_id = frame_id_build(cache->sp, cache->pc); } static void kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { char dummy_valuep[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; int ofs, regsz; regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; ofs = (regnum >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) ? kgdb_trgt_frame_offset[regnum] + ofs_fix : -1; if (ofs == -1) return; cache = kgdb_trgt_frame_cache(next_frame, this_cache); switch (cache->frame_type) { case FT_NORMAL: break; case FT_INTRFRAME: ofs += 4; break; case FT_TIMERFRAME: break; case FT_INTRTRAPFRAME: ofs -= ofs_fix; break; default: fprintf_unfiltered(gdb_stderr, "Correct FT_XXX frame offsets " "for %d\n", cache->frame_type); break; } *addrp = cache->sp + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { UNKNOWN_FRAME, &kgdb_trgt_trapframe_this_id, &kgdb_trgt_trapframe_prev_register }; const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { char *pname; CORE_ADDR pc; pc = frame_pc_unwind(next_frame); pname = NULL; find_pc_partial_function(pc, &pname, NULL, NULL); if (pname == NULL) return (NULL); if (strcmp(pname, "dblfault_handler") == 0) return (&kgdb_trgt_dblfault_unwind); if (strcmp(pname, "calltrap") == 0 || (pname[0] == 'X' && pname[1] != '_')) return (&kgdb_trgt_trapframe_unwind); /* printf("%s: %llx =%s\n", __func__, pc, pname); */ return (NULL); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt_ia64.c b/gnu/usr.bin/gdb/kgdb/trgt_ia64.c index 4efa6eb5f6cd..6ba800bd0144 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_ia64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_ia64.c @@ -1,326 +1,338 @@ /* * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #ifdef CROSS_DEBUGGER #include #include #include #include #else #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + CORE_ADDR addr; + char *expr; + + asprintf(&expr, "&cpuid_to_pcpu[%d]->pc_md.pcb", cpuid); + addr = kgdb_parse(expr); + free(expr); + return (addr); +} + void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; uint64_t r; kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } /* Registers 0-127: general registers. */ supply_register(IA64_GR1_REGNUM, (char *)&pcb.pcb_special.gp); supply_register(IA64_GR4_REGNUM, (char *)&pcb.pcb_preserved.gr4); supply_register(IA64_GR5_REGNUM, (char *)&pcb.pcb_preserved.gr5); supply_register(IA64_GR6_REGNUM, (char *)&pcb.pcb_preserved.gr6); supply_register(IA64_GR7_REGNUM, (char *)&pcb.pcb_preserved.gr7); supply_register(IA64_GR12_REGNUM, (char *)&pcb.pcb_special.sp); supply_register(IA64_GR12_REGNUM+1, (char *)&pcb.pcb_special.tp); /* Registers 128-255: floating-point registers. */ supply_register(IA64_FR2_REGNUM, (char *)&pcb.pcb_preserved_fp.fr2); supply_register(IA64_FR2_REGNUM+1, (char *)&pcb.pcb_preserved_fp.fr3); supply_register(IA64_FR2_REGNUM+2, (char *)&pcb.pcb_preserved_fp.fr4); supply_register(IA64_FR2_REGNUM+3, (char *)&pcb.pcb_preserved_fp.fr5); supply_register(IA64_FR16_REGNUM, (char *)&pcb.pcb_preserved_fp.fr16); supply_register(IA64_FR16_REGNUM+1, (char*)&pcb.pcb_preserved_fp.fr17); supply_register(IA64_FR16_REGNUM+2, (char*)&pcb.pcb_preserved_fp.fr18); supply_register(IA64_FR16_REGNUM+3, (char*)&pcb.pcb_preserved_fp.fr19); supply_register(IA64_FR16_REGNUM+4, (char*)&pcb.pcb_preserved_fp.fr20); supply_register(IA64_FR16_REGNUM+5, (char*)&pcb.pcb_preserved_fp.fr21); supply_register(IA64_FR16_REGNUM+6, (char*)&pcb.pcb_preserved_fp.fr22); supply_register(IA64_FR16_REGNUM+7, (char*)&pcb.pcb_preserved_fp.fr23); supply_register(IA64_FR16_REGNUM+8, (char*)&pcb.pcb_preserved_fp.fr24); supply_register(IA64_FR16_REGNUM+9, (char*)&pcb.pcb_preserved_fp.fr25); supply_register(IA64_FR16_REGNUM+10,(char*)&pcb.pcb_preserved_fp.fr26); supply_register(IA64_FR16_REGNUM+11,(char*)&pcb.pcb_preserved_fp.fr27); supply_register(IA64_FR16_REGNUM+12,(char*)&pcb.pcb_preserved_fp.fr28); supply_register(IA64_FR16_REGNUM+13,(char*)&pcb.pcb_preserved_fp.fr29); supply_register(IA64_FR16_REGNUM+14,(char*)&pcb.pcb_preserved_fp.fr30); supply_register(IA64_FR16_REGNUM+15,(char*)&pcb.pcb_preserved_fp.fr31); /* Registers 320-327: branch registers. */ if (pcb.pcb_special.__spare == ~0UL) supply_register(IA64_BR0_REGNUM, (char *)&pcb.pcb_special.rp); supply_register(IA64_BR1_REGNUM, (char *)&pcb.pcb_preserved.br1); supply_register(IA64_BR2_REGNUM, (char *)&pcb.pcb_preserved.br2); supply_register(IA64_BR3_REGNUM, (char *)&pcb.pcb_preserved.br3); supply_register(IA64_BR4_REGNUM, (char *)&pcb.pcb_preserved.br4); supply_register(IA64_BR5_REGNUM, (char *)&pcb.pcb_preserved.br5); /* Registers 328-333: misc. other registers. */ supply_register(IA64_PR_REGNUM, (char *)&pcb.pcb_special.pr); if (pcb.pcb_special.__spare == ~0UL) { r = pcb.pcb_special.iip + ((pcb.pcb_special.psr >> 41) & 3); supply_register(IA64_IP_REGNUM, (char *)&r); supply_register(IA64_CFM_REGNUM, (char *)&pcb.pcb_special.cfm); } else { supply_register(IA64_IP_REGNUM, (char *)&pcb.pcb_special.rp); supply_register(IA64_CFM_REGNUM, (char *)&pcb.pcb_special.pfs); } /* Registers 334-461: application registers. */ supply_register(IA64_RSC_REGNUM, (char *)&pcb.pcb_special.rsc); r = pcb.pcb_special.bspstore; if (pcb.pcb_special.__spare == ~0UL) r += pcb.pcb_special.ndirty; else r = ia64_bsp_adjust(r, IA64_CFM_SOF(pcb.pcb_special.pfs) - IA64_CFM_SOL(pcb.pcb_special.pfs)); supply_register(IA64_BSP_REGNUM, (char *)&r); supply_register(IA64_BSPSTORE_REGNUM, (char *)&r); supply_register(IA64_RNAT_REGNUM, (char *)&pcb.pcb_special.rnat); supply_register(IA64_UNAT_REGNUM, (char *)&pcb.pcb_special.unat); supply_register(IA64_FPSR_REGNUM, (char *)&pcb.pcb_special.fpsr); if (pcb.pcb_special.__spare == ~0UL) supply_register(IA64_PFS_REGNUM, (char *)&pcb.pcb_special.pfs); supply_register(IA64_LC_REGNUM, (char *)&pcb.pcb_preserved.lc); } void kgdb_trgt_store_registers(int regno __unused) { fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); } void kgdb_trgt_new_objfile(struct objfile *objfile) { } struct kgdb_frame_cache { CORE_ADDR bsp; CORE_ADDR ip; CORE_ADDR sp; CORE_ADDR saved_bsp; }; #define SPECIAL(x) offsetof(struct trapframe, tf_special) \ + offsetof(struct _special, x) #define SCRATCH(x) offsetof(struct trapframe, tf_scratch) \ + offsetof(struct _caller_saved, x) #define SCRATCH_FP(x) offsetof(struct trapframe, tf_scratch_fp) \ + offsetof(struct _caller_saved_fp, x) static int kgdb_trgt_frame_ofs_gr[32] = { -1, /* gr0 */ SPECIAL(gp), SCRATCH(gr2), SCRATCH(gr3), -1, -1, -1, -1, /* gr4-gr7 */ SCRATCH(gr8), SCRATCH(gr9), SCRATCH(gr10), SCRATCH(gr11), SPECIAL(sp), SPECIAL(tp), SCRATCH(gr14), SCRATCH(gr15), SCRATCH(gr16), SCRATCH(gr17), SCRATCH(gr18), SCRATCH(gr19), SCRATCH(gr20), SCRATCH(gr21), SCRATCH(gr22), SCRATCH(gr23), SCRATCH(gr24), SCRATCH(gr25), SCRATCH(gr26), SCRATCH(gr27), SCRATCH(gr28), SCRATCH(gr29), SCRATCH(gr30), SCRATCH(gr31) }; static int kgdb_trgt_frame_ofs_fr[32] = { -1, /* fr0: constant 0.0 */ -1, /* fr1: constant 1.0 */ -1, -1, -1, -1, /* fr2-fr5 */ SCRATCH_FP(fr6), SCRATCH_FP(fr7), SCRATCH_FP(fr8), SCRATCH_FP(fr9), SCRATCH_FP(fr10), SCRATCH_FP(fr11), SCRATCH_FP(fr12), SCRATCH_FP(fr13), SCRATCH_FP(fr14), SCRATCH_FP(fr15) }; static int kgdb_trgt_frame_ofs_br[8] = { SPECIAL(rp), -1, -1, -1, -1, -1, /* br1-br5 */ SCRATCH(br6), SCRATCH(br7) }; static int kgdb_trgt_frame_ofs_ar[49] = { /* ar0-ar15 */ SPECIAL(rsc), -1, /* ar.bsp */ SPECIAL(bspstore), SPECIAL(rnat), -1, -1, -1, -1, -1, /* ar20-ar24 */ SCRATCH(csd), SCRATCH(ssd), -1, -1, -1, -1, -1, /* ar27-ar31 */ SCRATCH(ccv), -1, -1, -1, /* ar33-ar35 */ SPECIAL(unat), -1, -1, -1, /* ar37-ar39 */ SPECIAL(fpsr), -1, -1, -1, -1, -1, -1, -1, /* ar41-ar47 */ -1, -1, -1, -1, -1, -1, -1, -1, /* ar48-ar55 */ -1, -1, -1, -1, -1, -1, -1, -1, /* ar56-ar63 */ SPECIAL(pfs) }; static struct kgdb_frame_cache * kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); *this_cache = cache; frame_unwind_register(next_frame, IA64_BSP_REGNUM, buf); cache->bsp = extract_unsigned_integer(buf, register_size(current_gdbarch, IA64_BSP_REGNUM)); cache->ip = frame_func_unwind(next_frame); frame_unwind_register(next_frame, SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, SP_REGNUM)); } return (cache); } static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_frame_cache *cache; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *this_id = frame_id_build_special(cache->sp, cache->ip, cache->bsp); } static void kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { char buf[MAX_REGISTER_SIZE]; char dummy_valuep[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; CORE_ADDR bsp; int ofs, regsz; regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; cache = kgdb_trgt_frame_cache(next_frame, this_cache); if (regnum == IA64_BSP_REGNUM) { if (cache->saved_bsp == 0) { target_read_memory(cache->sp + 16 + SPECIAL(bspstore), buf, regsz); bsp = extract_unsigned_integer(buf, regsz); target_read_memory(cache->sp + 16 + SPECIAL(ndirty), buf, regsz); bsp += extract_unsigned_integer(buf, regsz); cache->saved_bsp = bsp; } store_unsigned_integer(valuep, regsz, cache->saved_bsp); return; } if (regnum == IA64_PR_REGNUM) ofs = SPECIAL(pr); else if (regnum == IA64_IP_REGNUM) ofs = SPECIAL(iip); else if (regnum == IA64_PSR_REGNUM) ofs = SPECIAL(psr); else if (regnum == IA64_CFM_REGNUM) ofs = SPECIAL(cfm); else if (regnum >= IA64_GR0_REGNUM && regnum <= IA64_GR31_REGNUM) ofs = kgdb_trgt_frame_ofs_gr[regnum - IA64_GR0_REGNUM]; else if (regnum >= IA64_FR0_REGNUM && regnum <= IA64_FR15_REGNUM) ofs = kgdb_trgt_frame_ofs_fr[regnum - IA64_FR0_REGNUM]; else if (regnum >= IA64_BR0_REGNUM && regnum <= IA64_BR7_REGNUM) ofs = kgdb_trgt_frame_ofs_br[regnum - IA64_BR0_REGNUM]; else if (regnum >= IA64_RSC_REGNUM && regnum <= IA64_PFS_REGNUM) ofs = kgdb_trgt_frame_ofs_ar[regnum - IA64_RSC_REGNUM]; else ofs = -1; if (ofs == -1) return; *addrp = cache->sp + 16 + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { UNKNOWN_FRAME, &kgdb_trgt_trapframe_this_id, &kgdb_trgt_trapframe_prev_register }; const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { char *pname; CORE_ADDR ip; ip = frame_func_unwind(next_frame); pname = NULL; find_pc_partial_function(ip, &pname, NULL, NULL); if (pname == NULL) return (NULL); if (strncmp(pname, "ivt_", 4) == 0) return (&kgdb_trgt_trapframe_unwind); /* printf("%s: %lx =%s\n", __func__, ip, pname); */ return (NULL); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt_mips.c b/gnu/usr.bin/gdb/kgdb/trgt_mips.c index 423cacd8a061..6ad2274681ef 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_mips.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_mips.c @@ -1,223 +1,229 @@ /* * Copyright (c) 2007 Juniper Networks, Inc. * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: src/gnu/usr.bin/gdb/kgdb/trgt_alpha.c,v 1.2.2.1 2005/09/15 05:32:10 marcel */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef CROSS_DEBUGGER #include #endif #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { #ifndef CROSS_DEBUGGER struct kthr *kt; struct pcb pcb; kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]); supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]); supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]); supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]); supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]); supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]); supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]); supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]); supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]); supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]); supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]); supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]); #endif } void kgdb_trgt_store_registers(int regno __unused) { fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__); } void kgdb_trgt_new_objfile(struct objfile *objfile) { } #ifndef CROSS_DEBUGGER struct kgdb_frame_cache { CORE_ADDR pc; CORE_ADDR sp; }; static int kgdb_trgt_frame_offset[] = { offsetof(struct trapframe, zero), offsetof(struct trapframe, ast), offsetof(struct trapframe, v0), offsetof(struct trapframe, v1), offsetof(struct trapframe, a0), offsetof(struct trapframe, a1), offsetof(struct trapframe, a2), offsetof(struct trapframe, a3), offsetof(struct trapframe, t0), offsetof(struct trapframe, t1), offsetof(struct trapframe, t2), offsetof(struct trapframe, t3), offsetof(struct trapframe, t4), offsetof(struct trapframe, t5), offsetof(struct trapframe, t6), offsetof(struct trapframe, t7), offsetof(struct trapframe, s0), offsetof(struct trapframe, s1), offsetof(struct trapframe, s2), offsetof(struct trapframe, s3), offsetof(struct trapframe, s4), offsetof(struct trapframe, s5), offsetof(struct trapframe, s6), offsetof(struct trapframe, s7), offsetof(struct trapframe, t8), offsetof(struct trapframe, t9), offsetof(struct trapframe, k0), offsetof(struct trapframe, k1), offsetof(struct trapframe, gp), offsetof(struct trapframe, sp), offsetof(struct trapframe, s8), offsetof(struct trapframe, ra), }; static struct kgdb_frame_cache * kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); *this_cache = cache; cache->pc = frame_func_unwind(next_frame); frame_unwind_register(next_frame, SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, SP_REGNUM)); } return (cache); } static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_frame_cache *cache; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *this_id = frame_id_build(cache->sp, cache->pc); } static void kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused, void **this_cache __unused, int regnum __unused, int *optimizedp __unused, enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused, int *realnump __unused, void *valuep __unused) { char dummy_valuep[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; int ofs, regsz; regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ? kgdb_trgt_frame_offset[regnum] : -1; if (ofs == -1) return; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *addrp = cache->sp + ofs * 8; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { UNKNOWN_FRAME, &kgdb_trgt_trapframe_this_id, &kgdb_trgt_trapframe_prev_register }; #endif const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { #ifndef CROSS_DEBUGGER char *pname; CORE_ADDR pc; pc = frame_pc_unwind(next_frame); pname = NULL; find_pc_partial_function(pc, &pname, NULL, NULL); if (pname == NULL) return (NULL); if ((strcmp(pname, "MipsKernIntr") == 0) || (strcmp(pname, "MipsKernGenException") == 0) || (strcmp(pname, "MipsUserIntr") == 0) || (strcmp(pname, "MipsUserGenException") == 0)) return (&kgdb_trgt_trapframe_unwind); #endif return (NULL); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c b/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c index a83c2d0a31ce..ef8d7f180112 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c @@ -1,195 +1,201 @@ /*- * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #ifdef CROSS_DEBUGGER #include #include #else #include #include #endif #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; struct gdbarch_tdep *tdep; int i; tdep = gdbarch_tdep (current_gdbarch); kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } /* * r14-r31 are saved in the pcb */ for (i = 14; i <= 31; i++) { supply_register(tdep->ppc_gp0_regnum + i, (char *)&pcb.pcb_context[i]); } /* r1 is saved in the sp field */ supply_register(tdep->ppc_gp0_regnum + 1, (char *)&pcb.pcb_sp); supply_register(tdep->ppc_lr_regnum, (char *)&pcb.pcb_lr); supply_register(tdep->ppc_cr_regnum, (char *)&pcb.pcb_cr); } void kgdb_trgt_store_registers(int regno __unused) { fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); } void kgdb_trgt_new_objfile(struct objfile *objfile) { } struct kgdb_frame_cache { CORE_ADDR pc; CORE_ADDR sp; }; static struct kgdb_frame_cache * kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); *this_cache = cache; cache->pc = frame_func_unwind(next_frame); frame_unwind_register(next_frame, SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, SP_REGNUM)); } return (cache); } static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_frame_cache *cache; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *this_id = frame_id_build(cache->sp, cache->pc); } static void kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { char dummy_valuep[MAX_REGISTER_SIZE]; struct gdbarch_tdep *tdep; struct kgdb_frame_cache *cache; int ofs, regsz; tdep = gdbarch_tdep(current_gdbarch); regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; if (regnum >= tdep->ppc_gp0_regnum && regnum <= tdep->ppc_gplast_regnum) ofs = offsetof(struct trapframe, fixreg[regnum - tdep->ppc_gp0_regnum]); else if (regnum == tdep->ppc_lr_regnum) ofs = offsetof(struct trapframe, lr); else if (regnum == tdep->ppc_cr_regnum) ofs = offsetof(struct trapframe, cr); else if (regnum == tdep->ppc_xer_regnum) ofs = offsetof(struct trapframe, xer); else if (regnum == tdep->ppc_ctr_regnum) ofs = offsetof(struct trapframe, ctr); else if (regnum == PC_REGNUM) ofs = offsetof(struct trapframe, srr0); else return; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *addrp = cache->sp + 8 + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { UNKNOWN_FRAME, &kgdb_trgt_trapframe_this_id, &kgdb_trgt_trapframe_prev_register }; const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { char *pname; CORE_ADDR pc; pc = frame_pc_unwind(next_frame); pname = NULL; find_pc_partial_function(pc, &pname, NULL, NULL); if (pname == NULL) return (NULL); if (strcmp(pname, "asttrapexit") == 0 || strcmp(pname, "trapexit") == 0) return (&kgdb_trgt_trapframe_unwind); /* printf("%s: %llx =%s\n", __func__, pc, pname); */ return (NULL); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c b/gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c index d20a4d6afc8d..65f7ab53810e 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c @@ -1,192 +1,198 @@ /*- * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; struct gdbarch_tdep *tdep; int i; tdep = gdbarch_tdep (current_gdbarch); kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } /* * r14-r31 are saved in the pcb */ for (i = 14; i <= 31; i++) { supply_register(tdep->ppc_gp0_regnum + i, (char *)&pcb.pcb_context[i]); } /* r1 is saved in the sp field */ supply_register(tdep->ppc_gp0_regnum + 1, (char *)&pcb.pcb_sp); /* r2 is saved in the toc field */ supply_register(tdep->ppc_gp0_regnum + 2, (char *)&pcb.pcb_toc); supply_register(tdep->ppc_lr_regnum, (char *)&pcb.pcb_lr); supply_register(tdep->ppc_cr_regnum, (char *)&pcb.pcb_cr); } void kgdb_trgt_store_registers(int regno __unused) { fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); } void kgdb_trgt_new_objfile(struct objfile *objfile) { } struct kgdb_frame_cache { CORE_ADDR pc; CORE_ADDR sp; }; static struct kgdb_frame_cache * kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); *this_cache = cache; cache->pc = frame_func_unwind(next_frame); frame_unwind_register(next_frame, SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, SP_REGNUM)); } return (cache); } static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_frame_cache *cache; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *this_id = frame_id_build(cache->sp, cache->pc); } static void kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { char dummy_valuep[MAX_REGISTER_SIZE]; struct gdbarch_tdep *tdep; struct kgdb_frame_cache *cache; int ofs, regsz; tdep = gdbarch_tdep(current_gdbarch); regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; if (regnum >= tdep->ppc_gp0_regnum && regnum <= tdep->ppc_gplast_regnum) ofs = offsetof(struct trapframe, fixreg[regnum - tdep->ppc_gp0_regnum]); else if (regnum == tdep->ppc_lr_regnum) ofs = offsetof(struct trapframe, lr); else if (regnum == tdep->ppc_cr_regnum) ofs = offsetof(struct trapframe, cr); else if (regnum == tdep->ppc_xer_regnum) ofs = offsetof(struct trapframe, xer); else if (regnum == tdep->ppc_ctr_regnum) ofs = offsetof(struct trapframe, ctr); else if (regnum == PC_REGNUM) ofs = offsetof(struct trapframe, srr0); else return; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *addrp = cache->sp + 48 + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { UNKNOWN_FRAME, &kgdb_trgt_trapframe_this_id, &kgdb_trgt_trapframe_prev_register }; const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { char *pname; CORE_ADDR pc; pc = frame_pc_unwind(next_frame); pname = NULL; find_pc_partial_function(pc, &pname, NULL, NULL); if (pname == NULL) return (NULL); if (strcmp(pname, "asttrapexit") == 0 || strcmp(pname, "trapexit") == 0) return (&kgdb_trgt_trapframe_unwind); /* printf("%s: %llx =%s\n", __func__, pc, pname); */ return (NULL); } diff --git a/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c b/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c index 8fece2419a92..070194a7500e 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c @@ -1,199 +1,205 @@ /* * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); if (kt == NULL) return; if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } supply_register(SPARC_SP_REGNUM, (char *)&pcb.pcb_sp); sparc_supply_rwindow(current_regcache, pcb.pcb_sp, -1); supply_register(SPARC64_PC_REGNUM, (char *)&pcb.pcb_pc); pcb.pcb_pc += 4; supply_register(SPARC64_NPC_REGNUM, (char *)&pcb.pcb_pc); } void kgdb_trgt_store_registers(int regno __unused) { fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); } void kgdb_trgt_new_objfile(struct objfile *objfile) { } struct kgdb_frame_cache { CORE_ADDR pc; CORE_ADDR sp; CORE_ADDR fp; }; static struct kgdb_frame_cache * kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) { char buf[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; cache = *this_cache; if (cache == NULL) { cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); *this_cache = cache; cache->pc = frame_func_unwind(next_frame); frame_unwind_register(next_frame, SPARC_SP_REGNUM, buf); cache->sp = extract_unsigned_integer(buf, register_size(current_gdbarch, SPARC_SP_REGNUM)); frame_unwind_register(next_frame, SPARC_FP_REGNUM, buf); cache->fp = extract_unsigned_integer(buf, register_size(current_gdbarch, SPARC_FP_REGNUM)); cache->fp += BIAS - sizeof(struct trapframe); } return (cache); } static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct kgdb_frame_cache *cache; cache = kgdb_trgt_frame_cache(next_frame, this_cache); *this_id = frame_id_build(cache->sp, cache->pc); } static void kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { char dummy_valuep[MAX_REGISTER_SIZE]; struct kgdb_frame_cache *cache; int ofs, regsz; regsz = register_size(current_gdbarch, regnum); if (valuep == NULL) valuep = dummy_valuep; memset(valuep, 0, regsz); *optimizedp = 0; *addrp = 0; *lvalp = not_lval; *realnump = -1; cache = kgdb_trgt_frame_cache(next_frame, this_cache); switch (regnum) { case SPARC_SP_REGNUM: ofs = offsetof(struct trapframe, tf_sp); break; case SPARC64_PC_REGNUM: ofs = offsetof(struct trapframe, tf_tpc); break; case SPARC64_NPC_REGNUM: ofs = offsetof(struct trapframe, tf_tnpc); break; case SPARC_O0_REGNUM: case SPARC_O1_REGNUM: case SPARC_O2_REGNUM: case SPARC_O3_REGNUM: case SPARC_O4_REGNUM: case SPARC_O5_REGNUM: case SPARC_O7_REGNUM: ofs = offsetof(struct trapframe, tf_out) + (regnum - SPARC_O0_REGNUM) * 8; break; default: if (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) { ofs = (regnum - SPARC_L0_REGNUM) * 8; *addrp = cache->sp + BIAS + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } return; } *addrp = cache->fp + ofs; *lvalp = lval_memory; target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { UNKNOWN_FRAME, &kgdb_trgt_trapframe_this_id, &kgdb_trgt_trapframe_prev_register }; const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { char *pname; CORE_ADDR pc; pc = frame_func_unwind(next_frame); pname = NULL; find_pc_partial_function(pc, &pname, NULL, NULL); if (pname == NULL) return (NULL); if (strcmp(pname, "tl0_intr") == 0 || strcmp(pname, "tl0_trap") == 0 || strcmp(pname, "tl1_intr") == 0 || strcmp(pname, "tl1_trap") == 0) return (&kgdb_trgt_trapframe_unwind); /* printf("%s: %lx =%s\n", __func__, pc, pname); */ return (NULL); }