aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2022-10-27 14:42:23 -0700
committerTim Newsome <tim@sifive.com>2022-11-22 09:29:50 -0800
commite69735db0bb5dc0932f741815dab00849bf10f9c (patch)
tree98809553cec6cd4bc21477655747c1c2764f7026
parentb1f3a7581928f66f8e87a1cb4307065068747088 (diff)
downloadriscv-openocd-e69735db0bb5dc0932f741815dab00849bf10f9c.zip
riscv-openocd-e69735db0bb5dc0932f741815dab00849bf10f9c.tar.gz
riscv-openocd-e69735db0bb5dc0932f741815dab00849bf10f9c.tar.bz2
gdb_server: Operate on available targets.
When SMP is enabled, gdb will always use the first target in the SMP group. That doesn't work when that first target is unavailable, but others in the SMP group are still available. For cases where gdb expects an operation to affect the entire group (run control, memory access), find the first available target in an SMP group and use that. Change-Id: I4bed600da3ac0fdfe4287d8fdd090a58452db501 Signed-off-by: Tim Newsome <tim@sifive.com>
-rw-r--r--src/server/gdb_server.c56
1 files changed, 40 insertions, 16 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 67dfb9c..edea5f5 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -154,6 +154,29 @@ static int gdb_use_target_description = 1;
/* current processing free-run type, used by file-I/O */
static char gdb_running_type;
+/* Find an available target in the SMP group that gdb is connected to. For
+ * commands that affect an entire SMP group (like memory access and run control)
+ * this will give better results than returning the unavailable target and having
+ * the command fail. If gdb was aware that targets can be unavailable we
+ * wouldn't need this logic.
+ */
+struct target *get_available_target_from_connection(struct connection *connection)
+{
+ struct gdb_service *gdb_service = connection->service->priv;
+ struct target *target = gdb_service->target;
+ if (target->state == TARGET_UNAVAILABLE && target->smp) {
+ struct target_list *tlist;
+ foreach_smp_target(tlist, target->smp_targets) {
+ struct target *t = tlist->target;
+ if (t->state != TARGET_UNAVAILABLE)
+ return t;
+ }
+ /* If we can't find an available target, just return the
+ * original. */
+ }
+ return target;
+}
+
static int gdb_last_signal(struct target *target)
{
switch (target->debug_reason) {
@@ -976,9 +999,9 @@ static int gdb_target_callback_event_handler(struct target *target,
enum target_event event, void *priv)
{
struct connection *connection = priv;
- struct gdb_service *gdb_service = connection->service->priv;
+ struct target *gdb_target = get_available_target_from_connection(connection);
- if (gdb_service->target != target)
+ if (gdb_target != target)
return ERROR_OK;
switch (event) {
@@ -1503,7 +1526,7 @@ static int gdb_error(struct connection *connection, int retval)
static int gdb_read_memory_packet(struct connection *connection,
char const *packet, int packet_size)
{
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
char *separator;
uint64_t addr = 0;
uint32_t len = 0;
@@ -1578,7 +1601,7 @@ static int gdb_read_memory_packet(struct connection *connection,
static int gdb_write_memory_packet(struct connection *connection,
char const *packet, int packet_size)
{
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
char *separator;
uint64_t addr = 0;
uint32_t len = 0;
@@ -1629,7 +1652,7 @@ static int gdb_write_memory_packet(struct connection *connection,
static int gdb_write_memory_binary_packet(struct connection *connection,
char const *packet, int packet_size)
{
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
char *separator;
uint64_t addr = 0;
uint32_t len = 0;
@@ -1708,7 +1731,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
static int gdb_step_continue_packet(struct connection *connection,
char const *packet, int packet_size)
{
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
int current = 0;
uint64_t address = 0x0;
int retval = ERROR_OK;
@@ -1736,7 +1759,7 @@ static int gdb_step_continue_packet(struct connection *connection,
static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
char const *packet, int packet_size)
{
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
int type;
enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */;
@@ -1918,7 +1941,7 @@ static int gdb_memory_map(struct connection *connection,
* have to regenerate it a couple of times.
*/
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
struct flash_bank *p;
char *xml = NULL;
int size = 0;
@@ -2988,7 +3011,7 @@ static int gdb_query_packet(struct connection *connection,
static bool gdb_handle_vcont_packet(struct connection *connection, const char *packet, int packet_size)
{
struct gdb_connection *gdb_connection = connection->priv;
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
const char *parse = packet;
int retval;
@@ -3227,7 +3250,7 @@ static void gdb_restart_inferior(struct connection *connection, const char *pack
static bool gdb_handle_vrun_packet(struct connection *connection, const char *packet, int packet_size)
{
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
const char *parse = packet;
/* Skip "vRun" */
@@ -3273,7 +3296,7 @@ static int gdb_v_packet(struct connection *connection,
struct gdb_connection *gdb_connection = connection->priv;
int result;
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
if (strncmp(packet, "vCont", 5) == 0) {
bool handled;
@@ -3444,7 +3467,7 @@ static int gdb_detach(struct connection *connection)
static int gdb_fileio_response_packet(struct connection *connection,
char const *packet, int packet_size)
{
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
char *separator;
char *parsing_point;
int fileio_retcode = strtoul(packet + 1, &separator, 16);
@@ -3731,10 +3754,11 @@ static int gdb_input_inner(struct connection *connection)
}
if (gdb_con->ctrl_c) {
- if (target->state == TARGET_RUNNING) {
- struct target *t = target;
- if (target->rtos)
- target->rtos->gdb_target_for_threadid(connection, target->rtos->current_threadid, &t);
+ struct target *available_target = get_available_target_from_connection(connection);
+ if (available_target->state == TARGET_RUNNING) {
+ struct target *t = available_target;
+ if (available_target->rtos)
+ available_target->rtos->gdb_target_for_threadid(connection, target->rtos->current_threadid, &t);
retval = target_halt(t);
if (retval == ERROR_OK)
retval = target_poll(t);