Andrew Burgess 4f626cad04 gdb/remote: some fixes for 'maint set target-async off'
While working on another patch relating to remote targets, I wanted to
test with 'maint set target-async off' in place.  Unfortunately I ran
into some problems.  This commit is an attempt to fix one of the
issues I hit.

In my particular case I was actually running with:

  maint set target-async off
  maint set target-non-stop off

that is, we're telling GDB to force the targets to operate in
non-async mode, and in all-stop mode.  Here's my GDB session showing
the problem:

  (gdb) maintenance set target-async off
  (gdb) maintenance set target-non-stop off
  (gdb) target extended-remote :54321
  Remote debugging using :54321
  (gdb) attach 2365960
  Attaching to process 2365960
  No unwaited-for children left.
  (gdb)

Notice the 'No unwaited-for children left.' error, this is the
problem.  There's no reason why GDB should not be able to attach to
the process.

The problem is this:

  1. The user runs 'attach PID' and this sends GDB into attach_command
  in infcmd.c.  From here we call the ::attach method on the attach
  target, which will be the extended_remote_target.

  2. In extended_remote_target::attach, we attach to the remote target
  and get the first reply (which is a stop packet).  We put off
  processing the stop packet until the end of ::attach.  We setup the
  inferior and thread to represent the process we attached to, and
  download the target description.  Finally, we process the initial
  stop packet.

  If '!target_is_non_stop_p ()' and '!target_can_async_p ()', which is
  the case for us given the maintenance commands we used, we cache the
  stop packet within the remote_state::buf for later processing.

  3. Back in attach_command, if 'target_is_non_stop_p ()' then we
  request that the target stops.  This will either process any cached
  stop replies, or request that the target stops, and process the stop
  replies.  However, this code is not what we use due to non-stop mode
  being disabled.  So, we skip to the next step which is to call
  validate_exec_file.

  4. Calling validate_exec_file can cause packets to be sent to the
  remote target, and replies received, the first path I hit is the
  call to target_pid_to_exec_file, which calls
  remote_target::pid_to_exec_file, which can then try to read the
  executable from the remote.  Sending an receiving packets will make
  use of the remote_state::buf object.

  5. The attempt to attach continues, but the damage is already done...

So, the problem is that, in step #2 we cache a stop reply in the
remote_state::buf, and then in step #4 we reuse the remote_state::buf
object, discarding any cached stop reply.  As a result, the initial
stop, which is sent when GDB first attaches to the target, is lost.

This problem can clearly be seen, I feel, by looking at the
remote_state::cached_wait_status flag.  This flag tells GDB if there
is a wait status cached in remote_state::buf.  However, in
remote_target::putpkt_binary and remote_target::getpkt_or_notif_sane_1
this flag is just set back to 0, doing this immediately discards any
cached data.

I don't know if this scheme ever made sense,  looking at commit
2d717e4f8a54, where the cached_wait_status flag was added, it appears
that there was nothing between where the stop was cached, and where
the stop was consumed, so, I suspect, there never was a situation
where we ended up in putpkt_binary or getpkt_or_notif_sane_1 and
needed to clear to the flag, maybe the clearing was added "just in
case".  Whatever the history, I claim that this clearing this flag is
no longer a good idea.

So, my first step toward fixing this issue was to replace the two
instances of 'rs->cached_wait_status = 0;' in ::putpkt_binary and
::getpkt_or_notif_sane_1 with 'gdb_assert (rs->cached_wait_status ==
0);', this, at least would show me when GDB was doing something
dangerous, and indeed, this assert is now hit in my test case above.

I did play with using some kind of scoped restore to backup, and
restore the remote_state::buf object in all the places within remote.c
that I was hitting where the ::buf was being corrupted.  The first
problem with this is that, where the ::cached_wait_status flag is
reset is _not_ where ::buf is corrupted.  For the ::putpkt_binary
case, by the time we get to the method the buffer has already been
corrupted in many cases, so we end up needing to add the scoped
save/restore within the callers, which means we need the save/restore
in _lots_ of places.

Plus, using this save/restore model feels like the wrong solution.  I
don't think that it's obvious that the buffer might be holding cached
data, and I think it would be too easy for new corruptions of the
buffer to be introduced, which could easily go unnoticed for a long
time.

So, I really wanted a solution that didn't require us to cache data in
the ::buf object.

Luckily, I think we already have such a solution in place, the
remote_state::stop_reply_queue, it seems like this does exactly the
same task, just in a slightly different way.  With the
::stop_reply_queue, the stop packets are processed upon receipt and
the stop_reply object is added to the queue.  With the ::buf cache
solution, the unprocessed stop reply is cached in the ::buf, and
processed later.

So, finally, in this commit, I propose to remove the
remote_state::cached_wait_status flag and to stop using the ::buf to
cache stop replies.  Instead, stop replies will now always be stored
in the ::stop_reply_queue.

There are two places where we use the ::buf to hold a cached stop
reply, the first is in the ::attach method, and the second is in
remote_target::start_remote, however, the second of these cases is far
less problematic, as after caching the stop reply in ::buf we call the
global start_remote function, which does very little work before
calling normal_stop, which processes the cached stop reply.  However,
my plan is to switch both users over to using ::stop_reply_queue so
that the old (unsafe) ::cached_wait_status mechanism can be completely
removed.

The next problem is that the ::stop_reply_queue is currently only used
for async-mode, and so, in remote_target::push_stop_reply, where we
push stop_reply objects into the ::stop_reply_queue, we currently also
mark the async event token.  I've modified this so we only mark the
async event token if 'target_is_async_p ()' - note, _is_, not _can_
here. The ::push_stop_reply method is called in places where async
mode has been temporarily disabled, but, when async mode is switched
back on (see remote_target::async) we will mark the event token if
there are events in the queue.

Another change of interest is in remote_target::remote_interrupt_as.
Previously this code checked ::cached_wait_status, but didn't check
for events in the ::stop_reply_queue.  Now that ::cached_wait_status
has been removed we now check the queue length instead, which should
have the same result.

Finally, in remote_target::wait_as, I've tried to merge the processing
of the ::stop_reply_queue with how we used to handle the
::cached_wait_status flag.

Currently, when processing the ::stop_reply_queue we call
process_stop_reply and immediately return.  However, when handling
::cached_wait_status we run through the whole of ::wait_as, and return
at the end of the function.

If we consider a standard stop packet, the two differences I see are:

  1. Resetting of the remote_state::waiting_for_stop_reply, flag; this
  is not currently done when processing a stop from the
  ::stop_reply_queue.

  2. The final return value has the possibility of being adjusted at
  the end of ::wait_as, as well as there being calls to
  record_currthread, non of which are done if we process a stop from
  the ::stop_reply_queue.

After discussion on the mailing list:

  https://sourceware.org/pipermail/gdb-patches/2021-December/184535.html

it was suggested that, when an event is pushed into the
::stop_reply_queue, the ::waiting_for_stop_reply flag is never going
to be set.  As a result, we don't need to worry about the first
difference.  I have however, added a gdb_assert to validate the
assumption that the flag is never going to be set.  If in future the
situation ever changes, then we should find out pretty quickly.

As for the second difference, I have resolved this by having all stop
packets taken from the ::stop_reply_queue, pass through the return
value adjustment code at the end of ::wait_as.

An example of a test that reveals the benefits of this commit is:

  make check-gdb \
    RUNTESTFLAGS="--target_board=native-extended-gdbserver \
                  GDBFLAGS='-ex maint\ set\ target-async\ off \
                            -ex maint\ set\ target-non-stop\ off' \
                  gdb.base/attach.exp"

For testing I've been running test on x86-64/GNU Linux, and run with
target boards unix, native-gdbserver, and native-extended-gdbserver.
For each board I've run with the default GDBFLAGS, as well as with:

  GDBFLAGS='-ex maint\ set\ target-async\ off \
            -ex maint\ set\ target-non-stop\ off' \

Though running with the above GDBFLAGS is clearly a lot more unstable
both before and after my patch, I'm not seeing any consistent new
failures with my patch, except, with the native-extended-gdbserver
board, where I am seeing new failures, but only because more tests are
now running.  For that configuration alone I see the number of
unresolved go down by 49, the number of passes goes up by 446, and the
number of failures also increases by 144.  All of the failures are new
tests as far as I can tell.
2021-12-18 10:19:55 +00:00
2021-12-18 00:00:13 +00:00
2020-09-25 10:24:44 -04:00
2021-09-09 23:30:12 -04:00
2021-11-29 20:28:29 -05:00
2021-11-15 12:20:12 +10:30
2021-11-14 18:07:50 +10:30
2021-11-29 20:28:29 -05:00
2021-10-29 13:31:37 +03:00
2021-11-12 19:02:12 +10:30
2021-11-13 09:04:03 -08:00
2021-11-13 09:04:03 -08:00

		   README for GNU development tools

This directory contains various GNU compilers, assemblers, linkers, 
debuggers, etc., plus their support routines, definitions, and documentation.

If you are receiving this as part of a GDB release, see the file gdb/README.
If with a binutils release, see binutils/README;  if with a libg++ release,
see libg++/README, etc.  That'll give you info about this
package -- supported targets, how to use it, how to report bugs, etc.

It is now possible to automatically configure and build a variety of
tools with one command.  To build all of the tools contained herein,
run the ``configure'' script here, e.g.:

	./configure 
	make

To install them (by default in /usr/local/bin, /usr/local/lib, etc),
then do:
	make install

(If the configure script can't determine your type of computer, give it
the name as an argument, for instance ``./configure sun4''.  You can
use the script ``config.sub'' to test whether a name is recognized; if
it is, config.sub translates it to a triplet specifying CPU, vendor,
and OS.)

If you have more than one compiler on your system, it is often best to
explicitly set CC in the environment before running configure, and to
also set CC when running make.  For example (assuming sh/bash/ksh):

	CC=gcc ./configure
	make

A similar example using csh:

	setenv CC gcc
	./configure
	make

Much of the code and documentation enclosed is copyright by
the Free Software Foundation, Inc.  See the file COPYING or
COPYING.LIB in the various directories, for a description of the
GNU General Public License terms under which you can copy the files.

REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info
on where and how to report problems.
Description
Unofficial mirror of sourceware binutils-gdb repository. Updated daily.
Readme 780 MiB
Languages
C 51.8%
Makefile 22.4%
Assembly 12.3%
C++ 6%
Roff 1.4%
Other 5.4%