int
gdb_rx_begin(void)
{
	int c, cksum;

	gdb_rxp = NULL;
	do {
		/*
		 * Wait for the start character, ignore all others.
		 * XXX needs a timeout.
		 */
		while ((c = gdb_getc()) != '$')
			;

		/* Read until a # or end of buffer is found. */
		cksum = 0;
		gdb_rxsz = 0;
		while (gdb_rxsz < sizeof(gdb_rxbuf) - 1) {
			c = gdb_getc();
			if (c == '#')
				break;
			gdb_rxbuf[gdb_rxsz++] = c;
			cksum += c;
		}
		gdb_rxbuf[gdb_rxsz] = 0;
		cksum &= 0xff;

		/* Bail out on a buffer overflow. */
		if (c != '#') {
			gdb_cur->gdb_putc('-');
			return (ENOSPC);
		}

		c = gdb_getc();
		cksum -= (C2N(c) << 4) & 0xf0;
		c = gdb_getc();
		cksum -= C2N(c) & 0x0f;
		gdb_cur->gdb_putc((cksum == 0) ? '+' : '-');
		if (cksum != 0)
			printf("GDB: packet `%s' has invalid checksum\n",
			    gdb_rxbuf);
	} while (cksum != 0);

	gdb_rxp = gdb_rxbuf;
	return (0);
}
Exemple #2
0
static int run(struct gdb_data *data, char *buf)
{
	printc("Running\n");

	if (run_set_pc(data, buf) < 0 ||
	    device_ctl(DEVICE_CTL_RUN) < 0)
		return gdb_send(data, "E00");

	for (;;) {
		device_status_t status = device_poll();

		if (status == DEVICE_STATUS_ERROR)
			return gdb_send(data, "E00");

		if (status == DEVICE_STATUS_HALTED) {
			printc("Target halted\n");
			goto out;
		}

		if (status == DEVICE_STATUS_INTR)
			goto out;

		while (gdb_peek(data, 0)) {
			int c = gdb_getc(data);

			if (c < 0)
				return -1;

			if (c == 3) {
				printc("Interrupted by gdb\n");
				goto out;
			}
		}
	}

 out:
	if (device_ctl(DEVICE_CTL_HALT) < 0)
		return gdb_send(data, "E00");

	return run_final_status(data);
}
int
gdb_tx_end(void)
{
	const char *p;
	int runlen;
	unsigned char c, cksum;

	do {
		gdb_cur->gdb_putc('$');

		cksum = 0;
		p = gdb_txbuf;
		while (p < gdb_txp) {
			/* Send a character and start run-length encoding. */
			c = *p++;
			gdb_cur->gdb_putc(c);
			cksum += c;
			runlen = 0;
			/* Determine run-length and update checksum. */
			while (p < gdb_txp && *p == c) {
				runlen++;
				p++;
			}
			/* Emit the run-length encoded string. */
			while (runlen >= 97) {
				gdb_cur->gdb_putc('*');
				cksum += '*';
				gdb_cur->gdb_putc(97+29);
				cksum += 97+29;
				runlen -= 97;
				if (runlen > 0) {
					gdb_cur->gdb_putc(c);
					cksum += c;
					runlen--;
				}
			}
			if (runlen == 1) {
				gdb_cur->gdb_putc(c);
				cksum += c;
				runlen--;
			}
			if (runlen == 0)
				continue;
			/* Don't emit '$', '#', '+' or '-'. */
			if (runlen == 7) {
				gdb_cur->gdb_putc(c);
				cksum += c;
				runlen--;
			}
			if (runlen == 6 || runlen == 14 || runlen == 16) {
				gdb_cur->gdb_putc(c);
				cksum += c;
				runlen--;
			}
			gdb_cur->gdb_putc('*');
			cksum += '*';
			gdb_cur->gdb_putc(runlen+29);
			cksum += runlen+29;
		}

		gdb_cur->gdb_putc('#');
		c = cksum >> 4;
		gdb_cur->gdb_putc(N2C(c));
		c = cksum & 0x0f;
		gdb_cur->gdb_putc(N2C(c));

		c = gdb_getc();
	} while (c != '+');

	return (0);
}