Index: stable/7/gnu/usr.bin/gdb/kgdb/kgdb.h =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/kgdb.h (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/kgdb.h (revision 178877) @@ -1,72 +1,76 @@ /* * 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; -extern char *kernel; -extern bfd *kern_bfd; 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 kgdb_add_kld_cmd(char *, int); -void kgdb_kld_init(void); -void kgdb_target(void); +void initialize_kld_target(void); +void initialize_kgdb_target(void); +void kgdb_dmesg(void); +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); uintptr_t kgdb_lookup(const char *sym); -CORE_ADDR kgdb_parse(const char *exp); +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_ */ Index: stable/7/gnu/usr.bin/gdb/kgdb/kld.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/kld.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/kld.c (revision 178877) @@ -1,473 +1,502 @@ /* * 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 "kgdb.h" struct lm_info { CORE_ADDR base_address; }; /* Offsets of fields in linker_file structure. */ static CORE_ADDR off_address, off_filename, off_pathname, off_next; /* KVA of 'linker_path' which corresponds to the kern.module_path sysctl .*/ static CORE_ADDR module_path_addr; +static CORE_ADDR linker_files_addr; +static CORE_ADDR kernel_file_addr; static struct target_so_ops kld_so_ops; static int kld_ok (char *path) { struct stat sb; if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode)) return (1); return (0); } /* * Look for a matching file checking for debug suffixes before the raw file: - * - filename + ".symbols" (e.g. foo.ko.symbols) * - filename + ".debug" (e.g. foo.ko.debug) * - filename (e.g. foo.ko) */ static const char *kld_suffixes[] = { ".debug", "", NULL }; static int check_kld_path (char *path, size_t path_size) { const char **suffix; char *ep; ep = path + strlen(path); suffix = kld_suffixes; while (*suffix != NULL) { if (strlcat(path, *suffix, path_size) < path_size) { if (kld_ok(path)) return (1); } /* Restore original path to remove suffix. */ *ep = '\0'; suffix++; } return (0); } /* * Try to find the path for a kld by looking in the kernel's directory and * in the various paths in the module path. */ static int find_kld_path (char *filename, char *path, size_t path_size) { char *module_path; char *kernel_dir, *module_dir, *cp; int error; - kernel_dir = dirname(kernel); - if (kernel_dir != NULL) { - snprintf(path, path_size, "%s/%s", kernel_dir, filename); - if (check_kld_path(path, path_size)) - return (1); + if (exec_bfd) { + kernel_dir = dirname(bfd_get_filename(exec_bfd)); + if (kernel_dir != NULL) { + snprintf(path, path_size, "%s/%s", kernel_dir, + filename); + if (check_kld_path(path, path_size)) + return (1); + } } if (module_path_addr != 0) { target_read_string(module_path_addr, &module_path, PATH_MAX, &error); if (error == 0) { make_cleanup(xfree, module_path); cp = module_path; while ((module_dir = strsep(&cp, ";")) != NULL) { snprintf(path, path_size, "%s/%s", module_dir, filename); if (check_kld_path(path, path_size)) return (1); } } } return (0); } /* * Read a kernel pointer given a KVA in 'address'. */ static CORE_ADDR read_pointer (CORE_ADDR address) { CORE_ADDR value; if (target_read_memory(address, (char *)&value, TARGET_PTR_BIT / 8) != 0) return (0); return (extract_unsigned_integer(&value, TARGET_PTR_BIT / 8)); } /* * Try to find this kld in the kernel linker's list of linker files. */ static int find_kld_address (char *arg, CORE_ADDR *address) { CORE_ADDR kld; char *kld_filename; char *filename; int error; - if (off_address == 0 || off_filename == 0 || off_next == 0) + if (linker_files_addr == 0 || off_address == 0 || off_filename == 0 || + off_next == 0) return (0); filename = basename(arg); - for (kld = kgdb_parse("linker_files.tqh_first"); kld != 0; + for (kld = read_pointer(linker_files_addr); kld != 0; kld = read_pointer(kld + off_next)) { /* Try to read this linker file's filename. */ target_read_string(read_pointer(kld + off_filename), &kld_filename, PATH_MAX, &error); if (error) continue; /* Compare this kld's filename against our passed in name. */ if (strcmp(kld_filename, filename) != 0) { xfree(kld_filename); continue; } xfree(kld_filename); /* * We found a match, use its address as the base * address if we can read it. */ *address = read_pointer(kld + off_address); if (*address == 0) return (0); return (1); } return (0); } struct add_section_info { struct section_addr_info *section_addrs; int sect_index; CORE_ADDR base_addr; }; static void add_section (bfd *bfd, asection *sect, void *arg) { struct add_section_info *asi = arg; CORE_ADDR address; char *name; /* Ignore non-resident sections. */ if ((bfd_get_section_flags(bfd, sect) & (SEC_ALLOC | SEC_LOAD)) == 0) return; name = xstrdup(bfd_get_section_name(bfd, sect)); make_cleanup(xfree, name); address = asi->base_addr + bfd_get_section_vma(bfd, sect); asi->section_addrs->other[asi->sect_index].name = name; asi->section_addrs->other[asi->sect_index].addr = address; asi->section_addrs->other[asi->sect_index].sectindex = sect->index; printf_unfiltered("\t%s_addr = %s\n", name, local_hex_string(address)); asi->sect_index++; } static void load_kld (char *path, CORE_ADDR base_addr, int from_tty) { struct add_section_info asi; struct cleanup *cleanup; bfd *bfd; /* Open the kld. */ bfd = bfd_openr(path, gnutarget); if (bfd == NULL) error("\"%s\": can't open: %s", path, bfd_errmsg(bfd_get_error())); cleanup = make_cleanup_bfd_close(bfd); if (!bfd_check_format(bfd, bfd_object)) error("\%s\": not an object file", path); /* Make sure we have a .text section. */ if (bfd_get_section_by_name (bfd, ".text") == NULL) error("\"%s\": can't find text section", path); printf_unfiltered("add symbol table from file \"%s\" at\n", path); /* Build a section table for symbol_file_add() from the bfd sections. */ asi.section_addrs = alloc_section_addr_info(bfd_count_sections(bfd)); cleanup = make_cleanup(xfree, asi.section_addrs); asi.sect_index = 0; asi.base_addr = base_addr; bfd_map_over_sections(bfd, add_section, &asi); if (from_tty && (!query("%s", ""))) error("Not confirmed."); symbol_file_add(path, from_tty, asi.section_addrs, 0, OBJF_USERLOADED); do_cleanups(cleanup); } -void +static void kgdb_add_kld_cmd (char *arg, int from_tty) { char path[PATH_MAX]; CORE_ADDR base_addr; + if (!exec_bfd) + error("No kernel symbol file"); + /* Try to open the raw path to handle absolute paths first. */ snprintf(path, sizeof(path), "%s", arg); if (!check_kld_path(path, sizeof(path))) { /* * If that didn't work, look in the various possible * paths for the module. */ if (!find_kld_path(arg, path, sizeof(path))) { error("Unable to locate kld"); return; } } if (!find_kld_address(arg, &base_addr)) { error("Unable to find kld in kernel"); return; } load_kld(path, base_addr, from_tty); reinit_frame_cache(); } static void kld_relocate_section_addresses (struct so_list *so, struct section_table *sec) { sec->addr += so->lm_info->base_address; sec->endaddr += so->lm_info->base_address; } static void kld_free_so (struct so_list *so) { xfree(so->lm_info); } static void kld_clear_solib (void) { } static void kld_solib_create_inferior_hook (void) { } static void kld_special_symbol_handling (void) { } static struct so_list * kld_current_sos (void) { struct so_list *head, **prev, *new; CORE_ADDR kld, kernel; char *path; int error; + if (linker_files_addr == 0 || kernel_file_addr == 0 || + off_address == 0 || off_filename == 0 || off_next == 0) + return (NULL); + head = NULL; prev = &head; /* * Walk the list of linker files creating so_list entries for * each non-kernel file. */ - kernel = kgdb_parse("linker_kernel_file"); - for (kld = kgdb_parse("linker_files.tqh_first"); kld != 0; + kernel = read_pointer(kernel_file_addr); + for (kld = read_pointer(linker_files_addr); kld != 0; kld = read_pointer(kld + off_next)) { /* Skip the main kernel file. */ if (kld == kernel) continue; new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->lm_info = xmalloc(sizeof(*new->lm_info)); new->lm_info->base_address = 0; /* Read the base filename and store it in so_original_name. */ target_read_string(read_pointer(kld + off_filename), &path, sizeof(new->so_original_name), &error); if (error != 0) { warning("kld_current_sos: Can't read filename: %s\n", safe_strerror(error)); free_so(new); continue; } strlcpy(new->so_original_name, path, sizeof(new->so_original_name)); xfree(path); /* * Try to read the pathname (if it exists) and store * it in so_name. */ if (off_pathname != 0) { target_read_string(read_pointer(kld + off_pathname), &path, sizeof(new->so_name), &error); if (error != 0) { warning( "kld_current_sos: Can't read pathname for \"%s\": %s\n", new->so_original_name, safe_strerror(error)); strlcpy(new->so_name, new->so_original_name, sizeof(new->so_name)); } else { strlcpy(new->so_name, path, sizeof(new->so_name)); xfree(path); } } else strlcpy(new->so_name, new->so_original_name, sizeof(new->so_name)); /* Read this kld's base address. */ new->lm_info->base_address = read_pointer(kld + off_address); if (new->lm_info->base_address == 0) { warning( "kld_current_sos: Invalid address for kld \"%s\"", new->so_original_name); free_so(new); continue; } /* Append to the list. */ *prev = new; prev = &new->next; } return (head); } static int kld_open_symbol_file_object (void *from_ttyp) { return (0); } static int kld_in_dynsym_resolve_code (CORE_ADDR pc) { return (0); } static int kld_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname) { char path[PATH_MAX]; int fd; *temp_pathname = NULL; if (!find_kld_path(solib, path, sizeof(path))) { errno = ENOENT; return (-1); } fd = open(path, o_flags, 0); if (fd >= 0) *temp_pathname = xstrdup(path); return (fd); } +void +kld_new_objfile (struct objfile *objfile) +{ + + if (!have_partial_symbols()) + return; + + /* + * Compute offsets of relevant members in struct linker_file + * and the addresses of global variables. Don't warn about + * kernels that don't have 'pathname' in the linker_file + * struct since 6.x kernels don't have it. + */ + off_address = kgdb_parse("&((struct linker_file *)0)->address"); + off_filename = kgdb_parse("&((struct linker_file *)0)->filename"); + off_pathname = kgdb_parse_quiet("&((struct linker_file *)0)->pathname"); + off_next = kgdb_parse("&((struct linker_file *)0)->link.tqe_next"); + module_path_addr = kgdb_parse("linker_path"); + linker_files_addr = kgdb_parse("&linker_files.tqh_first"); + kernel_file_addr = kgdb_parse("&linker_kernel_file"); +} + static int load_klds_stub (void *arg) { SOLIB_ADD(NULL, 1, ¤t_target, auto_solib_add); return (0); } void -kgdb_kld_init (void) +kld_init (void) { - struct cmd_list_element *c; - /* Compute offsets of relevant members in struct linker_file. */ - off_address = kgdb_parse("&((struct linker_file *)0)->address"); - off_filename = kgdb_parse("&((struct linker_file *)0)->filename"); - off_pathname = kgdb_parse("&((struct linker_file *)0)->pathname"); - off_next = kgdb_parse("&((struct linker_file *)0)->link.tqe_next"); - if (off_address == 0 || off_filename == 0 || off_next == 0) - return; + catch_errors(load_klds_stub, NULL, NULL, RETURN_MASK_ALL); +} - module_path_addr = kgdb_parse("linker_path"); +void +initialize_kld_target(void) +{ + struct cmd_list_element *c; kld_so_ops.relocate_section_addresses = kld_relocate_section_addresses; kld_so_ops.free_so = kld_free_so; kld_so_ops.clear_solib = kld_clear_solib; kld_so_ops.solib_create_inferior_hook = kld_solib_create_inferior_hook; kld_so_ops.special_symbol_handling = kld_special_symbol_handling; kld_so_ops.current_sos = kld_current_sos; kld_so_ops.open_symbol_file_object = kld_open_symbol_file_object; kld_so_ops.in_dynsym_resolve_code = kld_in_dynsym_resolve_code; kld_so_ops.find_and_open_solib = kld_find_and_open_solib; current_target_so_ops = &kld_so_ops; - - catch_errors(load_klds_stub, NULL, NULL, RETURN_MASK_ALL); c = add_com("add-kld", class_files, kgdb_add_kld_cmd, "Usage: add-kld FILE\n\ Load the symbols from the kernel loadable module FILE."); set_cmd_completer(c, filename_completer); } Index: stable/7/gnu/usr.bin/gdb/kgdb/kthr.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/kthr.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/kthr.c (revision 178877) @@ -1,222 +1,228 @@ /* * 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 "kgdb.h" #include static uintptr_t dumppcb; static int dumptid; static uintptr_t stoppcbs; static __cpumask_t stopped_cpus; static struct kthr *first; struct kthr *curkthr; uintptr_t kgdb_lookup(const char *sym) { struct nlist nl[2]; nl[0].n_name = (char *)(uintptr_t)sym; nl[1].n_name = NULL; if (kvm_nlist(kvm, nl) != 0) return (0); return (nl[0].n_value); } struct kthr * kgdb_thr_first(void) { return (first); } struct kthr * kgdb_thr_init(void) { struct proc p; struct thread td; struct kthr *kt; uintptr_t addr, paddr; + + while (first != NULL) { + kt = first; + first = kt->next; + free(kt); + } addr = kgdb_lookup("_allproc"); if (addr == 0) { warnx("kvm_nlist(_allproc): %s", kvm_geterr(kvm)); return (NULL); } kvm_read(kvm, addr, &paddr, sizeof(paddr)); dumppcb = kgdb_lookup("_dumppcb"); if (dumppcb == 0) { warnx("kvm_nlist(_dumppcb): %s", kvm_geterr(kvm)); return (NULL); } addr = kgdb_lookup("_dumptid"); if (addr != 0) kvm_read(kvm, addr, &dumptid, sizeof(dumptid)); else dumptid = -1; addr = kgdb_lookup("_stopped_cpus"); if (addr != 0) kvm_read(kvm, addr, &stopped_cpus, sizeof(stopped_cpus)); else stopped_cpus = 0; stoppcbs = kgdb_lookup("_stoppcbs"); 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 && ((1 << td.td_oncpu) & stopped_cpus) && stoppcbs != 0) kt->pcb = (uintptr_t) stoppcbs + sizeof(struct 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); } 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) { 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); } Index: stable/7/gnu/usr.bin/gdb/kgdb/main.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/main.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/main.c (revision 178877) @@ -1,500 +1,467 @@ /* * 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 /* libgdb stuff. */ #include #include #include #include #include #include #include +#include #include #include +#include #include #include #include -extern void (*init_ui_hook)(char *); - extern frame_unwind_sniffer_ftype *kgdb_sniffer_kluge; -extern void symbol_file_add_main (char *args, int from_tty); - #include "kgdb.h" -kvm_t *kvm; -static char kvm_err[_POSIX2_LINE_MAX]; - static int dumpnr; static int quiet; static int verbose; static char crashdir[PATH_MAX]; -char *kernel; +static char *kernel; static char *remote; static char *vmcore; +static struct ui_file *parse_gdberr; static void (*kgdb_new_objfile_chain)(struct objfile * objfile); static void -kgdb_atexit(void) -{ - if (kvm != NULL) - kvm_close(kvm); -} - -static void usage(void) { fprintf(stderr, "usage: %s [-afqv] [-d crashdir] [-c core | -n dumpnr | -r device]\n" "\t[kernel [core]]\n", getprogname()); exit(1); } static void kernel_from_dumpnr(int nr) { char path[PATH_MAX]; FILE *info; char *s; struct stat st; int l; /* * If there's a kernel image right here in the crash directory, then * use it. The kernel image is either called kernel. or is in a * subdirectory kernel. and called kernel. The latter allows us * to collect the modules in the same place. */ snprintf(path, sizeof(path), "%s/kernel.%d", crashdir, nr); if (stat(path, &st) == 0) { if (S_ISREG(st.st_mode)) { kernel = strdup(path); return; } if (S_ISDIR(st.st_mode)) { snprintf(path, sizeof(path), "%s/kernel.%d/kernel", crashdir, nr); if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { kernel = strdup(path); return; } } } /* * No kernel image here. Parse the dump header. The kernel object * directory can be found there and we probably have the kernel * image still in it. The object directory may also have a kernel * with debugging info (called kernel.debug). If we have a debug * kernel, use it. */ snprintf(path, sizeof(path), "%s/info.%d", crashdir, nr); info = fopen(path, "r"); if (info == NULL) { warn(path); return; } while (fgets(path, sizeof(path), info) != NULL) { l = strlen(path); if (l > 0 && path[l - 1] == '\n') path[--l] = '\0'; if (strncmp(path, " ", 4) == 0) { s = strchr(path, ':'); s = (s == NULL) ? path + 4 : s + 1; l = snprintf(path, sizeof(path), "%s/kernel.debug", s); if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) { path[l - 6] = '\0'; if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) break; } kernel = strdup(path); break; } } fclose(info); } static void kgdb_new_objfile(struct objfile *objfile) { -#if 0 - printf("XXX: %s(%p)\n", __func__, objfile); - if (objfile != NULL) { - goto out; - } + static int once = 1; -out: -#endif + kld_new_objfile(objfile); + kgdb_trgt_new_objfile(objfile); + if (kgdb_new_objfile_chain != NULL) kgdb_new_objfile_chain(objfile); + + if (once && objfile != NULL && objfile == symfile_objfile) { + /* + * The initial kernel has just been loaded. Start the + * remote target if we have one. + */ + once = 0; + if (remote != NULL) + push_remote_target (remote, 0); + } } +/* + * Parse an expression and return its value. If 'quiet' is true, then + * any error messages from the parser are masked. + */ CORE_ADDR -kgdb_parse(const char *exp) +kgdb_parse_1(const char *exp, int quiet) { + struct ui_file *old_stderr; struct cleanup *old_chain; struct expression *expr; struct value *val; char *s; CORE_ADDR n; + old_stderr = gdb_stderr; + if (quiet) + gdb_stderr = parse_gdberr; n = 0; s = xstrdup(exp); old_chain = make_cleanup(xfree, s); if (gdb_parse_exp_1(&s, NULL, 0, &expr) && *s == '\0') { make_cleanup(free_current_contents, &expr); if (gdb_evaluate_expression(expr, &val)) n = value_as_address(val); } do_cleanups(old_chain); + gdb_stderr = old_stderr; return (n); } #define MSGBUF_SEQ_TO_POS(size, seq) ((seq) % (size)) -static void -kgdb_init_target(void) +void +kgdb_dmesg(void) { CORE_ADDR bufp; int size, rseq, wseq; - int kern_desc; char c; - 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); - - symbol_file_add_main (kernel, 0); - if (remote) - push_remote_target (remote, 0); - else - kgdb_target(); - /* * Display the unread portion of the message buffer. This gives the * user a some initial data to work from. */ if (quiet) return; bufp = kgdb_parse("msgbufp->msg_ptr"); size = (int)kgdb_parse("msgbufp->msg_size"); rseq = (int)kgdb_parse("msgbufp->msg_rseq"); wseq = (int)kgdb_parse("msgbufp->msg_wseq"); rseq = MSGBUF_SEQ_TO_POS(size, rseq); wseq = MSGBUF_SEQ_TO_POS(size, wseq); if (bufp == 0 || size == 0 || rseq == wseq) return; printf("\nUnread portion of the kernel message buffer:\n"); while (rseq < wseq) { read_memory(bufp + rseq, &c, 1); putchar(c); rseq++; if (rseq == size) rseq = 0; } if (c != '\n') putchar('\n'); putchar('\n'); } static void -kgdb_interp_command_loop(void *data) +kgdb_init(char *argv0 __unused) { - static int once = 0; - if (!once) { - once = 1; - kgdb_init_target(); - print_stack_frame(get_selected_frame(), - frame_relative_level(get_selected_frame()), 1); + parse_gdberr = mem_fileopen(); + set_prompt("(kgdb) "); + initialize_kgdb_target(); + initialize_kld_target(); + kgdb_new_objfile_chain = target_new_objfile_hook; + target_new_objfile_hook = kgdb_new_objfile; +} + +/* + * Remote targets can support any number of syntaxes and we want to + * support them all with one addition: we support specifying a device + * node for a serial device without the "/dev/" prefix. + * + * What we do is to stat(2) the existing remote target first. If that + * fails, we try it with "/dev/" prepended. If that succeeds we use + * the resulting path, otherwise we use the original target. If + * either stat(2) succeeds make sure the file is either a character + * device or a FIFO. + */ +static void +verify_remote(void) +{ + char path[PATH_MAX]; + struct stat st; + + if (stat(remote, &st) != 0) { + snprintf(path, sizeof(path), "/dev/%s", remote); + if (stat(path, &st) != 0) + return; + free(remote); + remote = strdup(path); } - command_loop(); + if (!S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) + errx(1, "%s: not a special file, FIFO or socket", remote); } static void -kgdb_init(char *argv0 __unused) +add_arg(struct captured_main_args *args, char *arg) { - static struct interp_procs procs = { - NULL, - NULL, - NULL, - NULL, - NULL, - kgdb_interp_command_loop - }; - struct interp *kgdb; - kgdb = interp_new("kgdb", NULL, cli_out_new(gdb_stdout), &procs); - interp_add(kgdb); - set_prompt("(kgdb) "); - kgdb_new_objfile_chain = target_new_objfile_hook; - target_new_objfile_hook = kgdb_new_objfile; + args->argc++; + args->argv = reallocf(args->argv, (args->argc + 1) * sizeof(char *)); + if (args->argv == NULL) + err(1, "Out of memory building argument list"); + args->argv[args->argc] = arg; } int main(int argc, char *argv[]) { char path[PATH_MAX]; struct stat st; struct captured_main_args args; char *s; - int a, ch, writecore; + int a, ch; dumpnr = -1; strlcpy(crashdir, "/var/crash", sizeof(crashdir)); s = getenv("KGDB_CRASH_DIR"); if (s != NULL) strlcpy(crashdir, s, sizeof(crashdir)); /* Convert long options into short options. */ for (a = 1; a < argc; a++) { s = argv[a]; if (s[0] == '-') { s++; /* Long options take either 1 or 2 dashes. */ if (s[0] == '-') s++; if (strcmp(s, "quiet") == 0) argv[a] = "-q"; else if (strcmp(s, "fullname") == 0) argv[a] = "-f"; } } quiet = 0; - writecore = 0; + memset (&args, 0, sizeof args); + args.use_windows = 0; + args.interpreter_p = INTERP_CONSOLE; + args.argv = malloc(sizeof(char *)); + args.argv[0] = argv[0]; while ((ch = getopt(argc, argv, "ac:d:fn:qr:vw")) != -1) { switch (ch) { case 'a': annotation_level++; break; case 'c': /* use given core file. */ if (vmcore != NULL) { warnx("option %c: can only be specified once", optopt); usage(); /* NOTREACHED */ } vmcore = strdup(optarg); break; case 'd': /* lookup dumps in given directory. */ strlcpy(crashdir, optarg, sizeof(crashdir)); break; case 'f': annotation_level = 1; break; case 'n': /* use dump with given number. */ dumpnr = strtol(optarg, &s, 0); if (dumpnr < 0 || *s != '\0') { warnx("option %c: invalid kernel dump number", optopt); usage(); /* NOTREACHED */ } break; case 'q': quiet = 1; + add_arg(&args, "-q"); break; case 'r': /* use given device for remote session. */ if (remote != NULL) { warnx("option %c: can only be specified once", optopt); usage(); /* NOTREACHED */ } remote = strdup(optarg); break; case 'v': /* increase verbosity. */ verbose++; break; case 'w': /* core file is writeable. */ - writecore = 1; + add_arg(&args, "--write"); break; case '?': default: usage(); } } if (((vmcore != NULL) ? 1 : 0) + ((dumpnr >= 0) ? 1 : 0) + ((remote != NULL) ? 1 : 0) > 1) { warnx("options -c, -n and -r are mutually exclusive"); usage(); /* NOTREACHED */ } if (verbose > 1) warnx("using %s as the crash directory", crashdir); if (argc > optind) kernel = strdup(argv[optind++]); if (argc > optind && (dumpnr >= 0 || remote != NULL)) { warnx("options -n and -r do not take a core file. Ignored"); optind = argc; } if (dumpnr >= 0) { snprintf(path, sizeof(path), "%s/vmcore.%d", crashdir, dumpnr); if (stat(path, &st) == -1) err(1, path); if (!S_ISREG(st.st_mode)) errx(1, "%s: not a regular file", path); vmcore = strdup(path); - } else if (remote != NULL && remote[0] != ':' && remote[0] != '|') { - if (stat(remote, &st) != 0) { - snprintf(path, sizeof(path), "/dev/%s", remote); - if (stat(path, &st) != 0) { - err(1, "%s", remote); - /* NOTREACHED */ - } - free(remote); - remote = strdup(path); - } - if (!S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) { - errx(1, "%s: not a special file, FIFO or socket", - remote); - /* NOTREACHED */ - } + } else if (remote != NULL) { + verify_remote(); } else if (argc > optind) { if (vmcore == NULL) vmcore = strdup(argv[optind++]); if (argc > optind) warnx("multiple core files specified. Ignored"); } else if (vmcore == NULL && kernel == NULL) { vmcore = strdup(_PATH_MEM); kernel = strdup(getbootfile()); } if (verbose) { if (vmcore != NULL) warnx("core file: %s", vmcore); if (remote != NULL) warnx("device file: %s", remote); if (kernel != NULL) warnx("kernel image: %s", kernel); } - /* - * At this point we must either have a core file or have a kernel - * with a remote target. - */ + /* A remote target requires an explicit kernel argument. */ if (remote != NULL && kernel == NULL) { warnx("remote debugging requires a kernel"); usage(); /* NOTREACHED */ } - if (vmcore == NULL && remote == NULL) { - warnx("need a core file or a device for remote debugging"); - usage(); - /* NOTREACHED */ - } /* If we don't have a kernel image yet, try to find one. */ if (kernel == NULL) { if (dumpnr >= 0) kernel_from_dumpnr(dumpnr); if (kernel == NULL) errx(1, "couldn't find a suitable kernel image"); if (verbose) warnx("kernel image: %s", kernel); } + add_arg(&args, kernel); - if (remote == NULL) { - kvm = kvm_openfiles(kernel, vmcore, NULL, - writecore ? O_RDWR : O_RDONLY, kvm_err); - if (kvm == NULL) - errx(1, kvm_err); - atexit(kgdb_atexit); - kgdb_thr_init(); - } + if (vmcore != NULL) + add_arg(&args, vmcore); /* The libgdb code uses optind too. Reset it... */ optind = 0; - memset (&args, 0, sizeof args); - args.argv = argv; - args.argc = 1 + quiet; - if (quiet) - argv[1] = "-q"; - argv[args.argc] = NULL; - args.use_windows = 0; - args.interpreter_p = "kgdb"; + /* Terminate argv list. */ + add_arg(&args, NULL); init_ui_hook = kgdb_init; kgdb_sniffer_kluge = kgdb_trgt_trapframe_sniffer; return (gdb_main(&args)); } Index: stable/7/gnu/usr.bin/gdb/kgdb/trgt.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/trgt.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/trgt.c (revision 178877) @@ -1,247 +1,364 @@ /* * 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 "kgdb.h" +static void kgdb_core_cleanup(void *); + +static char *vmcore; static struct target_ops kgdb_trgt_ops; -bfd *kern_bfd; +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(ptid_build(kt->pid, 0, kt->tid)); + kt = kgdb_thr_next(kt); + } + if (curkthr != 0) + inferior_ptid = ptid_build(curkthr->pid, 0, 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) { static char buf[64]; char *p, *s; p = buf + snprintf(buf, sizeof(buf), "PID=%d", ptid_get_pid(ti->ptid)); s = kgdb_thr_extra_thread_info(ptid_get_tid(ti->ptid)); if (s != NULL) snprintf(p, sizeof(buf) - (p - buf), ": %s", s); return (buf); } static void kgdb_trgt_files_info(struct target_ops *target) { - print_section_info(target, kern_bfd); + 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 %ld", ptid_get_tid(ptid)); return (buf); } static int kgdb_trgt_thread_alive(ptid_t ptid) { return (kgdb_thr_lookup_tid(ptid_get_tid(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(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); } +int fbsdcoreops_suppress_target = 1; + void -kgdb_target(void) +initialize_kgdb_target(void) { - struct kthr *kt; - struct thread_info *ti; kgdb_trgt_ops.to_magic = OPS_MAGIC; kgdb_trgt_ops.to_shortname = "kernel"; - kgdb_trgt_ops.to_longname = "kernel core files"; - kgdb_trgt_ops.to_doc = "Kernel core files."; - kgdb_trgt_ops.to_stratum = thread_stratum; + 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; - if (build_section_table(kern_bfd, &kgdb_trgt_ops.to_sections, - &kgdb_trgt_ops.to_sections_end) != 0) - errx(1, "\"%s\": can't find the file sections: %s", - kernel, bfd_errmsg(bfd_get_error())); - add_target(&kgdb_trgt_ops); - push_target(&kgdb_trgt_ops); - kt = kgdb_thr_first(); - while (kt != NULL) { - ti = add_thread(ptid_build(kt->pid, 0, kt->tid)); - kt = kgdb_thr_next(kt); - } - if (curkthr != 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 thread context"); - kgdb_kld_init(); } Index: stable/7/gnu/usr.bin/gdb/kgdb/trgt_amd64.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/trgt_amd64.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/trgt_amd64.c (revision 178877) @@ -1,186 +1,191 @@ /* * 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" void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; 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)) { 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); } 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); } Index: stable/7/gnu/usr.bin/gdb/kgdb/trgt_arm.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/trgt_arm.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/trgt_arm.c (revision 178877) @@ -1,232 +1,237 @@ /* * 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" 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_tid(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); } Index: stable/7/gnu/usr.bin/gdb/kgdb/trgt_i386.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/trgt_i386.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/trgt_i386.c (revision 178877) @@ -1,348 +1,354 @@ /* * 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 #include "kgdb.h" +static int ofs_fix; + void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; 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)) { 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_tid(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) { warnx("kvm_nlist(_cpu0prvpage): %s", kvm_geterr(kvm)); 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 intrframe; CORE_ADDR pc; CORE_ADDR sp; }; 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); cache->intrframe = (pname[0] == 'X') ? 1 : 0; 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; - static int ofs_fix = 0; - static int ofs_fixed = 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; - if (!ofs_fixed) { - /* - * 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; - ofs_fixed = 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); *addrp = cache->sp + ofs + (cache->intrframe ? 4 : 0); *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); } Index: stable/7/gnu/usr.bin/gdb/kgdb/trgt_ia64.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/trgt_ia64.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/trgt_ia64.c (revision 178877) @@ -1,314 +1,319 @@ /* * 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" void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; uint64_t r; 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)) { 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); } Index: stable/7/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c (revision 178877) @@ -1,185 +1,190 @@ /*- * 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" 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_tid(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); } Index: stable/7/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c =================================================================== --- stable/7/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c (revision 178876) +++ stable/7/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c (revision 178877) @@ -1,194 +1,199 @@ /* * 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" void kgdb_trgt_fetch_registers(int regno __unused) { struct kthr *kt; struct pcb pcb; 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)) { 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); }