This is an automated email from Gerrit.

Matthias Welwarsky ([email protected]) just uploaded a new patch set to 
Gerrit, which you can find at http://openocd.zylin.com/4448

-- gerrit

commit 0ec91879a9d6c26d7087a211c6697b601770ffc7
Author: Matthias Welwarsky <[email protected]>
Date:   Mon Mar 5 14:50:51 2018 +0100

    gdb_server: fake step if thread is not current rtos thread
    
    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 <[email protected]>

diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index a15c5bb..e466290 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -2622,6 +2622,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;
@@ -2637,9 +2639,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;
@@ -2673,10 +2686,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;

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to