Example #1
0
static void gdb_read_command()
{
  u8 c;
  u8 chk_read, chk_calc;

  cmd_len = 0;
  memset(cmd_bfr, 0, sizeof cmd_bfr);

  c = gdb_read_byte();
  if (c == '+')
  {
    // ignore ack
    return;
  }
  else if (c == 0x03)
  {
    CPU::Break();
    gdb_signal(GDB_SIGTRAP);
    return;
  }
  else if (c != GDB_STUB_START)
  {
    DEBUG_LOG(GDB_STUB, "gdb: read invalid byte %02x", c);
    return;
  }

  while ((c = gdb_read_byte()) != GDB_STUB_END)
  {
    cmd_bfr[cmd_len++] = c;
    if (cmd_len == sizeof cmd_bfr)
    {
      ERROR_LOG(GDB_STUB, "gdb: cmd_bfr overflow");
      gdb_nak();
      return;
    }
  }

  chk_read = hex2char(gdb_read_byte()) << 4;
  chk_read |= hex2char(gdb_read_byte());

  chk_calc = gdb_calc_chksum();

  if (chk_calc != chk_read)
  {
    ERROR_LOG(GDB_STUB,
              "gdb: invalid checksum: calculated %02x and read %02x for $%s# (length: %d)",
              chk_calc, chk_read, cmd_bfr, cmd_len);
    cmd_len = 0;

    gdb_nak();
    return;
  }

  DEBUG_LOG(GDB_STUB, "gdb: read command %c with a length of %d: %s", cmd_bfr[0], cmd_len, cmd_bfr);
  gdb_ack();
}
Example #2
0
static size_t gdb_consume_packet(uint8_t *data, size_t len)
{
   size_t done;

   debug(GDBSTUB_PKT, "consume (%D): [", len);
#ifdef CONFIG_GDBSTUB_PKT_DBG
   debug_write(data, len);
   debug_write((uint8_t*)"]\n", 2);
#endif

   while(len)
   {
      switch(*data)
      {
      case GDB_ACK_BYTE:
	 if(!gdb_enabled())
	 {
	    debug(GDBSTUB_PKT, "gdb connect\n");
	    gdb_enable();
	 }
	 done = 1;
	 break;

      case GDB_PKT_BYTE:
	 done = gdb_parse_packet(data, len);
	 if(!done)
	    goto __end;
	 break;

      case GDB_INT_BYTE:
	 done = 1;
	 debug(GDBSTUB_PKT, "interrupt sequence requested\n");
	 gdb_interrupt_sequence();
	 break;

      case GDB_NAK_BYTE:
	 done = 1;
	 gdb_ack();
	 break;

      default:
	 done = 1;
	 debug(GDBSTUB_PKT, "gdb_stub unsupported '\\x%x' (sz %D)\n", *data, len);
	 gdb_unsupported();
	 break;
      }

      len -= done;
      data += done;
   }

__end:
   return len;
}
Example #3
0
static void __gdb_cmd_resume(uint8_t stp)
{
   dbg_resume(stp);
   gdb_ack();
   gdb_set_lock(0);
}
Example #4
0
static int gdbserver_main(struct GDBState *s)
{
    char buf[MAX_PACKET_LEN];
    char outbuf[MAX_PACKET_LEN];
    char *ptr;
    uint32_t addr, len;
    int32_t thread, type, ret;

    for (;;) {
        memset(buf, 0, sizeof(buf));
        memset(outbuf, 0, sizeof(outbuf));
        get_packet(s, &buf[0]);
        gdb_ack(s);
        printf("command (%lu): %s\n", strlen(buf), buf);
        ptr = &buf[3];
        switch (buf[2]) {
            case '?':
                gdb_reply(s, "T05thread:00;");
                break;
            case 'g':
                cpu_read_registers(s, outbuf);
                gdb_reply(s, outbuf);
                break;
            case 'H':
                type = *ptr++;
                thread = strtoull(ptr, (char **)&ptr, 16);
                if (thread <= 0) {
                    gdb_reply(s, "OK");
                    break;
                } else if (thread >= 1) {
                    gdb_reply(s, "E22");
                    break;
                }
                switch (type) {
                    case 'c':
                    case 'g':
                        gdb_reply(s, "OK");
                        break;
                    default:
                        gdb_reply(s, "E22");
                        break;
                }
                break;
            case 'k':
                goto end_command;
            case 'm':
                /* +$m9200,4#98 */
                addr = strtoull(ptr, (char **)&ptr, 16);
                if (*ptr == ',')
                    ++ptr;
                len = strtoull(ptr, NULL, 16);
                cpu_read_memory(s, addr, len, outbuf);
                gdb_reply(s, outbuf);
                break;
            case 'p':
                outbuf[0] = '\0';
                gdb_reply(s, outbuf);
                break;
            case 'q':
                if (!strncmp(ptr, "Supported", 9)) {
                    snprintf(outbuf, sizeof(outbuf), "PacketSize=%x", MAX_PACKET_LEN);
                    gdb_reply(s, outbuf);
                } else if (!strncmp(ptr, "Offset", 6)) {
                    gdb_reply(s, "Text=00000000;Data=00000000;Bss=00000000");
                } else if (*ptr == 'C')
                    gdb_reply(s, "QC1");
                else
                    gdb_reply(s, "");
                break;
            case 'v':
                if (!strncmp(ptr, "Cont", 4)) {
                    ptr += 4;
                    if (*ptr == '?') {
                        gdb_reply(s, "vCont;c;C;s;S");
                        break;
                    }
                    //set_reg(s->env, REG_PC, get_reg(s->env, REG_PC)+4);
                    set_reg(s->env, REG_PC, 0x8224);
                    gdb_reply(s, "S05");
                } else
                    return 0;
                break;
            case 'z':
            case 'Z':
                type = strtoul(ptr, (char **)&ptr, 16);
                if (*ptr == ',')
                    ptr++;
                addr = strtoull(ptr, (char **)&ptr, 16);
                if (*ptr == ',')
                    ptr++;
                len = strtoull(ptr, (char **)&ptr, 16);
                if (buf[2] == 'Z')
                    ret = gdb_breakpoint_insert(addr, len, type);
                else
                    ret = gdb_breakpoint_remove(addr, len, type);
                if (ret >= 0)
                    gdb_reply(s, "OK");
                break;
            default:
                return 0;
        }
    }

end_command:

    return 0;
}
Example #5
0
/*
 * command parsing an dispatching
 */
static
int
gdb_parse_command(unsigned int *regfile)
{
	if(!gdb_verify_checksum()) {
		gdb_nak();
		return INIT;
	} else {
		gdb_ack();
	}

	switch(cmd[0]) {

		case 'H':
			{
				/*
				 * Command H (actually Hct) is used to select
				 * the current thread (-1 meaning all threads)
				 * We just fake we recognize the the command
				 * and send an 'OK' response.
				 */
				gdb_reply("OK");
			} break;

		case 'q':
			{
				extern unsigned __data_start;
				extern unsigned __bss_start;

				/*
				 * There are several q commands:
				 *
				 *     qXXXX        Request info about XXXX.
				 *     QXXXX=yyyy   Set value of XXXX to yyyy.
				 *     qOffsets     Get segment offsets
				 *
				 * Currently we only support the 'qOffsets'
				 * form.
				 *
				 * *Note* that we actually have to lie,
				 * At first thought looks like we should
				 * return '_start', '__data_start' &
				 * '__bss_start', however gdb gets
				 * confused because the kernel link script
				 * pre-links at 0x80000000. To keep gdb
				 * gdb happy we just substract that amount.
				 */
				if(strcmp(cmd+1, "Offsets")== 0) {
					gdb_reply(
						"Text=%x;Data=%x;Bss=%x",
						0,
						((unsigned)(&__data_start))-0x80000000,
						((unsigned)(&__bss_start))-0x80000000
					);
				} else {
					gdb_reply("ENS");
				}
			} break;

		case '?':
			{
				/*
				 * command '?' is used for retrieving the signal
				 * that stopped the program. Fully implemeting
				 * this command requires help from the debugger,
				 * by now we just fake a SIGKILL
				 */
				gdb_reply("S09");	/* SIGKILL = 9 */
			} break;

		case 'g':
			{
				/*
				 * command 'g' is used for reading the register
				 * file. Faked by now.
				 *
				 * For x86 the register order is:
				 *
				 *    eax, ebx, ecx, edx,
				 *    esp, ebp, esi, edi,
				 *    eip, eflags,
				 *    cs, ss, ds, es
				 *
				 * Note that even thought the segment descriptors
				 * are actually 16 bits wide, gdb requires them
				 * as 32 bit integers. Note also that for some
				 * reason (unknown to me) gdb wants the register
				 * dump in *big endian* format.
				 */
				gdb_regreply(regfile, GDB_REGISTER_FILE_COUNT);
			} break;

		case 'm':
			{
				char *ptr;
				unsigned address;
				unsigned len;

				/*
				 * The 'm' command has the form mAAA,LLL
				 * where AAA is the address and LLL is the
				 * number of bytes.
				 */
				ptr= cmd+1;
				address= 0;
				len= 0;
				while(ptr && *ptr && (*ptr!= ',')) {
					address<<= 4;
					address+= parse_nibble(*ptr);
					ptr+= 1;
				}
				if(*ptr== ',') {
					ptr+= 1;
				}
				while(ptr && *ptr) {
					len<<= 4;
					len+= parse_nibble(*ptr);
					ptr+= 1;
				}

				if(len> 128) {
					len= 128;
				}

				/*
				 * We cannot directly access the requested memory
				 * for gdb may be trying to access an stray pointer
				 * We copy the memory to a safe buffer using
				 * the bulletproof user_memcpy().
				 */
				if(user_memcpy(safe_mem, (char*)address, len)< 0) {
					gdb_reply("E02");
				} else {
					gdb_memreply(safe_mem, len);
				}
			} break;

		case 'k':
			{
				/*
				 * Command 'k' actual semantics is 'kill the damn thing'.
				 * However gdb sends that command when you disconnect
				 * from a debug session. I guess that 'kill' for the
				 * kernel would map to reboot... however that's a
				 * a very mean thing to do, instead we just quit
				 * the gdb state machine and fallback to the regular
				 * kernel debugger command prompt.
				 */
				return QUIT;
			} break;

		default:
			{
				gdb_reply("E01");
			} break;
	}

	return WAITACK;
}