aboutsummaryrefslogtreecommitdiff
path: root/src/gdb_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gdb_main.c')
-rw-r--r--src/gdb_main.c133
1 files changed, 74 insertions, 59 deletions
diff --git a/src/gdb_main.c b/src/gdb_main.c
index d93a8ce..6b2059f 100644
--- a/src/gdb_main.c
+++ b/src/gdb_main.c
@@ -24,26 +24,15 @@
* Originally written for GDB 6.8, updated and tested with GDB 7.2.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <assert.h>
-
-#include "platform.h"
-
#include "general.h"
#include "hex_utils.h"
#include "gdb_if.h"
#include "gdb_packet.h"
#include "gdb_main.h"
-
#include "jtagtap.h"
#include "jtag_scan.h"
#include "adiv5.h"
-
#include "target.h"
-
#include "command.h"
#include "crc32.h"
@@ -52,7 +41,7 @@
#define ERROR_IF_NO_TARGET() \
if(!cur_target) { gdb_putpacketz("EFF"); break; }
-static unsigned char pbuf[BUF_SIZE];
+static char pbuf[BUF_SIZE];
static target *cur_target;
static target *last_target;
@@ -75,6 +64,7 @@ gdb_main(void)
{
int size;
bool single_step = false;
+ char last_activity = 0;
DEBUG("Entring GDB protocol main loop\n");
/* GDB protocol main loop */
@@ -82,25 +72,24 @@ gdb_main(void)
SET_IDLE_STATE(1);
size = gdb_getpacket(pbuf, BUF_SIZE);
SET_IDLE_STATE(0);
+ continue_activity:
switch(pbuf[0]) {
/* Implementation of these is mandatory! */
case 'g': { /* 'g': Read general registers */
ERROR_IF_NO_TARGET();
- uint32_t arm_regs[cur_target->regs_size];
- target_regs_read(cur_target, (void*)arm_regs);
- gdb_putpacket(hexify(pbuf, (void*)arm_regs, cur_target->regs_size), cur_target->regs_size * 2);
+ uint8_t arm_regs[target_regs_size(cur_target)];
+ target_regs_read(cur_target, arm_regs);
+ gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)),
+ sizeof(arm_regs) * 2);
break;
}
case 'm': { /* 'm addr,len': Read len bytes from addr */
uint32_t addr, len;
ERROR_IF_NO_TARGET();
- sscanf(pbuf, "m%08lX,%08lX", &addr, &len);
- DEBUG("m packet: addr = %08lX, len = %08lX\n", addr, len);
+ sscanf(pbuf, "m%" SCNx32 ",%" SCNx32, &addr, &len);
+ DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
uint8_t mem[len];
- if(((addr & 3) == 0) && ((len & 3) == 0))
- target_mem_read_words(cur_target, (void*)mem, addr, len);
- else
- target_mem_read_bytes(cur_target, (void*)mem, addr, len);
+ target_mem_read(cur_target, mem, addr, len);
if(target_check_error(cur_target))
gdb_putpacketz("E01");
else
@@ -109,8 +98,8 @@ gdb_main(void)
}
case 'G': { /* 'G XX': Write general registers */
ERROR_IF_NO_TARGET();
- uint32_t arm_regs[cur_target->regs_size];
- unhexify((void*)arm_regs, &pbuf[1], cur_target->regs_size);
+ uint8_t arm_regs[target_regs_size(cur_target)];
+ unhexify(arm_regs, &pbuf[1], sizeof(arm_regs));
target_regs_write(cur_target, arm_regs);
gdb_putpacketz("OK");
break;
@@ -119,14 +108,11 @@ gdb_main(void)
uint32_t addr, len;
int hex;
ERROR_IF_NO_TARGET();
- sscanf(pbuf, "M%08lX,%08lX:%n", &addr, &len, &hex);
- DEBUG("M packet: addr = %08lX, len = %08lX\n", addr, len);
+ sscanf(pbuf, "M%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &hex);
+ DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
uint8_t mem[len];
unhexify(mem, pbuf + hex, len);
- if(((addr & 3) == 0) && ((len & 3) == 0))
- target_mem_write_words(cur_target, addr, (void*)mem, len);
- else
- target_mem_write_bytes(cur_target, addr, (void*)mem, len);
+ target_mem_write(cur_target, addr, mem, len);
if(target_check_error(cur_target))
gdb_putpacketz("E01");
else
@@ -158,14 +144,27 @@ gdb_main(void)
break;
}
+ last_activity = pbuf[0];
/* Wait for target halt */
while(!(sig = target_halt_wait(cur_target))) {
unsigned char c = gdb_if_getchar_to(0);
if((c == '\x03') || (c == '\x04')) {
target_halt_request(cur_target);
+ last_activity = 's';
}
}
SET_RUN_STATE(0);
+
+ /* Negative signal indicates we're in a syscall */
+ if (sig < 0)
+ break;
+
+ /* Target disappeared */
+ if (cur_target == NULL) {
+ gdb_putpacket_f("X%02X", sig);
+ break;
+ }
+
/* Report reason for halt */
if(target_check_hw_wp(cur_target, &watch_addr)) {
/* Watchpoint hit */
@@ -175,6 +174,28 @@ gdb_main(void)
}
break;
}
+ case 'F': { /* Semihosting call finished */
+ int retcode, errcode, items;
+ char c, *p;
+ if (pbuf[1] == '-')
+ p = &pbuf[2];
+ else
+ p = &pbuf[1];
+ items = sscanf(p, "%x,%x,%c", &retcode, &errcode, &c);
+ if (pbuf[1] == '-')
+ retcode = -retcode;
+
+ target_hostio_reply(cur_target, retcode, errcode);
+
+ /* if break is requested */
+ if (items == 3 && c == 'C') {
+ gdb_putpacketz("T02");
+ break;
+ }
+
+ pbuf[0] = last_activity;
+ goto continue_activity;
+ }
/* Optional GDB packet support */
case '!': /* Enable Extended GDB Protocol. */
@@ -186,7 +207,7 @@ gdb_main(void)
break;
case 0x04:
- case 'D': /* GDB 'detach' command. */
+ case 'D': /* GDB 'detach' command. */
if(cur_target)
target_detach(cur_target);
last_target = cur_target;
@@ -218,12 +239,9 @@ gdb_main(void)
uint32_t addr, len;
int bin;
ERROR_IF_NO_TARGET();
- sscanf(pbuf, "X%08lX,%08lX:%n", &addr, &len, &bin);
- DEBUG("X packet: addr = %08lX, len = %08lX\n", addr, len);
- if(((addr & 3) == 0) && ((len & 3) == 0))
- target_mem_write_words(cur_target, addr, (void*)pbuf+bin, len);
- else
- target_mem_write_bytes(cur_target, addr, (void*)pbuf+bin, len);
+ sscanf(pbuf, "X%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &bin);
+ DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
+ target_mem_write(cur_target, addr, pbuf+bin, len);
if(target_check_error(cur_target))
gdb_putpacketz("E01");
else
@@ -258,12 +276,12 @@ handle_q_string_reply(const char *str, const char *param)
{
unsigned long addr, len;
- if (sscanf(param, "%08lX,%08lX", &addr, &len) != 2) {
+ if (sscanf(param, "%08lx,%08lx", &addr, &len) != 2) {
gdb_putpacketz("E01");
return;
}
if (addr < strlen (str)) {
- uint8_t reply[len+2];
+ char reply[len+2];
reply[0] = 'm';
strncpy (reply + 1, &str[addr], len);
if(len > strlen(&str[addr]))
@@ -281,7 +299,7 @@ handle_q_packet(char *packet, int len)
uint32_t addr, alen;
if(!strncmp(packet, "qRcmd,", 6)) {
- unsigned char *data;
+ char *data;
int datalen;
/* calculate size and allocate buffer for command */
@@ -310,11 +328,11 @@ handle_q_packet(char *packet, int len)
cur_target = target_attach(last_target,
gdb_target_destroy_callback);
}
- if((!cur_target) || (!cur_target->xml_mem_map)) {
+ if (!cur_target) {
gdb_putpacketz("E01");
return;
}
- handle_q_string_reply(cur_target->xml_mem_map, packet + 23);
+ handle_q_string_reply(target_mem_map(cur_target), packet + 23);
} else if (strncmp (packet, "qXfer:features:read:target.xml:", 31) == 0) {
/* Read target description */
@@ -323,12 +341,12 @@ handle_q_packet(char *packet, int len)
cur_target = target_attach(last_target,
gdb_target_destroy_callback);
}
- if((!cur_target) || (!cur_target->tdesc)) {
+ if (!cur_target) {
gdb_putpacketz("E01");
return;
}
- handle_q_string_reply(cur_target->tdesc, packet + 31);
- } else if (sscanf(packet, "qCRC:%08lX,%08lX", &addr, &alen) == 2) {
+ handle_q_string_reply(target_tdesc(cur_target), packet + 31);
+ } else if (sscanf(packet, "qCRC:%" PRIx32 ",%" PRIx32, &addr, &alen) == 2) {
if(!cur_target) {
gdb_putpacketz("E01");
return;
@@ -348,7 +366,7 @@ handle_v_packet(char *packet, int plen)
int bin;
static uint8_t flash_mode = 0;
- if (sscanf(packet, "vAttach;%08lX", &addr) == 1) {
+ if (sscanf(packet, "vAttach;%08lx", &addr) == 1) {
/* Attach to remote target processor */
target *t;
uint32_t i;
@@ -371,11 +389,16 @@ handle_v_packet(char *packet, int plen)
} else if(last_target) {
cur_target = target_attach(last_target,
gdb_target_destroy_callback);
- target_reset(cur_target);
- gdb_putpacketz("T05");
+
+ /* If we were able to attach to the target again */
+ if (cur_target) {
+ target_reset(cur_target);
+ gdb_putpacketz("T05");
+ } else gdb_putpacketz("E01");
+
} else gdb_putpacketz("E01");
- } else if (sscanf(packet, "vFlashErase:%08lX,%08lX", &addr, &len) == 2) {
+ } else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) {
/* Erase Flash Memory */
DEBUG("Flash Erase %08lX %08lX\n", addr, len);
if(!cur_target) { gdb_putpacketz("EFF"); return; }
@@ -391,7 +414,7 @@ handle_v_packet(char *packet, int plen)
else
gdb_putpacketz("EFF");
- } else if (sscanf(packet, "vFlashWrite:%08lX:%n", &addr, &bin) == 1) {
+ } else if (sscanf(packet, "vFlashWrite:%08lx:%n", &addr, &bin) == 1) {
/* Write Flash Memory */
len = plen - bin;
DEBUG("Flash Write %08lX %08lX\n", addr, len);
@@ -402,7 +425,7 @@ handle_v_packet(char *packet, int plen)
} else if (!strcmp(packet, "vFlashDone")) {
/* Commit flash operations. */
- gdb_putpacketz("OK");
+ gdb_putpacketz(target_flash_done(cur_target) ? "EFF" : "OK");
flash_mode = 0;
} else {
@@ -425,13 +448,9 @@ handle_z_packet(char *packet, int plen)
* with real sscanf() though... */
//sscanf(packet, "%*[zZ]%hhd,%08lX,%hhd", &type, &addr, &len);
type = packet[1] - '0';
- sscanf(packet + 2, ",%08lX,%d", &addr, &len);
+ sscanf(packet + 2, ",%" PRIx32 ",%d", &addr, &len);
switch(type) {
case 1: /* Hardware breakpoint */
- if(!cur_target->set_hw_bp) { /* Not supported */
- gdb_putpacketz("");
- return;
- }
if(set)
ret = target_set_hw_bp(cur_target, addr);
else
@@ -441,10 +460,6 @@ handle_z_packet(char *packet, int plen)
case 2:
case 3:
case 4:
- if(!cur_target->set_hw_wp) { /* Not supported */
- gdb_putpacketz("");
- return;
- }
if(set)
ret = target_set_hw_wp(cur_target, type, addr, len);
else