diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2002-06-05 18:02:28 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2002-06-05 18:02:28 +0000 |
commit | ab30ec96d98dd5f63998fac1e29d4c8b2a3d7c54 (patch) | |
tree | 62e7ca2cb98baddf1c0a57cb1f17f60762436582 /usr.bin | |
parent | f47bbb15f8e7e60f27c533327f0d2436fb1b4d9b (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/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/pmdb/core.c | 141 | ||||
-rw-r--r-- | usr.bin/pmdb/core.h | 44 | ||||
-rw-r--r-- | usr.bin/pmdb/pmdb.c | 62 | ||||
-rw-r--r-- | usr.bin/pmdb/pmdb.h | 9 |
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 |