gdb_server: fake step if thread is not current rtos thread 48/4448/11
authorMatthias Welwarsky <matthias.welwarsky@sysgo.com>
Mon, 5 Mar 2018 13:50:51 +0000 (14:50 +0100)
committerMatthias Welwarsky <matthias@welwarsky.de>
Fri, 16 Mar 2018 08:57:20 +0000 (08:57 +0000)
gdb assumes that a rtos can make any thread active at will in response
to a 'Hg' packet. It further assumes that it needs to step-over after
setting a breakpoint on frame #0 of any non-current thread. Both
assumptions are not valid for an actual rtos. We fake the step-over to
not trigger an internal error in gdb. See
https://sourceware.org/bugzilla/show_bug.cgi?id=22925 for details.

Change-Id: Ida60cd134033c1d58ada77b87fe664a58f61e2c0
Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
Reviewed-on: http://openocd.zylin.com/4448
Tested-by: jenkins
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
src/server/gdb_server.c

index 712c393417353c5a90bcf532a5c1daa5f66ac8d9..74074a1f116c139ce32fdf24ef3f67ec16d7b207 100644 (file)
@@ -2695,6 +2695,8 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p
 
        /* single-step or step-over-breakpoint */
        if (parse[0] == 's') {
+               bool fake_step = false;
+
                if (strncmp(parse, "s:", 2) == 0) {
                        struct target *ct = target;
                        int current_pc = 1;
@@ -2710,9 +2712,20 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p
                                parse = endp;
                        }
 
-                       if (target->rtos != NULL)
+                       if (target->rtos != NULL) {
+                               /* FIXME: why is this necessary? rtos state should be up-to-date here already! */
+                               rtos_update_threads(target);
+
                                target->rtos->gdb_target_for_threadid(connection, thread_id, &ct);
 
+                               /*
+                                * check if the thread to be stepped is the current rtos thread
+                                * if not, we must fake the step
+                                */
+                               if (target->rtos->current_thread != thread_id)
+                                       fake_step = true;
+                       }
+
                        if (parse[0] == ';') {
                                ++parse;
                                --packet_size;
@@ -2746,10 +2759,33 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p
                                }
                        }
 
-                       LOG_DEBUG("target %s single-step thread %"PRId64, target_name(ct), thread_id);
+                       LOG_DEBUG("target %s single-step thread %"PRIx64, target_name(ct), thread_id);
                        log_add_callback(gdb_log_callback, connection);
                        target_call_event_callbacks(ct, TARGET_EVENT_GDB_START);
 
+                       /*
+                        * work around an annoying gdb behaviour: when the current thread
+                        * is changed in gdb, it assumes that the target can follow and also
+                        * make the thread current. This is an assumption that cannot hold
+                        * for a real target running a multi-threading OS. We just fake
+                        * the step to not trigger an internal error in gdb. See
+                        * https://sourceware.org/bugzilla/show_bug.cgi?id=22925 for details
+                        */
+                       if (fake_step) {
+                               int sig_reply_len;
+                               char sig_reply[128];
+
+                               LOG_DEBUG("fake step thread %"PRIx64, thread_id);
+
+                               sig_reply_len = snprintf(sig_reply, sizeof(sig_reply),
+                                                                                "T05thread:%016"PRIx64";", thread_id);
+
+                               gdb_put_packet(connection, sig_reply, sig_reply_len);
+                               log_remove_callback(gdb_log_callback, connection);
+
+                               return true;
+                       }
+
                        /* support for gdb_sync command */
                        if (gdb_connection->sync) {
                                gdb_connection->sync = false;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)