[BACK]Return to pmdb.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / pmdb

Annotation of src/usr.bin/pmdb/pmdb.c, Revision 1.1

1.1     ! art         1: /*     $PMDB: pmdb.c,v 1.41 2002/03/12 14:24:30 art Exp $      */
        !             2: /*
        !             3:  * Copyright (c) 2002 Artur Grabowski <art@openbsd.org>
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  *
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. The name of the author may not be used to endorse or promote products
        !            13:  *    derived from this software without specific prior written permission.
        !            14:  *
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
        !            16:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
        !            17:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
        !            18:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
        !            19:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
        !            21:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        !            22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
        !            23:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
        !            24:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            25:  */
        !            26:
        !            27: #include <sys/types.h>
        !            28: #include <sys/ptrace.h>
        !            29: #include <sys/wait.h>
        !            30:
        !            31: #include <stdlib.h>
        !            32: #include <stdio.h>
        !            33: #include <unistd.h>
        !            34: #include <signal.h>
        !            35: #include <err.h>
        !            36: #include <errno.h>
        !            37: #include <string.h>
        !            38:
        !            39: #include <sys/endian.h>
        !            40:
        !            41: #include "pmdb.h"
        !            42: #include "symbol.h"
        !            43: #include "clit.h"
        !            44: #include "break.h"
        !            45:
        !            46: static int cmd_show_registers(int, char **, void *);
        !            47: static int cmd_show_backtrace(int, char **, void *);
        !            48: static int cmd_quit(int, char **, void *);
        !            49:
        !            50: struct clit cmds[] = {
        !            51:        /* debugging info commands. */
        !            52:        { "regs", "show registers", 0, 0, cmd_show_registers, (void *)-1 },
        !            53:        { "trace", "show backtrace", 0, 0, cmd_show_backtrace, (void *)-1 },
        !            54:
        !            55:        /* Process handling commands. */
        !            56:        { "run", "run process", 0, 0, cmd_process_run, (void *)-1 },
        !            57:        { "continue", "continue process", 0, 0, cmd_process_cont, (void *)-1 },
        !            58:        { "kill", "kill process", 0, 0, cmd_process_kill, (void *)-1 },
        !            59:
        !            60:        /* signal handling commands. */
        !            61:        { "signal", "ignore signal", 2, 2, cmd_signal_ignore, (void *)-1 },
        !            62:        { "sigstate", "show signal state", 0, 0, cmd_signal_show, (void *)-1 },
        !            63:
        !            64:        /* breakpoints */
        !            65:        { "break", "set breakpoint", 1, 1, cmd_bkpt_add, (void *)-1 },
        !            66:        { "step", "single step one insn", 0, 0, cmd_sstep, (void *)-1 },
        !            67:
        !            68:        /* misc commands. */
        !            69:        { "help", "print help", 0, 1, cmd_help, NULL },
        !            70:        { "quit", "quit", 0, 0, cmd_quit, (void *)-1 },
        !            71:        { "exit", "quit", 0, 0, cmd_quit, (void *)-1 },
        !            72: };
        !            73:
        !            74: int
        !            75: main(int argc, char **argv)
        !            76: {
        !            77:        extern const char *__progname;
        !            78:        struct pstate ps;
        !            79:        int i, ncmds;
        !            80:        int status;
        !            81:        void *cm;
        !            82:        char *pmenv;
        !            83:        int level;
        !            84:
        !            85:        if (argc < 2) {
        !            86:                fprintf(stderr, "Usage: %s <program> args\n", __progname);
        !            87:                exit(1);
        !            88:        }
        !            89:
        !            90:        if ((pmenv = getenv("IN_PMDB")) != NULL) {
        !            91:                level = atoi(pmenv);
        !            92:                level++;
        !            93:        } else
        !            94:                level = 0;
        !            95:
        !            96:        if (level > 0)
        !            97:                asprintf(&prompt_add, "(%d)", level);
        !            98:        asprintf(&pmenv, "%d", level);
        !            99:        setenv("IN_PMDB", pmenv, 1);
        !           100:
        !           101:        ps.ps_pid = 0;
        !           102:        ps.ps_state = NONE;
        !           103:        ps.ps_argc = --argc;
        !           104:        ps.ps_argv = ++argv;
        !           105:        ps.ps_flags = 0;
        !           106:        ps.ps_signum = 0;
        !           107:        ps.ps_npc = 1;
        !           108:        TAILQ_INIT(&ps.ps_bkpts);
        !           109:        TAILQ_INIT(&ps.ps_sstep_cbs);
        !           110:
        !           111:        signal(SIGINT, SIG_IGN);
        !           112:
        !           113:        ncmds = sizeof(cmds)/sizeof(cmds[0]);
        !           114:
        !           115:        for (i = 0; i < ncmds; i++)
        !           116:                if (cmds[i].arg == (void *)-1)
        !           117:                        cmds[i].arg = &ps;
        !           118:
        !           119:        md_def_init();
        !           120:        init_sigstate(&ps);
        !           121:
        !           122:        process_load(&ps);
        !           123:
        !           124:        cm = cmdinit(cmds, ncmds);
        !           125:        while (ps.ps_state != TERMINATED) {
        !           126:                int signum;
        !           127:                int stopped;
        !           128:                int cont;
        !           129:
        !           130:                if (ps.ps_state == STOPPED) {
        !           131:                        sym_update(&ps);
        !           132:                }
        !           133:
        !           134:                if (ps.ps_state != RUNNING && cmdloop(cm) == 0) {
        !           135:                        cmd_quit(0, NULL, &ps);
        !           136:                }
        !           137:
        !           138:                if (ps.ps_state == TERMINATED)
        !           139:                        break;
        !           140:
        !           141:                if (wait(&status) == 0)
        !           142:                        err(1, "wait");
        !           143:                if (WIFEXITED(status)) {
        !           144:                        if ((ps.ps_flags & PSF_KILL) == 0) {
        !           145:                                ps.ps_state = NONE;
        !           146:                        } else {
        !           147:                                ps.ps_state = TERMINATED;
        !           148:                        }
        !           149:                        fprintf(stderr, "process exited with status %d\n",
        !           150:                            WEXITSTATUS(status));
        !           151:                        continue;
        !           152:                }
        !           153:                if (WIFSIGNALED(status)) {
        !           154:                        signum = WTERMSIG(status);
        !           155:                        stopped = 0;
        !           156:                } else {
        !           157:                        signum = WSTOPSIG(status);
        !           158:                        stopped = 1;
        !           159:                }
        !           160:                cont = 0;
        !           161:                if (stopped)
        !           162:                        cont = bkpt_check(&ps);
        !           163:                process_signal(&ps, signum, stopped, cont);
        !           164:        }
        !           165:
        !           166:        cmdend(cm);
        !           167:
        !           168:        sym_destroy(&ps);
        !           169:
        !           170:        return (0);
        !           171: }
        !           172:
        !           173: /* XXX - move to some other file. */
        !           174: int
        !           175: read_from_pid(pid_t pid, off_t from, void *to, size_t size)
        !           176: {
        !           177:        struct ptrace_io_desc piod;
        !           178:
        !           179:        piod.piod_op = PIOD_READ_D;
        !           180:        piod.piod_offs = (void *)(long)from;
        !           181:        piod.piod_addr = to;
        !           182:        piod.piod_len = size;
        !           183:
        !           184:        return (ptrace(PT_IO, pid, (caddr_t)&piod, 0) != size);
        !           185: }
        !           186:
        !           187:
        !           188: int
        !           189: write_to_pid(pid_t pid, off_t to, void *from, size_t size)
        !           190: {
        !           191:        struct ptrace_io_desc piod;
        !           192:
        !           193:        piod.piod_op = PIOD_WRITE_D;
        !           194:        piod.piod_offs = (void *)(long)to;
        !           195:        piod.piod_addr = from;
        !           196:        piod.piod_len = size;
        !           197:
        !           198:        return (ptrace(PT_IO, pid, (caddr_t)&piod, 0) != size);
        !           199: }
        !           200:
        !           201: static int
        !           202: cmd_show_registers(int argc, char **argv, void *arg)
        !           203: {
        !           204:        struct pstate *ps = arg;
        !           205:        char buf[256];
        !           206:        int i;
        !           207:        reg *rg;
        !           208:
        !           209:        if (ps->ps_state != STOPPED) {
        !           210:                fprintf(stderr, "process not stopped\n");
        !           211:                return 0;
        !           212:        }
        !           213:
        !           214:        rg = alloca(sizeof(*rg) * md_def.nregs);
        !           215:
        !           216:        if (md_getregs(ps, rg))
        !           217:                err(1, "can't get registers");
        !           218:        for (i = 0; i < md_def.nregs; i++)
        !           219:                printf("%s:\t0x%.*lx\t%s\n", md_def.md_reg_names[i],
        !           220:                    (int)(sizeof(reg) * 2), (long)rg[i],
        !           221:                    sym_print(ps, rg[i], buf, sizeof(buf)));
        !           222:        return 0;
        !           223: }
        !           224:
        !           225: static int
        !           226: cmd_show_backtrace(int argc, char **argv, void *arg)
        !           227: {
        !           228:        struct pstate *ps = arg;
        !           229:        int i;
        !           230:
        !           231:        if (ps->ps_state != STOPPED) {
        !           232:                fprintf(stderr, "process not stopped\n");
        !           233:                return 0;
        !           234:        }
        !           235:
        !           236:        /* no more than 100 frames */
        !           237:        for (i = 0; i < 100; i++) {
        !           238:                struct md_frame mfr;
        !           239:                char namebuf[1024], *name;
        !           240:                reg offs;
        !           241:                int j;
        !           242:
        !           243:                mfr.nargs = -1;
        !           244:
        !           245:                if (md_getframe(ps, i, &mfr))
        !           246:                        break;
        !           247:
        !           248:                name = sym_name_and_offset(ps, mfr.pc, namebuf,
        !           249:                    sizeof(namebuf), &offs);
        !           250:                if (name == NULL) {
        !           251:                        snprintf(namebuf, sizeof(namebuf), "0x%lx", mfr.pc);
        !           252:                        name = namebuf;
        !           253:                }
        !           254:
        !           255:                printf("%s(", name);
        !           256:                for (j = 0; j < mfr.nargs; j++) {
        !           257:                        printf("0x%lx", mfr.args[j]);
        !           258:                        if (j < mfr.nargs - 1)
        !           259:                                printf(", ");
        !           260:                }
        !           261:                printf(")+0x%lx\n", offs);
        !           262:        }
        !           263:        return 0;
        !           264: }
        !           265:
        !           266: static int
        !           267: cmd_quit(int argc, char **argv, void *arg)
        !           268: {
        !           269:        struct pstate *ps = arg;
        !           270:
        !           271:        ps->ps_flags |= PSF_KILL;
        !           272:
        !           273:        if (process_kill(ps))
        !           274:                return 1;
        !           275:
        !           276:        ps->ps_state = TERMINATED;
        !           277:        return 1;
        !           278: }
        !           279:
        !           280: /*
        !           281:  * Perform command completion.
        !           282:  * Pretty simple. if there are spaces in "buf", the last string is a symbol
        !           283:  * otherwise it's a command.
        !           284:  */
        !           285: int
        !           286: cmd_complt(char *buf, size_t buflen)
        !           287: {
        !           288:        struct clit *match;
        !           289:        char *start;
        !           290:        int command;
        !           291:        int i, j, len;
        !           292:        int onlymatch;
        !           293:
        !           294:        command = (strchr(buf, ' ') == NULL);
        !           295:
        !           296:        if (!command) {
        !           297:                /* XXX - can't handle symbols yet. */
        !           298:                return -1;
        !           299:        }
        !           300:
        !           301:        start = buf;
        !           302:        len = strlen(buf);
        !           303:
        !           304:        match = NULL;
        !           305:        for (i = 0; i < sizeof(cmds) / sizeof(cmds[i]); i++) {
        !           306:                if (strncmp(start, cmds[i].cmd, len) == 0) {
        !           307:                        struct clit *cmdp;
        !           308:
        !           309:                        cmdp = &cmds[i];
        !           310:                        if (match == NULL) {
        !           311:                                onlymatch = 1;
        !           312:                                match = cmdp;
        !           313:                                strlcpy(buf, match->cmd, buflen);
        !           314:                                continue;
        !           315:                        }
        !           316:                        onlymatch = 0;
        !           317:                        for (j = len; j < buflen; j++) {
        !           318:                                if (buf[j] != cmdp->cmd[j]) {
        !           319:                                        buf[j] = '\0';
        !           320:                                        break;
        !           321:                                }
        !           322:                                if (cmdp->cmd[j] == '\0')
        !           323:                                        break;
        !           324:                        }
        !           325:                }
        !           326:        }
        !           327:
        !           328:        /*
        !           329:         * Be nice. If there could be arguments for this command and it's
        !           330:         * the only match append a space.
        !           331:         */
        !           332:        if (match && onlymatch /*&& match->maxargc > 0*/)
        !           333:                strlcat(buf, " ", buflen);
        !           334:
        !           335:        return (match && onlymatch) ? 0 : -1;
        !           336: }
        !           337:
        !           338: /*
        !           339:  * The "stadard" wrapper
        !           340:  */
        !           341: void *
        !           342: emalloc(size_t sz)
        !           343: {
        !           344:        void *ret;
        !           345:        if ((ret = malloc(sz)) == NULL)
        !           346:                err(1, "malloc");
        !           347:        return (ret);
        !           348: }