PERFORCE change 54621 for review
Marcel Moolenaar
marcel at FreeBSD.org
Fri Jun 11 05:58:37 GMT 2004
http://perforce.freebsd.org/chv.cgi?CH=54621
Change 54621 by marcel at marcel_nfs on 2004/06/11 05:57:42
o Add kthr.c. It will contain kernel thread support functions.
The functions are dummies for now.
o Handle the gdb packets. This is mostly untested, but taken
from the kernel which is known to work.
o Add command line processing:
+ Add option -n, which takes an integer and instructs kgdb
to open /var/crash/vmcore.<n> and parse /var/crash/info.<n>
for the corresponding kernel. If kernel.debug exists, it
is used. Otherwise kernel is used. If no kernel is found,
the user has to enter the kernel file name explicitly.
+ Accept [kernel [core]]. If -n has been given, kernel takes
precedence and core cannot be given directly.
Affected files ...
.. //depot/projects/gdb/usr.bin/kgdb/Makefile#5 edit
.. //depot/projects/gdb/usr.bin/kgdb/kgdb.h#2 edit
.. //depot/projects/gdb/usr.bin/kgdb/kthr.c#1 add
.. //depot/projects/gdb/usr.bin/kgdb/main.c#6 edit
.. //depot/projects/gdb/usr.bin/kgdb/md_i386.c#2 edit
.. //depot/projects/gdb/usr.bin/kgdb/packet.c#2 edit
Differences ...
==== //depot/projects/gdb/usr.bin/kgdb/Makefile#5 (text+ko) ====
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= kgdb
-SRCS= main.c md_${MACHINE_ARCH}.c packet.c
+SRCS= kthr.c main.c md_${MACHINE_ARCH}.c packet.c
DPADD= ${LIBKVM} ${LIBUTIL}
LDADD= -lkvm -lutil
==== //depot/projects/gdb/usr.bin/kgdb/kgdb.h#2 (text+ko) ====
@@ -31,7 +31,6 @@
extern size_t gdb_rxsz;
extern char *gdb_txp;
-void gdb_packet(void);
void gdb_packet_data(const char *, size_t);
int gdb_packet_recv(char *, size_t);
int gdb_packet_send(const char *, size_t);
@@ -108,9 +107,15 @@
extern kvm_t *kvm;
struct kthr {
- void *frame;
+ void *td_frame;
+ int td_tid;
};
extern struct kthr *curkthr;
+struct kthr *kgdb_thr_first(void);
+struct kthr *kgdb_thr_lookup(int);
+struct kthr *kgdb_thr_next(struct kthr *);
+struct kthr *kgdb_thr_select(struct kthr *);
+
#endif /* _KGDB_H_ */
==== //depot/projects/gdb/usr.bin/kgdb/main.c#6 (text+ko) ====
@@ -27,6 +27,8 @@
#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>
@@ -54,8 +56,11 @@
char *gdb_rp_dev;
pid_t gdb_pid;
+int dumpnr;
+char crashdir[PATH_MAX];
+char *kernel;
+char *vmcore;
kvm_t *kvm;
-struct kthr *curkthr;
char *cmdfile_name;
int cmdfile_fd;
@@ -63,6 +68,14 @@
static const char cmd_set_prompt[] = "set prompt (kgdb) \n";
static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-d dumpno] [kernel] [core]\n",
+ getprogname());
+ exit(1);
+}
+
+static void
atexit_unlink_cmdfile(void)
{
close(cmdfile_fd); /* Is likely closed already. */
@@ -93,19 +106,100 @@
return (write(gdb_rp_fd, p, sz));
}
-void gdb_packet(void)
+static void
+parse_dump(void)
{
- printf("`%s'\n", gdb_rxp);
+ char path[PATH_MAX];
+ FILE *info;
+ char *s;
+ struct stat st;
+ int l;
+
+ snprintf(path, sizeof(path), "%s/vmcore.%d", crashdir, dumpnr);
+ if (stat(path, &st) == -1)
+ err(1, path);
+ vmcore = strdup(path);
+ snprintf(path, sizeof(path), "%s/info.%d", crashdir, dumpnr);
+ 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) {
+ path[l - 6] = '\0';
+ if (stat(path, &st) == -1)
+ break;
+ }
+ kernel = strdup(path);
+ break;
+ }
+ }
+ fclose(info);
}
int
-main(int argc __unused, char *argv[] __unused)
+main(int argc, char *argv[])
{
char buf[256];
fd_set rfds, wfds, xfds;
+ char *s;
ssize_t sz;
int fdin, fdout;
int f, nfds, status;
+ int ch;
+
+ strcpy(crashdir, "/var/crash");
+ while ((ch = getopt(argc, argv, "n:")) != -1) {
+ switch (ch) {
+ case 'n':
+ if (dumpnr) {
+ warnx("option %c specified multiple times",
+ optopt);
+ usage();
+ /* NOTREACHED */
+ }
+ dumpnr = strtol(optarg, &s, 0);
+ if (dumpnr == 0 || *s != '\0') {
+ warnx("option %c: invalid kernel dump number",
+ optopt);
+ usage();
+ /* NOTREACHED */
+ }
+ parse_dump();
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ if (kernel != NULL)
+ free(kernel);
+ kernel = strdup(*argv++);
+ argc--;
+ }
+ while (argc > 0) {
+ if (vmcore != NULL)
+ errx(1, "multiple core files specified");
+ vmcore = strdup(*argv++);
+ argc--;
+ }
+
+ if (kernel == NULL)
+ errx(1, "kernel not specified");
+ if (vmcore == NULL)
+ errx(1, "core file not specified");
cmdfile_name = strdup("/tmp/kgdb.XXXXXXXX");
if (cmdfile_name == NULL)
==== //depot/projects/gdb/usr.bin/kgdb/md_i386.c#2 (text+ko) ====
@@ -44,7 +44,7 @@
gdb_cpu_getreg(int regnum, size_t *regsz)
{
static register_t synth;
- struct trapframe *tf = curkthr->frame;
+ struct trapframe *tf = curkthr->td_frame;
*regsz = gdb_cpu_regsz(regnum);
switch (regnum) {
@@ -73,7 +73,7 @@
void
gdb_cpu_setreg(int regnum, register_t val)
{
- struct trapframe *tf = curkthr->frame;
+ struct trapframe *tf = curkthr->td_frame;
switch (regnum) {
case GDB_REG_PC: tf->tf_eip = val; break;
==== //depot/projects/gdb/usr.bin/kgdb/packet.c#2 (text+ko) ====
@@ -30,6 +30,7 @@
#include <sys/types.h>
#include <assert.h>
#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <kvm.h>
@@ -53,6 +54,114 @@
10 + (((c) < 'a') ? (c) - 'A' : (c) - 'a'))
#define N2C(n) (((n) < 10) ? (n) + '0' : (n) + 'a' - 10)
+static void
+gdb_packet(void)
+{
+ struct kthr *thr_iter;
+
+ thr_iter = NULL;
+ printf("GDB: got '%s'\n", gdb_rxp);
+ switch (gdb_rx_char()) {
+ case '?': /* Last signal. */
+ gdb_tx_begin('S');
+ gdb_tx_hex(gdb_cpu_signal(0, 0), 2);
+ gdb_tx_end();
+ break;
+ case 'g': { /* Read registers. */
+ size_t r;
+ gdb_tx_begin(0);
+ for (r = 0; r < GDB_NREGS; r++)
+ gdb_tx_reg(r);
+ gdb_tx_end();
+ break;
+ }
+ case 'G': /* Write registers. */
+ gdb_tx_err(0);
+ break;
+ case 'H': { /* Set thread. */
+ intmax_t tid;
+ struct kthr *thr;
+ gdb_rx_char();
+ gdb_rx_varhex(&tid);
+ if (tid > 0) {
+ thr = kgdb_thr_lookup(tid);
+ if (thr == NULL) {
+ gdb_tx_err(ENOENT);
+ break;
+ }
+ kgdb_thr_select(thr);
+ }
+ gdb_tx_ok();
+ break;
+ }
+ case 'm': { /* Read memory. */
+ uintmax_t addr, size;
+ if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' ||
+ gdb_rx_varhex(&size)) {
+ gdb_tx_err(EINVAL);
+ break;
+ }
+ gdb_tx_begin(0);
+ gdb_tx_mem((char *)(uintptr_t)addr, size);
+ gdb_tx_end();
+ break;
+ }
+ case 'M': /* Write memory. */
+ gdb_tx_err(0);
+ break;
+ case 'P': { /* Write register. */
+ uintmax_t reg, val;
+ if (gdb_rx_varhex(®) || gdb_rx_char() != '=' ||
+ gdb_rx_varhex(&val)) {
+ gdb_tx_err(EINVAL);
+ break;
+ }
+ gdb_cpu_setreg(reg, val);
+ gdb_tx_ok();
+ break;
+ }
+ case 'q': /* General query. */
+ if (gdb_rx_equal("fThreadInfo")) {
+ thr_iter = kgdb_thr_first();
+ gdb_tx_begin('m');
+ gdb_tx_hex(thr_iter->td_tid, 8);
+ gdb_tx_end();
+ } else if (gdb_rx_equal("sThreadInfo")) {
+ if (thr_iter == NULL) {
+ gdb_tx_err(ENXIO);
+ break;
+ }
+ thr_iter = kgdb_thr_next(thr_iter);
+ if (thr_iter != NULL) {
+ gdb_tx_begin('m');
+ gdb_tx_hex(thr_iter->td_tid, 8);
+ gdb_tx_end();
+ } else {
+ gdb_tx_begin('l');
+ gdb_tx_end();
+ }
+ } else if (!gdb_cpu_query())
+ gdb_tx_empty();
+ break;
+ case 'T': { /* Thread alive. */
+ intmax_t tid;
+ gdb_rx_varhex(&tid);
+ if (kgdb_thr_lookup(tid) != NULL)
+ gdb_tx_ok();
+ else
+ gdb_tx_err(ENOENT);
+ break;
+ }
+ case -1:
+ /* Empty command. Treat as unknown command. */
+ /* FALLTHROUGH */
+ default:
+ /* Unknown command. Send empty response. */
+ gdb_tx_empty();
+ break;
+ }
+}
+
/*
* Functions to receive and extract from a packet.
*/
More information about the p4-projects
mailing list