summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-01-29 23:44:34 +0000
committerjhb <jhb@FreeBSD.org>2008-01-29 23:44:34 +0000
commit890a8204e80435a502b4080fe72c6c2c4034a574 (patch)
tree7600d6c2dedd064660be855544e99f43d83bab14 /gnu
parent12a6269e8f4d906c68e0171be4c4ce877c287436 (diff)
downloadFreeBSD-src-890a8204e80435a502b4080fe72c6c2c4034a574.zip
FreeBSD-src-890a8204e80435a502b4080fe72c6c2c4034a574.tar.gz
- Rework the kld support to hook into GDB's shared library support.
kgdb(8) now treats kld's as shared libraries relative to the kernel "binary". Thus, you can use 'info sharedlibrary' to list the kld's along with 'sharedlibrary' and 'nosharedlibrary' to manage symbol loading and unloading. Note that there isn't an easy way to force GDB to use a specific path for a shared library. However, you can use 'nosharedlibrary' to unload all the klds and then use 'sharedlibrary' to load specific klds where it gets the kld correct and use 'add-kld' for the kld's where the default open behavior doesn't work. klds opened via 'sharedlibrary' (and during startup) do have their sections listed in 'info files'. - Change the 'add-kld' command to use filename completion to complete its argument.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/gdb/kgdb/kgdb.h1
-rw-r--r--gnu/usr.bin/gdb/kgdb/kld.c240
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt.c5
3 files changed, 165 insertions, 81 deletions
diff --git a/gnu/usr.bin/gdb/kgdb/kgdb.h b/gnu/usr.bin/gdb/kgdb/kgdb.h
index 637d91d..1ec306b 100644
--- a/gnu/usr.bin/gdb/kgdb/kgdb.h
+++ b/gnu/usr.bin/gdb/kgdb/kgdb.h
@@ -50,6 +50,7 @@ extern struct kthr *curkthr;
void kgdb_add_kld_cmd(char *, int);
void kgdb_auto_load_klds(void);
+void kgdb_kld_init(void);
void kgdb_target(void);
void kgdb_trgt_fetch_registers(int);
void kgdb_trgt_store_registers(int);
diff --git a/gnu/usr.bin/gdb/kgdb/kld.c b/gnu/usr.bin/gdb/kgdb/kld.c
index 95158ea..072226f 100644
--- a/gnu/usr.bin/gdb/kgdb/kld.c
+++ b/gnu/usr.bin/gdb/kgdb/kld.c
@@ -29,28 +29,35 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/stat.h>
-#include <libgen.h>
+#include <fcntl.h>
#include <kvm.h>
+#include <libgen.h>
#include <defs.h>
+#include <command.h>
+#include <completer.h>
+#include <environ.h>
#include <frame-unwind.h>
#include <inferior.h>
#include <objfiles.h>
#include <gdbcore.h>
#include <language.h>
+#include <solist.h>
#include "kgdb.h"
-/*
- * TODO
- *
- * - Use 'target_read_memory()' instead of kvm_read().
- * - Hook into the solib stuff perhaps?
- */
+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 struct target_so_ops kld_so_ops;
+
static int
kld_ok (char *path)
{
@@ -101,7 +108,6 @@ check_kld_path (char *path, size_t path_size)
static int
find_kld_path (char *filename, char *path, size_t path_size)
{
- CORE_ADDR module_path_addr;
char *module_path;
char *kernel_dir, *module_dir, *cp;
int error;
@@ -112,7 +118,6 @@ find_kld_path (char *filename, char *path, size_t path_size)
if (check_kld_path(path, path_size))
return (1);
}
- module_path_addr = kgdb_parse("linker_path");
if (module_path_addr != 0) {
target_read_string(module_path_addr, &module_path, PATH_MAX,
&error);
@@ -289,78 +294,159 @@ kgdb_add_kld_cmd (char *arg, int from_tty)
}
static void
-dummy_cleanup (void *arg)
+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
-load_single_kld (CORE_ADDR kld)
+kld_free_so (struct so_list *so)
{
- CORE_ADDR address;
- char kldpath[PATH_MAX];
- char *path, *filename;
- int errcode, path_ok;
-
- /* Try to read this linker file's filename. */
- target_read_string(read_pointer(kld + off_filename), &filename,
- PATH_MAX, &errcode);
- if (errcode)
- error("Unable to read kld filename");
-
- make_cleanup(xfree, filename);
- path_ok = 0;
-
- /* Try to read this linker file's pathname. */
- if (off_pathname != 0) {
- target_read_string(read_pointer(kld + off_pathname), &path,
- PATH_MAX, &errcode);
- if (errcode == 0) {
- make_cleanup(xfree, path);
-
- /*
- * If we have a pathname, try to load the kld
- * from there.
- */
- strlcpy(kldpath, path, sizeof(kldpath));
- if (check_kld_path(kldpath, sizeof(kldpath)))
- path_ok = 1;
- }
- }
+
+ 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;
+
+ prev = &head;
/*
- * If we didn't get a pathname from the linker file path, try
- * to find this kld in the various search paths.
+ * Walk the list of linker files creating so_list entries for
+ * each non-kernel file.
*/
- if (!path_ok && !find_kld_path(filename, kldpath, sizeof(kldpath)))
- error("Unable to find kld file for \"%s\".", filename);
+ kernel = kgdb_parse("linker_kernel_file");
+ for (kld = kgdb_parse("linker_files.tqh_first"); kld != 0;
+ kld = read_pointer(kld + off_next)) {
+ /* Skip the main kernel file. */
+ if (kld == kernel)
+ continue;
- /* Read this kld's base address and add its symbols. */
- address = read_pointer(kld + off_address);
- if (address == 0)
- error("Invalid address for kld \"%s\"", filename);
+ new = xmalloc(sizeof(*new));
+ memset(new, 0, sizeof(*new));
- load_kld(kldpath, address, 0, 0);
+ new->lm_info = xmalloc(sizeof(*new->lm_info));
+ new->lm_info->base_address = 0;
- printf_unfiltered("Loaded symbols for kld \"%s\" from \"%s\"\n",
- filename, path);
+ /* 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
-load_kld_stub (void *arg)
+kld_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
{
- CORE_ADDR kld = *(CORE_ADDR *)arg;
+ 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);
+}
- load_single_kld(kld);
+static int
+load_klds_stub (void *arg)
+{
- return (1);
+ SOLIB_ADD(NULL, 1, &current_target, auto_solib_add);
+ return (0);
}
void
-kgdb_auto_load_klds (void)
+kgdb_kld_init (void)
{
- struct cleanup *cleanup;
- CORE_ADDR kld, kernel;
- int loaded_kld;
+ struct cmd_list_element *c;
/* Compute offsets of relevant members in struct linker_file. */
off_address = kgdb_parse("&((struct linker_file *)0)->address");
@@ -370,24 +456,24 @@ kgdb_auto_load_klds (void)
if (off_address == 0 || off_filename == 0 || off_next == 0)
return;
- /* Walk the list of linker files auto-loading klds. */
- cleanup = make_cleanup(dummy_cleanup, NULL);
- loaded_kld = 0;
- kld = kgdb_parse("linker_files.tqh_first");
- kernel = kgdb_parse("linker_kernel_file");
- for (kld = kgdb_parse("linker_files.tqh_first"); kld != 0;
- kld = read_pointer(kld + off_next)) {
- /* Skip the main kernel file. */
- if (kld == kernel)
- continue;
+ module_path_addr = kgdb_parse("linker_path");
- if (catch_errors(load_kld_stub, &kld,
- "Error while reading kld symbols:\n", RETURN_MASK_ALL))
- loaded_kld = 1;
- }
+ 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;
- do_cleanups(cleanup);
+ current_target_so_ops = &kld_so_ops;
+
+ catch_errors(load_klds_stub, NULL, NULL, RETURN_MASK_ALL);
- if (loaded_kld)
- reinit_frame_cache();
+ 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);
}
diff --git a/gnu/usr.bin/gdb/kgdb/trgt.c b/gnu/usr.bin/gdb/kgdb/trgt.c
index 5c39bae..a312767 100644
--- a/gnu/usr.bin/gdb/kgdb/trgt.c
+++ b/gnu/usr.bin/gdb/kgdb/trgt.c
@@ -243,8 +243,5 @@ kgdb_target(void)
"Set current process context");
add_com ("tid", class_obscure, kgdb_set_tid_cmd,
"Set current thread context");
- add_com ("add-kld", class_files, kgdb_add_kld_cmd,
- "Usage: add-kld FILE\n\
-Load the symbols from the kernel loadable module FILE.");
- kgdb_auto_load_klds();
+ kgdb_kld_init();
}
OpenPOWER on IntegriCloud