Пример #1
0
static void gdb_read_mem()
{
  static u8 reply[GDB_BFR_MAX - 4];
  u32 addr, len;
  u32 i;

  i = 1;
  addr = 0;
  while (cmd_bfr[i] != ',')
    addr = (addr << 4) | hex2char(cmd_bfr[i++]);
  i++;

  len = 0;
  while (i < cmd_len)
    len = (len << 4) | hex2char(cmd_bfr[i++]);
  DEBUG_LOG(GDB_STUB, "gdb: read memory: %08x bytes from %08x", len, addr);

  if (len * 2 > sizeof reply)
    gdb_reply("E01");
  u8* data = Memory::GetPointer(addr);
  if (!data)
    return gdb_reply("E0");
  mem2hex(reply, data, len);
  reply[len * 2] = '\0';
  gdb_reply((char*)reply);
}
Пример #2
0
static void gdb_handle_set_thread()
{
  if (memcmp(cmd_bfr, "Hg0", 3) == 0 || memcmp(cmd_bfr, "Hc-1", 4) == 0 ||
      memcmp(cmd_bfr, "Hc0", 4) == 0 || memcmp(cmd_bfr, "Hc1", 4) == 0)
    return gdb_reply("OK");
  gdb_reply("E01");
}
Пример #3
0
static void gdb_handle_query()
{
  DEBUG_LOG(GDB_STUB, "gdb: query '%s'", cmd_bfr + 1);

  if (!strcmp((const char*)(cmd_bfr + 1), "TStatus"))
  {
    return gdb_reply("T0");
  }

  gdb_reply("");
}
Пример #4
0
static void gdb_write_register()
{
  u32 id;

  u8* bufptr = cmd_bfr + 3;

  id = hex2char(cmd_bfr[1]);
  if (cmd_bfr[2] != '=')
  {
    ++bufptr;
    id <<= 4;
    id |= hex2char(cmd_bfr[2]);
  }

  switch (id)
  {
  case 0 ... 31:
    GPR(id) = re32hex(bufptr);
    break;
  case 32 ... 63:
    riPS0(id - 32) = re64hex(bufptr);
    break;
  case 64:
    PC = re32hex(bufptr);
    break;
  case 65:
    MSR.Hex = re32hex(bufptr);
    break;
  case 66:
    PowerPC::SetCR(re32hex(bufptr));
    break;
  case 67:
    LR = re32hex(bufptr);
    break;
  case 68:
    CTR = re32hex(bufptr);
    break;
  case 69:
    PowerPC::ppcState.spr[SPR_XER] = re32hex(bufptr);
    break;
  case 70:
    // do nothing, we dont have MQ
    break;
  case 71:
    FPSCR.Hex = re32hex(bufptr);
    break;
  default:
    return gdb_reply("E01");
    break;
  }

  gdb_reply("OK");
}
Пример #5
0
static void gdb_read_register()
{
  static u8 reply[64];
  u32 id;

  memset(reply, 0, sizeof reply);
  id = hex2char(cmd_bfr[1]);
  if (cmd_bfr[2] != '\0')
  {
    id <<= 4;
    id |= hex2char(cmd_bfr[2]);
  }

  switch (id)
  {
  case 0 ... 31:
    wbe32hex(reply, GPR(id));
    break;
  case 32 ... 63:
    wbe64hex(reply, riPS0(id - 32));
    break;
  case 64:
    wbe32hex(reply, PC);
    break;
  case 65:
    wbe32hex(reply, MSR.Hex);
    break;
  case 66:
    wbe32hex(reply, PowerPC::GetCR());
    break;
  case 67:
    wbe32hex(reply, LR);
    break;
  case 68:
    wbe32hex(reply, CTR);
    break;
  case 69:
    wbe32hex(reply, PowerPC::ppcState.spr[SPR_XER]);
    break;
  case 70:
    wbe32hex(reply, 0x0BADC0DE);
    break;
  case 71:
    wbe32hex(reply, FPSCR.Hex);
    break;
  default:
    return gdb_reply("E01");
    break;
  }

  gdb_reply((char*)reply);
}
Пример #6
0
static void gdb_handle_signal()
{
  char bfr[128];
  memset(bfr, 0, sizeof bfr);
  sprintf(bfr, "T%02x%02x:%08x;%02x:%08x;", sig, 64, PC, 1, GPR(1));
  gdb_reply(bfr);
}
Пример #7
0
static void gdb_write_mem()
{
  u32 addr, len;
  u32 i;

  i = 1;
  addr = 0;
  while (cmd_bfr[i] != ',')
    addr = (addr << 4) | hex2char(cmd_bfr[i++]);
  i++;

  len = 0;
  while (cmd_bfr[i] != ':')
    len = (len << 4) | hex2char(cmd_bfr[i++]);
  DEBUG_LOG(GDB_STUB, "gdb: write memory: %08x bytes to %08x", len, addr);

  u8* dst = Memory::GetPointer(addr);
  if (!dst)
    return gdb_reply("E00");
  hex2mem(dst, cmd_bfr + i + 1, len);
  gdb_reply("OK");
}
Пример #8
0
static void gdb_write_registers()
{
  u32 i;
  u8* bufptr = cmd_bfr;

  for (i = 0; i < 32; i++)
  {
    GPR(i) = re32hex(bufptr + i * 8);
  }
  bufptr += 32 * 8;

  gdb_reply("OK");
}
Пример #9
0
static void gdb_remove_bp()
{
  u32 type, addr, len, i;

  type = hex2char(cmd_bfr[1]);
  switch (type)
  {
  case 0:
  case 1:
    type = GDB_BP_TYPE_X;
    break;
  case 2:
    type = GDB_BP_TYPE_W;
    break;
  case 3:
    type = GDB_BP_TYPE_R;
    break;
  case 4:
    type = GDB_BP_TYPE_A;
    break;
  default:
    return gdb_reply("E01");
  }

  addr = 0;
  len = 0;

  i = 3;
  while (cmd_bfr[i] != ',')
    addr = (addr << 4) | hex2char(cmd_bfr[i++]);
  i++;

  while (i < cmd_len)
    len = (len << 4) | hex2char(cmd_bfr[i++]);

  gdb_bp_remove(type, addr, len);
  gdb_reply("OK");
}
Пример #10
0
static void _gdb_add_bp()
{
  u32 type;
  u32 i, addr = 0, len = 0;

  type = hex2char(cmd_bfr[1]);
  switch (type)
  {
  case 0:
  case 1:
    type = GDB_BP_TYPE_X;
    break;
  case 2:
    type = GDB_BP_TYPE_W;
    break;
  case 3:
    type = GDB_BP_TYPE_R;
    break;
  case 4:
    type = GDB_BP_TYPE_A;
    break;
  default:
    return gdb_reply("E01");
  }

  i = 3;
  while (cmd_bfr[i] != ',')
    addr = addr << 4 | hex2char(cmd_bfr[i++]);
  i++;

  while (i < cmd_len)
    len = len << 4 | hex2char(cmd_bfr[i++]);

  if (!gdb_add_bp(type, addr, len))
    return gdb_reply("E02");
  gdb_reply("OK");
}
Пример #11
0
static void gdb_read_registers()
{
  static u8 bfr[GDB_BFR_MAX - 4];
  u8* bufptr = bfr;
  u32 i;

  memset(bfr, 0, sizeof bfr);

  for (i = 0; i < 32; i++)
  {
    wbe32hex(bufptr + i * 8, GPR(i));
  }
  bufptr += 32 * 8;

  gdb_reply((char*)bfr);
}
Пример #12
0
void gdb_handle_exception()
{
  while (gdb_active())
  {
    if (!gdb_data_available())
      continue;
    gdb_read_command();
    if (cmd_len == 0)
      continue;

    switch (cmd_bfr[0])
    {
    case 'q':
      gdb_handle_query();
      break;
    case 'H':
      gdb_handle_set_thread();
      break;
    case '?':
      gdb_handle_signal();
      break;
    case 'k':
      gdb_deinit();
      INFO_LOG(GDB_STUB, "killed by gdb");
      return;
    case 'g':
      gdb_read_registers();
      break;
    case 'G':
      gdb_write_registers();
      break;
    case 'p':
      gdb_read_register();
      break;
    case 'P':
      gdb_write_register();
      break;
    case 'm':
      gdb_read_mem();
      break;
    case 'M':
      gdb_write_mem();
      PowerPC::ppcState.iCache.Reset();
      Host_UpdateDisasmDialog();
      break;
    case 's':
      gdb_step();
      return;
    case 'C':
    case 'c':
      gdb_continue();
      return;
    case 'z':
      gdb_remove_bp();
      break;
    case 'Z':
      _gdb_add_bp();
      break;
    default:
      gdb_reply("");
      break;
    }
  }
}
Пример #13
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;
}
Пример #14
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;
}