This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] [Ada/ravenscar] error during "continue" after task/thread switch


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0ca1fc291305ee1701b8236c0e26e8d8c5eaf0a2

commit 0ca1fc291305ee1701b8236c0e26e8d8c5eaf0a2
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Mon Apr 30 17:05:42 2018 -0500

    [Ada/ravenscar] error during "continue" after task/thread switch
    
    When debugging a program using the Ada ravenscar profile, resuming
    a program's execution after having switched to a different task
    sometimes yields the following error:
    
         (gdb) cont
         Continuing.
         Cannot execute this command while the target is running.
         Use the "interrupt" command to stop the target
         and then try again.
    
    In short, the Ravenscar profile is a standardized subset of Ada which
    allows tasking (often mapped to threads). We often use it on baremetal
    targets where there is no OS support. Thread support is implemented
    as a thread target_ops layer. It sits on top of the "remote" layer,
    so we can do thread debugging against baremetal targets to which GDB
    is connected via "target remote".
    
    What happens, when the user request the program to resume execution,
    is the following:
    
      - the ravenscar-thread target_ops layer gets the order to resume
        the program's execution. The current thread is not the active
        thread in the inferior, and the "remote" layer doesn't know
        about that thread anyway. So what we do is (see ravenscar_resume):
    
           + switch inferior_ptid to the ptid of the actually active thread;
           + ask the layer beneath us to actually do the resume.
    
      - Once that's done, the resuming itself is done. But execute_command
        (in top.c) actually does a bit more. More precisely, it unconditionally
        checks to see if the language may no longer be matching the current
        frame:
    
            check_frame_language_change ();
    
    The problem, here, is that we haven't received the "stop" event
    from the inferior, yet. This part will be handled by the event loop,
    which is done later. So, checking for the language-change here
    doesn't make sense, since we don't really have a frame. In our
    case, the error comes from the fact that we end up trying to read
    the registers, which causes the error while the remote protocol
    is waiting for the event showing the inferior stopped.
    
    This apparently used to work, but it is believed that this was only
    accidental. In other words, we had enough information already cached
    within GDB that we were able to perform the entire call to
    check_frame_language_change without actually querying the target.
    On PowerPC targets, this started to fail as a side-effect of a minor
    change in the way we get to the regcache during the handling of
    software-single-step (which seems fine).
    
    This patch fixes the issue by only calling check_frame_language_change
    in cases the inferior isn't running. Otherwise, it skips it, knowing
    that the event loop should eventually get to it.
    
    gdb/ChangeLog:
    
            * top.c (execute_command): Do not call check_frame_language_change
            if the inferior is running.
    
    Tested on x86_64-linux, no regression. Also tested on aarch64-elf,
    arm-elf, leon3-elf, and ppc-elf, but using AdaCore's testsuite.

Diff:
---
 gdb/top.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/gdb/top.c b/gdb/top.c
index 8903a92..d9d4639 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -642,7 +642,12 @@ execute_command (const char *p, int from_tty)
 	}
     }
 
-  check_frame_language_change ();
+  /* Only perform the frame-language-change check if the command
+     we just finished executing did not resume the inferior's execution.
+     If it did resume the inferior, we will do that check after
+     the inferior stopped.  */
+  if (has_stack_frames () && !is_running (inferior_ptid))
+    check_frame_language_change ();
 
   discard_cleanups (cleanup_if_error);
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]