示例#1
0
/*
 * Receive a packet.
 */
static int
kgdb_recv(u_char *bp, int maxlen)
{
	u_char *p;
	int c, csum, tmpcsum;
	int len;

	DPRINTF(("kgdb_recv:  "));
	do {
		p = bp;
		csum = len = 0;
		while ((c = GETC()) != KGDB_START)
			DPRINTF(("%c",c));
		DPRINTF(("%c Start ",c));

		while ((c = GETC()) != KGDB_END && len < maxlen) {
			DPRINTF(("%c",c));
			c &= 0x7f;
			csum += c;
			*p++ = c;
			len++;
		}
		csum &= 0xff;
		*p = '\0';
		DPRINTF(("%c End ", c));

		if (len >= maxlen) {
			DPRINTF(("Long- "));
			PUTC(KGDB_BADP);
			continue;
		}
		tmpcsum = csum;

		c = GETC();
		DPRINTF(("%c",c));
		csum -= digit2i(c) * 16;
		c = GETC();
		DPRINTF(("%c",c));
		csum -= digit2i(c);

		if (csum == 0) {
			DPRINTF(("Good+ "));
			PUTC(KGDB_GOODP);
			/* Sequence present? */
			if (bp[2] == ':') {
				DPRINTF(("Seq %c%c ", bp[0], bp[1]));
				PUTC(bp[0]);
				PUTC(bp[1]);
				len -= 3;
				kgdb_copy(bp + 3, bp, len);
			}
			break;
		}
		DPRINTF((" Bad(wanted %x, off by %d)- ", tmpcsum, csum));
		__USE(tmpcsum);
		PUTC(KGDB_BADP);
	} while (1);
	DPRINTF(("kgdb_recv: %s\n", bp));
	return (len);
}
示例#2
0
/*
 * Receive a packet.
 */
static int
kgdb_recv(u_char *bp, int maxlen)
{
	u_char *p;
	int c, csum;
	int len;

	do {
		p = bp;
		csum = len = 0;
		while ((c = GETC()) != KGDB_START)
			;

		while ((c = GETC()) != KGDB_END && len < maxlen) {
			c &= 0x7f;
			csum += c;
			*p++ = c;
			len++;
		}
		csum &= 0xff;
		*p = '\0';

		if (len >= maxlen) {
			PUTC(KGDB_BADP);
			continue;
		}

		csum -= digit2i(GETC()) * 16;
		csum -= digit2i(GETC());

		if (csum == 0) {
			PUTC(KGDB_GOODP);
			/* Sequence present? */
			if (bp[2] == ':') {
				PUTC(bp[0]);
				PUTC(bp[1]);
				len -= 3;
				kgdb_copy(bp + 3, bp, len);
			}
			break;
		}
		PUTC(KGDB_BADP);
	} while (1);
#ifdef	DEBUG_KGDB
	printf("kgdb_recv: %s\n", bp);
#endif
	return (len);
}
示例#3
0
/*
 * This function does all command procesing for interfacing to
 * a remote gdb.
 */
int
kgdb_trap(int type, struct frame *frame)
{
    u_long len;
    u_char *addr;
    u_char *cp;
    u_char out, in;
    int outlen;
    int inlen;
    u_long gdb_regs[NUM_REGS];

    if ((int)kgdb_dev < 0) {
        /* not debugging */
        return (0);
    }
    if (kgdb_active == 0) {
        if (type != T_TRAP15) {
            /* No debugger active -- let trap handle this. */
            return (0);
        }
        kgdb_getc = 0;
        for (inlen = 0; constab[inlen].cn_probe; inlen++)
            if (major(constab[inlen].cn_dev) == major(kgdb_dev)) {
                kgdb_getc = constab[inlen].cn_getc;
                kgdb_putc = constab[inlen].cn_putc;
                break;
            }
        if (kgdb_getc == 0 || kgdb_putc == 0)
            return (0);
        /*
         * If the packet that woke us up isn't an exec packet,
         * ignore it since there is no active debugger.  Also,
         * we check that it's not an ack to be sure that the
         * remote side doesn't send back a response after the
         * local gdb has exited.  Otherwise, the local host
         * could trap into gdb if it's running a gdb kernel too.
         */
        in = GETC;
        /*
         * If we came in asynchronously through the serial line,
         * the framing character is eaten by the receive interrupt,
         * but if we come in through a synchronous trap (i.e., via
         * kgdb_connect()), we will see the extra character.
         */
        if (in == FRAME_START)
            in = GETC;

        /*
         * Check that this is a debugger exec message.  If so,
         * slurp up the entire message then ack it, and fall
         * through to the recv loop.
         */
        if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0)
            return (0);
        while (GETC != FRAME_END)
            ;
        /*
         * Do the printf *before* we ack the message.  This way
         * we won't drop any inbound characters while we're
         * doing the polling printf.
         */
        printf("kgdb started from device %x\n", kgdb_dev);
        kgdb_send(in | KGDB_ACK, (u_char *)0, 0);
        kgdb_active = 1;
    }
    /*
     * Stick frame regs into our reg cache then tell remote host
     * that an exception has occurred.
     */
    regs_to_gdb(frame, gdb_regs);
    if (type != T_TRAP15) {
        /*
         * Only send an asynchronous SIGNAL message when we hit
         * a breakpoint.  Otherwise, we will drop the incoming
         * packet while we output this one (and on entry the other
         * side isn't interested in the SIGNAL type -- if it is,
         * it will have used a signal packet.)
         */
        outbuffer[0] = computeSignal(type);
        kgdb_send(KGDB_SIGNAL, outbuffer, 1);
    }

    while (1) {
        in = kgdb_recv(inbuffer, &inlen);
        if (in == 0 || (in & KGDB_ACK))
            /* Ignore inbound acks and error conditions. */
            continue;

        out = in | KGDB_ACK;
        switch (KGDB_CMD(in)) {

        case KGDB_SIGNAL:
            /*
             * if this command came from a running gdb,
             * answer it -- the other guy has no way of
             * knowing if we're in or out of this loop
             * when he issues a "remote-signal".  (Note
             * that without the length check, we could
             * loop here forever if the ourput line is
             * looped back or the remote host is echoing.)
             */
            if (inlen == 0) {
                outbuffer[0] = computeSignal(type);
                kgdb_send(KGDB_SIGNAL, outbuffer, 1);
            }
            continue;

        case KGDB_REG_R:
        case KGDB_REG_R | KGDB_DELTA:
            cp = outbuffer;
            outlen = 0;
            for (len = inbuffer[0]; len < NUM_REGS; ++len) {
                if (reg_cache[len] != gdb_regs[len] ||
                        (in & KGDB_DELTA) == 0) {
                    if (outlen + 5 > SL_MAXDATA) {
                        out |= KGDB_MORE;
                        break;
                    }
                    cp[outlen] = len;
                    kgdb_copy((u_char *)&gdb_regs[len],
                              &cp[outlen + 1], 4);
                    reg_cache[len] = gdb_regs[len];
                    outlen += 5;
                }
            }
            break;

        case KGDB_REG_W:
        case KGDB_REG_W | KGDB_DELTA:
            cp = inbuffer;
            for (len = 0; len < inlen; len += 5) {
                int j = cp[len];

                kgdb_copy(&cp[len + 1],
                          (u_char *)&gdb_regs[j], 4);
                reg_cache[j] = gdb_regs[j];
            }
            gdb_to_regs(frame, gdb_regs);
            outlen = 0;
            break;

        case KGDB_MEM_R:
            len = inbuffer[0];
            kgdb_copy(&inbuffer[1], (u_char *)&addr, 4);
            if (len > SL_MAXDATA) {
                outlen = 1;
                outbuffer[0] = E2BIG;
            } else if (!kgdb_acc(addr, len, B_READ)) {
                outlen = 1;
                outbuffer[0] = EFAULT;
            } else {
                outlen = len + 1;
                outbuffer[0] = 0;
                kgdb_copy(addr, &outbuffer[1], len);
            }
            break;

        case KGDB_MEM_W:
            len = inlen - 4;
            kgdb_copy(inbuffer, (u_char *)&addr, 4);
            outlen = 1;
            if (!kgdb_acc(addr, len, B_READ))
                outbuffer[0] = EFAULT;
            else {
                outbuffer[0] = 0;
                if (!kgdb_acc(addr, len, B_WRITE))
                    chgkprot(addr, len, B_WRITE);
                kgdb_copy(&inbuffer[4], addr, len);
                ICIA();
            }
            break;

        case KGDB_KILL:
            kgdb_active = 0;
            printf("kgdb detached\n");
        /* fall through */
        case KGDB_CONT:
            kgdb_send(out, 0, 0);
            frame->f_sr &=~ PSL_T;
            return (1);

        case KGDB_STEP:
            kgdb_send(out, 0, 0);
            frame->f_sr |= PSL_T;
            return (1);

        case KGDB_EXEC:
        default:
            /* Unknown command.  Ack with a null message. */
            outlen = 0;
            break;
        }
        /* Send the reply */
        kgdb_send(out, outbuffer, outlen);
    }
}
示例#4
0
static inline void
gdb_to_regs(struct frame *fp, u_long *regs)
{
    kgdb_copy((u_char *)regs, (u_char *)fp->f_regs, 16*4);
    kgdb_copy((u_char *)&regs[GDB_SR], (u_char *)&fp->f_stackadj, 2*4);
}