Add the beginnings of kernel debugging support. the kgdb(1) tool

is basicly a shell on top of libgdb that knows about kernel threads,
kernel modules and kvm(3). As the word "beginnings" implies, not
all of the features have been implemented yet. The tool is useful
and I'd like feedback on the taken route.

The simplest way to debug a kernel core file is:
	kgdb -n 0

This opens /var/crash/vmcore.0 with the corresponding kernel in
the object directory (kernel.debug is used if it exists).

Typical things that need to be added are:
o  Auto loading of kernel modules,
o  Handling of trapframes so that backtraces can be taken across
   them,
o  Some fancy commands to extract useful information out of a core
   file,
o  Various (probably many) other things.
This commit is contained in:
Marcel Moolenaar 2004-07-25 05:29:15 +00:00
parent 4f23b47afa
commit 60b992ff2f
11 changed files with 1089 additions and 0 deletions

View File

@ -0,0 +1,14 @@
# $FreeBSD$
PROG= kgdb
SRCS= kthr.c main.c trgt.c trgt_${MACHINE_ARCH}.c
WARNS?= 2
BULIBS= ${OBJ_BU}/libbfd/libbfd.a ${OBJ_BU}/libopcodes/libopcodes.a \
${OBJ_BU}/libiberty/libiberty.a
GDBLIBS= ${OBJ_GDB}/libgdb/libgdb.a
DPADD= ${GDBLIBS} ${BULIBS} ${LIBKVM} ${LIBM} ${LIBREADLINE} ${LIBTERMCAP}
LDADD= ${GDBLIBS} ${BULIBS} -lkvm -lm -lreadline -ltermcap
.include <bsd.prog.mk>

View File

@ -0,0 +1,50 @@
.\" 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$
.Dd August 1, 2004
.Os
.Dt KGDB 1
.Sh NAME
.Nm kgdb
.Nd The kernel debugger
.Sh SYNOPSIS
.Nm
.Op Ar -v
.Op Ar -d crashdir
.Op Ar -n dumpnr
.Op Ar kernel [ Ar core ]
.Sh DESCRIPTION
The
.Nm
utility is a debugger based on
.Xr gdb 1
that allows debugging of kernel core files.
.Sh SEE ALSO
.Xr gdb 1
.Sh HISTORY
The
.Nm
utility first appeared in its current form in
.Fx 5.3 .

View File

@ -0,0 +1,55 @@
/*
* 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_
extern kvm_t *kvm;
extern int verbose;
struct kthr {
struct kthr *next;
uintptr_t kaddr;
uintptr_t kstack;
uintptr_t pcb;
int tid;
};
extern struct kthr *curkthr;
void kgdb_target(void);
void kgdb_trgt_fetch_registers(int);
void kgdb_trgt_store_registers(int);
struct kthr *kgdb_thr_first(void);
struct kthr *kgdb_thr_init(void);
struct kthr *kgdb_thr_lookup(int);
struct kthr *kgdb_thr_next(struct kthr *);
struct kthr *kgdb_thr_select(struct kthr *);
#endif /* _KGDB_H_ */

141
gnu/usr.bin/gdb/kgdb/kthr.c Normal file
View File

@ -0,0 +1,141 @@
/*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <err.h>
#include <inttypes.h>
#include <kvm.h>
#include <stdio.h>
#include <stdlib.h>
#include "kgdb.h"
static uintptr_t dumppcb;
static int dumptid;
static struct kthr *first;
struct kthr *curkthr;
static uintptr_t
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) {
warnx("kvm_nlist(%s): %s", sym, kvm_geterr(kvm));
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;
addr = lookup("_allproc");
if (addr == 0)
return (NULL);
kvm_read(kvm, addr, &paddr, sizeof(paddr));
dumppcb = lookup("_dumppcb");
if (dumppcb == 0)
return (NULL);
addr = lookup("_dumptid");
if (addr != 0)
kvm_read(kvm, addr, &dumptid, sizeof(dumptid));
else
dumptid = -1;
while (paddr != 0) {
if (kvm_read(kvm, paddr, &p, sizeof(p)) != sizeof(p))
warnx("kvm_read: %s", kvm_geterr(kvm));
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));
kt = malloc(sizeof(*kt));
kt->next = first;
kt->kaddr = addr;
kt->pcb = (td.td_tid == dumptid) ? dumppcb :
(uintptr_t)td.td_pcb;
kt->kstack = td.td_kstack;
kt->tid = td.td_tid;
first = kt;
addr = (uintptr_t)TAILQ_NEXT(&td, td_plist);
}
paddr = (uintptr_t)LIST_NEXT(&p, p_list);
}
curkthr = kgdb_thr_lookup(dumptid);
if (curkthr == NULL)
curkthr = first;
return (first);
}
struct kthr *
kgdb_thr_lookup(int tid)
{
struct kthr *kt;
kt = first;
while (kt != NULL && kt->tid != tid)
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);
}

288
gnu/usr.bin/gdb/kgdb/main.c Normal file
View File

@ -0,0 +1,288 @@
/*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <errno.h>
#include <err.h>
#include <fcntl.h>
#include <inttypes.h>
#include <kvm.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* libgdb stuff. */
#include <defs.h>
#include <frame.h>
#include <inferior.h>
#include <interps.h>
#include <cli-out.h>
#include <main.h>
#include <target.h>
#include <top.h>
extern void (*init_ui_hook)(char *);
extern void symbol_file_add_main (char *args, int from_tty);
#include "kgdb.h"
kvm_t *kvm;
static int dumpnr;
static int verbose;
static char crashdir[PATH_MAX];
static char *kernel;
static char *vmcore;
static void (*kgdb_new_objfile_chain)(struct objfile * objfile);
static void
usage(void)
{
fprintf(stderr,
"usage: %s [-v] [-d crashdir] [-n dumpnr] [kernel [core]]\n",
getprogname());
exit(1);
}
static void
use_dump(int nr)
{
char path[PATH_MAX];
FILE *info;
char *s;
struct stat st;
int l;
snprintf(path, sizeof(path), "%s/vmcore.%d", crashdir, nr);
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);
/*
* See if there's a kernel image right here, use it. The kernel
* image is either called kernel.<nr> or is in a subdirectory
* kernel.<nr> and called kernel.
*/
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 in it still.
*/
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);
if (verbose && kernel == NULL)
warnx("dump %d: no kernel found", nr);
}
static void
kgdb_new_objfile(struct objfile *objfile)
{
#if 0
printf("XXX: %s(%p)\n", __func__, objfile);
if (objfile != NULL) {
goto out;
}
out:
#endif
if (kgdb_new_objfile_chain != NULL)
kgdb_new_objfile_chain(objfile);
}
static void
kgdb_interp_command_loop(void *data)
{
static int once = 0;
if (!once) {
symbol_file_add_main (kernel, 0);
print_stack_frame(get_current_frame(), -1, 0);
once = 1;
}
command_loop();
}
static void
kgdb_init(char *argv0 __unused)
{
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_target();
kgdb_new_objfile_chain = target_new_objfile_hook;
target_new_objfile_hook = kgdb_new_objfile;
}
int
main(int argc, char *argv[])
{
struct captured_main_args args;
char *s;
int ch;
dumpnr = -1;
strlcpy(crashdir, "/var/crash", sizeof(crashdir));
s = getenv("KGDB_CRASH_DIR");
if (s != NULL)
strlcpy(crashdir, s, sizeof(crashdir));
while ((ch = getopt(argc, argv, "d:n:v")) != -1) {
switch (ch) {
case 'd':
strlcpy(crashdir, optarg, sizeof(crashdir));
break;
case 'n':
dumpnr = strtol(optarg, &s, 0);
if (dumpnr < 0 || *s != '\0') {
warnx("option %c: invalid kernel dump number",
optopt);
usage();
/* NOTREACHED */
}
break;
case 'v':
verbose++;
break;
case '?':
default:
usage();
}
}
if (verbose > 1)
warnx("using %s as the crash directory", crashdir);
if (dumpnr >= 0)
use_dump(dumpnr);
if (argc > optind) {
if (kernel != NULL)
free(kernel);
kernel = strdup(argv[optind++]);
}
while (argc > optind) {
if (vmcore != NULL)
errx(1, "multiple core files specified");
vmcore = strdup(argv[optind++]);
}
if (kernel == NULL)
errx(1, "kernel not specified");
if (vmcore == NULL)
errx(1, "core file not specified");
if (verbose) {
warnx("kernel image: %s", kernel);
warnx("core file: %s", vmcore);
}
s = malloc(_POSIX2_LINE_MAX);
kvm = kvm_openfiles(kernel, vmcore, NULL, O_RDONLY, s);
if (kvm == NULL)
errx(1, s);
free(s);
kgdb_thr_init();
memset (&args, 0, sizeof args);
args.argc = 1;
args.argv = argv;
args.use_windows = 0;
args.interpreter_p = "kgdb";
init_ui_hook = kgdb_init;
return (gdb_main(&args));
}

112
gnu/usr.bin/gdb/kgdb/trgt.c Normal file
View File

@ -0,0 +1,112 @@
/*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <kvm.h>
#include "kgdb.h"
#include <defs.h>
#include <gdbthread.h>
#include <inferior.h>
#include <target.h>
static struct target_ops kgdb_trgt_ops;
static char *
kgdb_trgt_extra_thread_info(struct thread_info *ti __unused)
{
return (NULL);
}
static void
kgdb_trgt_find_new_threads(void)
{
}
static char *
kgdb_trgt_pid_to_str(ptid_t ptid)
{
static char buf[16];
snprintf(buf, sizeof(buf), "TID %d", ptid_get_pid(ptid));
return (buf);
}
static int
kgdb_trgt_thread_alive(ptid_t ptid)
{
return (kgdb_thr_lookup(ptid_get_pid(ptid)) != NULL);
}
static int
kgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write,
struct mem_attrib *attrib __unused, struct target_ops *target __unused)
{
if (len == 0)
return (0);
if (!write)
return (kvm_read(kvm, memaddr, myaddr, len));
else
return (kvm_write(kvm, memaddr, myaddr, len));
}
void
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_has_memory = 1;
kgdb_trgt_ops.to_has_registers = 1;
kgdb_trgt_ops.to_has_stack = 1;
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_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;
add_target(&kgdb_trgt_ops);
push_target(&kgdb_trgt_ops);
kt = kgdb_thr_first();
while (kt != NULL) {
ti = add_thread(ptid_build(kt->tid, 0, 0));
kt = kgdb_thr_next(kt);
}
inferior_ptid = ptid_build(curkthr->tid, 0, 0);
}

View File

@ -0,0 +1,73 @@
/*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <machine/pcb.h>
#include <err.h>
#include <kvm.h>
#include <string.h>
#include "kgdb.h"
#include <defs.h>
#include <target.h>
#include <gdbthread.h>
#include <inferior.h>
#include <regcache.h>
void
kgdb_trgt_fetch_registers(int regno __unused)
{
struct kthr *kt;
struct pcb pcb;
kt = kgdb_thr_lookup(ptid_get_pid(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(9, (char *)&pcb.pcb_context[0]);
supply_register(10, (char *)&pcb.pcb_context[1]);
supply_register(11, (char *)&pcb.pcb_context[2]);
supply_register(12, (char *)&pcb.pcb_context[3]);
supply_register(13, (char *)&pcb.pcb_context[4]);
supply_register(14, (char *)&pcb.pcb_context[5]);
supply_register(15, (char *)&pcb.pcb_context[6]);
supply_register(30, (char *)&pcb.pcb_hw.apcb_ksp);
supply_register(64, (char *)&pcb.pcb_context[7]);
}
void
kgdb_trgt_store_registers(int regno __unused)
{
fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
}

View File

@ -0,0 +1,73 @@
/*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <machine/pcb.h>
#include <err.h>
#include <kvm.h>
#include <string.h>
#include "kgdb.h"
#include <defs.h>
#include <target.h>
#include <gdbthread.h>
#include <inferior.h>
#include <regcache.h>
void
kgdb_trgt_fetch_registers(int regno __unused)
{
struct kthr *kt;
struct pcb pcb;
kt = kgdb_thr_lookup(ptid_get_pid(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(1, (char *)&pcb.pcb_rbx);
supply_register(6, (char *)&pcb.pcb_rbp);
supply_register(7, (char *)&pcb.pcb_rsp);
supply_register(12, (char *)&pcb.pcb_r12);
supply_register(13, (char *)&pcb.pcb_r13);
supply_register(14, (char *)&pcb.pcb_r14);
supply_register(15, (char *)&pcb.pcb_r15);
supply_register(16, (char *)&pcb.pcb_rip);
supply_register(17, (char *)&pcb.pcb_rflags);
}
void
kgdb_trgt_store_registers(int regno __unused)
{
fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
}

View File

@ -0,0 +1,69 @@
/*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <machine/pcb.h>
#include <err.h>
#include <kvm.h>
#include <string.h>
#include "kgdb.h"
#include <defs.h>
#include <target.h>
#include <gdbthread.h>
#include <inferior.h>
#include <regcache.h>
void
kgdb_trgt_fetch_registers(int regno __unused)
{
struct kthr *kt;
struct pcb pcb;
kt = kgdb_thr_lookup(ptid_get_pid(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(3, (char *)&pcb.pcb_ebx);
supply_register(4, (char *)&pcb.pcb_esp);
supply_register(5, (char *)&pcb.pcb_ebp);
supply_register(6, (char *)&pcb.pcb_esi);
supply_register(7, (char *)&pcb.pcb_edi);
supply_register(8, (char *)&pcb.pcb_eip);
}
void
kgdb_trgt_store_registers(int regno __unused)
{
fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
}

View File

@ -0,0 +1,133 @@
/*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <err.h>
#include <kvm.h>
#include <string.h>
#include "kgdb.h"
#include <defs.h>
#include <target.h>
#include <gdbthread.h>
#include <inferior.h>
#include <regcache.h>
void
kgdb_trgt_fetch_registers(int regno __unused)
{
struct kthr *kt;
struct pcb pcb;
uint64_t r;
kt = kgdb_thr_lookup(ptid_get_pid(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(1, (char *)&pcb.pcb_special.gp);
supply_register(4, (char *)&pcb.pcb_preserved.gr4);
supply_register(5, (char *)&pcb.pcb_preserved.gr5);
supply_register(6, (char *)&pcb.pcb_preserved.gr6);
supply_register(7, (char *)&pcb.pcb_preserved.gr7);
supply_register(12, (char *)&pcb.pcb_special.sp);
supply_register(13, (char *)&pcb.pcb_special.tp);
/* Registers 128-255: floating-point registers. */
supply_register(130, (char *)&pcb.pcb_preserved_fp.fr2);
supply_register(131, (char *)&pcb.pcb_preserved_fp.fr3);
supply_register(132, (char *)&pcb.pcb_preserved_fp.fr4);
supply_register(133, (char *)&pcb.pcb_preserved_fp.fr5);
supply_register(144, (char *)&pcb.pcb_preserved_fp.fr16);
supply_register(145, (char *)&pcb.pcb_preserved_fp.fr17);
supply_register(146, (char *)&pcb.pcb_preserved_fp.fr18);
supply_register(147, (char *)&pcb.pcb_preserved_fp.fr19);
supply_register(148, (char *)&pcb.pcb_preserved_fp.fr20);
supply_register(149, (char *)&pcb.pcb_preserved_fp.fr21);
supply_register(150, (char *)&pcb.pcb_preserved_fp.fr22);
supply_register(151, (char *)&pcb.pcb_preserved_fp.fr23);
supply_register(152, (char *)&pcb.pcb_preserved_fp.fr24);
supply_register(153, (char *)&pcb.pcb_preserved_fp.fr25);
supply_register(154, (char *)&pcb.pcb_preserved_fp.fr26);
supply_register(155, (char *)&pcb.pcb_preserved_fp.fr27);
supply_register(156, (char *)&pcb.pcb_preserved_fp.fr28);
supply_register(157, (char *)&pcb.pcb_preserved_fp.fr29);
supply_register(158, (char *)&pcb.pcb_preserved_fp.fr30);
supply_register(159, (char *)&pcb.pcb_preserved_fp.fr31);
/* Registers 320-327: branch registers. */
if (pcb.pcb_special.__spare == ~0UL)
supply_register(320, (char *)&pcb.pcb_special.rp);
supply_register(321, (char *)&pcb.pcb_preserved.br1);
supply_register(322, (char *)&pcb.pcb_preserved.br2);
supply_register(323, (char *)&pcb.pcb_preserved.br3);
supply_register(324, (char *)&pcb.pcb_preserved.br4);
supply_register(325, (char *)&pcb.pcb_preserved.br5);
/* Registers 328-333: misc. other registers. */
supply_register(330, (char *)&pcb.pcb_special.pr);
if (pcb.pcb_special.__spare == ~0UL) {
r = pcb.pcb_special.iip + ((pcb.pcb_special.psr >> 41) & 3);
supply_register(331, (char *)&r);
supply_register(333, (char *)&pcb.pcb_special.cfm);
} else {
supply_register(331, (char *)&pcb.pcb_special.rp);
supply_register(333, (char *)&pcb.pcb_special.pfs);
}
/* Registers 334-461: application registers. */
supply_register(350, (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(351, (char *)&r); /* bsp */
supply_register(352, (char *)&r); /* bspstore */
supply_register(353, (char *)&pcb.pcb_special.rnat);
supply_register(370, (char *)&pcb.pcb_special.unat);
supply_register(374, (char *)&pcb.pcb_special.fpsr);
if (pcb.pcb_special.__spare == ~0UL)
supply_register(398, (char *)&pcb.pcb_special.pfs);
supply_register(399, (char *)&pcb.pcb_preserved.lc);
}
void
kgdb_trgt_store_registers(int regno __unused)
{
fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
}

View File

@ -0,0 +1,81 @@
/*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <machine/asm.h>
#include <machine/pcb.h>
#include <err.h>
#include <kvm.h>
#include <string.h>
#include "kgdb.h"
#include <defs.h>
#include <target.h>
#include <gdbthread.h>
#include <inferior.h>
#include <regcache.h>
void
kgdb_trgt_fetch_registers(int regno __unused)
{
struct kthr *kt;
struct pcb pcb;
uint64_t r;
kt = kgdb_thr_lookup(ptid_get_pid(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));
}
/* 0-7: global registers (g0-g7) */
/* 8-15: output registers (o0-o7) */
r = pcb.pcb_sp - CCFSZ;
supply_register(14, (char *)&r);
/* 16-23: local registers (l0-l7) */
/* 24-31: input registers (i0-i7) */
supply_register(30, (char *)&pcb.pcb_sp);
/* 32-63: single precision FP (f0-f31) */
/* 64-79: double precision FP (f32-f62) */
supply_register(80, (char *)&pcb.pcb_pc);
}
void
kgdb_trgt_store_registers(int regno __unused)
{
fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
}