]> git.sur5r.net Git - openocd/commitdiff
gdb_server: add support for vCont
authorMatthias Welwarsky <matthias.welwarsky@sysgo.com>
Wed, 20 Sep 2017 10:02:08 +0000 (12:02 +0200)
committerMatthias Welwarsky <matthias@welwarsky.de>
Wed, 21 Feb 2018 11:51:16 +0000 (11:51 +0000)
Make gdb use target support for single-stepping if available.

Change-Id: Ie72345a1e749aefba7cd175ccbf5cf51d4f1a632
Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
Reviewed-on: http://openocd.zylin.com/3833
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
src/server/gdb_server.c

index f90f12bb5c805c3c86dabb38ccad71e3b44994dc..d866fc6e2a4641167875f2294e4aae2bcd2cb980 100644 (file)
@@ -41,6 +41,8 @@
 #include <target/breakpoints.h>
 #include <target/target_request.h>
 #include <target/register.h>
+#include <target/target.h>
+#include <target/target_type.h>
 #include "server.h"
 #include <flash/nor/core.h>
 #include "gdb_server.h"
@@ -110,6 +112,8 @@ static char *gdb_port_next;
 static void gdb_log_callback(void *priv, const char *file, unsigned line,
                const char *function, const char *string);
 
+static void gdb_sig_halted(struct connection *connection);
+
 /* number of gdb connections, mainly to suppress gdb related debugging spam
  * in helper/log.c when no gdb connections are actually active */
 int gdb_actual_connections;
@@ -2470,7 +2474,7 @@ static int gdb_query_packet(struct connection *connection,
                        &buffer,
                        &pos,
                        &size,
-                       "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;qXfer:threads:read+;QStartNoAckMode+",
+                       "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;qXfer:threads:read+;QStartNoAckMode+;vContSupported+",
                        (GDB_BUFFER_SIZE - 1),
                        ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-',
                        (gdb_target_desc_supported == 1) ? '+' : '-');
@@ -2559,6 +2563,90 @@ static int gdb_query_packet(struct connection *connection,
        return ERROR_OK;
 }
 
+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);
+       const char *parse = packet;
+       int retval;
+
+       /* query for vCont supported */
+       if (parse[0] == '?') {
+               if (target->type->step != NULL) {
+                       /* gdb doesn't accept c without C and s without S */
+                       gdb_put_packet(connection, "vCont;c;C;s;S", 13);
+                       return true;
+               }
+               return false;
+       }
+
+       if (parse[0] == ';') {
+               ++parse;
+               --packet_size;
+       }
+
+       /* simple case, a continue packet */
+       if (parse[0] == 'c') {
+               LOG_DEBUG("target %s continue", target_name(target));
+               log_add_callback(gdb_log_callback, connection);
+               retval = target_resume(target, 1, 0, 0, 0);
+               if (retval == ERROR_OK) {
+                       gdb_connection->frontend_state = TARGET_RUNNING;
+                       target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
+               }
+               return true;
+       }
+
+       /* single-step or step-over-breakpoint */
+       if (parse[0] == 's') {
+               if (strncmp(parse, "s:", 2) == 0) {
+                       int handle_breakpoint = 1;
+                       struct target *ct = target;
+                       int64_t thread_id;
+                       char *endp;
+
+                       parse += 2;
+                       packet_size -= 2;
+
+                       thread_id = strtoll(parse, &endp, 16);
+                       if (endp != NULL) {
+                               packet_size -= endp - parse;
+                               parse = endp;
+                       }
+
+                       if (parse[0] == ';') {
+                               ++parse;
+                               --packet_size;
+
+                               if (parse[0] == 'c') {
+                                       parse += 1;
+                                       packet_size -= 1;
+
+                                       handle_breakpoint = 0;
+                               }
+                       }
+
+                       LOG_DEBUG("target %s single-step thread %"PRId64, target_name(ct), thread_id);
+                       retval = target_step(ct, 1, 0, handle_breakpoint);
+                       if (retval == ERROR_OK) {
+                               gdb_signal_reply(target, connection);
+                               /* stop forwarding log packets! */
+                               log_remove_callback(gdb_log_callback, connection);
+                       } else
+                       if (retval == ERROR_TARGET_TIMEOUT) {
+                               gdb_connection->frontend_state = TARGET_RUNNING;
+                               target_call_event_callbacks(ct, TARGET_EVENT_GDB_START);
+                       }
+               } else {
+                       LOG_ERROR("Unknown vCont packet");
+                       return false;
+               }
+               return true;
+       }
+
+       return false;
+}
+
 static int gdb_v_packet(struct connection *connection,
                char const *packet, int packet_size)
 {
@@ -2568,6 +2656,19 @@ static int gdb_v_packet(struct connection *connection,
 
        target = get_target_from_connection(connection);
 
+       if (strncmp(packet, "vCont", 5) == 0) {
+               bool handled;
+
+               packet += 5;
+               packet_size -= 5;
+
+               handled = gdb_handle_vcont_packet(connection, packet, packet_size);
+               if (!handled)
+                       gdb_put_packet(connection, "", 0);
+
+               return ERROR_OK;
+       }
+
        /* if flash programming disabled - send a empty reply */
 
        if (gdb_flash_program == 0) {