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
This commit is contained in:
John Baldwin 2008-04-29 20:32:45 +00:00
parent 0f95e62599
commit 3461a0f244
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178670
11 changed files with 339 additions and 185 deletions

View File

@ -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_ */

View File

@ -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,20 +472,17 @@ load_klds_stub (void *arg)
}
void
kgdb_kld_init (void)
kld_init (void)
{
catch_errors(load_klds_stub, NULL, NULL, RETURN_MASK_ALL);
}
void
initialize_kld_target(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;
module_path_addr = kgdb_parse("linker_path");
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;
@ -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.");

View File

@ -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) {

View File

@ -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,41 +54,30 @@ __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)
{
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
@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;