summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-04-29 20:32:45 +0000
committerjhb <jhb@FreeBSD.org>2008-04-29 20:32:45 +0000
commit2f2328129fd9e404133e4bd2bd6e30b17c614f00 (patch)
tree8ccee22e4fc9762034642464ab8622aa5daddde0 /gnu
parente7d287052b4ae9d21e3a77681c65058a24a0db88 (diff)
downloadFreeBSD-src-2f2328129fd9e404133e4bd2bd6e30b17c614f00.zip
FreeBSD-src-2f2328129fd9e404133e4bd2bd6e30b17c614f00.tar.gz
Rework how kgdb manages kernel and vmcore files to be a bit more gdb-ish
so that kgdb can be used more like a normal gdb: - Load the kernel via the standard 'exec' target and allow it to be changed via the 'file' command. - Instead of explicitly loading the kernel file as the mail symbol file during startup, just pass it to gdb_main() as the executable file. - Change the kld support (via shared libraries) to cache the address of the linker_files and linker_kernel_file variables in addition to the offsets of various members in 'struct linker_file'. - When a new symbol file is loaded, recompute the addresses and offsets used by the kld support code. - When a new symbol file is loaded, recalculate the ofs_fix variable to account for the different ways a trapframe can be passed to trap frame handlers in i386. This is done by adding a MD kgdb_trgt_new_objfile() hook that is empty on all but i386. - Don't use the directory name of the kernel specified on the command line to find kernel modules in the kld support code. Instead, extract the filename of the current executable via exec_bfd. Now the 'kernel' variable is private to main.c again. - Make the 'add-kld' command explicitly fail if no executable is loaded. - Make the support for vmcores a real core-dump target that opens the kernel and vmcore on open and closes the kvm connection when closed, etc. - The 'core' command can now be used to select a vmcore to use, either a crash dump file or /dev/mem for live debugging. - The 'detach' command can be used to detach from a vmcore w/o attaching to a new one. - kgdb no longer explicitly opens a core dump during startup and no longer has to use an atexit() hook to close the kvm connection on shutdown. - Symbols for kld's are automatically loaded anytime a core is opened. Also, the unread portion of dmesg is dumped just as it was done on kgdb startup previously. - Don't require either a remote target or core dump if a kernel is specified. You can now just run 'kgdb kernel' similar to running gdb on an executable and later connect to a remote target or core dump. - Use a more relaxed way to verify remote targets specified via -r. Instead of explicitly allowing a few non-file target specifications, just assume that if stat() on the arg and on "/dev/" + arg both fail that is some non-file target and pass it to gdb. - Don't use a custom interpreter. The existing kgdb_init() hook and the target_new_objfile() hook give us sufficient hooks during startup to setup kgdb-specific behavior now. - Always add the 'proc', 'tid', and 'add-kld' commands on startup and not just if we have a core dump. Currently the 'proc' and 'tid' commands do not work for remote targets (I will fix at least 'tid' in the next round of changes though). However, the 'add-kld' command works fine for loading symbols for a kernel module on a remote target. - Always setup the 'kld' shared library target operations instead of just if we have a core dump. Although symbols for kernel modules are not automatically loaded when connecting to a remote target, you can do 'info sharedlibrary' after connecting to the remote target and kgdb will find all the modules. You can then use the 'sharedlibrary' command to load symbols from the module files. - Change kthr_init() to free the existing list of kthr objects before generating a new one. This allows it to be invoked multiple times w/o leaking memory. MFC after: 1 week
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/gdb/kgdb/kgdb.h16
-rw-r--r--gnu/usr.bin/gdb/kgdb/kld.c75
-rw-r--r--gnu/usr.bin/gdb/kgdb/kthr.c6
-rw-r--r--gnu/usr.bin/gdb/kgdb/main.c205
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt.c161
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt_amd64.c5
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt_arm.c5
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt_i386.c34
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt_ia64.c5
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt_powerpc.c5
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt_sparc64.c5
11 files changed, 338 insertions, 184 deletions
diff --git a/gnu/usr.bin/gdb/kgdb/kgdb.h b/gnu/usr.bin/gdb/kgdb/kgdb.h
index 0c324e6..b9a5df6 100644
--- a/gnu/usr.bin/gdb/kgdb/kgdb.h
+++ b/gnu/usr.bin/gdb/kgdb/kgdb.h
@@ -32,8 +32,6 @@
struct thread_info;
extern kvm_t *kvm;
-extern char *kernel;
-extern bfd *kern_bfd;
struct kthr {
struct kthr *next;
@@ -48,11 +46,14 @@ struct kthr {
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;
@@ -67,6 +68,9 @@ 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_ */
diff --git a/gnu/usr.bin/gdb/kgdb/kld.c b/gnu/usr.bin/gdb/kgdb/kld.c
index 4a57692..76541cd 100644
--- a/gnu/usr.bin/gdb/kgdb/kld.c
+++ b/gnu/usr.bin/gdb/kgdb/kld.c
@@ -55,6 +55,8 @@ 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;
@@ -70,7 +72,6 @@ kld_ok (char *path)
/*
* 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)
*/
@@ -112,11 +113,14 @@ find_kld_path (char *filename, char *path, size_t path_size)
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,
@@ -160,11 +164,12 @@ find_kld_address (char *arg, CORE_ADDR *address)
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),
@@ -256,12 +261,15 @@ load_kld (char *path, CORE_ADDR base_addr, int from_tty)
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))) {
@@ -324,6 +332,10 @@ kld_current_sos (void)
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;
@@ -331,8 +343,8 @@ kld_current_sos (void)
* 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)
@@ -429,6 +441,28 @@ kld_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
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)
{
@@ -438,19 +472,16 @@ load_klds_stub (void *arg)
}
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;
@@ -464,8 +495,6 @@ kgdb_kld_init (void)
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.");
diff --git a/gnu/usr.bin/gdb/kgdb/kthr.c b/gnu/usr.bin/gdb/kgdb/kthr.c
index 4c51c0e..7c76b80 100644
--- a/gnu/usr.bin/gdb/kgdb/kthr.c
+++ b/gnu/usr.bin/gdb/kgdb/kthr.c
@@ -78,6 +78,12 @@ kgdb_thr_init(void)
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) {
diff --git a/gnu/usr.bin/gdb/kgdb/main.c b/gnu/usr.bin/gdb/kgdb/main.c
index 7762763..3d94406 100644
--- a/gnu/usr.bin/gdb/kgdb/main.c
+++ b/gnu/usr.bin/gdb/kgdb/main.c
@@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$");
#include <sys/wait.h>
#include <errno.h>
#include <err.h>
-#include <fcntl.h>
#include <inttypes.h>
#include <kvm.h>
#include <limits.h>
@@ -55,42 +54,31 @@ __FBSDID("$FreeBSD$");
#include <interps.h>
#include <cli-out.h>
#include <main.h>
+#include <objfiles.h>
#include <target.h>
#include <top.h>
+#include <ui-file.h>
#include <bfd.h>
#include <gdbcore.h>
#include <wrapper.h>
-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)
{
@@ -168,27 +156,42 @@ kernel_from_dumpnr(int nr)
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;
+
+ kld_new_objfile(objfile);
+ kgdb_trgt_new_objfile(objfile);
-out:
-#endif
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);
@@ -198,45 +201,19 @@ kgdb_parse(const char *exp)
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.
@@ -266,37 +243,54 @@ kgdb_init_target(void)
}
static void
-kgdb_interp_command_loop(void *data)
+kgdb_init(char *argv0 __unused)
+{
+
+ 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)
{
- static int once = 0;
+ char path[PATH_MAX];
+ struct stat st;
- if (!once) {
- once = 1;
- kgdb_init_target();
- print_stack_frame(get_selected_frame(),
- frame_relative_level(get_selected_frame()), 1);
+ 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
@@ -306,7 +300,7 @@ main(int argc, char *argv[])
struct stat st;
struct captured_main_args args;
char *s;
- int a, ch, writecore;
+ int a, ch;
dumpnr = -1;
@@ -331,7 +325,11 @@ main(int argc, char *argv[])
}
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) {
@@ -364,6 +362,7 @@ main(int argc, char *argv[])
break;
case 'q':
quiet = 1;
+ add_arg(&args, "-q");
break;
case 'r': /* use given device for remote session. */
if (remote != NULL) {
@@ -378,7 +377,7 @@ main(int argc, char *argv[])
verbose++;
break;
case 'w': /* core file is writeable. */
- writecore = 1;
+ add_arg(&args, "--write");
break;
case '?':
default:
@@ -411,21 +410,8 @@ main(int argc, char *argv[])
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++]);
@@ -445,20 +431,12 @@ main(int argc, char *argv[])
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) {
@@ -470,27 +448,16 @@ main(int argc, char *argv[])
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;
diff --git a/gnu/usr.bin/gdb/kgdb/trgt.c b/gnu/usr.bin/gdb/kgdb/trgt.c
index a312767..9898f6b 100644
--- a/gnu/usr.bin/gdb/kgdb/trgt.c
+++ b/gnu/usr.bin/gdb/kgdb/trgt.c
@@ -32,22 +32,32 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/user.h>
#include <err.h>
+#include <fcntl.h>
#include <kvm.h>
#include <defs.h>
+#include <readline/readline.h>
+#include <readline/tilde.h>
#include <command.h>
#include <exec.h>
#include <frame-unwind.h>
+#include <gdbcore.h>
#include <gdbthread.h>
#include <inferior.h>
+#include <language.h>
#include <regcache.h>
+#include <solib.h>
#include <target.h>
#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)
@@ -69,6 +79,111 @@ kgdb_kernbase (void)
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)
{
@@ -86,7 +201,9 @@ 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
@@ -135,6 +252,13 @@ kgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write,
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)
{
@@ -200,21 +324,26 @@ kgdb_set_tid_cmd (char *arg, int from_tty)
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;
@@ -223,25 +352,13 @@ kgdb_target(void)
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;
-
- 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()));
+ kgdb_trgt_ops.to_insert_breakpoint = kgdb_trgt_ignore_breakpoints;
+ kgdb_trgt_ops.to_remove_breakpoint = kgdb_trgt_ignore_breakpoints;
add_target(&kgdb_trgt_ops);
- 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();
}
diff --git a/gnu/usr.bin/gdb/kgdb/trgt_amd64.c b/gnu/usr.bin/gdb/kgdb/trgt_amd64.c
index 064d482..d37e9da 100644
--- a/gnu/usr.bin/gdb/kgdb/trgt_amd64.c
+++ b/gnu/usr.bin/gdb/kgdb/trgt_amd64.c
@@ -74,6 +74,11 @@ 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;
diff --git a/gnu/usr.bin/gdb/kgdb/trgt_arm.c b/gnu/usr.bin/gdb/kgdb/trgt_arm.c
index afdcbc6..e99d5b2 100644
--- a/gnu/usr.bin/gdb/kgdb/trgt_arm.c
+++ b/gnu/usr.bin/gdb/kgdb/trgt_arm.c
@@ -89,6 +89,11 @@ 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;
diff --git a/gnu/usr.bin/gdb/kgdb/trgt_i386.c b/gnu/usr.bin/gdb/kgdb/trgt_i386.c
index 995f1a6..f0546ba 100644
--- a/gnu/usr.bin/gdb/kgdb/trgt_i386.c
+++ b/gnu/usr.bin/gdb/kgdb/trgt_i386.c
@@ -41,12 +41,15 @@ __FBSDID("$FreeBSD$");
#include <target.h>
#include <gdbthread.h>
#include <inferior.h>
+#include <objfiles.h>
#include <regcache.h>
#include <frame-unwind.h>
#include <i386-tdep.h>
#include "kgdb.h"
+static int ofs_fix;
+
void
kgdb_trgt_fetch_registers(int regno __unused)
{
@@ -74,6 +77,23 @@ 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;
@@ -285,8 +305,6 @@ kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
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);
@@ -298,18 +316,6 @@ kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
*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)
diff --git a/gnu/usr.bin/gdb/kgdb/trgt_ia64.c b/gnu/usr.bin/gdb/kgdb/trgt_ia64.c
index 86d83fc..f9e0136 100644
--- a/gnu/usr.bin/gdb/kgdb/trgt_ia64.c
+++ b/gnu/usr.bin/gdb/kgdb/trgt_ia64.c
@@ -135,6 +135,11 @@ 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;
diff --git a/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c b/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c
index 5c0ffe7..95e6161 100644
--- a/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c
+++ b/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c
@@ -83,6 +83,11 @@ 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;
diff --git a/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c b/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c
index 3e4a41a..736a499 100644
--- a/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c
+++ b/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c
@@ -73,6 +73,11 @@ 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;
OpenPOWER on IntegriCloud