summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/binutils/gdb/Makefile2
-rw-r--r--gnu/usr.bin/binutils/gdb/fbsd-kgdb.h1
-rw-r--r--gnu/usr.bin/binutils/gdb/kvm-fbsd.c31
-rw-r--r--gnu/usr.bin/binutils/gdb/solib-fbsd-kld.c298
4 files changed, 330 insertions, 2 deletions
diff --git a/gnu/usr.bin/binutils/gdb/Makefile b/gnu/usr.bin/binutils/gdb/Makefile
index aebd002..f30885a 100644
--- a/gnu/usr.bin/binutils/gdb/Makefile
+++ b/gnu/usr.bin/binutils/gdb/Makefile
@@ -39,7 +39,7 @@ XSRCS= annotate.c arch-utils.c ax-general.c ax-gdb.c bcache.c \
scm-exp.c scm-lang.c scm-valprint.c \
coffread.c dbxread.c dwarfread.c dwarf2read.c elfread.c \
solib.c solib-svr4.c solib-legacy.c
-XSRCS+= freebsd-uthread.c kvm-fbsd.c
+XSRCS+= freebsd-uthread.c kvm-fbsd.c solib-fbsd-kld.c
SRCS= init.c ${XSRCS} nm.h tm.h xm.h gdbversion.c xregex.h
.if exists(${.CURDIR}/Makefile.${TARGET_ARCH})
diff --git a/gnu/usr.bin/binutils/gdb/fbsd-kgdb.h b/gnu/usr.bin/binutils/gdb/fbsd-kgdb.h
index e5dbf5f..e774436 100644
--- a/gnu/usr.bin/binutils/gdb/fbsd-kgdb.h
+++ b/gnu/usr.bin/binutils/gdb/fbsd-kgdb.h
@@ -7,6 +7,7 @@
extern int kernel_debugging;
extern int kernel_writablecore;
+extern struct target_so_ops kgdb_so_ops;
#define ADDITIONAL_OPTIONS \
{"kernel", no_argument, &kernel_debugging, 1}, \
diff --git a/gnu/usr.bin/binutils/gdb/kvm-fbsd.c b/gnu/usr.bin/binutils/gdb/kvm-fbsd.c
index 23dbeaf..a9d85e8 100644
--- a/gnu/usr.bin/binutils/gdb/kvm-fbsd.c
+++ b/gnu/usr.bin/binutils/gdb/kvm-fbsd.c
@@ -56,6 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "bfd.h"
#include "target.h"
#include "gdbcore.h"
+#include "solist.h"
static void
kcore_files_info (struct target_ops *);
@@ -73,6 +74,10 @@ xfer_mem (CORE_ADDR, char *, int, int, struct mem_attrib *,
static int
xfer_umem (CORE_ADDR, char *, int, int);
+#ifdef SOLIB_ADD
+static int kcore_solib_add_stub (PTR);
+#endif
+
static char *core_file;
static kvm_t *core_kd;
static struct pcb cur_pcb;
@@ -210,6 +215,12 @@ kcore_close (int quitting)
inferior_ptid = null_ptid; /* Avoid confusion from thread stuff. */
+ /* Clear out solib state while the bfd is still open. See
+ comments in clear_solib in solib.c. */
+#ifdef CLEAR_SOLIB
+ CLEAR_SOLIB ();
+#endif
+
if (core_kd)
{
kvm_close (core_kd);
@@ -306,7 +317,16 @@ kcore_open (char *filename /* the core file */, int from_tty)
printf ("---\n");
}
- if (!ontop)
+ if (ontop)
+ {
+ /* Add symbols and section mappings for any kernel modules. */
+#ifdef SOLIB_ADD
+ current_target_so_ops = &kgdb_so_ops;
+ catch_errors (kcore_solib_add_stub, &from_tty, (char *) 0,
+ RETURN_MASK_ALL);
+#endif
+ }
+ else
{
warning ("you won't be able to access this core file until you terminate\n"
"your %s; do ``info files''", target_longname);
@@ -712,6 +732,15 @@ set_proc_cmd (char *arg, int from_tty)
error ("invalid proc address");
}
+#ifdef SOLIB_ADD
+static int
+kcore_solib_add_stub (PTR from_ttyp)
+{
+ SOLIB_ADD (NULL, *(int *) from_ttyp, &current_target, auto_solib_add);
+ return 0;
+}
+#endif /* SOLIB_ADD */
+
void
_initialize_kcorelow (void)
{
diff --git a/gnu/usr.bin/binutils/gdb/solib-fbsd-kld.c b/gnu/usr.bin/binutils/gdb/solib-fbsd-kld.c
new file mode 100644
index 0000000..72d4807
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/solib-fbsd-kld.c
@@ -0,0 +1,298 @@
+/* Handle FreeBSD kernel modules as shared libraries.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
+ 2001
+ Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* $FreeBSD$ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#define _KERNEL
+#include <sys/linker.h>
+#undef _KERNEL
+
+/* XXX, kludge to avoid duplicate definitions while sys/linker.h is used. */
+#define _ELF_COMMON_H
+
+#include "defs.h"
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "inferior.h"
+
+#include "solist.h"
+
+struct lm_info
+ {
+ CORE_ADDR address;
+ };
+
+static int try_modpath (char *buf, int buflen, char *fmt, ...);
+static char *guess_modpath (char *modname);
+
+static void
+kgdb_relocate_section_addresses (struct so_list *so,
+ struct section_table *sec)
+{
+ sec->addr += so->lm_info->address;
+ sec->endaddr += so->lm_info->address;
+}
+
+static int
+kgdb_open_symbol_file_object (void *from_ttyp)
+{
+ warning ("kgdb_open_symbol_file_object called\n");
+ return 0;
+}
+
+static struct so_list *
+kgdb_current_sos (void)
+{
+ linker_file_list_t linker_files;
+ struct linker_file lfile;
+ struct minimal_symbol *msymbol;
+ struct linker_file *lfilek;
+ struct so_list *head = NULL;
+ struct so_list **link_ptr = &head;
+
+ CORE_ADDR lfiles_addr;
+
+ msymbol = lookup_minimal_symbol ("linker_files", NULL, symfile_objfile);
+ if (msymbol == NULL || SYMBOL_VALUE_ADDRESS (msymbol) == 0)
+ {
+ warning ("failed to find linker_files symbol\n");
+ return 0;
+ }
+ lfiles_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (target_read_memory (lfiles_addr, (char *)&linker_files,
+ sizeof (linker_files)))
+ {
+ warning ("failed to read linker_files data\n");
+ return 0;
+ }
+ for (lfilek = TAILQ_FIRST (&linker_files); lfilek != NULL;
+ lfilek = TAILQ_NEXT (&lfile, link))
+ {
+ struct so_list *new;
+ struct cleanup *old_chain;
+ char *buf;
+ int errcode;
+
+ if (target_read_memory ((CORE_ADDR) lfilek, (char *) &lfile,
+ sizeof (lfile)))
+ {
+ warning ("failed to read linker file data at %p\n", lfilek);
+ return 0;
+ }
+ target_read_string ((CORE_ADDR) lfile.filename, &buf,
+ SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+ if (errcode != 0)
+ {
+ warning ("cannot read linker file pathname: %s\n",
+ safe_strerror (errcode));
+ return 0;
+ }
+ if (strlen (buf) < 3 || strcmp (&buf[strlen (buf) - 3], ".ko") != 0)
+ {
+ xfree (buf);
+ continue;
+ }
+
+ new = (struct so_list *) xmalloc (sizeof (struct so_list));
+ old_chain = make_cleanup (xfree, new);
+
+ memset (new, 0, sizeof (*new));
+
+ new->lm_info = xmalloc (sizeof (struct lm_info));
+ make_cleanup (xfree, new->lm_info);
+
+ new->lm_info->address = (CORE_ADDR) lfile.address;
+
+ strncpy (new->so_original_name, buf, SO_NAME_MAX_PATH_SIZE - 1);
+ new->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ xfree (buf);
+ snprintf (new->so_name, SO_NAME_MAX_PATH_SIZE, "%s",
+ guess_modpath (new->so_original_name));
+
+ new->next = NULL;
+ *link_ptr = new;
+ link_ptr = &new->next;
+
+ discard_cleanups (old_chain);
+ }
+ return head;
+}
+
+static int
+kgdb_in_dynsym_resolve_code (CORE_ADDR pc)
+{
+ warning ("kgdb_in_dynsym_resolve_code called\n");
+ return 0;
+}
+
+static void
+kgdb_special_symbol_handling (void)
+{
+}
+
+static void
+kgdb_solib_create_inferior_hook (void)
+{
+ warning ("kgdb_solib_create_inferior_hook called\n");
+}
+
+static void
+kgdb_clear_solib (void)
+{
+}
+
+static void
+kgdb_free_so (struct so_list *so)
+{
+ xfree (so->lm_info);
+}
+
+static int
+try_modpath (char *buf, int buflen, char *fmt, ...)
+{
+ struct stat sb;
+ va_list ap;
+
+ va_start (ap, fmt);
+ vsnprintf (buf, buflen, fmt, ap);
+ va_end(ap);
+
+ return (stat (buf, &sb) == 0);
+}
+
+static char *
+guess_modpath (char *modname)
+{
+ static char buf[2048], moddir[128], syspath[1024];
+ struct minimal_symbol *msymbol;
+ char *kernpath, *objpath, *p, *version;
+ int errcode, n, syspathlen;
+
+ /* Set default module location */
+ snprintf (buf, sizeof (buf), "/boot/kernel/%s", modname);
+
+ /* Guess at the subdirectory off sys/modules. XXX, only sometimes correct */
+ n = strlen (modname);
+ if (n > 3 && strcmp (&modname[n - 3], ".ko") == 0)
+ n -= 3;
+ snprintf (moddir, sizeof (moddir), "%.*s", n, modname);
+
+ /* Try to locate the kernel compile location from version[] */
+ msymbol = lookup_minimal_symbol ("version", NULL, symfile_objfile);
+ if (msymbol == NULL || SYMBOL_VALUE_ADDRESS (msymbol) == 0)
+ {
+ warning("cannot find `version' symbol; using default module path\n");
+ return buf;
+ }
+ target_read_string (SYMBOL_VALUE_ADDRESS (msymbol), &version, 2048, &errcode);
+ if (errcode != 0)
+ {
+ warning ("cannot read `version' string; using default module path: %s\n",
+ safe_strerror (errcode));
+ return buf;
+ }
+
+ /* Find the kernel build path after user@host: on the second line. */
+ if ((p = strchr (version, '\n')) == NULL ||
+ (kernpath = strchr (p, ':')) == NULL ||
+ (p = strchr (kernpath, '\n')) == NULL)
+ {
+ warning ("cannot parse version[]; using default module path\n");
+ xfree (version);
+ return buf;
+ }
+ kernpath++;
+ *p = '\0';
+
+ /*
+ * Find the absolute path to src/sys by skipping back over path
+ * components until we find a "/sys/".
+ */
+ syspathlen = 0;
+ while (p > kernpath && syspathlen == 0)
+ {
+ while (p > kernpath && *p != '/')
+ p--;
+ if (strncmp (p, "/sys/", 5) == 0)
+ syspathlen = p - kernpath + 4;
+ else if (p > kernpath)
+ p--;
+ }
+ if (syspathlen == 0)
+ {
+ warning ("cannot find /sys/ in `%s'; using default module path\n",
+ kernpath);
+ xfree (version);
+ return buf;
+ }
+ /*
+ * For kernels compiled with buildkernel, the object path will have
+ * been prepended to the /sys/ path in `kernpath'.
+ */
+ objpath = getenv ("MAKEOBJDIRPREFIX");
+ if (objpath == NULL)
+ objpath = "/usr/obj";
+ n = strlen (objpath);
+ if (syspathlen > n + 1 && strncmp (kernpath, objpath, n) == 0 &&
+ kernpath[n] == '/')
+ snprintf (syspath, sizeof (syspath), "%.*s", syspathlen - n, kernpath + n);
+ else
+ snprintf (syspath, sizeof (syspath), "%.*s", syspathlen, kernpath);
+
+ /* Now try to find the module file */
+ if (!try_modpath (buf, sizeof (buf), "./%s.debug", modname) &&
+ !try_modpath (buf, sizeof (buf), "./%s", modname) && !try_modpath (buf,
+ sizeof (buf), "%s/modules%s/modules/%s/%s.debug", kernpath, syspath,
+ moddir, modname) && !try_modpath (buf, sizeof (buf),
+ "%s/modules%s/modules/%s/%s", kernpath, syspath, moddir, modname) &&
+ !try_modpath (buf, sizeof (buf), "/boot/kernel/%s.debug", modname) &&
+ !try_modpath (buf, sizeof (buf), "/boot/kernel/%s", modname))
+ {
+ warning ("cannot find file for module %s\n", modname);
+ snprintf (buf, sizeof (buf), "%s", modname);
+ }
+ xfree (version);
+
+ return buf;
+}
+
+struct target_so_ops kgdb_so_ops;
+
+void
+_initialize_kgdb_solib (void)
+{
+ kgdb_so_ops.relocate_section_addresses = kgdb_relocate_section_addresses;
+ kgdb_so_ops.free_so = kgdb_free_so;
+ kgdb_so_ops.clear_solib = kgdb_clear_solib;
+ kgdb_so_ops.solib_create_inferior_hook = kgdb_solib_create_inferior_hook;
+ kgdb_so_ops.special_symbol_handling = kgdb_special_symbol_handling;
+ kgdb_so_ops.current_sos = kgdb_current_sos;
+ kgdb_so_ops.open_symbol_file_object = kgdb_open_symbol_file_object;
+ kgdb_so_ops.in_dynsym_resolve_code = kgdb_in_dynsym_resolve_code;
+}
OpenPOWER on IntegriCloud