Esempio n. 1
0
int dram_main(int argc, char *argv)
{
  /* Here we have a in memory value we can change in the debugger
   * to begin booting in NOR Flash
   */

  static volatile uint32_t wait = DRAM_BOOT_MODE;
  int ret;

  /* Disable the PMC.  This is necessary on the SAMA5D4-MB Rev C. board.  On
   * that board, the PMIC can lock up the I2C bus.  The work around is
   * awkward:
   *
   *   1. Open JP23 (disabling the WM8904 data line)
   *   2. Execute DRAMBOOT.  The WM8904 will be disabled while JP23 is open.
   *   3. At the prompt to "Send the Intel HEX file now", close JP23,
   *      enabling the WM8904.
   *   4. Send the NuttX file.  When NuttX starts, the WM8904 is initialized,
   *      JP23 will be closed and the PMIC will be initialized.
   */

  sam_pmic_initialize();

  /* DRAM was already initialized at boot time, so we are ready to load the
   * Intel HEX stream into DRAM.
   *
   * Hmm.. With no hardware handshake, there is a possibility of data loss
   * to overrunning incoming data buffer.  So far I have not seen this at
   * 115200 8N1, but still it is a possibility.
   */

  printf("Send Intel HEX file now\n");
  fflush(stdout);

  ret = hex2mem(0,                           /* Accept Intel HEX on stdin */
                (uint32_t)SAM_DDRCS_VSECTION,
                (uint32_t)(SAM_DDRCS_VSECTION + CONFIG_SAMA5_DDRCS_SIZE),
                0);
  if (ret < 0)
    {
      /* We failed the load */

      printf("ERROR: Intel HEX file load failed: %d\n", ret);
      fflush(stdout);
      for(;;);
    }

  /* No success indication.. The following cache/MMU operations will clobber
   * any I/O that we attempt (Hmm.. unless, perhaps, if we delayed.  But who
   * wants a delay?).
   */

  /* Flush the entire data cache assure that everything is in memory before
   * we disable caching.
   */

  arch_clean_dcache((uintptr_t)SAM_DDRCS_VSECTION,
                    (uintptr_t)(SAM_DDRCS_VSECTION + CONFIG_SAMA5_DDRCS_SIZE));

  /* Interrupts must be disabled through the following.  In this configuration,
   * there should only be timer interrupts.  Your NuttX configuration must use
   * CONFIG_SERIAL_LOWCONSOLE=y or printf() will hang when the interrupts
   * are disabled!
   */

  (void)up_irq_save();

  /* Disable the caches and the MMU.  Disabling the MMU should be safe here
   * because there is a 1-to-1 identity mapping between the physical and
   * virtual addressing.
   */

  cp15_disable_mmu();
  cp15_disable_caches();

  /* Invalidate caches and TLBs */

  cp15_invalidate_icache();
  cp15_invalidate_dcache_all();
  cp15_invalidate_tlbs();

  /* Then jump into NOR flash */

  while (wait)
    {
    }

  DRAM_ENTRY();

  return 0; /* We should not get here in either case */
}
Esempio n. 2
0
/*
 * This function does all command procesing for interfacing to gdb.
 */
void gdb_stub_handler(int exception_vector)
{
  int    sigval;
  int    addr, length;
  char * ptr;

#ifdef GDB_REMOTE_UDP
  gdb_udp_poll_start();
#endif /* GDB_REMOTE_UDP */
  
  if(remote_debug) 
	  GDB_PRINTF("vector=%d, ps=0x%x, pc=0x%x\n", exception_vector, gdb_registers[PS], gdb_registers[PC]);

  /* reply to host that an exception has occurred */
  sigval = compute_signal(exception_vector);
  remcomOutBuffer[0] = 'S';
  remcomOutBuffer[1] =  hexchars[sigval >> 4];
  remcomOutBuffer[2] =  hexchars[sigval % 16];
  remcomOutBuffer[3] = 0;

  if(remote_debug)
	  GDB_PRINTF("GDB send packet: %s\n", remcomOutBuffer);
  gdb_put_packet(remcomOutBuffer);

  while (1) {
    remcomOutBuffer[0] = 0;
    gdb_get_packet(remcomInBuffer);
	if(remote_debug)
		GDB_PRINTF("GDB reveive packet: %s\n", remcomInBuffer);
    switch (remcomInBuffer[0]) {
      case '?' :   remcomOutBuffer[0] = 'S';
                   remcomOutBuffer[1] =  hexchars[sigval >> 4];
                   remcomOutBuffer[2] =  hexchars[sigval % 16];
                   remcomOutBuffer[3] = 0;
                 break;
      case 'd' : remote_debug = !(remote_debug);  /* toggle debug flag */
                 break;
      case 'g' : /* return the value of the CPU registers */
                mem2hex((char*) gdb_registers, remcomOutBuffer, NUMREGBYTES, 0);
                break;
      case 'G' : /* set the value of the CPU registers - return OK */
                hex2mem(&remcomInBuffer[1], (char*) gdb_registers, NUMREGBYTES, 0);
                gdb_strcpy(remcomOutBuffer,"OK");
                break;

      /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
      case 'm' :
		    /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
				ptr = &remcomInBuffer[1];
				if (hex2int(&ptr,&addr))
					if (*(ptr++) == ',')
						if (hex2int(&ptr,&length))
						{
							ptr = 0;
							mem_err = 0;
                            mem2hex((char*) addr, remcomOutBuffer, length, 1);

							if (mem_err) {
								gdb_strcpy (remcomOutBuffer, "E03");
								if(remote_debug)
									GDB_PRINTF("memory fault");
							}
                        }

				if (ptr)
				{
				  gdb_strcpy(remcomOutBuffer,"E01");
				  if(remote_debug)
					  GDB_PRINTF("malformed read memory command: %s",remcomInBuffer);
				}
	          break;

      /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
      case 'M' :
		    /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
			ptr = &remcomInBuffer[1];
			if (hex2int(&ptr,&addr))
				if (*(ptr++) == ',')
					if (hex2int(&ptr,&length))
						if (*(ptr++) == ':')
						{
							mem_err = 0;
							hex2mem(ptr, (char*) addr, length, 1);

							if (mem_err) {
							gdb_strcpy (remcomOutBuffer, "E03");
							if(remote_debug)
								GDB_PRINTF("memory fault");
							} else {
								gdb_strcpy(remcomOutBuffer,"OK");
							}

							ptr = 0;
						}
            if (ptr)
            {
		      gdb_strcpy(remcomOutBuffer,"E02");
		      if(remote_debug)
				  GDB_PRINTF("malformed write memory command: %s",remcomInBuffer);
		    }
            break;

      /* cAA..AA    Continue at address AA..AA(optional) */
      /* sAA..AA   Step one instruction from AA..AA(optional) */
      case 'c' :
      case 's' :
		/* try to read optional parameter, pc unchanged if no parm */
		ptr = &remcomInBuffer[1];
		if (hex2int(&ptr,&addr))
			gdb_registers[PC] = addr;


		/* set the trace bit if we're stepping */
		if (remcomInBuffer[0] == 's') 
			gdb_registers[PS] |= 0x100;
		else
			gdb_registers[PS] &= 0xfffffeff;

#ifdef GDB_REMOTE_UDP
  		gdb_udp_poll_stop();
#endif /* GDB_REMOTE_UDP */
		return;
//		break;

	  /* kill the program */
	  case 'k' :  /* do nothing */
		break;

	  /* Z<type-1x>,<address-x>,<length-x>    Add breakpoint */
	  case 'Z' :
		if(hex(remcomInBuffer[1]) != 0)
		{
			/* We support only software break points so far */
			break;
		}

		ptr = &remcomInBuffer[2];
		if (*(ptr++) == ',')
			if (hex2int(&ptr,&addr))
			{
				if (*(ptr++) == ',')
				{
					if (hex2int(&ptr,&length))
					{
						if(length != 1)
						{
							gdb_strcpy(remcomOutBuffer,"E02");
							if(remote_debug)
								GDB_PRINTF("Breakpoint address length isn't equal to 1.");
							break;
						}
						ptr = 0;
					}
				}
			}

		if (ptr)
		{
		  gdb_strcpy(remcomOutBuffer,"E01");
		  if(remote_debug)
			  GDB_PRINTF("malformed add breakpoint command: %s",remcomInBuffer);
		}
		else
		{
			struct zbreak *z;

			/* check whether this break point already set */
			z = zbreak_list_find(addr);
			if(z)
			{
				/* Repeated packet */
				gdb_strcpy(remcomOutBuffer,"OK");
				break;
			}
			
			/* get an free zbreak */
			mem_err = 0;
			z = zbreak_new(addr);
			if(z == NULL)
			{
				gdb_strcpy(remcomOutBuffer,"E03");
				if(remote_debug)
				  GDB_PRINTF("new zbreak failed.\n");
				break;
			}
			if (mem_err) {
				gdb_strcpy (remcomOutBuffer, "E03");
				if(remote_debug)
					GDB_PRINTF("memory fault");
				break;
			}
			gdb_strcpy(remcomOutBuffer, "OK");
		}
		break;

	  /* z<type-1x>,<address-x>,<length-x>    Remove breakpoint */
	  /* zz    Remove all breakpoints */
	  case 'z' : 
		if(hex(remcomInBuffer[1]) == 'z')
		{
			/* remove all breakpoints */
			while(valid_zbreak_list.next != &valid_zbreak_list)
			{
				zbreak_free(valid_zbreak_list.next);
			}
			gdb_strcpy(remcomOutBuffer, "OK");
			break;
		}

		if(hex(remcomInBuffer[1]) != 0)
		{
			/* We support only software break points so far */
			break;
		}

		ptr = &remcomInBuffer[2];
		if (*(ptr++) == ',')
			if (hex2int(&ptr,&addr))
			{
				if (*(ptr++) == ',')
				{
					if (hex2int(&ptr,&length))
					{
						if(length != 1)
						{
							gdb_strcpy(remcomOutBuffer,"E02");
							if(remote_debug)
								GDB_PRINTF("Breakpoint address length isn't equal to 1.");
							break;
						}
						ptr = 0;
					}
				}
			}

		if (ptr)
		{
		  gdb_strcpy(remcomOutBuffer,"E01");
		  if(remote_debug)
			  GDB_PRINTF("malformed remove breakpoint command: %s",remcomInBuffer);
		}
		else
		{
			struct zbreak *z;

			z = zbreak_list_find(addr);
			if(z == NULL)
			{
				gdb_strcpy(remcomOutBuffer,"E03");
				if(remote_debug)
				  GDB_PRINTF("Breakpoint no found.\n");
				break;
			}

			/* free zbreak */
			zbreak_free(z);

			gdb_strcpy(remcomOutBuffer,"OK");
		}
		break;
      } /* switch */

    /* reply to the request */
	if(remote_debug)
		GDB_PRINTF("GDB send packet: %s\n", remcomOutBuffer);
    gdb_put_packet(remcomOutBuffer);
    }
}
Esempio n. 3
0
/*
 * This function does all command processing for interfacing to
 * a remote gdb.  Note that the error codes are ignored by gdb
 * at present, but might eventually become meaningful. (XXX)
 * It might makes sense to use POSIX errno values, because
 * that is what the gdb/remote.c functions want to return.
 */
int
kgdb_trap(int type, db_regs_t *regs)
{
	label_t jmpbuf;
	vaddr_t addr;
	size_t len;
	u_char *p;

	if (kgdb_dev < 0 || kgdb_getc == NULL) {
		/* not debugging */
		return (0);
	}

	/* Detect and recover from unexpected traps. */
	if (kgdb_recover != 0) {
		printf("kgdb: caught trap 0x%x at %p\n",
			   type, (void *)PC_REGS(regs));
		kgdb_send("E0E"); /* 14==EFAULT */
		longjmp(kgdb_recover);
	}

	/*
	 * The first entry to this function is normally through
	 * a breakpoint trap in kgdb_connect(), in which case we
	 * must advance past the breakpoint because gdb will not.
	 *
	 * Machines vary as to where they leave the PC after a
	 * breakpoint trap.  Those that leave the PC set to the
	 * address of the trap instruction (i.e. pc532) will not
	 * define FIXUP_PC_AFTER_BREAK(), and therefore will just
	 * advance the PC.  On machines that leave the PC set to
	 * the instruction after the trap, FIXUP_PC_AFTER_BREAK
	 * will be defined to back-up the PC, so that after the
	 * "first-time" part of the if statement below has run,
	 * the PC will be the same as it was on entry.
	 *
	 * On the first entry here, we expect that gdb is not yet
	 * listening to us, so just enter the interaction loop.
	 * After the debugger is "active" (connected) it will be
	 * waiting for a "signaled" message from us.
	 */
	if (kgdb_active == 0) {
		if (!IS_BREAKPOINT_TRAP(type, 0)) {
			/* No debugger active -- let trap handle this. */
			return (0);
		}
		/* Make the PC point at the breakpoint... */
#ifdef	FIXUP_PC_AFTER_BREAK
		FIXUP_PC_AFTER_BREAK(regs);
#endif
		/* ... and then advance past it. */
#ifdef	PC_ADVANCE
		PC_ADVANCE(regs);
#else
		SET_PC_REGS(regs, PC_REGS(regs) + BKPT_SIZE);
#endif
		kgdb_active = 1;
	} else {
		/* Tell remote host that an exception has occurred. */
		snprintf(buffer, sizeof buffer, "S%02x", kgdb_signal(type));
		kgdb_send(buffer);
	}

	/* Stick frame regs into our reg cache. */
	kgdb_getregs(regs, gdb_regs);

	/*
	 * Interact with gdb until it lets us go.
	 * If we cause a trap, resume here.
	 */
	(void)setjmp((kgdb_recover = &jmpbuf));
	for (;;) {
		kgdb_recv(buffer, sizeof(buffer));
		switch (buffer[0]) {

		default:
			/* Unknown command. */
			kgdb_send("");
			continue;

		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".
			 */
			snprintf(buffer, sizeof buffer, "S%02x",
			    kgdb_signal(type));
			kgdb_send(buffer);
			continue;

		case KGDB_REG_R:
			mem2hex(buffer, gdb_regs, sizeof(gdb_regs));
			kgdb_send(buffer);
			continue;

		case KGDB_REG_W:
			p = hex2mem(gdb_regs, buffer + 1, sizeof(gdb_regs));
			if (p == NULL || *p != '\0')
				kgdb_send("E01");
			else {
				kgdb_setregs(regs, gdb_regs);
				kgdb_send("OK");
			}
			continue;

		case KGDB_MEM_R:
			p = buffer + 1;
			addr = hex2i(&p);
			if (*p++ != ',') {
				kgdb_send("E02");
				continue;
			}
			len = hex2i(&p);
			if (*p != '\0') {
				kgdb_send("E03");
				continue;
			}
			if (len > sizeof(buffer) / 2) {
				kgdb_send("E04");
				continue;
			}
			if (kgdb_acc(addr, len) == 0) {
				kgdb_send("E05");
				continue;
			}
			db_read_bytes(addr, (size_t)len,
					(char *)buffer + sizeof(buffer) / 2);
			mem2hex(buffer, buffer + sizeof(buffer) / 2, len);
			kgdb_send(buffer);
			continue;

		case KGDB_MEM_W:
			p = buffer + 1;
			addr = hex2i(&p);
			if (*p++ != ',') {
				kgdb_send("E06");
				continue;
			}
			len = hex2i(&p);
			if (*p++ != ':') {
				kgdb_send("E07");
				continue;
			}
			if (len > (sizeof(buffer) - (p - buffer))) {
				kgdb_send("E08");
				continue;
			}
			p = hex2mem(buffer, p, sizeof(buffer));
			if (p == NULL) {
				kgdb_send("E09");
				continue;
			}
			if (kgdb_acc(addr, len) == 0) {
				kgdb_send("E0A");
				continue;
			}
			db_write_bytes(addr, (size_t)len, (char *)buffer);
			kgdb_send("OK");
			continue;

		case KGDB_DETACH:
			kgdb_active = 0;
			printf("kgdb detached\n");
			db_clear_single_step(regs);
			kgdb_send("OK");
			goto out;

		case KGDB_KILL:
			kgdb_active = 0;
			printf("kgdb detached\n");
			db_clear_single_step(regs);
			goto out;

		case KGDB_CONT:
			if (buffer[1]) {
				p = buffer + 1;
				addr = hex2i(&p);
				if (*p) {
					kgdb_send("E0B");
					continue;
				}
				SET_PC_REGS(regs, addr);
			}
			db_clear_single_step(regs);
			goto out;

		case KGDB_STEP:
			if (buffer[1]) {
				p = buffer + 1;
				addr = hex2i(&p);
				if (*p) {
					kgdb_send("E0B");
					continue;
				}
				SET_PC_REGS(regs, addr);
			}
			db_set_single_step(regs);
			goto out;
		}
	}
 out:
	kgdb_recover = 0;
	return (1);
}
Esempio n. 4
0
/*
 * This function does all command processing for interfacing to gdb.
 */
static int
handle_exception (struct pt_regs *regs)
{
	int addr;
	int length;
	char *ptr;
	kgdb_data kd;
	int i;

	if (!initialized) {
		printf("kgdb: exception before kgdb is initialized! huh?\n");
		return (0);
	}

	/* probably should check which exception occured as well */
	if (longjmp_on_fault) {
		longjmp_on_fault = 0;
		kgdb_longjmp((long*)error_jmp_buf, KGDBERR_MEMFAULT);
		panic("kgdb longjump failed!\n");
	}

	if (kgdb_active) {
		printf("kgdb: unexpected exception from within kgdb\n");
		return (0);
	}
	kgdb_active = 1;

	kgdb_interruptible(0);

	printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));

	if (kgdb_setjmp((long*)error_jmp_buf) != 0)
		panic("kgdb: error or fault in entry init!\n");

	kgdb_enter(regs, &kd);

	if (first_entry) {
		/*
		 * the first time we enter kgdb, we save the processor
		 * state so that we can return to the monitor if the
		 * remote end quits gdb (or at least, tells us to quit
		 * with the 'k' packet)
		 */
		entry_regs = *regs;
		first_entry = 0;
	}

	ptr = remcomOutBuffer;

	*ptr++ = 'T';

	*ptr++ = hexchars[kd.sigval >> 4];
	*ptr++ = hexchars[kd.sigval & 0xf];

	for (i = 0; i < kd.nregs; i++) {
		kgdb_reg *rp = &kd.regs[i];

		*ptr++ = hexchars[rp->num >> 4];
		*ptr++ = hexchars[rp->num & 0xf];
		*ptr++ = ':';
		ptr = mem2hex((char *)&rp->val, ptr, 4);
		*ptr++ = ';';
	}

	*ptr = 0;

#ifdef KGDB_DEBUG
	if (kdebug)
		printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
#endif

	putpacket(remcomOutBuffer);

	while (1) {
		volatile int errnum;

		remcomOutBuffer[0] = 0;

		getpacket(remcomInBuffer);
		ptr = &remcomInBuffer[1];

#ifdef KGDB_DEBUG
		if (kdebug)
			printf("kgdb:  remcomInBuffer: %s\n", remcomInBuffer);
#endif

		errnum = kgdb_setjmp((long*)error_jmp_buf);

		if (errnum == 0) switch (remcomInBuffer[0]) {

		case '?':               /* report most recent signal */
			remcomOutBuffer[0] = 'S';
			remcomOutBuffer[1] = hexchars[kd.sigval >> 4];
			remcomOutBuffer[2] = hexchars[kd.sigval & 0xf];
			remcomOutBuffer[3] = 0;
			break;

#ifdef KGDB_DEBUG
		case 'd':
			/* toggle debug flag */
			kdebug ^= 1;
			break;
#endif

		case 'g':	/* return the value of the CPU registers. */
			length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX);
			mem2hex(remcomRegBuffer, remcomOutBuffer, length);
			break;

		case 'G':   /* set the value of the CPU registers */
			length = strlen(ptr);
			if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS);
			hex2mem(ptr, remcomRegBuffer, length/2);
			kgdb_putregs(regs, remcomRegBuffer, length/2);
			strcpy(remcomOutBuffer,"OK");
			break;

		case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
				/* Try to read %x,%x.  */

			if (hexToInt(&ptr, &addr)
			    && *ptr++ == ','
			    && hexToInt(&ptr, &length))	{
				mem2hex((char *)addr, remcomOutBuffer, length);
			} else {
				kgdb_error(KGDBERR_BADPARAMS);
			}
			break;

		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
			/* Try to read '%x,%x:'.  */

			if (hexToInt(&ptr, &addr)
			    && *ptr++ == ','
			    && hexToInt(&ptr, &length)
			    && *ptr++ == ':') {
				hex2mem(ptr, (char *)addr, length);
				strcpy(remcomOutBuffer, "OK");
			} else {
				kgdb_error(KGDBERR_BADPARAMS);
			}
			break;


		case 'k':    /* kill the program, actually return to monitor */
			kd.extype = KGDBEXIT_KILL;
			*regs = entry_regs;
			first_entry = 1;
			goto doexit;

		case 'C':    /* CSS  continue with signal SS */
			*ptr = '\0';	/* ignore the signal number for now */
			/* fall through */

		case 'c':    /* cAA..AA  Continue; address AA..AA optional */
			/* try to read optional parameter, pc unchanged if no parm */
			kd.extype = KGDBEXIT_CONTINUE;

			if (hexToInt(&ptr, &addr)) {
				kd.exaddr = addr;
				kd.extype |= KGDBEXIT_WITHADDR;
			}

			goto doexit;

		case 'S':    /* SSS  single step with signal SS */
			*ptr = '\0';	/* ignore the signal number for now */
			/* fall through */

		case 's':
			kd.extype = KGDBEXIT_SINGLE;

			if (hexToInt(&ptr, &addr)) {
				kd.exaddr = addr;
				kd.extype |= KGDBEXIT_WITHADDR;
			}

		doexit:
/* Need to flush the instruction cache here, as we may have deposited a
 * breakpoint, and the icache probably has no way of knowing that a data ref to
 * some location may have changed something that is in the instruction cache.
 */
			kgdb_flush_cache_all();
			kgdb_exit(regs, &kd);
			kgdb_active = 0;
			kgdb_interruptible(1);
			return (1);

		case 'r':		/* Reset (if user process..exit ???)*/
			panic("kgdb reset.");
			break;

		case 'P':    /* Pr=v  set reg r to value v (r and v are hex) */
			if (hexToInt(&ptr, &addr)
			    && *ptr++ == '='
			    && ((length = strlen(ptr)) & 1) == 0) {
				hex2mem(ptr, remcomRegBuffer, length/2);
				kgdb_putreg(regs, addr,
					remcomRegBuffer, length/2);
				strcpy(remcomOutBuffer,"OK");
			} else {
				kgdb_error(KGDBERR_BADPARAMS);
			}
			break;
		}			/* switch */

		if (errnum != 0)
			sprintf(remcomOutBuffer, "E%02d", errnum);

#ifdef KGDB_DEBUG
		if (kdebug)
			printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
#endif

		/* reply to the request */
		putpacket(remcomOutBuffer);

	} /* while(1) */
}
Esempio n. 5
0
/* All expected commands are sent from remote.c. Send a response according
   to the description in remote.c. */
static void
handle_exception (int sigval)
{
	/* Avoid warning of not used. */

	USEDFUN(handle_exception);
	USEDVAR(internal_stack[0]);

	/* Send response. */

	stub_is_stopped (sigval);

	for (;;) {
		remcomOutBuffer[0] = '\0';
		getpacket (remcomInBuffer);
		switch (remcomInBuffer[0]) {
			case 'g':
				/* Read registers: g
				   Success: Each byte of register data is described by two hex digits.
				   Registers are in the internal order for GDB, and the bytes
				   in a register  are in the same order the machine uses.
				   Failure: void. */
				
				{
#ifdef PROCESS_SUPPORT
					/* Use the special register content in the executing thread. */
					copy_registers (&reg_g, &reg, sizeof(registers));
					/* Replace the content available on the stack. */
					if (current_thread_g != executing_task) {
						copy_registers_from_stack (current_thread_g, &reg_g);
					}
					mem2hex ((unsigned char *)remcomOutBuffer, (unsigned char *)&reg_g, sizeof(registers));
#else
					mem2hex(remcomOutBuffer, (char *)&reg, sizeof(registers));
#endif
				}
				break;
				
			case 'G':
				/* Write registers. GXX..XX
				   Each byte of register data  is described by two hex digits.
				   Success: OK
				   Failure: void. */
#ifdef PROCESS_SUPPORT
				hex2mem ((unsigned char *)&reg_g, &remcomInBuffer[1], sizeof(registers));
				if (current_thread_g == executing_task) {
					copy_registers (&reg, &reg_g, sizeof(registers));
				}
				else {
					copy_registers_to_stack(current_thread_g, &reg_g);
				}
#else
				hex2mem((char *)&reg, &remcomInBuffer[1], sizeof(registers));
#endif
				gdb_cris_strcpy (remcomOutBuffer, "OK");
				break;
				
			case 'P':
				/* Write register. Pn...=r...
				   Write register n..., hex value without 0x, with value r...,
				   which contains a hex value without 0x and two hex digits
				   for each byte in the register (target byte order). P1f=11223344 means
				   set register 31 to 44332211.
				   Success: OK
				   Failure: E02, E05 */
				{
					char *suffix;
					int regno = gdb_cris_strtol (&remcomInBuffer[1], &suffix, 16);
					int status;
#ifdef PROCESS_SUPPORT
					if (current_thread_g != executing_task)
						status = write_stack_register (current_thread_g, regno, suffix+1);
					else
#endif
						status = write_register (regno, suffix+1);

					switch (status) {
						case E02:
							/* Do not support read-only registers. */
							gdb_cris_strcpy (remcomOutBuffer, error_message[E02]);
							break;
						case E05:
							/* Do not support non-existing registers. */
							gdb_cris_strcpy (remcomOutBuffer, error_message[E05]);
							break;
						case E07:
							/* Do not support non-existing registers on the stack. */
							gdb_cris_strcpy (remcomOutBuffer, error_message[E07]);
							break;
						default:
							/* Valid register number. */
							gdb_cris_strcpy (remcomOutBuffer, "OK");
							break;
					}
				}
				break;
				
			case 'm':
				/* Read from memory. mAA..AA,LLLL
				   AA..AA is the address and LLLL is the length.
				   Success: XX..XX is the memory content.  Can be fewer bytes than
				   requested if only part of the data may be read. m6000120a,6c means
				   retrieve 108 byte from base address 6000120a.
				   Failure: void. */
				{
                                        char *suffix;
					unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1],
                                                                                               &suffix, 16);                                        int length = gdb_cris_strtol(suffix+1, 0, 16);
                                        
                                        mem2hex(remcomOutBuffer, addr, length);
                                }
				break;
				
			case 'X':
				/* Write to memory. XAA..AA,LLLL:XX..XX
				   AA..AA is the start address,  LLLL is the number of bytes, and
				   XX..XX is the binary data.
				   Success: OK
				   Failure: void. */
			case 'M':
				/* Write to memory. MAA..AA,LLLL:XX..XX
				   AA..AA is the start address,  LLLL is the number of bytes, and
				   XX..XX is the hexadecimal data.
				   Success: OK
				   Failure: void. */
				{
					char *lenptr;
					char *dataptr;
					unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1],
										      &lenptr, 16);
					int length = gdb_cris_strtol(lenptr+1, &dataptr, 16);
					if (*lenptr == ',' && *dataptr == ':') {
						if (remcomInBuffer[0] == 'M') {
							hex2mem(addr, dataptr + 1, length);
						}
						else /* X */ {
							bin2mem(addr, dataptr + 1, length);
						}
						gdb_cris_strcpy (remcomOutBuffer, "OK");
					}
					else {
						gdb_cris_strcpy (remcomOutBuffer, error_message[E06]);
					}
				}
				break;
				
			case 'c':
				/* Continue execution. cAA..AA
				   AA..AA is the address where execution is resumed. If AA..AA is
				   omitted, resume at the present address.
				   Success: return to the executing thread.
				   Failure: will never know. */
				if (remcomInBuffer[1] != '\0') {
					reg.pc = gdb_cris_strtol (&remcomInBuffer[1], 0, 16);
				}
				enableDebugIRQ();
				return;
				
			case 's':
				/* Step. sAA..AA
				   AA..AA is the address where execution is resumed. If AA..AA is
				   omitted, resume at the present address. Success: return to the
				   executing thread. Failure: will never know.
				   
				   Should never be invoked. The single-step is implemented on
				   the host side. If ever invoked, it is an internal error E04. */
				gdb_cris_strcpy (remcomOutBuffer, error_message[E04]);
				putpacket (remcomOutBuffer);
				return;
				
			case '?':
				/* The last signal which caused a stop. ?
				   Success: SAA, where AA is the signal number.
				   Failure: void. */
				remcomOutBuffer[0] = 'S';
				remcomOutBuffer[1] = hex_asc_hi(sigval);
				remcomOutBuffer[2] = hex_asc_lo(sigval);
				remcomOutBuffer[3] = 0;
				break;
				
			case 'D':
				/* Detach from host. D
				   Success: OK, and return to the executing thread.
				   Failure: will never know */
				putpacket ("OK");
				return;
				
			case 'k':
			case 'r':
				/* kill request or reset request.
				   Success: restart of target.
				   Failure: will never know. */
				kill_restart ();
				break;
				
			case 'C':
			case 'S':
			case '!':
			case 'R':
			case 'd':
				/* Continue with signal sig. Csig;AA..AA
				   Step with signal sig. Ssig;AA..AA
				   Use the extended remote protocol. !
				   Restart the target system. R0
				   Toggle debug flag. d
				   Search backwards. tAA:PP,MM
				   Not supported: E04 */
				gdb_cris_strcpy (remcomOutBuffer, error_message[E04]);
				break;
#ifdef PROCESS_SUPPORT

			case 'T':
				/* Thread alive. TXX
				   Is thread XX alive?
				   Success: OK, thread XX is alive.
				   Failure: E03, thread XX is dead. */
				{
					int thread_id = (int)gdb_cris_strtol (&remcomInBuffer[1], 0, 16);
					/* Cannot tell whether it is alive or not. */
					if (thread_id >= 0 && thread_id < number_of_tasks)
						gdb_cris_strcpy (remcomOutBuffer, "OK");
				}
				break;
								
			case 'H':
				/* Set thread for subsequent operations: Hct
				   c = 'c' for thread used in step and continue;
				   t can be -1 for all threads.
				   c = 'g' for thread used in other  operations.
				   t = 0 means pick any thread.
				   Success: OK
				   Failure: E01 */
				{
					int thread_id = gdb_cris_strtol (&remcomInBuffer[2], 0, 16);
					if (remcomInBuffer[1] == 'c') {
						/* c = 'c' for thread used in step and continue */
						/* Do not change current_thread_c here. It would create a mess in
						   the scheduler. */
						gdb_cris_strcpy (remcomOutBuffer, "OK");
					}
					else if (remcomInBuffer[1] == 'g') {
						/* c = 'g' for thread used in other  operations.
						   t = 0 means pick any thread. Impossible since the scheduler does
						   not allow that. */
						if (thread_id >= 0 && thread_id < number_of_tasks) {
							current_thread_g = thread_id;
							gdb_cris_strcpy (remcomOutBuffer, "OK");
						}
						else {
							/* Not expected - send an error message. */
							gdb_cris_strcpy (remcomOutBuffer, error_message[E01]);
						}
					}
					else {
						/* Not expected - send an error message. */
						gdb_cris_strcpy (remcomOutBuffer, error_message[E01]);
					}
				}
				break;
				
			case 'q':
			case 'Q':
				/* Query of general interest. qXXXX
				   Set general value XXXX. QXXXX=yyyy */
				{
					int pos;
					int nextpos;
					int thread_id;
					
					switch (remcomInBuffer[1]) {
						case 'C':
							/* Identify the remote current thread. */
							gdb_cris_strcpy (&remcomOutBuffer[0], "QC");
							remcomOutBuffer[2] = hex_asc_hi(current_thread_c);
							remcomOutBuffer[3] = hex_asc_lo(current_thread_c);
							remcomOutBuffer[4] = '\0';
							break;
						case 'L':
							gdb_cris_strcpy (&remcomOutBuffer[0], "QM");
							/* Reply with number of threads. */
							if (os_is_started()) {
								remcomOutBuffer[2] = hex_asc_hi(number_of_tasks);
								remcomOutBuffer[3] = hex_asc_lo(number_of_tasks);
							}
							else {
								remcomOutBuffer[2] = hex_asc_hi(0);
								remcomOutBuffer[3] = hex_asc_lo(1);
							}
							/* Done with the reply. */
							remcomOutBuffer[4] = hex_asc_lo(1);
							pos = 5;
							/* Expects the argument thread id. */
							for (; pos < (5 + HEXCHARS_IN_THREAD_ID); pos++)
								remcomOutBuffer[pos] = remcomInBuffer[pos];
							/* Reply with the thread identifiers. */
							if (os_is_started()) {
								/* Store the thread identifiers of all tasks. */
								for (thread_id = 0; thread_id < number_of_tasks; thread_id++) {
									nextpos = pos + HEXCHARS_IN_THREAD_ID - 1;
									for (; pos < nextpos; pos ++)
										remcomOutBuffer[pos] = hex_asc_lo(0);
									remcomOutBuffer[pos++] = hex_asc_lo(thread_id);
								}
							}
							else {
								/* Store the thread identifier of the boot task. */
								nextpos = pos + HEXCHARS_IN_THREAD_ID - 1;
								for (; pos < nextpos; pos ++)
									remcomOutBuffer[pos] = hex_asc_lo(0);
								remcomOutBuffer[pos++] = hex_asc_lo(current_thread_c);
							}
							remcomOutBuffer[pos] = '\0';
							break;
						default:
							/* Not supported: "" */
							/* Request information about section offsets: qOffsets. */
							remcomOutBuffer[0] = 0;
							break;
					}
				}
				break;
#endif /* PROCESS_SUPPORT */
				
			default:
				/* The stub should ignore other request and send an empty
				   response ($#<checksum>). This way we can extend the protocol and GDB
				   can tell whether the stub it is talking to uses the old or the new. */
				remcomOutBuffer[0] = 0;
				break;
		}
		putpacket(remcomOutBuffer);
	}
}
Esempio n. 6
0
/*
 * This function does all command procesing for interfacing to gdb.
 */
void
gdb_handle_exception (db_regs_t *raw_regs, int type, int code)
{
  int    sigval;
  int    addr, length;
  char * ptr;
  struct i386regs {
    unsigned int eax;
    unsigned int ecx;
    unsigned int edx;
    unsigned int ebx;
    unsigned int esp;
    unsigned int ebp;
    unsigned int esi;
    unsigned int edi;
    unsigned int eip;
    unsigned int eflags;
    unsigned int cs;
    unsigned int ss;
    unsigned int ds;
    unsigned int es;
  };
  struct i386regs registers;

  registers.eax = raw_regs->tf_eax;
  registers.ebx = raw_regs->tf_ebx;
  registers.ecx = raw_regs->tf_ecx;
  registers.edx = raw_regs->tf_edx;

  registers.esp = raw_regs->tf_esp;
  registers.ebp = raw_regs->tf_ebp;
  registers.esi = raw_regs->tf_esi;
  registers.edi = raw_regs->tf_edi;

  registers.eip = raw_regs->tf_eip;
  registers.eflags = raw_regs->tf_eflags;

  registers.cs = raw_regs->tf_cs;
  registers.ss = raw_regs->tf_ss;
  registers.ds = raw_regs->tf_ds;
  registers.es = raw_regs->tf_es;

  /* reply to host that an exception has occurred */
  sigval = computeSignal (type);
  ptr = remcomOutBuffer;

  *ptr++ = 'T';
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval & 0xf];

  *ptr++ = hexchars[PC >> 4];
  *ptr++ = hexchars[PC & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.eip, ptr, 4);
  *ptr++ = ';';

  *ptr++ = hexchars[FP >> 4];
  *ptr++ = hexchars[FP & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.ebp, ptr, 4);
  *ptr++ = ';';

  *ptr++ = hexchars[SP >> 4];
  *ptr++ = hexchars[SP & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.esp, ptr, 4);
  *ptr++ = ';';

  *ptr++ = 0;

  putpacket (remcomOutBuffer);

  while (1)
    {
      remcomOutBuffer[0] = 0;

      getpacket (remcomInBuffer);
      switch (remcomInBuffer[0]) 
	{
	case '?':
	  remcomOutBuffer[0] = 'S';
	  remcomOutBuffer[1] = hexchars[sigval >> 4];
	  remcomOutBuffer[2] = hexchars[sigval % 16];
	  remcomOutBuffer[3] = 0;
	  break;

	case 'D':		/* detach; say OK and turn off gdb */
	  putpacket(remcomOutBuffer);
	  boothowto &= ~RB_GDB;
	  return;

	case 'g':		/* return the value of the CPU registers */
	  mem2hex ((vm_offset_t)&registers, remcomOutBuffer, NUMREGBYTES);
	  break;

	case 'G':		/* set the value of the CPU registers - return OK */
	  hex2mem (&remcomInBuffer[1], (vm_offset_t)&registers, NUMREGBYTES);
	  strcpy (remcomOutBuffer, "OK");
	  break;

	case 'P':		/* Set the value of one register */
	  {
	    int regno;

	    ptr = &remcomInBuffer[1];

	    if (hexToInt (&ptr, &regno)
		&& *ptr++ == '='
		&& regno < NUM_REGS)
	      {
		hex2mem (ptr, (vm_offset_t)&registers + regno * 4, 4);
		strcpy(remcomOutBuffer,"OK");
	      }
	    else
	      strcpy (remcomOutBuffer, "P01");
	    break;
	  }
	case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
	  /* Try to read %x,%x.  */

	  ptr = &remcomInBuffer[1];

	  if (hexToInt (&ptr, &addr)
	      && *(ptr++) == ','
	      && hexToInt (&ptr, &length))
	    {
	      if (mem2hex((vm_offset_t) addr, remcomOutBuffer, length) == NULL)
		strcpy (remcomOutBuffer, "E03");
	      break;
	    }
	  else
	    strcpy (remcomOutBuffer, "E01");
	  break;

	case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */

	  /* Try to read '%x,%x:'.  */

	  ptr = &remcomInBuffer[1];

	  if (hexToInt(&ptr,&addr)
	      && *(ptr++) == ','
	      && hexToInt(&ptr, &length)
	      && *(ptr++) == ':')
	    {
	      if (hex2mem(ptr, (vm_offset_t) addr, length) == NULL)
		strcpy (remcomOutBuffer, "E03");
	      else
		strcpy (remcomOutBuffer, "OK");
	    }
	  else
	    strcpy (remcomOutBuffer, "E02");
	  break;

	  /* cAA..AA    Continue at address AA..AA(optional) */
	  /* sAA..AA   Step one instruction from AA..AA(optional) */
	case 'c' :
	case 's' :
	  /* try to read optional parameter, pc unchanged if no parm */

	  ptr = &remcomInBuffer[1];
	  if (hexToInt(&ptr,&addr))
	    registers.eip = addr;


	  /* set the trace bit if we're stepping */
	  if (remcomInBuffer[0] == 's')
	    registers.eflags |= PSL_T;
	  else
	    registers.eflags &= ~PSL_T;

	  raw_regs->tf_eax = registers.eax;
	  raw_regs->tf_ebx = registers.ebx;
	  raw_regs->tf_ecx = registers.ecx;
	  raw_regs->tf_edx = registers.edx;

	  raw_regs->tf_esp = registers.esp;
	  raw_regs->tf_ebp = registers.ebp;
	  raw_regs->tf_esi = registers.esi;
	  raw_regs->tf_edi = registers.edi;

	  raw_regs->tf_eip = registers.eip;
	  raw_regs->tf_eflags = registers.eflags;

	  raw_regs->tf_cs = registers.cs;
	  raw_regs->tf_ss = registers.ss;
	  raw_regs->tf_ds = registers.ds;
	  raw_regs->tf_es = registers.es;
	  return;

	} /* switch */

      /* reply to the request */
      putpacket (remcomOutBuffer);
    }
}
Esempio n. 7
0
static void
handle_exception (int exceptionVector)
{
  int sigval;
  int addr, length, reg;
  char *ptr;

  gdb_i386vector = exceptionVector;

  if (remote_debug)
    printf ("vector=%d, sr=0x%x, pc=0x%x\n",
	    exceptionVector,
	    registers[PS],
	    registers[PC]);

  /* Reply to host that an exception has occurred.  Always return the
     PC, SP, and FP, since gdb always wants them.  */
  ptr = remcomOutBuffer;
  *ptr++ = 'T';
  sigval = computeSignal (exceptionVector);
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval % 16];

  *ptr++ = hexchars[ESP];
  *ptr++ = ':';
  mem2hex ((char *) &registers[ESP], ptr, REGBYTES, 0);
  ptr += REGBYTES * 2;
  *ptr++ = ';';

  *ptr++ = hexchars[EBP];
  *ptr++ = ':';
  mem2hex ((char *) &registers[EBP], ptr, REGBYTES, 0);
  ptr += REGBYTES * 2;
  *ptr++ = ';';

  *ptr++ = hexchars[PC];
  *ptr++ = ':';
  mem2hex ((char *) &registers[PC], ptr, REGBYTES, 0);
  ptr += REGBYTES * 2;
  *ptr++ = ';';

  *ptr = '\0';

  putpacket (remcomOutBuffer);

  while (1 == 1)
    {
      error = 0;
      remcomOutBuffer[0] = 0;
      getpacket (remcomInBuffer);
      switch (remcomInBuffer[0])
	{
	case '?':
	  remcomOutBuffer[0] = 'S';
	  remcomOutBuffer[1] = hexchars[sigval >> 4];
	  remcomOutBuffer[2] = hexchars[sigval % 16];
	  remcomOutBuffer[3] = 0;
	  break;
	case 'd':
	  remote_debug = !(remote_debug);	/* toggle debug flag */
	  break;
	case 'g':		/* return the value of the CPU registers */
	  mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
	  break;
	case 'G':		/* set the value of the CPU registers - return OK */
	  hex2mem (&remcomInBuffer[1], (char *) registers, NUMREGBYTES, 0);
	  strcpy (remcomOutBuffer, "OK");
	  break;

	case 'P':		/* Set specific register */
	  ptr = &remcomInBuffer[1];
	  if (hexToInt (&ptr, &reg)
	      && *ptr++ == '=')
	    {
	      hex2mem (ptr, (char *) &registers[reg], REGBYTES, 0);
	      strcpy (remcomOutBuffer, "OK");
	    }
	  else
	    {
	      strcpy (remcomOutBuffer, "E01");
	      debug_error ("malformed register set command; %s",
			   remcomInBuffer);
	    }
	  break;

	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
	case 'm':
	  /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
	  ptr = &remcomInBuffer[1];
	  if (hexToInt (&ptr, &addr))
	    if (*(ptr++) == ',')
	      if (hexToInt (&ptr, &length))
		{
		  ptr = 0;
		  mem_err = 0;
		  mem2hex ((char *) addr, remcomOutBuffer, length, 1);
		  if (mem_err)
		    {
		      strcpy (remcomOutBuffer, "E03");
		      debug_error ("memory fault", 0);
		    }
		}

	  if (ptr)
	    {
	      strcpy (remcomOutBuffer, "E01");
	      debug_error ("malformed read memory command: %s", remcomInBuffer);
	    }
	  break;

	  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
	case 'M':
	  /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
	  ptr = &remcomInBuffer[1];
	  if (hexToInt (&ptr, &addr))
	    if (*(ptr++) == ',')
	      if (hexToInt (&ptr, &length))
		if (*(ptr++) == ':')
		  {
		    mem_err = 0;
		    hex2mem (ptr, (char *) addr, length, 1);

		    if (mem_err)
		      {
			strcpy (remcomOutBuffer, "E03");
			debug_error ("memory fault", 0);
		      }
		    else
		      {
			strcpy (remcomOutBuffer, "OK");
		      }

		    ptr = 0;
		  }
	  if (ptr)
	    {
	      strcpy (remcomOutBuffer, "E02");
	      debug_error ("malformed write memory command: %s", remcomInBuffer);
	    }
	  break;

	  /* cAA..AA    Continue at address AA..AA(optional) */
	  /* sAA..AA   Step one instruction from AA..AA(optional) */
	case 'c':
	case 's':
	  /* try to read optional parameter, pc unchanged if no parm */
	  ptr = &remcomInBuffer[1];
	  if (hexToInt (&ptr, &addr))
	    registers[PC] = addr;

	  /* clear the trace bit */
	  registers[PS] &= 0xfffffeff;

	  /* set the trace bit if we're stepping */
	  if (remcomInBuffer[0] == 's')
	    registers[PS] |= 0x100;

	  _returnFromException ();	/* this is a jump */

	  break;

	  /* Detach.  */
	case 'D':
	  putpacket (remcomOutBuffer);
	  registers[PS] &= 0xfffffeff;
	  _returnFromException ();	/* this is a jump */

	  break;

	  /* kill the program */
	case 'k':		/* do nothing */
	  break;
	}			/* switch */

      /* reply to the request */
      putpacket (remcomOutBuffer);
    }
}
Esempio n. 8
0
/*
 * This function does all command procesing for interfacing to gdb.
 */
void
gdb_handle_exception (db_regs_t *raw_regs, int type, int code)
{
  int    sigval;
  long   addr, length;
  char * ptr;
  struct alpharegs {
    u_int64_t r[32];
    u_int64_t f[32];
    u_int64_t pc, vfp;
  };
  static struct alpharegs registers;
  int i;

  clear_single_step(raw_regs);

  bzero(&registers, sizeof registers);

  /*
   * Map trapframe to registers.
   * Ignore float regs for now.
   */
  for (i = 0; i < FRAME_SIZE; i++)
    if (tf2gdb[i] >= 0)
      registers.r[tf2gdb[i]] = raw_regs->tf_regs[i];
  registers.pc = raw_regs->tf_regs[FRAME_PC];

  /* reply to host that an exception has occurred */
  sigval = computeSignal (type, code);
  ptr = remcomOutBuffer;

  *ptr++ = 'T';
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval & 0xf];

  *ptr++ = hexchars[PC >> 4];
  *ptr++ = hexchars[PC & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.pc, ptr, 8);
  *ptr++ = ';';

  *ptr++ = hexchars[FP >> 4];
  *ptr++ = hexchars[FP & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.r[FP], ptr, 8);
  *ptr++ = ';';

  *ptr++ = hexchars[SP >> 4];
  *ptr++ = hexchars[SP & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.r[SP], ptr, 8);
  *ptr++ = ';';

  *ptr++ = 0;

  putpacket (remcomOutBuffer);

  while (1)
    {
      remcomOutBuffer[0] = 0;

      getpacket (remcomInBuffer);
      switch (remcomInBuffer[0]) 
	{
	case '?':
	  remcomOutBuffer[0] = 'S';
	  remcomOutBuffer[1] = hexchars[sigval >> 4];
	  remcomOutBuffer[2] = hexchars[sigval % 16];
	  remcomOutBuffer[3] = 0;
	  break;

	case 'D':		/* detach; say OK and turn off gdb */
	  putpacket(remcomOutBuffer);
	  boothowto &= ~RB_GDB;
	  return;

	case 'k':
	  prom_halt();
	  /*NOTREACHED*/
	  break;

	case 'g':		/* return the value of the CPU registers */
	  mem2hex ((vm_offset_t)&registers, remcomOutBuffer, NUMREGBYTES);
	  break;

	case 'G':		/* set the value of the CPU registers - return OK */
	  hex2mem (&remcomInBuffer[1], (vm_offset_t)&registers, NUMREGBYTES);
	  strcpy (remcomOutBuffer, "OK");
	  break;

	case 'P':		/* Set the value of one register */
	  {
	    long regno;

	    ptr = &remcomInBuffer[1];

	    if (hexToInt (&ptr, &regno)
		&& *ptr++ == '='
		&& regno < NUM_REGS)
	      {
		hex2mem (ptr, (vm_offset_t)&registers + regno * 8, 8);
		strcpy(remcomOutBuffer,"OK");
	      }
	    else
	      strcpy (remcomOutBuffer, "P01");
	    break;
	  }
	case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
	  /* Try to read %x,%x.  */

	  ptr = &remcomInBuffer[1];

	  if (hexToInt (&ptr, &addr)
	      && *(ptr++) == ','
	      && hexToInt (&ptr, &length))
	    {
	      if (mem2hex((vm_offset_t) addr, remcomOutBuffer, length) == NULL)
		strcpy (remcomOutBuffer, "E03");
	      break;
	    }
	  else
	    strcpy (remcomOutBuffer, "E01");
	  break;

	case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */

	  /* Try to read '%x,%x:'.  */

	  ptr = &remcomInBuffer[1];

	  if (hexToInt(&ptr,&addr)
	      && *(ptr++) == ','
	      && hexToInt(&ptr, &length)
	      && *(ptr++) == ':')
	    {
	      if (hex2mem(ptr, (vm_offset_t) addr, length) == NULL)
		strcpy (remcomOutBuffer, "E03");
	      else
		strcpy (remcomOutBuffer, "OK");
	    }
	  else
	    strcpy (remcomOutBuffer, "E02");
	  break;

	  /* cAA..AA    Continue at address AA..AA(optional) */
	  /* sAA..AA   Step one instruction from AA..AA(optional) */
	case 'c' :
	case 's' :
	  /* try to read optional parameter, pc unchanged if no parm */

	  ptr = &remcomInBuffer[1];
	  if (hexToInt(&ptr,&addr))
	    registers.pc = addr;

	  /*
	   * Map gdb registers back to trapframe (ignoring fp regs).
	   */
	  for (i = 0; i < NUM_REGS; i++)
	    if (gdb2tf[i] >= 0)
	      raw_regs->tf_regs[gdb2tf[i]] = registers.r[i];
	  raw_regs->tf_regs[FRAME_PC] = registers.pc;

	  if (remcomInBuffer[0] == 's')
	    if (!set_single_step(raw_regs))
	      printf("Can't set single step breakpoint\n");

	  return;

	} /* switch */

      /* reply to the request */
      putpacket (remcomOutBuffer);
    }
}