summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2002-06-05 18:02:28 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2002-06-05 18:02:28 +0000
commitab30ec96d98dd5f63998fac1e29d4c8b2a3d7c54 (patch)
tree62e7ca2cb98baddf1c0a57cb1f17f60762436582 /usr.bin
parentf47bbb15f8e7e60f27c533327f0d2436fb1b4d9b (diff)
core support from Jean-Francois Brousseau <krapht@secureops.com> with
a few tweaks of mine. tested on sparc64 and i386.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/pmdb/Makefile4
-rw-r--r--usr.bin/pmdb/core.c141
-rw-r--r--usr.bin/pmdb/core.h44
-rw-r--r--usr.bin/pmdb/pmdb.c62
-rw-r--r--usr.bin/pmdb/pmdb.h9
5 files changed, 242 insertions, 18 deletions
diff --git a/usr.bin/pmdb/Makefile b/usr.bin/pmdb/Makefile
index 8f19d4e175d..aa76fc8c8f6 100644
--- a/usr.bin/pmdb/Makefile
+++ b/usr.bin/pmdb/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.6 2002/05/11 00:20:20 espie Exp $
+# $OpenBSD: Makefile,v 1.7 2002/06/05 18:02:27 fgsch Exp $
.include <bsd.own.mk>
@@ -9,7 +9,7 @@ NOPROG=no, man
.else
PROG=pmdb
-SRCS=pmdb.c symbol.c clit.c process.c signal.c break.c
+SRCS=pmdb.c symbol.c clit.c process.c signal.c break.c core.c
# support for NetBSD
.if defined(OBJECT_FMT)
diff --git a/usr.bin/pmdb/core.c b/usr.bin/pmdb/core.c
new file mode 100644
index 00000000000..761274890d1
--- /dev/null
+++ b/usr.bin/pmdb/core.c
@@ -0,0 +1,141 @@
+/* $OpenBSD: core.c,v 1.1 2002/06/05 18:02:27 fgsch Exp $ */
+/*
+ * Copyright (c) 2002 Jean-Francois Brousseau <krapht@secureops.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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/param.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "core.h"
+#include "pmdb.h"
+
+int
+read_core(const char *path, struct pstate *ps)
+{
+ struct corefile *cf;
+ void *core_map;
+ off_t c_off;
+ int i, cfd;
+
+ cf = (struct corefile *)malloc(sizeof(*cf));
+ if (cf == NULL)
+ err(1, "malloc");
+
+ cfd = open(path, O_RDONLY, 0600);
+ if (cfd < 0)
+ err(1, "open() failed on core file");
+
+ if (fstat(cfd, &(cf->cfstat)) < 0)
+ err(1, "fstat() failed on core");
+
+ if (cf->cfstat.st_mtimespec.tv_sec < ps->exec_stat.st_mtimespec.tv_sec)
+ warnx("executable is more recent than core file!");
+
+ core_map = mmap(NULL, cf->cfstat.st_size, PROT_READ, MAP_SHARED,
+ cfd, 0);
+ if (core_map == MAP_FAILED)
+ err(1, "mmap() failed on core");
+
+ cf->chdr = (struct core *)core_map;
+ c_off = cf->chdr->c_hdrsize;
+ if (CORE_GETMAGIC(*(cf->chdr)) != COREMAGIC)
+ errx(1, "hey, that's not a core file");
+
+ printf("Core file generated from '%s' by signal %d (SIG%s)\n",
+ cf->chdr->c_name, cf->chdr->c_signo,
+ sys_signame[cf->chdr->c_signo]);
+
+#ifdef DEBUG
+ printf("Core: text=0x%lx, data=0x%lx, stack=0x%lx\n",
+ cf->chdr->c_tsize, cf->chdr->c_dsize, cf->chdr->c_ssize);
+#endif
+
+ cf->segs = (struct coreseg **)calloc(cf->chdr->c_nseg,
+ sizeof(cf->segs));
+ if (cf->segs == NULL)
+ err(1, "calloc");
+
+ for (i = 0; i < cf->chdr->c_nseg; i++) {
+ cf->segs[i] = (struct coreseg *)(core_map + c_off);
+ if (CORE_GETMAGIC(*(cf->segs[i])) != CORESEGMAGIC)
+ errx(1, "invalid segment hdr for segment %d", i);
+
+ if (CORE_GETFLAG(*(cf->segs[i])) & CORE_CPU) {
+ cf->regs = (struct reg *)
+ ((long) cf->segs[i] + cf->chdr->c_seghdrsize);
+ }
+
+ if (CORE_GETFLAG(*(cf->segs[i])) & CORE_STACK)
+ cf->c_stack = cf->segs[i] + cf->chdr->c_seghdrsize;
+
+ c_off += cf->chdr->c_seghdrsize + cf->segs[i]->c_size;
+
+#ifdef DEBUG
+ (void)printf("seg[%d]: midmag=0x%lx addr=0x%lx size=0x%lx\n",
+ i, cf->segs[i]->c_midmag, cf->segs[i]->c_addr,
+ cf->segs[i]->c_size);
+#endif
+ }
+
+ cf->path = (char *)path;
+ ps->ps_flags |= PSF_CORE;
+ ps->ps_core = cf;
+
+ return (0);
+}
+
+void
+free_core(struct pstate *ps)
+{
+ struct corefile *cf = ps->ps_core;
+
+ if (cf == NULL)
+ return;
+
+ if (cf->segs != NULL) {
+ free(cf->segs);
+ cf->segs = NULL;
+ }
+}
+
+void
+core_printregs(struct corefile *cf)
+{
+ reg *rg;
+ int i;
+
+ rg = (reg *)cf->regs;
+ for (i = 0; i < md_def.nregs; i++)
+ printf("%s:\t0x%.*lx\n", md_def.md_reg_names[i],
+ (int)(sizeof(reg) * 2), (long) rg[i]);
+}
diff --git a/usr.bin/pmdb/core.h b/usr.bin/pmdb/core.h
new file mode 100644
index 00000000000..520c2716549
--- /dev/null
+++ b/usr.bin/pmdb/core.h
@@ -0,0 +1,44 @@
+/* $OpenBSD: core.h,v 1.1 2002/06/05 18:02:27 fgsch Exp $ */
+/*
+ * Copyright (c) 2002 Jean-Francois Brousseau <krapht@secureops.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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/param.h>
+#include <sys/core.h>
+#include <sys/stat.h>
+
+struct pstate;
+
+struct corefile {
+ char *path;
+ struct stat cfstat;
+ struct core *chdr; /* core header */
+ struct coreseg **segs;
+ struct reg *regs;
+ void *c_stack; /* pointer to the top of the stack */
+};
+
+int read_core(const char *, struct pstate *);
+void free_core(struct pstate *);
+void core_printregs(struct corefile *);
diff --git a/usr.bin/pmdb/pmdb.c b/usr.bin/pmdb/pmdb.c
index 481c39c54d9..43a8ae790f2 100644
--- a/usr.bin/pmdb/pmdb.c
+++ b/usr.bin/pmdb/pmdb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmdb.c,v 1.6 2002/03/19 23:17:58 fgsch Exp $ */
+/* $OpenBSD: pmdb.c,v 1.7 2002/06/05 18:02:27 fgsch Exp $ */
/*
* Copyright (c) 2002 Artur Grabowski <art@openbsd.org>
* All rights reserved.
@@ -27,6 +27,7 @@
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
+#include <sys/endian.h>
#include <stdlib.h>
#include <stdio.h>
@@ -36,12 +37,11 @@
#include <errno.h>
#include <string.h>
-#include <sys/endian.h>
-
#include "pmdb.h"
#include "symbol.h"
#include "clit.h"
#include "break.h"
+#include "core.h"
static int cmd_show_registers(int, char **, void *);
static int cmd_show_backtrace(int, char **, void *);
@@ -76,22 +76,45 @@ struct clit cmds[] = {
#define NCMDS sizeof(cmds)/sizeof(cmds[0])
+void
+usage()
+{
+ extern char *__progname;
+
+ fprintf(stderr, "Usage: %s [-c core] <program> args\n", __progname);
+ exit(1);
+}
+
int
main(int argc, char **argv)
{
- extern const char *__progname;
struct pstate ps;
- int i;
+ int i, c;
int status;
void *cm;
- char *pmenv;
+ char *pmenv, *core;
int level;
if (argc < 2) {
- fprintf(stderr, "Usage: %s <program> args\n", __progname);
- exit(1);
+ usage();
}
+ core = NULL;
+
+ while ((c = getopt(argc, argv, "c:")) != -1) {
+ switch(c) {
+ case 'c':
+ core = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
if ((pmenv = getenv("IN_PMDB")) != NULL) {
level = atoi(pmenv);
level++;
@@ -105,8 +128,8 @@ main(int argc, char **argv)
ps.ps_pid = 0;
ps.ps_state = NONE;
- ps.ps_argc = --argc;
- ps.ps_argv = ++argv;
+ ps.ps_argc = argc;
+ ps.ps_argv = argv;
ps.ps_flags = 0;
ps.ps_signum = 0;
ps.ps_npc = 1;
@@ -124,6 +147,9 @@ main(int argc, char **argv)
process_load(&ps);
+ if (core != NULL)
+ read_core(core, &ps);
+
cm = cmdinit(cmds, NCMDS);
while (ps.ps_state != TERMINATED) {
int signum;
@@ -210,8 +236,13 @@ cmd_show_registers(int argc, char **argv, void *arg)
reg *rg;
if (ps->ps_state != STOPPED) {
+ if (ps->ps_flags & PSF_CORE) {
+ /* dump registers from core */
+ core_printregs(ps->ps_core);
+ return (0);
+ }
fprintf(stderr, "process not stopped\n");
- return 0;
+ return (0);
}
rg = alloca(sizeof(*rg) * md_def.nregs);
@@ -222,7 +253,7 @@ cmd_show_registers(int argc, char **argv, void *arg)
printf("%s:\t0x%.*lx\t%s\n", md_def.md_reg_names[i],
(int)(sizeof(reg) * 2), (long)rg[i],
sym_print(ps, rg[i], buf, sizeof(buf)));
- return 0;
+ return (0);
}
static int
@@ -233,7 +264,7 @@ cmd_show_backtrace(int argc, char **argv, void *arg)
if (ps->ps_state != STOPPED) {
fprintf(stderr, "process not stopped\n");
- return 0;
+ return (0);
}
/* no more than 100 frames */
@@ -268,7 +299,8 @@ cmd_show_backtrace(int argc, char **argv, void *arg)
printf(")+0x%lx\n", offs);
}
}
- return 0;
+
+ return (0);
}
static int
@@ -344,7 +376,7 @@ cmd_complt(char *buf, size_t buflen)
}
/*
- * The "stadard" wrapper
+ * The "standard" wrapper
*/
void *
emalloc(size_t sz)
diff --git a/usr.bin/pmdb/pmdb.h b/usr.bin/pmdb/pmdb.h
index 055201ecf81..d5aeec0e511 100644
--- a/usr.bin/pmdb/pmdb.h
+++ b/usr.bin/pmdb/pmdb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmdb.h,v 1.2 2002/03/15 16:41:06 jason Exp $ */
+/* $OpenBSD: pmdb.h,v 1.3 2002/06/05 18:02:27 fgsch Exp $ */
/*
* Copyright (c) 2002 Artur Grabowski <art@openbsd.org>
* All rights reserved.
@@ -27,6 +27,8 @@
#include <sys/signal.h> /* for NSIG */
#include <sys/queue.h>
#include <sys/ptrace.h>
+#include <sys/stat.h>
+
#include <err.h>
/* XXX - ugh, yuck, bleah. */
@@ -40,6 +42,7 @@
struct breakpoint;
struct callback;
+struct corefile;
struct sym_table;
struct sym_ops;
@@ -59,6 +62,8 @@ struct pstate {
TAILQ_HEAD(,sym_table) ps_syms; /* all symbols tables in a list */
struct sym_table *ps_sym_exe; /* symbol table for the executable */
struct sym_ops *ps_sops; /* operations on symbol tables */
+ struct stat exec_stat; /* stat of the exec file */
+ struct corefile *ps_core; /* core file data */
TAILQ_HEAD(,breakpoint) ps_bkpts; /* breakpoints */
TAILQ_HEAD(,callback) ps_sstep_cbs; /* single step actions */
};
@@ -67,6 +72,8 @@ struct pstate {
#define PSF_SYMBOLS 0x02 /* basic symbols loaded */
#define PSF_KILL 0x04 /* kill this process asap */
#define PSF_STEP 0x08 /* next continue should sstep */
+#define PSF_CORE 0x10 /* core file loaded */
+#define PSF_ATCH 0x20 /* process attached with PT_ATTACH */
/* ps_sigstate */
#define SS_STOP 0x00