Commit graph

1232 commits

Author SHA1 Message Date
Simon Marchi
e0700ba44c gdb: make string-like set show commands use std::string variable
String-like settings (var_string, var_filename, var_optional_filename,
var_string_noescape) currently take a pointer to a `char *` storage
variable (typically global) that holds the setting's value.  I'd like to
"mordernize" this by changing them to use an std::string for storage.

An obvious reason is that string operations on std::string are often
easier to write than with C strings.  And they avoid having to do any
manual memory management.

Another interesting reason is that, with `char *`, nullptr and an empty
string often both have the same meaning of "no value".  String settings
are initially nullptr (unless initialized otherwise).  But when doing
"set foo" (where `foo` is a string setting), the setting now points to
an empty string.  For example, solib_search_path is nullptr at startup,
but points to an empty string after doing "set solib-search-path".  This
leads to some code that needs to check for both to check for "no value".
Or some code that converts back and forth between NULL and "" when
getting or setting the value.  I find this very error-prone, because it
is very easy to forget one or the other.  With std::string, we at least
know that the variable is not "NULL".  There is only one way of
representing an empty string setting, that is with an empty string.

I was wondering whether the distinction between NULL and "" would be
important for some setting, but it doesn't seem so.  If that ever
happens, it would be more C++-y and self-descriptive to use
optional<string> anyway.

Actually, there's one spot where this distinction mattered, it's in
init_history, for the test gdb.base/gdbinit-history.exp.  init_history
sets the history filename to the default ".gdb_history" if it sees that
the setting was never set - if history_filename is nullptr.  If
history_filename is an empty string, it means the setting was explicitly
cleared, so it leaves it as-is.  With the change to std::string, this
distinction doesn't exist anymore.  This can be fixed by moving the code
that chooses a good default value for history_filename to
_initialize_top.  This is ran before -ex commands are processed, so an
-ex command can then clear that value if needed (what
gdb.base/gdbinit-history.exp tests).

Another small improvement, in my opinion is that we can now easily
give string parameters initial values, by simply initializing the global
variables, instead of xstrdup-ing it in the _initialize function.

In Python and Guile, when registering a string-like parameter, we
allocate (with new) an std::string that is owned by the param_smob (in
Guile) and the parmpy_object (in Python) objects.

This patch started by changing all relevant add_setshow_* commands to
take an `std::string *` instead of a `char **` and fixing everything
that failed to build.  That includes of course all string setting
variable and their uses.

string_option_def now uses an std::string also, because there's a
connection between options and settings (see
add_setshow_cmds_for_options).

The add_path function in source.c is really complex and twisted, I'd
rather not try to change it to work on an std::string right now.
Instead, I added an overload that copies the std:string to a `char *`
and back.  This means more copying, but this is not used in a hot path
at all, so I think it is acceptable.

Change-Id: I92c50a1bdd8307141cdbacb388248e4e4fc08c93
Co-authored-by: Lancelot SIX <lsix@lancelotsix.com>
2021-10-03 17:53:16 +01:00
Lancelot SIX
1d7fe7f01b gdb: Introduce setting construct within cmd_list_element
cmd_list_element can contain a pointer to data that can be set and / or
shown.  This is achieved with the void* VAR member which points to the
data that can be accessed, while the VAR_TYPE member (of type enum
var_types) indicates how to interpret the data pointed to.

With this pattern, the user of the cmd_list_element needs to know what
is the storage type associated with a given VAR_TYPES in order to do
the proper casting.  No automatic safeguard is available to prevent
miss-use of the pointer.  Client code typically looks something like:

	switch (c->var_type)
	{
	  case var_zuinteger:
	    unsigned int v = *(unsigned int*) c->var;
	    ...
	    break;
	  case var_boolean:
	    bool v = *(bool *) c->var;
	    ...
	    break;
	  ...
	}

This patch proposes to add an abstraction around the var_types and void*
pointer pair.  The abstraction is meant to prevent the user from having
to handle the cast and verify that the data is read or written as a type
that is coherent with the setting's var_type.  This is achieved by
introducing the struct setting which exposes a set of templated get /
set member functions.  The template parameter is the type of the
variable that holds the referred variable.

Using those accessors allows runtime checks to be inserted in order to
ensure that the data pointed to has the expected type.  For example,
instantiating the member functions with bool will yield something
similar to:

	const bool &get<bool> () const
	{
	  gdb_assert (m_var_type == var_boolean);
	  gdb_assert (m_var != nullptr);
	  return *static_cast<bool *> (m_var);
	}
	void set<bool> (const bool &var)
	{
	  gdb_assert (m_var_type == var_boolean);
	  gdb_assert (m_var != nullptr);
	  *static_cast<bool *> (m_var) = var;
	}

Using the new abstraction, our initial example becomes:

	switch (c->var_type)
	{
	  case var_zuinteger:
	    unsigned int v = c->var->get<unsigned int> ();
	    ...
	    break;
	  case var_boolean:
	    bool v = c->var->get<bool> ();
	    ...
	    break;
	  ...
	}

While the call site is still similar, the introduction of runtime checks
help ensure correct usage of the data.

In order to avoid turning the bulk of add_setshow_cmd_full into a
templated function, and following a suggestion from Pedro Alves, a
setting can be constructed from a pre validated type erased reference to
a variable.  This is what setting::erased_args is used for.

Introducing an opaque abstraction to describe a setting will also make
it possible to use callbacks to retrieve or set the value of the setting
on the fly instead of pointing to a static chunk of memory.  This will
be done added in a later commit.

Given that a cmd_list_element may or may not reference a setting, the
VAR and VAR_TYPES members of the struct are replaced with a
gdb::optional<setting> named VAR.

Few internal function signatures have been modified to take into account
this new abstraction:

-The functions value_from_setting, str_value_from_setting and
 get_setshow_command_value_string used to have a 'cmd_list_element *'
 parameter but only used it for the VAR and VAR_TYPE member. They now
 take a 'const setting &' parameter instead.
- Similarly, the 'void *' and a 'enum var_types' parameters of
  pascm_param_value and gdbpy_parameter_value have been replaced with a
  'const setting &' parameter.

No user visible change is expected after this patch.

Tested on GNU/Linux x86_64, with no regression noticed.

Co-authored-by: Simon Marchi <simon.marchi@polymtl.ca>
Change-Id: Ie1d08c3ceb8b30b3d7bf1efe036eb8acffcd2f34
2021-10-03 17:53:16 +01:00
Simon Marchi
abe8cab7cb gdb: enable target_async around stop_all_threads call in process_initial_stop_replies
The following scenario hangs:

 - maint set target-non-stop on
 - `gdbserver --attach`
 - a multi-threaded program

For example:

Terminal 1:

    $ gnome-calculator&
    [1] 495731
    $ ../gdbserver/gdbserver --once --attach :1234 495731
    Attached; pid = 495731
    Listening on port 1234

Terminal 2:

    $ ./gdb -nx -q --data-directory=data-directory /usr/bin/gnome-calculator -ex "maint set target-non-stop on" -ex "tar rem :1234"
    Reading symbols from /usr/bin/gnome-calculator...
    (No debugging symbols found in /usr/bin/gnome-calculator)
    Remote debugging using :1234
    * hangs *

What happens is:

 - The protocol between gdb and gdbserver is in non-stop mode, but the
   user-visible behavior is all-stop
 - On connect, gdbserver sends one stop reply for one thread that is
   stops, the others stay running
 - In process_initial_stop_replies, gdb calls stop_all_threads to stop
   these other threads, because we are using the all-stop user-visible
   mode
 - stop_all_threads sends a stop request for all the running threads and
   then waits for resulting events
 - At this point, the remote target is in target_async(0) mode, which
   makes stop_all_threads not consider it for events
 - stop_all_threads loops indefinitely (it does not even block
   indefinitely, it is in an infinite busy loop) because there are no
   event sources.  wait_one_event returns a TARGET_WAITKIND_NO_RESUMED
   wait status.

Fix that by making the remote target async around the stop_all_threads
call.

I haven't implemented it because I'm not sure how to do it, but I think
it would be a good idea to have, in stop_all_threads / wait_one /
handle_one, an assert to check that if we are expecting one or more
event, then there are some targets that are in a state where they can
supply some events.  Otherwise, we'll necessarily be stuck in this
infinite loop, and it's probably due to a bug in GDB.  I'm not too sure
where to put this or how to express it though.  Perhaps in
stop_all_threads, here:

	  for (int i = 0; i < waits_needed; i++)
	    {
	      wait_one_event event = wait_one ();
	      *here*
	      if (handle_one (event))
		break;
	    }

If at that point, the returned event is TARGET_WAITKIND_NO_RESUMED,
there's a problem.  We expect some event, because we've asked some
threads to stop, but all targets are answering that they won't have any
events for us.  That's a contradiction, and a sign that something has
gone wrong.  It could perhaps event be:

    gdb_assert (event.ws.kind != TARGET_WAITKIND_NO_RESUMED);

in handle_one, as the idea is the same in prepare_for_detach.

A bit more sophisticated would be: we know which targets we are
expecting waits from, since we know which threads we have asked to
stop.  So if any of these targets returns TARGET_WAITKIND_NO_RESUMED,
something is fishy.

Add a test that tests attaching with gdbserver's --attach flag to a
multi-threaded program, and then connecting to it.  Without the fix, the
test reproduces the hang.

Change-Id: If6f6690a4887ca66693ef1af64791dda4c65f24f
2021-09-28 20:18:30 -04:00
Tom Tromey
c80e29dba9 Change get_ada_task_ptid parameter type
get_ada_task_ptid currently takes a 'long' as its 'thread' parameter
type.  However, on some platforms this is actually a pointer, and
using 'long' can sometimes end up with the value being sign-extended.
This sign extension can cause problems later, if the tid is then later
used as an address again.

This patch changes the parameter type to ULONGEST and updates all the
uses.  This approach preserves sign extension on the targets where it
is apparently intended, while avoiding it on others.

Co-Authored-By: John Baldwin <jhb@FreeBSD.org>
2021-09-23 09:30:54 -06:00
Tom Tromey
96bbe3ef96 Change ptid_t::tid to ULONGEST
The ptid_t 'tid' member is normally used as an address in gdb -- both
bsd-uthread and ravenscar-thread use it this way.  However, because
the type is 'long', this can cause problems with sign extension.

This patch changes the type to ULONGEST to ensure that sign extension
does not occur.
2021-09-23 09:30:54 -06:00
Tom Tromey
184ea2f731 Remove defaulted 'tid' parameter to ptid_t constructor
I wanted to find, and potentially modify, all the spots where the
'tid' parameter to the ptid_t constructor was used.  So, I temporarily
removed this parameter and then rebuilt.

In order to make it simpler to search through the "real" (nonzero)
uses of this parameter, something I knew I'd have to do multiple
times, I removed any ", 0" from constructor calls.

Co-Authored-By: John Baldwin <jhb@FreeBSD.org>
2021-09-23 09:30:54 -06:00
Simon Marchi
82d1f134cc gdb: follow-fork: push target and add thread in target_follow_fork
In the context of ROCm-gdb [1], the ROCm target sits on top of the
linux-nat target.  when a process forks, it needs to carry over some
data from the forking inferior to the fork child inferior.  Ideally, the
ROCm target would implement the follow_fork target_ops method, but there
are some small problems.  This patch fixes these, which helps the ROCm
target, but also makes things more consistent and a bit nicer in
general, I believe.

The main problem is: when follow-fork-mode is "parent",
target_follow_fork is called with the parent as the current inferior.
When it's "child", target_follow_fork is called with the child as the
current inferior.  This means that target_follow_fork is sometimes
called on the parent's target stack and sometimes on the child's target
stack.

The parent's target stack may contain targets above the process target,
such as the ROCm target.  So if follow-fork-child is "parent", the ROCm
target would get notified of the fork and do whatever is needed.  But
the child's target stack, at that moment, only contains the exec and
process target copied over from the parent.  The child's target stack is
set up by follow_fork_inferior, before calling target_follow_fork.  In
that case, the ROCm target wouldn't get notified of the fork.

For consistency, I think it would be good to always call
target_follow_fork on the parent inferior's target stack.  I think it
makes sense as a way to indicate "this inferior has called fork, do
whatever is needed".  The desired outcome of the fork (whether an
inferior is created for the child, do we need to detach from the child)
can be indicated by passed parameter.

I therefore propose these changes:

 - make follow_fork_inferior always call target_follow_fork with the
   parent as the current inferior.  That lets all targets present on the
   parent's target stack do some fork-related handling and push
   themselves on the fork child's target stack if needed.

   For this purpose, pass the child inferior down to target_follow_fork
   and follow_fork implementations.  This is nullptr if no inferior is
   created for the child, because we want to detach from it.

 - as a result, in follow_fork_inferior, detach from the parent inferior
   (if needed) only after the target_follow_fork call.  This is needed
   because we want to call target_follow_fork before the parent's
   target stack is torn down.

 - hand over to the targets in the parent's target stack (including the
   process target) the responsibility to push themselves, if needed, to
   the child's target stack.  Also hand over the responsibility to the
   process target, at the same time, to create the child's initial
   thread (just like we do for follow_exec).

 - pass the child inferior to exec_on_vfork, so we don't need to swap
   the current inferior between parent and child.  Nothing in
   exec_on_vfork depends on the current inferior, after this change.

   Although this could perhaps be replaced with just having the exec
   target implement follow_fork and push itself in the child's target
   stack, like the process target does... We would just need to make
   sure the process target calls beneath()->follow_fork(...).  I'm not
   sure about this one.

gdb/ChangeLog:

	* target.h (struct target_ops) <follow_fork>: Add inferior*
	parameter.
	(target_follow_fork): Likewise.
	* target.c (default_follow_fork): Likewise.
	(target_follow_fork): Likewise.
	* fbsd-nat.h (class fbsd_nat_target) <follow_fork>: Likewise.
	(fbsd_nat_target::follow_fork): Likewise, and call
	inf_ptrace_target::follow_fork.
	* linux-nat.h (class linux_nat_target) <follow_fork>: Likewise.
	* linux-nat.c (linux_nat_target::follow_fork): Likewise, and
	call inf_ptrace_target::follow_fork.
	* obsd-nat.h (obsd_nat_target) <follow_fork>: Likewise.
	* obsd-nat.c (obsd_nat_target::follow_fork): Likewise, and call
	inf_ptrace_target::follow_fork.
	* remote.c (class remote_target) <follow_fork>: Likewise.
	(remote_target::follow_fork): Likewise, and call
	process_stratum_target::follow_fork.
	* process-stratum-target.h (class process_stratum_target)
	<follow_fork>: New.
	* process-stratum-target.c
	(process_stratum_target::follow_fork): New.
	* target-delegates.c: Re-generate.

[1] https://github.com/ROCm-Developer-Tools/ROCgdb

Change-Id: I460bd0af850f0485e8aed4b24c6d8262a4c69929
2021-08-03 20:26:49 -04:00
Simon Marchi
11bd012ed2 gdb: make inferior::m_cwd an std::string
Same idea as the previous patch, but for m_cwd.

To keep things consistent across the board, change get_inferior_cwd as
well, which is shared with GDBserver.  So update the related GDBserver
code too.

Change-Id: Ia2c047fda738d45f3d18bc999eb67ceb8400ce4e
2021-07-23 15:38:54 -04:00
Simon Marchi
90cc31c9e5 gdb: add setter/getter for inferior cwd
Add cwd/set_cwd to the inferior class, remove set_inferior_args.
Keep get_inferior_args, because it is used from fork_inferior, in shared
code.  The cwd could eventually be passed as a parameter eventually,
though, I think that would be cleaner.

Change-Id: Ifb72ea865d7e6f9a491308f0d5c1595579d8427e
2021-07-23 15:38:54 -04:00
Simon Marchi
3a849a3454 gdb: pass child_ptid and fork kind to target_ops::follow_fork
This is a small cleanup I think would be nice, that I spotted while
doing the following patch.

gdb/ChangeLog:

	* target.h (struct target_ops) <follow_fork>: Add ptid and
	target_waitkind parameters.
	(target_follow_fork): Likewise.
	* target.c (default_follow_fork): Likewise.
	(target_follow_fork): Likewise.
	* fbsd-nat.h (class fbsd_nat_target) <follow_fork>: Likewise.
	* fbsd-nat.c (fbsd_nat_target::follow_fork): Likewise.
	* linux-nat.h (class linux_nat_target) <follow_fork>: Likewise.
	* linux-nat.c (linux_nat_target::follow_fork): Likewise.
	* obsd-nat.h (class obsd_nat_target) <follow_fork>: Likewise.
	* obsd-nat.c (obsd_nat_target::follow_fork): Likewise.
	* remote.c (class remote_target) <follow_fork>: Likewise.
	* target-debug.h (target_debug_print_target_waitkind): New.
	* target-delegates.c: Re-generate.

Change-Id: I5421a542f2e19100a22b74cc333d2b235d0de3c8
2021-07-14 23:21:30 -04:00
Pedro Alves
d7cb0ef35b Fix detach with target remote (PR gdb/28080)
Commit 408f66864a ("detach in all-stop
with threads running") regressed "detach" with "target remote":

 (gdb) detach
 Detaching from program: target:/any/program, process 3671843
 Detaching from process 3671843
 Ending remote debugging.
 [Inferior 1 (process 3671843) detached]
 In main
 terminate called after throwing an instance of 'gdb_exception_error'
 Aborted (core dumped)

Here's the exception above being thrown:

 (top-gdb) bt
 #0  throw_error (error=TARGET_CLOSE_ERROR, fmt=0x555556035588 "Remote connection closed") at src/gdbsupport/common-exceptions.cc:222
 #1  0x0000555555bbaa46 in remote_target::readchar (this=0x555556a11040, timeout=10000) at src/gdb/remote.c:9440
 #2  0x0000555555bbb9e5 in remote_target::getpkt_or_notif_sane_1 (this=0x555556a11040, buf=0x555556a11058, forever=0, expecting_notif=0, is_notif=0x0) at src/gdb/remote.c:9928
 #3  0x0000555555bbbda9 in remote_target::getpkt_sane (this=0x555556a11040, buf=0x555556a11058, forever=0) at src/gdb/remote.c:10030
 #4  0x0000555555bc0e75 in remote_target::remote_hostio_send_command (this=0x555556a11040, command_bytes=13, which_packet=14, remote_errno=0x7fffffffcfd0, attachment=0x0, attachment_len=0x0) at src/gdb/remote.c:12137
 #5  0x0000555555bc1b6c in remote_target::remote_hostio_close (this=0x555556a11040, fd=8, remote_errno=0x7fffffffcfd0) at src/gdb/remote.c:12455
 #6  0x0000555555bc1bb4 in remote_target::fileio_close (During symbol reading: .debug_line address at offset 0x64f417 is 0 [in module build/gdb/gdb]
 this=0x555556a11040, fd=8, remote_errno=0x7fffffffcfd0) at src/gdb/remote.c:12462
 #7  0x0000555555c9274c in target_fileio_close (fd=3, target_errno=0x7fffffffcfd0) at src/gdb/target.c:3365
 #8  0x000055555595a19d in gdb_bfd_iovec_fileio_close (abfd=0x555556b9f8a0, stream=0x555556b11530) at src/gdb/gdb_bfd.c:439
 #9  0x0000555555e09e3f in opncls_bclose (abfd=0x555556b9f8a0) at src/bfd/opncls.c:599
 #10 0x0000555555e0a2c7 in bfd_close_all_done (abfd=0x555556b9f8a0) at src/bfd/opncls.c:847
 #11 0x0000555555e0a27a in bfd_close (abfd=0x555556b9f8a0) at src/bfd/opncls.c:814
 #12 0x000055555595a9d3 in gdb_bfd_close_or_warn (abfd=0x555556b9f8a0) at src/gdb/gdb_bfd.c:626
 #13 0x000055555595ad29 in gdb_bfd_unref (abfd=0x555556b9f8a0) at src/gdb/gdb_bfd.c:715
 #14 0x0000555555ae4730 in objfile::~objfile (this=0x555556515540, __in_chrg=<optimized out>) at src/gdb/objfiles.c:573
 #15 0x0000555555ae955a in std::_Sp_counted_ptr<objfile*, (__gnu_cxx::_Lock_policy)2>::_M_dispose (this=0x555556c20db0) at /usr/include/c++/9/bits/shared_ptr_base.h:377
 #16 0x000055555572b7c8 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x555556c20db0) at /usr/include/c++/9/bits/shared_ptr_base.h:155
 #17 0x00005555557263c3 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x555556bf0588, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr_base.h:730
 #18 0x0000555555ae745e in std::__shared_ptr<objfile, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x555556bf0580, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr_base.h:1169
 #19 0x0000555555ae747e in std::shared_ptr<objfile>::~shared_ptr (this=0x555556bf0580, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr.h:103
 #20 0x0000555555b1c1dc in __gnu_cxx::new_allocator<std::_List_node<std::shared_ptr<objfile> > >::destroy<std::shared_ptr<objfile> > (this=0x5555564cdd60, __p=0x555556bf0580) at /usr/include/c++/9/ext/new_allocator.h:153
 #21 0x0000555555b1bb1d in std::allocator_traits<std::allocator<std::_List_node<std::shared_ptr<objfile> > > >::destroy<std::shared_ptr<objfile> > (__a=..., __p=0x555556bf0580) at /usr/include/c++/9/bits/alloc_traits.h:497
 #22 0x0000555555b1b73e in std::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::_M_erase (this=0x5555564cdd60, __position=std::shared_ptr<objfile> (expired, weak count 1) = {get() = 0x555556515540}) at /usr/include/c++/9/bits/stl_list.h:1921
 #23 0x0000555555b1afeb in std::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::erase (this=0x5555564cdd60, __position=std::shared_ptr<objfile> (expired, weak count 1) = {get() = 0x555556515540}) at /usr/include/c++/9/bits/list.tcc:158
 #24 0x0000555555b19576 in program_space::remove_objfile (this=0x5555564cdd20, objfile=0x555556515540) at src/gdb/progspace.c:210
 #25 0x0000555555ae4502 in objfile::unlink (this=0x555556515540) at src/gdb/objfiles.c:487
 #26 0x0000555555ae5a12 in objfile_purge_solibs () at src/gdb/objfiles.c:875
 #27 0x0000555555c09686 in no_shared_libraries (ignored=0x0, from_tty=1) at src/gdb/solib.c:1236
 #28 0x00005555559e3f5f in detach_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:2769

So frame #28 already detached the remote process, and then we're
purging the shared libraries.  GDB had opened remote shared libraries
via the target: sysroot, so it tries closing them.  GDBserver is
tearing down already, so remote communication breaks down and we close
the remote target and throw TARGET_CLOSE_ERROR.

Note frame #14:

 #14 0x0000555555ae4730 in objfile::~objfile (this=0x555556515540, __in_chrg=<optimized out>) at src/gdb/objfiles.c:573

That's a dtor, thus noexcept.  That's the reason for the
std::terminate.

Stepping back a bit, why do we still have open remote files if we've
managed to detach already, and, we're debugging with "target remote"?
The reason is that commit 408f66864a
makes detach_command hold a reference to the target, so the remote
target won't be finally closed until frame #28 returns.  It's closing
the target that invalidates target file I/O handles.

This commit fixes the issue by not relying on target_close to
invalidate the target file I/O handles, instead invalidate them
immediately in remote_unpush_target.  So when GDB purges the solibs,
and we end up in target_fileio_close (frame #7 above), there's nothing
to do, and we don't try to talk with the remote target anymore.

The regression isn't seen when testing with
--target_board=native-gdbserver, because that does "set sysroot" to
disable the "target:" sysroot, for test run speed reasons.  So this
commit adds a testcase that explicitly tests detach with "set sysroot
target:".

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <pedro@palves.net>

	PR gdb/28080
	* remote.c (remote_unpush_target): Invalidate file I/O target
	handles.
	* target.c (fileio_handles_invalidate_target): Make extern.
	* target.h (fileio_handles_invalidate_target): Declare.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Pedro Alves  <pedro@palves.net>

	PR gdb/28080
	* gdb.base/detach-sysroot-target.exp: New.
	* gdb.base/detach-sysroot-target.c: New.

Reported-By: Jonah Graham <jonah@kichwacoders.com>

Change-Id: I851234910172f42a1b30e731161376c344d2727d
2021-07-13 15:30:04 +01:00
Simon Marchi
1edb66d856 gdb: make thread_info::suspend private, add getters / setters
A following patch will want to take some action when a pending wait
status is set on or removed from a thread.  Add a getter and a setter on
thread_info for the pending waitstatus, so that we can add some code in
the setter later.

The thing is, the pending wait status field is in the
thread_suspend_state, along with other fields that we need to backup
before and restore after the thread does an inferior function call.
Therefore, make the thread_suspend_state member private
(thread_info::suspend becomes thread_info::m_suspend), and add getters /
setters for all of its fields:

 - pending wait status
 - stop signal
 - stop reason
 - stop pc

For the pending wait status, add the additional has_pending_waitstatus
and clear_pending_waitstatus methods.

I think this makes the thread_info interface a bit nicer, because we
now access the fields as:

  thread->stop_pc ()

rather than

  thread->suspend.stop_pc

The stop_pc field being in the `suspend` structure is an implementation
detail of thread_info that callers don't need to be aware of.

For the backup / restore of the thread_suspend_state structure, add
save_suspend_to and restore_suspend_from methods.  You might wonder why
`save_suspend_to`, as opposed to a simple getter like

  thread_suspend_state &suspend ();

I want to make it clear that this is to be used only for backing up and
restoring the suspend state, _not_ to access fields like:

  thread->suspend ()->stop_pc

Adding some getters / setters allows adding some assertions.  I find
that this helps understand how things are supposed to work.  Add:

 - When getting the pending status (pending_waitstatus method), ensure
   that there is a pending status.
 - When setting a pending status (set_pending_waitstatus method), ensure
   there is no pending status.

There is one case I found where this wasn't true - in
remote_target::process_initial_stop_replies - which needed adjustments
to respect that contract.  I think it's because
process_initial_stop_replies is kind of (ab)using the
thread_info::suspend::waitstatus to store some statuses temporarily, for
its internal use (statuses it doesn't intent on leaving pending).

process_initial_stop_replies pulls out stop replies received during the
initial connection using target_wait.  It always stores the received
event in `evthread->suspend.waitstatus`.  But it only sets
waitstatus_pending_p, if it deems the event interesting enough to leave
pending, to be reported to the core:

      if (ws.kind != TARGET_WAITKIND_STOPPED
	  || ws.value.sig != GDB_SIGNAL_0)
	evthread->suspend.waitstatus_pending_p = 1;

It later uses this flag a bit below, to choose which thread to make the
"selected" one:

      if (selected == NULL
	  && thread->suspend.waitstatus_pending_p)
	selected = thread;

And ultimately that's used if the user-visible mode is all-stop, so that
we print the stop for that interesting thread:

  /* In all-stop, we only print the status of one thread, and leave
     others with their status pending.  */
  if (!non_stop)
    {
      thread_info *thread = selected;
      if (thread == NULL)
	thread = lowest_stopped;
      if (thread == NULL)
	thread = first;

      print_one_stopped_thread (thread);
    }

But in any case (all-stop or non-stop), print_one_stopped_thread needs
to access the waitstatus value of these threads that don't have a
pending waitstatus (those that had TARGET_WAITKIND_STOPPED +
GDB_SIGNAL_0).  This doesn't work with the assertions I've
put.

So, change the code to only set the thread's wait status if it is an
interesting one that we are going to leave pending.  If the thread
stopped due to a non-interesting event (TARGET_WAITKIND_STOPPED +
GDB_SIGNAL_0), don't store it.  Adjust print_one_stopped_thread to
understand that if a thread has no pending waitstatus, it's because it
stopped with TARGET_WAITKIND_STOPPED + GDB_SIGNAL_0.

The call to set_last_target_status also uses the pending waitstatus.
However, given that the pending waitstatus for the thread may have been
cleared in print_one_stopped_thread (and that there might not even be a
pending waitstatus in the first place, as explained above), it is no
longer possible to do it at this point.  To fix that, move the call to
set_last_target_status in print_one_stopped_thread.  I think this will
preserve the existing behavior, because set_last_target_status is
currently using the current thread's wait status.  And the current
thread is the last one for which print_one_stopped_thread is called.  So
by calling set_last_target_status in print_one_stopped_thread, we'll get
the same result.  set_last_target_status will possibly be called
multiple times, but only the last call will matter.  It just means
possibly more calls to set_last_target_status, but those are cheap.

Change-Id: Iedab9653238eaf8231abcf0baa20145acc8b77a7
2021-07-12 20:46:53 -04:00
Simon Marchi
7846f3aa61 gdb: add setter / getter for thread_info resumed state
A following patch will want to do things when a thread's resumed state
changes.  Make the `resumed` field private (renamed to `m_resumed`) and
add a getter and a setter for it.  The following patch in question will
therefore be able to add some code to the setter.

Change-Id: I360c48cc55a036503174313261ce4e757d795319
2021-07-12 20:46:52 -04:00
Andrew Burgess
4d60b89770 gdb/remote: Use true/false instead of 1/0
The remote_state::starting_up member variable is already of type bool,
but in some places we still write to it using 1 and 0.  This commit
just updates things to use true and false.

There should be no user visible change after this commit.

gdb/ChangeLog:

	* remote.c (remote_target::start_remote): Set 'starting_up' using
	boolean values instead of integers.
2021-06-28 16:31:30 +01:00
John Baldwin
d424629da8 remote: Fix indentation in remote_new_objfile.
gdb/remote.c:14541:5: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
    if (current_inferior ()->in_initial_library_scan)
    ^
gdb/remote.c:14527:3: note: previous statement is here
  if (remote == nullptr)
  ^

gdb/ChangeLog:

	* remote.c (remote_new_objfile): Fix indentation.
2021-06-12 10:43:29 -07:00
Simon Marchi
122373f7f2 gdb: try to load libthread_db only after reading all shared libraries when attaching / handling a fork child
When trying to attach to a pthread process on a Linux system with glibc 2.33,
we get:

    $ ./gdb -q -nx --data-directory=data-directory -p 1472010
    Attaching to process 1472010
    [New LWP 1472013]
    [New LWP 1472014]
    [New LWP 1472015]
    Error while reading shared library symbols for /usr/lib/libpthread.so.0:
    Cannot find user-level thread for LWP 1472015: generic error
    0x00007ffff6d3637f in poll () from /usr/lib/libc.so.6
    (gdb)

When attaching to a process (or handling a fork child, an operation very
similar to attaching), GDB reads the shared library list from the
process.  For each shared library (if "set auto-solib-add" is on), it
reads its symbols and calls the "new_objfile" observable.

The libthread-db code monitors this observable, and if it sees an
objfile named somewhat like "libpthread.so" go by, it tries to load
libthread_db.so in the GDB process itself.  libthread_db knows how to
navigate libpthread's data structures to get information about the
existing threads.

To locate these data structures, libthread_db calls ps_pglobal_lookup
(implemented in proc-service.c), passing in a symbol name and expecting
an address in return.

Before glibc 2.33, libthread_db always asked for symbols found in
libpthread.  There was no ordering problem: since we were always trying
to load libthread_db in reaction to processing libpthread (and reading
in its symbols) and libthread_db only asked symbols from libpthread, the
requested symbols could always be found.  Starting with glibc 2.33,
libthread_db now asks for a symbol name that can be found in
/lib/ld-linux-x86-64.so.2 (_rtld_global).  And the ordering in which GDB
reads the shared libraries from the inferior when attaching is
unfortunate, in that libpthread is processed before ld-linux.  So when
loading libthread_db in reaction to processing libpthread, and
libthread_db requests the symbol that is from ld-linux, GDB is not yet
able to supply it.

That problematic symbol lookup happens in the thread_from_lwp function,
when we call td_ta_map_lwp2thr_p, and an exception is thrown at this
point:

    #0  0x00007ffff6681012 in __cxxabiv1::__cxa_throw (obj=0x60e000006100, tinfo=0x555560033b50 <typeinfo for gdb_exception_error>, dest=0x55555d9404bc <gdb_exception_error::~gdb_exception_error()>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:78
    #1  0x000055555e5d3734 in throw_it(return_reason, errors, const char *, typedef __va_list_tag __va_list_tag *) (reason=RETURN_ERROR, error=GENERIC_ERROR, fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", ap=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdbsupport/common-exceptions.cc:200
    #2  0x000055555e5d37d4 in throw_verror (error=GENERIC_ERROR, fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", ap=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdbsupport/common-exceptions.cc:208
    #3  0x000055555e0b0ed2 in verror (string=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", args=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdb/utils.c:171
    #4  0x000055555e5e898a in error (fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s") at /home/simark/src/binutils-gdb/gdbsupport/errors.cc:43
    #5  0x000055555d06b4bc in thread_from_lwp (stopped=0x617000035d80, ptid=...) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:418
    #6  0x000055555d07040d in try_thread_db_load_1 (info=0x60c000011140) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:912
    #7  0x000055555d071103 in try_thread_db_load (library=0x55555f0c62a0 "libthread_db.so.1", check_auto_load_safe=false) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1014
    #8  0x000055555d072168 in try_thread_db_load_from_sdir () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1091
    #9  0x000055555d072d1c in thread_db_load_search () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1146
    #10 0x000055555d07365c in thread_db_load () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1203
    #11 0x000055555d07373e in check_for_thread_db () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1246
    #12 0x000055555d0738ab in thread_db_new_objfile (objfile=0x61300000c0c0) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1275
    #13 0x000055555bd10740 in std::__invoke_impl<void, void (*&)(objfile*), objfile*> (__f=@0x616000068d88: 0x55555d073745 <thread_db_new_objfile(objfile*)>) at /usr/include/c++/10.2.0/bits/invoke.h:60
    #14 0x000055555bd02096 in std::__invoke_r<void, void (*&)(objfile*), objfile*> (__fn=@0x616000068d88: 0x55555d073745 <thread_db_new_objfile(objfile*)>) at /usr/include/c++/10.2.0/bits/invoke.h:153
    #15 0x000055555bce0392 in std::_Function_handler<void (objfile*), void (*)(objfile*)>::_M_invoke(std::_Any_data const&, objfile*&&) (__functor=..., __args#0=@0x7fffffffb4a0: 0x61300000c0c0) at /usr/include/c++/10.2.0/bits/std_function.h:291
    #16 0x000055555d3595c0 in std::function<void (objfile*)>::operator()(objfile*) const (this=0x616000068d88, __args#0=0x61300000c0c0) at /usr/include/c++/10.2.0/bits/std_function.h:622
    #17 0x000055555d356b7f in gdb::observers::observable<objfile*>::notify (this=0x555566727020 <gdb::observers::new_objfile>, args#0=0x61300000c0c0) at /home/simark/src/binutils-gdb/gdb/../gdbsupport/observable.h:106
    #18 0x000055555da3f228 in symbol_file_add_with_addrs (abfd=0x61200001ccc0, name=0x6190000d9090 "/usr/lib/libpthread.so.0", add_flags=..., addrs=0x7fffffffbc10, flags=..., parent=0x0) at /home/simark/src/binutils-gdb/gdb/symfile.c:1131
    #19 0x000055555da3f763 in symbol_file_add_from_bfd (abfd=0x61200001ccc0, name=0x6190000d9090 "/usr/lib/libpthread.so.0", add_flags=<error reading variable: Cannot access memory at address 0xffffffffffffffb0>, addrs=0x7fffffffbc10, flags=<error reading variable: Cannot access memory at address 0xffffffffffffffc0>, parent=0x0) at /home/simark/src/binutils-gdb/gdb/symfile.c:1167
    #20 0x000055555d95f9fa in solib_read_symbols (so=0x6190000d8e80, flags=...) at /home/simark/src/binutils-gdb/gdb/solib.c:681
    #21 0x000055555d96233d in solib_add (pattern=0x0, from_tty=0, readsyms=1) at /home/simark/src/binutils-gdb/gdb/solib.c:987
    #22 0x000055555d93646e in enable_break (info=0x608000008f20, from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:2238
    #23 0x000055555d93cfc0 in svr4_solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:3049
    #24 0x000055555d96610d in solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib.c:1195
    #25 0x000055555cdee318 in post_create_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:318
    #26 0x000055555ce00e6e in setup_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:2439
    #27 0x000055555ce59c34 in handle_one (event=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:4887
    #28 0x000055555ce5cd00 in stop_all_threads () at /home/simark/src/binutils-gdb/gdb/infrun.c:5064
    #29 0x000055555ce7f0da in stop_waiting (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:8006
    #30 0x000055555ce67f5c in handle_signal_stop (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:6062
    #31 0x000055555ce63653 in handle_inferior_event (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:5727
    #32 0x000055555ce4f297 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:4105
    #33 0x000055555cdbe3bf in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
    #34 0x000055555d018047 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
    #35 0x000055555e5ea77e in handle_file_event (file_ptr=0x60600008b1c0, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
    #36 0x000055555e5eb09c in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
    #37 0x000055555e5e8d19 in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
    #38 0x000055555dd6e0d4 in wait_sync_command_done () at /home/simark/src/binutils-gdb/gdb/top.c:528
    #39 0x000055555dd6e372 in maybe_wait_sync_command_done (was_sync=0) at /home/simark/src/binutils-gdb/gdb/top.c:545
    #40 0x000055555d0ec7c8 in catch_command_errors (command=0x55555ce01bb8 <attach_command(char const*, int)>, arg=0x7fffffffe28d "1472010", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:452
    #41 0x000055555d0f03ad in captured_main_1 (context=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1149
    #42 0x000055555d0f1239 in captured_main (data=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1232
    #43 0x000055555d0f1315 in gdb_main (args=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1257
    #44 0x000055555bb70cf9 in main (argc=7, argv=0x7fffffffde88) at /home/simark/src/binutils-gdb/gdb/gdb.c:32

The exception is caught here:

    #0  __cxxabiv1::__cxa_begin_catch (exc_obj_in=0x60e0000060e0) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_catch.cc:84
    #1  0x000055555d95fded in solib_read_symbols (so=0x6190000d8e80, flags=...) at /home/simark/src/binutils-gdb/gdb/solib.c:689
    #2  0x000055555d96233d in solib_add (pattern=0x0, from_tty=0, readsyms=1) at /home/simark/src/binutils-gdb/gdb/solib.c:987
    #3  0x000055555d93646e in enable_break (info=0x608000008f20, from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:2238
    #4  0x000055555d93cfc0 in svr4_solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:3049
    #5  0x000055555d96610d in solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib.c:1195
    #6  0x000055555cdee318 in post_create_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:318
    #7  0x000055555ce00e6e in setup_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:2439
    #8  0x000055555ce59c34 in handle_one (event=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:4887
    #9  0x000055555ce5cd00 in stop_all_threads () at /home/simark/src/binutils-gdb/gdb/infrun.c:5064
    #10 0x000055555ce7f0da in stop_waiting (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:8006
    #11 0x000055555ce67f5c in handle_signal_stop (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:6062
    #12 0x000055555ce63653 in handle_inferior_event (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:5727
    #13 0x000055555ce4f297 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:4105
    #14 0x000055555cdbe3bf in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
    #15 0x000055555d018047 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
    #16 0x000055555e5ea77e in handle_file_event (file_ptr=0x60600008b1c0, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
    #17 0x000055555e5eb09c in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
    #18 0x000055555e5e8d19 in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
    #19 0x000055555dd6e0d4 in wait_sync_command_done () at /home/simark/src/binutils-gdb/gdb/top.c:528
    #20 0x000055555dd6e372 in maybe_wait_sync_command_done (was_sync=0) at /home/simark/src/binutils-gdb/gdb/top.c:545
    #21 0x000055555d0ec7c8 in catch_command_errors (command=0x55555ce01bb8 <attach_command(char const*, int)>, arg=0x7fffffffe28d "1472010", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:452
    #22 0x000055555d0f03ad in captured_main_1 (context=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1149
    #23 0x000055555d0f1239 in captured_main (data=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1232
    #24 0x000055555d0f1315 in gdb_main (args=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1257
    #25 0x000055555bb70cf9 in main (argc=7, argv=0x7fffffffde88) at /home/simark/src/binutils-gdb/gdb/gdb.c:32

Catching the exception at this point means that the thread_db_info
object for this inferior will be left in place, despite the failure to
load libthread_db.  This means that there won't be further attempts at
loading libthread_db, because thread_db_load will think that
libthread_db is already loaded for this inferior and will always exit
early.  To fix this, add a try/catch around calling try_thread_db_load_1
in try_thread_db_load, such that if some exception is thrown while
trying to load libthread_db, we reset / delete the thread_db_info for
that inferior.  That alone makes attach work fine again, because
check_for_thread_db is called again in the thread_db_inferior_created
observer (that happens after we learned about all shared libraries and
their symbols), and libthread_db is successfully loaded then.

When attaching, I think that the inferior_created observer is a good
place to try to load libthread_db: it is called once everything has
stabilized, when we learned about all shared libraries.

The only problem then is that when we first try (and fail) to load
libthread_db, in reaction to learning about libpthread, we show this
warning:

    warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.

This is misleading, because we do succeed in loading it later.  So when
attaching, I think we shouldn't try to load libthread_db in reaction to
the new_objfile events, we should wait until we have learned about all
shared libraries (using the inferior_created observable).  To do so, add
an `in_initial_library_scan` flag to struct inferior.  This flag is used
to postpone loading libthread_db if we are attaching or handling a fork
child.

When debugging remotely with GDBserver, the same problem happens, except
that the qSymbol mechanism (allowing the remote side to ask GDB for
symbols values) is involved.  The fix there is the same idea, we make
GDB wait until all shared libraries and their symbols are known before
sending out a qSymbol packet.  This way, we never present the remote
side a state where libpthread.so's symbols are known but ld-linux's
symbols aren't.

gdb/ChangeLog:

	* inferior.h (class inferior) <in_initial_library_scan>: New.
	* infcmd.c (post_create_inferior): Set in_initial_library_scan.
	* infrun.c (follow_fork_inferior): Likewise.
	* linux-thread-db.c (try_thread_db_load): Catch exception thrown
	by try_thread_db_load_1
	(thread_db_load): Return early if in_initial_library_scan is
	set.
	* remote.c (remote_new_objfile): Return early if
	in_initial_library_scan is set.

Change-Id: I7a279836cfbb2b362b4fde11b196b4aab82f5efb
2021-06-08 16:51:00 -04:00
Andrew Burgess
4351271e9c gdb: add some additional debug output in remote.c
I needed more debug output from:
  remote_target::select_thread_for_ambiguous_stop_reply
I thought this would be useful for others too.

gdb/ChangeLog:

	* remote.c (remote_target)
	<select_thread_for_ambiguous_stop_reply>: Add additional debug
	output.
2021-06-04 17:19:28 +01:00
Simon Marchi
24b21115f5 gdb: fix tab after space indentation issues
I spotted some indentation issues where we had some spaces followed by
tabs at beginning of line, that I wanted to fix.  So while at it, I did
a quick grep to find and fix all I could find.

gdb/ChangeLog:

	* Fix tab after space indentation issues throughout.

Change-Id: I1acb414dd9c593b474ae2b8667496584df4316fd
2021-05-27 15:18:49 -04:00
Simon Marchi
40cb8ca539 gdb: add breakpoint::locations method
Add the breakpoint::locations method, which returns a range that can be
used to iterate over a breakpoint's locations.  This shortens

  for (bp_location *loc = b->loc; loc != nullptr; loc = loc->next)

into

  for (bp_location *loc : b->locations ())

Change all the places that I found that could use it.

gdb/ChangeLog:

	* breakpoint.h (bp_locations_range): New.
	(struct breakpoint) <locations>: New.  Use where possible.

Change-Id: I1ba2f7d93d57e544e1f8609124587dcf2e1da037
2021-05-27 14:58:37 -04:00
Simon Marchi
5e84b7eefb gdb: remove add_alias_cmd overload that accepts a string
Same idea as previous patch, but for add_alias_cmd.  Remove the overload
that accepts the target command as a string (the target command name),
leaving only the one that takes the cmd_list_element.

gdb/ChangeLog:

	* command.h (add_alias_cmd): Accept target as
	cmd_list_element.  Update callers.

Change-Id: I546311f411e9e7da9302322d6ffad4e6c56df266
2021-05-27 14:00:08 -04:00
Simon Marchi
9f26053690 gdb: remove unnecessary lookup_cmd when deprecating commands
Remove a few instances where we look up a command by name, but could
just use the return value of a previous "add command" function call
instead.

gdb/ChangeLog:

	* mi/mi-main.c (_initialize_mi_main):
	* python/py-auto-load.c (gdbpy_initialize_auto_load):
	* remote.c (_initialize_remote):

Change-Id: I6d06f9ca636e340c88c1064ae870483ad392607d
2021-05-27 14:00:07 -04:00
Andrew Burgess
2f63ec5ccc gdb: some int to bool conversion in remote.c
Convert a couple of local variables from int to bool.  There should be
no user visible changes after this commit.

gdb/ChangeLog:

	* remote.c (check_pending_events_prevent_wildcard_vcont): Change
	argument type, update and re-wrap, header comment.
	(remote_target::commit_resumed): Convert any_process_wildcard and
	may_global_wildcard_vcont from int to bool.
2021-05-14 13:39:51 +01:00
Simon Marchi
294c36eb6a gdb: on exec, delegate pushing / unpushing target and adding thread to target_ops::follow_exec
On "exec", some targets need to unpush themselves from the inferior,
and do some bookkeeping, like forgetting the data associated to the
exec'ing inferior.

One such example is the thread-db target.  It does so in
a special case in thread_db_target::wait, just before returning the
TARGET_WAITKIND_EXECD event to its caller.

We have another such case in the context of rocm-gdb [1], where the
"rocm" target is pushed on top of the linux-nat target.  When an exec
happens, we want to unpush the rocm target from the exec'ing inferior to
close some file descriptors that refer to the pre-exec address space and
forget about that inferior.  We then want to push the target on the
inferior in which execution continues, to open the file descriptors for
the post-exec address space.

I think that a good way to address this cleanly is to do all this in the
target_ops::follow_exec implementations.  Make the
process_stratum_target::follow_exec implementation have the default
behavior of pushing itself to the new inferior's target stack (if
execution continues in a new inferior) and add the initial thread.

remote_target::follow_exec is an example of process target that wants to
do a bit more than the default behavior.  So it calls
process_stratum_target::follow_exec first and does the extra work
second.

linux-thread-db (a non-process target) implements follow_exec to do some
bookeeping (forget about that process' data), before handing down the
event down to the process target (which hits
process_stratum_target::follow_exec).

gdb/ChangeLog:

	* target.h (struct target_ops) <follow_exec>: Add ptid_t
	parameter.
	(target_follow_exec): Likewise.
	* target.c (target_follow_exec): Add ptid_t parameter.
	* infrun.c (follow_exec): Adjust call to target_follow_exec,
	don't push target nor create thread.
	* linux-thread-db.c (class thread_db_target) <follow_exec>: New.
	(thread_db_target::wait): Just return on TARGET_WAITKIND_EXECD.
	(thread_db_target::follow_exec): New.
	* remote.c (class remote_target) <follow_exec>: Add ptid_t parameter.
	(remote_target::follow_exec): Call
	process_stratum_target::follow_exec.
	* target-delegates.c: Re-generate.

Change-Id: I3f96d0ba3ea0dde6540b7e1b4d5cdb01635088c8
2021-05-13 15:29:00 -04:00
Marco Barisione
2f822da535 gdb: generate the prefix name for prefix commands on demand
Previously, the prefixname field of struct cmd_list_element was manually
set for prefix commands.  This seems verbose and error prone as it
required every single call to functions adding prefix commands to
specify the prefix name while the same information can be easily
generated.

Historically, this was not possible as the prefix field was null for
many commands, but this was fixed in commit
3f4d92ebdf by Philippe Waroquiers, so
we can rely on the prefix field being set when generating the prefix
name.

This commit also fixes a use after free in this scenario:
* A command gets created via Python (using the gdb.Command class).
  The prefix name member is dynamically allocated.
* An alias to the new command is created. The alias's prefixname is set
  to point to the prefixname for the original command with a direct
  assignment.
* A new command with the same name as the Python command is created.
* The object for the original Python command gets freed and its
  prefixname gets freed as well.
* The alias is updated to point to the new command, but its prefixname
  is not updated so it keeps pointing to the freed one.

gdb/ChangeLog:

	* command.h (add_prefix_cmd): Remove the prefixname argument as
	it can now be generated automatically.  Update all callers.
	(add_basic_prefix_cmd): Ditto.
	(add_show_prefix_cmd): Ditto.
	(add_prefix_cmd_suppress_notification): Ditto.
	(add_abbrev_prefix_cmd): Ditto.
	* cli/cli-decode.c (add_prefix_cmd): Ditto.
	(add_basic_prefix_cmd): Ditto.
	(add_show_prefix_cmd): Ditto.
	(add_prefix_cmd_suppress_notification): Ditto.
	(add_prefix_cmd_suppress_notification): Ditto.
	(add_abbrev_prefix_cmd): Ditto.
	* cli/cli-decode.h (struct cmd_list_element): Replace the
	prefixname member variable with a method which generates the
	prefix name at runtime.  Update all code reading the prefix
	name to use the method, and remove all code setting it.
	* python/py-cmd.c (cmdpy_destroyer): Remove code to free the
	prefixname member as it's now a method.
	(cmdpy_function): Determine if the command is a prefix by
	looking at prefixlist, not prefixname.
2021-05-12 11:19:22 +01:00
Andrew Burgess
8a82de5884 gdb: some int to bool conversion
Change int parameter to bool in remote_notice_new_inferior (remote.c)
and notice_new_inferior (infcmd.c), and update the callers.

There should be no user visible changes after this commit.

gdb/ChangeLog:

	* infcmd.c (notice_new_inferior): Change parameter type.
	* inferior.h (notice_new_inferior): Change parameter type.
	* remote.c (remote_notice_new_inferior): Change parameter type to
	bool.  Also update type of local variable to bool.
	(remote_target::update_thread_list): Change type of local variable
	to bool.
	(remote_target::process_stop_reply): Pass bool instead of int to
	remote_notice_new_inferior.
2021-05-07 17:00:25 +01:00
Simon Marchi
c90e7d6352 gdbsupport, gdb: give names to observers
Give a name to each observer, this will help produce more meaningful
debug message.

gdbsupport/ChangeLog:

	* observable.h (class observable) <struct observer> <observer>:
	Add name parameter.
	<name>: New field.
	<attach>: Add name parameter, update all callers.

Change-Id: Ie0cc4664925215b8d2b09e026011b7803549fba0
2021-04-24 19:26:41 -04:00
Tom de Vries
c39ebbf43f [gdb] Fix assert in remote_async_get_pending_events_handler
Occassionally I run into the following assert:
...
(gdb) PASS: gdb.multi/multi-target-continue.exp: inferior 5
Remote debugging from host ::1, port 49990^M
Process multi-target-continue created; pid = 31241^M
src/gdb/remote-notif.c:113: internal-error: \
  void remote_async_get_pending_events_handler(gdb_client_data): \
  Assertion `target_is_non_stop_p ()' failed.^M
...

The assert checks target_is_non_stop_p, which is related to the current
target.

Fix this by changing the assert such that it checks non-stopness related to
the event it's handling.

Tested on x86_64-linux.

gdb/ChangeLog:

2021-04-22  Simon Marchi  <simon.marchi@polymtl.ca>
	    Tom de Vries  <tdevries@suse.de>

	PR remote/27710
	* remote.c (remote_target_is_non_stop_p): New function.
	* remote.h (remote_target_is_non_stop_p): Declare.
	* remote-notif.c (remote_async_get_pending_events_handler): Fix assert
	to check non-stopness using notif_state->remote rather current target.
2021-04-22 17:01:00 +02:00
Simon Marchi
e97007b64a gdb: make target_ops::follow_fork return void
I noticed that all implementations return false, so
target_ops::follow_fork doesn't really need to return a value.  Change
it to return void.

gdb/ChangeLog:

	* target.h (struct target_ops) <follow_fork>: Return void.
	(target_follow_fork): Likewise.
	* target.c (default_follow_fork): Likewise.
	(target_follow_fork): Likewise.
	* infrun.c (follow_fork_inferior): Adjust.
	* fbsd-nat.h (class fbsd_nat_target) <follow_fork>: Return void.
	* fbsd-nat.c (fbsd_nat_target:::follow_fork): Likewise.
	* linux-nat.h (class linux_nat_target) <follow_fork>: Likewise.
	* linux-nat.c (linux_nat_target::follow_fork): Return void.
	* obsd-nat.h (class obsd_nat_target) <follow_fork>: Return void.
	* obsd-nat.c (obsd_nat_target::follow_fork): Likewise.
	* remote.c (class remote_target) <follow_fork>: Likewise.
	(remote_target::follow_fork): Likewise.
	* target-delegates.c: Re-generate.

Change-Id: If908c2f68b29fa275be2b0b9deb41e4c6a1b7879
2021-04-07 16:57:29 -04:00
Simon Marchi
b4b1a226df gdb: defer commit resume until all available events are consumed
Rationale
---------

Let's say you have multiple threads hitting a conditional breakpoint
at the same time, and all of these are going to evaluate to false.
All these threads will need to be resumed.

Currently, GDB fetches one target event (one SIGTRAP representing the
breakpoint hit) and decides that the thread should be resumed.  It
calls resume and commit_resume immediately.  It then fetches the
second target event, and does the same, until it went through all
threads.

The result is therefore something like:

  - consume event for thread A
  - resume thread A
  - commit resume (affects thread A)
  - consume event for thread B
  - resume thread B
  - commit resume (affects thread B)
  - consume event for thread C
  - resume thread C
  - commit resume (affects thread C)

For targets where it's beneficial to group resumptions requests (most
likely those that implement target_ops::commit_resume), it would be
much better to have:

  - consume event for thread A
  - resume thread A
  - consume event for thread B
  - resume thread B
  - consume event for thread C
  - resume thread C
  - commit resume (affects threads A, B and C)

Implementation details
----------------------

To achieve this, this patch adds another check in
maybe_set_commit_resumed_all_targets to avoid setting the
commit-resumed flag of targets that readily have events to provide to
infrun.

To determine if a target has events readily available to report, this
patch adds an `has_pending_events` target_ops method.  The method
returns a simple bool to say whether or not it has pending events to
report.

Testing
=======

To test this, I start GDBserver with a program that spawns multiple
threads:

 $ ../gdbserver/gdbserver --once :1234 ~/src/many-threads-stepping-over-breakpoints/many-threads-stepping-over-breakpoints

I then connect with GDB and install a conditional breakpoint that always
evaluates to false (and force the evaluation to be done by GDB):

 $ ./gdb -nx --data-directory=data-directory \
     /home/simark/src/many-threads-stepping-over-breakpoints/many-threads-stepping-over-breakpoints \
     -ex "set breakpoint condition-evaluation host" \
     -ex "set pag off" \
     -ex "set confirm off" \
     -ex "maint set target-non-stop on" \
     -ex "tar rem :1234" \
     -ex "tb main" \
     -ex "b 13 if 0" \
     -ex c \
     -ex "set debug infrun" \
     -ex "set debug remote 1" \
     -ex "set debug displaced"

I then do "continue" and look at the log.

The remote target receives a bunch of stop notifications for all
threads that have hit the breakpoint.  infrun consumes and processes
one event, decides it should not cause a stop, prepares a displaced
step, after which we should see:

 [infrun] maybe_set_commit_resumed_all_process_targets: not requesting commit-resumed for target remote, target has pending events

Same for a second thread (since we have 2 displaced step buffers).
For the following threads, their displaced step is deferred since
there are no more buffers available.

After consuming the last event the remote target has to offer, we get:

 [infrun] maybe_set_commit_resumed_all_process_targets: enabling commit-resumed for target remote
 [infrun] maybe_call_commit_resumed_all_process_targets: calling commit_resumed for target remote
 [remote] Sending packet: $vCont;s:p14d16b.14d1b1;s:p14d16b.14d1b2#55
 [remote] Packet received: OK

Without the patch, there would have been one vCont;s just after each
prepared displaced step.

gdb/ChangeLog:
yyyy-mm-dd  Simon Marchi  <simon.marchi@efficios.com>
	    Pedro Alves  <pedro@palves.net>

	* async-event.c (async_event_handler_marked): New.
	* async-event.h (async_event_handler_marked): Declare.
	* infrun.c (maybe_set_commit_resumed_all_targets): Switch to
	inferior before calling target method.  Don't commit-resumed if
	target_has_pending_events is true.
	* remote.c (remote_target::has_pending_events): New.
	* target-delegates.c: Regenerate.
	* target.c (target_has_pending_events): New.
	* target.h (target_ops::has_pending_events): New target method.
	(target_has_pending_events): New.

Change-Id: I18112ba19a1ff4986530c660f530d847bb4a1f1d
2021-03-26 16:02:11 +00:00
Simon Marchi
1192f124a3 gdb: generalize commit_resume, avoid commit-resuming when threads have pending statuses
The rationale for this patch comes from the ROCm port [1], the goal
being to reduce the number of back and forths between GDB and the
target when doing successive operations.  I'll start with explaining
the rationale and then go over the implementation.  In the ROCm / GPU
world, the term "wave" is somewhat equivalent to a "thread" in GDB.
So if you read if from a GPU stand point, just s/thread/wave/.

ROCdbgapi, the library used by GDB [2] to communicate with the GPU
target, gives the illusion that it's possible for the debugger to
control (start and stop) individual threads.  But in reality, this is
not how it works.  Under the hood, all threads of a queue are
controlled as a group.  To stop one thread in a group of running ones,
the state of all threads is retrieved from the GPU, all threads are
destroyed, and all threads but the one we want to stop are re-created
from the saved state.  The net result, from the point of view of GDB,
is that the library stopped one thread.  The same thing goes if we
want to resume one thread while others are running: the state of all
running threads is retrieved from the GPU, they are all destroyed, and
they are all re-created, including the thread we want to resume.

This leads to some inefficiencies when combined with how GDB works,
here are two examples:

 - Stopping all threads: because the target operates in non-stop mode,
   when the user interface mode is all-stop, GDB must stop all threads
   individually when presenting a stop.  Let's suppose we have 1000
   threads and the user does ^C.  GDB asks the target to stop one
   thread.  Behind the scenes, the library retrieves 1000 thread
   states and restores the 999 others still running ones.  GDB asks
   the target to stop another one.  The target retrieves 999 thread
   states and restores the 998 remaining ones.  That means that to
   stop 1000 threads, we did 1000 back and forths with the GPU.  It
   would have been much better to just retrieve the states once and
   stop there.

 - Resuming with pending events: suppose the 1000 threads hit a
   breakpoint at the same time.  The breakpoint is conditional and
   evaluates to true for the first thread, to false for all others.
   GDB pulls one event (for the first thread) from the target, decides
   that it should present a stop, so stops all threads using
   stop_all_threads.  All these other threads have a breakpoint event
   to report, which is saved in `thread_info::suspend::waitstatus` for
   later.  When the user does "continue", GDB resumes that one thread
   that did hit the breakpoint.  It then processes the pending events
   one by one as if they just arrived.  It picks one, evaluates the
   condition to false, and resumes the thread.  It picks another one,
   evaluates the condition to false, and resumes the thread.  And so
   on.  In between each resumption, there is a full state retrieval
   and re-creation.  It would be much nicer if we could wait a little
   bit before sending those threads on the GPU, until it processed all
   those pending events.

To address this kind of performance issue, ROCdbgapi has a concept
called "forward progress required", which is a boolean state that
allows its user (i.e. GDB) to say "I'm doing a bunch of operations,
you can hold off putting the threads on the GPU until I'm done" (the
"forward progress not required" state).  Turning forward progress back
on indicates to the library that all threads that are supposed to be
running should now be really running on the GPU.

It turns out that GDB has a similar concept, though not as general,
commit_resume.  One difference is that commit_resume is not stateful:
the target can't look up "does the core need me to schedule resumed
threads for execution right now".  It is also specifically linked to
the resume method, it is not used in other contexts.  The target
accumulates resumption requests through target_ops::resume calls, and
then commits those resumptions when target_ops::commit_resume is
called.  The target has no way to check if it's ok to leave resumed
threads stopped in other target methods.

To bridge the gap, this patch generalizes the commit_resume concept in
GDB to match the forward progress concept of ROCdbgapi.  The current
name (commit_resume) can be interpreted as "commit the previous resume
calls".  I renamed the concept to "commit_resumed", as in "commit the
threads that are resumed".

In the new version, we have two things:

 - the commit_resumed_state field in process_stratum_target: indicates
   whether GDB requires target stacks using this target to have
   resumed threads committed to the execution target/device.  If
   false, an execution target is allowed to leave resumed threads
   un-committed at the end of whatever method it is executing.

 - the commit_resumed target method: called when commit_resumed_state
   transitions from false to true.  While commit_resumed_state was
   false, the target may have left some resumed threads un-committed.
   This method being called tells it that it should commit them back
   to the execution device.

Let's take the "Stopping all threads" scenario from above and see how
it would work with the ROCm target with this change.  Before stopping
all threads, GDB would set the target's commit_resumed_state field to
false.  It would then ask the target to stop the first thread.  The
target would retrieve all threads' state from the GPU and mark that
one as stopped.  Since commit_resumed_state is false, it leaves all
the other threads (still resumed) stopped.  GDB would then proceed to
call target_stop for all the other threads.  Since resumed threads are
not committed, this doesn't do any back and forth with the GPU.

To simplify the implementation of targets, this patch makes it so that
when calling certain target methods, the contract between the core and
the targets guarantees that commit_resumed_state is false.  This way,
the target doesn't need two paths, one for commit_resumed_state ==
true and one for commit_resumed_state == false.  It can just assert
that commit_resumed_state is false and work with that assumption.
This also helps catch places where we forgot to disable
commit_resumed_state before calling the method, which represents a
probable optimization opportunity.  The commit adds assertions in the
target method wrappers (target_resume and friends) to have some
confidence that this contract between the core and the targets is
respected.

The scoped_disable_commit_resumed type is used to disable the commit
resumed state of all process targets on construction, and selectively
re-enable it on destruction (see below for criteria).  Note that it
only sets the process_stratum_target::commit_resumed_state flag.  A
subsequent call to maybe_call_commit_resumed_all_targets is necessary
to call the commit_resumed method on all target stacks with process
targets that got their commit_resumed_state flag turned back on.  This
separation is because we don't want to call the commit_resumed methods
in scoped_disable_commit_resumed's destructor, as they may throw.

On destruction, commit-resumed is not re-enabled for a given target
if:

 1. this target has no threads resumed, or

 2. this target has at least one resumed thread with a pending status
    known to the core (saved in thread_info::suspend::waitstatus).

The first point is not technically necessary, because a proper
commit_resumed implementation would be a no-op if the target has no
resumed threads.  But since we have a flag do to a quick check, it
shouldn't hurt.

The second point is more important: together with the
scoped_disable_commit_resumed instance added in fetch_inferior_event,
it makes it so the "Resuming with pending events" described above is
handled efficiently.  Here's what happens in that case:

 1. The user types "continue".

 2. Upon destruction, the scoped_disable_commit_resumed in the
    `proceed` function does not enable commit-resumed, as it sees some
    threads have pending statuses.

 3. fetch_inferior_event is called to handle another event, the
    breakpoint hit evaluates to false, and that thread is resumed.
    Because there are still more threads with pending statuses, the
    destructor of scoped_disable_commit_resumed in
    fetch_inferior_event still doesn't enable commit-resumed.

 4. Rinse and repeat step 3, until the last pending status is handled
    by fetch_inferior_event.  In that case,
    scoped_disable_commit_resumed's destructor sees there are no more
    threads with pending statues, so it asks the target to commit
    resumed threads.

This allows us to avoid all unnecessary back and forths, there is a
single commit_resumed call once all pending statuses are processed.

This change required remote_target::remote_stop_ns to learn how to
handle stopping threads that were resumed but pending vCont.  The
simplest example where that happens is when using the remote target in
all-stop, but with "maint set target-non-stop on", to force it to
operate in non-stop mode under the hood.  If two threads hit a
breakpoint at the same time, GDB will receive two stop replies.  It
will present the stop for one thread and save the other one in
thread_info::suspend::waitstatus.

Before this patch, when doing "continue", GDB first resumes the thread
without a pending status:

    Sending packet: $vCont;c:p172651.172676#f3

It then consumes the pending status in the next fetch_inferior_event
call:

    [infrun] do_target_wait_1: Using pending wait status status->kind = stopped, signal = GDB_SIGNAL_TRAP for Thread 1517137.1517137.
    [infrun] target_wait (-1.0.0, status) =
    [infrun]   1517137.1517137.0 [Thread 1517137.1517137],
    [infrun]   status->kind = stopped, signal = GDB_SIGNAL_TRAP

It then realizes it needs to stop all threads to present the stop, so
stops the thread it just resumed:

    [infrun] stop_all_threads:   Thread 1517137.1517137 not executing
    [infrun] stop_all_threads:   Thread 1517137.1517174 executing, need stop
    remote_stop called
    Sending packet: $vCont;t:p172651.172676#04

This is an unnecessary resume/stop.  With this patch, we don't commit
resumed threads after proceeding, because of the pending status:

    [infrun] maybe_commit_resumed_all_process_targets: not requesting commit-resumed for target extended-remote, a thread has a pending waitstatus

When GDB handles the pending status and stop_all_threads runs, we stop a
resumed but pending vCont thread:

    remote_stop_ns: Enqueueing phony stop reply for thread pending vCont-resume (1520940, 1520976, 0)

That thread was never actually resumed on the remote stub / gdbserver,
so we shouldn't send a packet to the remote side asking to stop the
thread.

Note that there are paths that resume the target and then do a
synchronous blocking wait, in sort of nested event loop, via
wait_sync_command_done.  For example, inferior function calls, or any
run control command issued from a breakpoint command list.  We handle
that making wait_sync_command_one a "sync" point -- force forward
progress, or IOW, force-enable commit-resumed state.

gdb/ChangeLog:
yyyy-mm-dd  Simon Marchi  <simon.marchi@efficios.com>
	    Pedro Alves  <pedro@palves.net>

	* infcmd.c (run_command_1, attach_command, detach_command)
	(interrupt_target_1): Use scoped_disable_commit_resumed.
	* infrun.c (do_target_resume): Remove
	target_commit_resume call.
	(commit_resume_all_targets): Remove.
	(maybe_set_commit_resumed_all_targets): New.
	(maybe_call_commit_resumed_all_targets): New.
	(enable_commit_resumed): New.
	(scoped_disable_commit_resumed::scoped_disable_commit_resumed)
	(scoped_disable_commit_resumed::~scoped_disable_commit_resumed)
	(scoped_disable_commit_resumed::reset)
	(scoped_disable_commit_resumed::reset_and_commit)
	(scoped_enable_commit_resumed::scoped_enable_commit_resumed)
	(scoped_enable_commit_resumed::~scoped_enable_commit_resumed):
	New.
	(proceed): Use scoped_disable_commit_resumed and
	maybe_call_commit_resumed_all_targets.
	(fetch_inferior_event): Use scoped_disable_commit_resumed.
	* infrun.h (struct scoped_disable_commit_resumed): New.
	(maybe_call_commit_resumed_all_process_targets): New.
	(struct scoped_enable_commit_resumed): New.
	* mi/mi-main.c (exec_continue): Use scoped_disable_commit_resumed.
	* process-stratum-target.h (class process_stratum_target):
	<commit_resumed_state>: New.
	* record-full.c (record_full_wait_1): Change commit_resumed_state
	around calling commit_resumed.
	* remote.c (class remote_target) <commit_resume>: Rename to...
	<commit_resumed>: ... this.
	(struct stop_reply): Move up.
	(remote_target::commit_resume): Rename to...
	(remote_target::commit_resumed): ... this.  Check if there is any
	thread pending vCont resume.
	(remote_target::remote_stop_ns): Generate stop replies for resumed
	but pending vCont threads.
	(remote_target::wait_ns): Add gdb_assert.
	* target-delegates.c: Regenerate.
	* target.c (target_wait, target_resume): Assert that the current
	process_stratum target isn't in commit-resumed state.
	(defer_target_commit_resume): Remove.
	(target_commit_resume): Remove.
	(target_commit_resumed): New.
	(make_scoped_defer_target_commit_resume): Remove.
	(target_stop): Assert that the current process_stratum target
	isn't in commit-resumed state.
	* target.h (struct target_ops) <commit_resume>: Rename to ...
	 <commit_resumed>: ... this.
	(target_commit_resume): Remove.
	(target_commit_resumed): New.
	(make_scoped_defer_target_commit_resume): Remove.
	* top.c (wait_sync_command_done): Use
	scoped_enable_commit_resumed.

[1] https://github.com/ROCm-Developer-Tools/ROCgdb/
[2] https://github.com/ROCm-Developer-Tools/ROCdbgapi

Change-Id: I836135531a29214b21695736deb0a81acf8cf566
2021-03-26 15:58:47 +00:00
Pedro Alves
323fd5b9f9 Fix problem exposed by gdb.server/stop-reply-no-thread-multi.exp
Running gdb.server/stop-reply-no-thread-multi.exp with "maint set
target-non-stop on" occasionally hit an internal error like this:

  ...
  continue
  Continuing.
  warning: multi-threaded target stopped without sending a thread-id, using first non-exited thread
  /home/pedro/gdb/binutils-gdb/src/gdb/inferior.c:291: internal-error: inferior* find_inferior_pid(process_stratum_target*, int): Assertion `pid != 0' failed.
  A problem internal to GDB has been detected,
  further debugging may prove unreliable.

  This is a bug, please report it.
  FAIL: gdb.server/stop-reply-no-thread-multi.exp: to_disable=Tthread: continue until exit (GDB internal error)

The backtrace looks like this:

 ...
 #5  0x0000560357b0879c in internal_error (file=0x560357be6c18 "/home/pedro/gdb/binutils-gdb/src/gdb/inferior.c", line=291, fmt=0x560357be6b21 "%s: Assertion `%s' failed.") at /home/pedro/gdb/binutils-gdb/src/gdbsupport/errors.cc:55
 #6  0x000056035762061b in find_inferior_pid (targ=0x5603596e9560, pid=0) at /home/pedro/gdb/binutils-gdb/src/gdb/inferior.c:291
 #7  0x00005603576206e6 in find_inferior_ptid (targ=0x5603596e9560, ptid=...) at /home/pedro/gdb/binutils-gdb/src/gdb/inferior.c:305
 #8  0x00005603577d43ed in remote_target::check_pending_events_prevent_wildcard_vcont (this=0x5603596e9560, may_global_wildcard=0x7fff84fb05f0) at /home/pedro/gdb/binutils-gdb/src/gdb/remote.c:7215
 #9  0x00005603577d2a9c in remote_target::commit_resumed (this=0x5603596e9560) at /home/pedro/gdb/binutils-gdb/src/gdb/remote.c:6680
 ...

pid is 0 in this case because the queued event is a process exit event
with no pid associated:

 (top-gdb) p event->ws
 During symbol reading: .debug_line address at offset 0x563c9a is 0 [in module /home/pedro/gdb/binutils-gdb/build/gdb/gdb]
 $1 = {kind = TARGET_WAITKIND_EXITED, value = {integer = 0, sig = GDB_SIGNAL_0, related_pid = {m_pid = 0, m_lwp = 0, m_tid = 0}, execd_pathname = 0x0, syscall_number = 0}}
 (top-gdb)

This fixes it, and adds a "maint set target-non-stop on/off" axis to the testcase.

gdb/ChangeLog:

	* remote.c
	(remote_target::check_pending_events_prevent_wildcard_vcont):
	Check whether the event's ptid is not null_ptid before looking up
	the corresponding inferior.

gdb/testsuite/ChangeLog:

	* gdb.server/stop-reply-no-thread-multi.exp (run_test): Add
	"target_non_stop" parameter and use it.
	(top level): Add "maint set target-non-stop on/off" testing axis.

Change-Id: Ia30cf275305ee4dcbbd33f731534cd71d1550eaa
2021-03-25 22:09:54 +00:00
Simon Marchi
328d42d87e gdb: remove current_top_target function
The current_top_target function is a hidden dependency on the current
inferior.  Since I'd like to slowly move towards reducing our dependency
on the global current state, remove this function and make callers use

  current_inferior ()->top_target ()

There is no expected change in behavior, but this one step towards
making those callers use the inferior from their context, rather than
refer to the global current inferior.

gdb/ChangeLog:

	* target.h (current_top_target): Remove, make callers use the
	current inferior instead.
	* target.c (current_top_target): Remove.

Change-Id: Iccd457036f84466cdaa3865aa3f9339a24ea001d
2021-03-24 18:08:24 -04:00
Luis Machado
754487e200 Unit testing for GDB-side remote memory tagging handling
Include some unit testing for the functions handling the new qMemTags and
QMemTags packets.

gdb/ChangeLog:

2021-03-24  Luis Machado  <luis.machado@linaro.org>

	* remote: Include gdbsupport/selftest.h.
	(test_memory_tagging_functions): New function.
	(_initialize_remote): Register test_memory_tagging_functions.
2021-03-24 14:48:51 -03:00
Luis Machado
2c2e7f87a8 Add GDB-side remote target support for memory tagging
This patch adds memory tagging support to GDB's remote side, with
packet string checks, new packet support and an implementation of
the two new tags methods fetch_memtags and store_memtags.

GDBserver needs to know how to read/write allocation tags, since that is
done via ptrace.  It doesn't need to know about logical tags.

The new packets are:

qMemTags:<address>,<length>:<type>
--

Reads tags of the specified type from the address range
[<address>, <address + length>)

QMemTags:<address>,<length>:<type>:<uninterpreted tag bytes>
--
Writes the tags of specified type represented by the uninterpreted bytes to
the address range [<address>, <address + length>).

The interpretation of what to do with the tag bytes is up to the arch-specific
code.

Note that these new packets consider the case of packet size overflow as an
error, given the common use case is to read/write only a few memory tags at
a time.  Having to use a couple new packets for multi-part transfers wouldn't
make sense for the little use it would have.

gdb/ChangeLog:

2021-03-24  Luis Machado  <luis.machado@linaro.org>

	* remote.c (PACKET_memory_tagging_feature): New enum.
	(remote_memory_tagging_p): New function.
	(remote_protocol_features): New "memory-tagging" entry.
	(remote_target::remote_query_supported): Handle memory tagging
	support.
	(remote_target::supports_memory_tagging): Implement.
	(create_fetch_memtags_request, parse_fetch_memtags_reply)
	(create_store_memtags_request): New functions.
	(remote_target::fetch_memtags): Implement.
	(remote_target::store_memtags): Implement.
	(_initialize_remote): Add new "memory-tagging-feature"
	config command.
2021-03-24 14:48:25 -03:00
Luis Machado
dbe692af2d New target methods for memory tagging support
This patch starts adding some of the generic pieces to accomodate memory
tagging.

We have three new target methods:

- supports_memory_tagging: Checks if the target supports memory tagging. This
  defaults to false for targets that don't support memory tagging.

- fetch_memtags: Fetches the allocation tags associated with a particular
  memory range [address, address + length).

  The default is to return 0 without returning any tags. This should only
  be called if memory tagging is supported.

- store_memtags: Stores a set of allocation tags for a particular memory
  range [address, address + length).

  The default is to return 0. This should only
  be called if memory tagging is supported.

gdb/ChangeLog:

2021-03-24  Luis Machado  <luis.machado@linaro.org>

	* remote.c (remote_target) <supports_memory_tagging>: New method
	override.
	<fetch_memtags>: New method override.
	<store_memtags>: New method override.
	(remote_target::supports_memory_tagging): New method.
	(remote_target::fetch_memtags): New method.
	(remote_target::store_memtags): New method.
	* target-delegates.c: Regenerate.
	* target.h (struct target_ops) <supports_memory_tagging>: New virtual
	method.
	<fetch_memtags>: New virtual method.
	<store_memtags>: New virtual method.
	(target_supports_memory_tagging): Define.
	(target_fetch_memtags): Define.
	(target_store_memtags): Define.
	* target-debug.h (target_debug_print_size_t)
	(target_debug_print_const_gdb_byte_vector_r)
	(target_debug_print_gdb_byte_vector_r): New functions.
2021-03-24 14:47:05 -03:00
Simon Marchi
02980c5645 gdb: remove push_target free functions
Same as the previous patch, but for the push_target functions.

The implementation of the move variant is moved to a new overload of
inferior::push_target.

gdb/ChangeLog:

	* target.h (push_target): Remove, update callers to use
	inferior::push_target.
	* target.c (push_target): Remove.
	* inferior.h (class inferior) <push_target>: New overload.

Change-Id: I5a95496666278b8f3965e5e8aecb76f54a97c185
2021-03-23 09:50:35 -04:00
Jan Matyas
64d38fdd99 Fix initial thread state of non-threaded remote targets
This change fixes the initial state of the main thread of remote
targets which have no concept of threading. Such targets are
treated as single-threaded by gdb, and this single thread needs
to be initially set to the "resumed" state, in the same manner as
threads in thread-aware remote targets (see remote.c,
remote_target::remote_add_thread).

Without this fix, the following assert was triggered on thread-
unaware remote targets:

    remote_target::select_thread_for_ambiguous_stop_reply(const target_waitstatus*): Assertion `first_resumed_thread != nullptr' failed.

The bug can be reproduced using gdbserver

    * by disabling packets 'T' and 'qThreadInfo', or
    * by disabling all thread-related packets.

The test suite has been updated to include these two scenarios, see
gdb.server/stop-reply-no-thread.exp.

Change-Id: I2c39c9de17e8d6922a8c1b9e259eb316a554a43d
2021-02-25 15:38:54 -05:00
Andrew Burgess
19cf757a87 gdb: spread a little 'const' through the target_section_table code
The code to access the target section table can be made more const, so
lets do that.  There should be no user visible changes after this
commit.

gdb/ChangeLog:

	* gdb/bfd-target.c (class target_bfd) <get_section_table>: Make
	return type const.
	* gdb/exec.c (struct exec_target) <get_section_table>: Likewise.
	(section_table_read_available_memory): Make local const.
	(exec_target::xfer_partial): Make local const.
	(print_section_info): Make parameter const.
	* gdb/exec.h (print_section_info): Likewise.
	* gdb/ppc64-tdep.c (ppc64_convert_from_func_ptr_addr): Make local
	const.
	* gdb/record-btrace.c (record_btrace_target::xfer_partial):
	Likewise.
	* gdb/remote.c (remote_target::remote_xfer_live_readonly_partial):
	Likewise.
	* gdb/s390-tdep.c (s390_load): Likewise.
	* gdb/solib-dsbt.c (scan_dyntag): Likewise.
	* gdb/solib-svr4.c (scan_dyntag): Likewise.
	* gdb/target-debug.h (target_debug_print_target_section_table_p):
	Rename to...
	(target_debug_print_const_target_section_table_p): ...this.
	* gdb/target-delegates.c: Regenerate.
	* gdb/target.c (target_get_section_table): Make return type const.
	(target_section_by_addr): Likewise.  Also make some locals const.
	(memory_xfer_partial_1): Make some locals const.
	* gdb/target.h (struct target_ops) <get_section_table>: Make
	return type const.
	(target_section_by_addr): Likewise.
	(target_get_section_table): Likewise.
2021-02-24 16:58:02 +00:00
Simon Marchi
baa8575b29 gdb: make remote target clear its handler in remote_target::wait
The remote target's remote_async_inferior_event_token is a flag that
tells when it wants the infrun loop to call its wait method.  The flag
is cleared in the async_event_handler's callback
(remote_async_inferior_event_handler), just before calling
inferior_event_handler.  However, since inferior_event_handler may
actually call another target's wait method, there needs to be code that
checks if we need to re-raise the flag.

It would be simpler instead for remote_target::wait to clear the flag
when it returns an event and there are no more to report after that.  If
another target's wait method gets called by inferior_event_handler, the
remote target's flag will stay naturally stay marked.

Note that this is already partially implemented in remote_target::wait,
since the remote target may have multiple events to report (and it can
only report one at the time):

  if (target_is_async_p ())
    {
      remote_state *rs = get_remote_state ();

      /* If there are are events left in the queue tell the event loop
	 to return here.  */
      if (!rs->stop_reply_queue.empty ())
	mark_async_event_handler (rs->remote_async_inferior_event_token);
    }

The code in remote_async_inferior_event_handler also checks for pending
events as well, in addition to the stop reply queue, so I've made
remote_target::wait check for that as well.  I'm not completely sure
this is ok, since I don't understand very well how the pending events
mechanism works.  But I figured it was safer to do this, worst case it
just leads to unnecessary calls to remote_target::wait.

gdb/ChangeLog:

	* remote.c (remote_target::wait): Clear async event handler at
	beginning, mark if needed at the end.
	(remote_async_inferior_event_handler): Don't set or clear async
	event handler.

Change-Id: I20117f5b5acc8a9972c90f16280249b766c1bf37
2021-02-04 13:34:11 -05:00
Simon Marchi
6b36ddeb1e gdb: make async event handlers clear themselves
The `ready` flag of async event handlers is cleared by the async event
handler system right before invoking the associated callback, in
check_async_event_handlers.

This is not ideal with how the infrun subsystem consumes events: all
targets' async event handler callbacks essentially just invoke
`inferior_event_handler`, which eventually calls `fetch_inferior_event`
and `do_target_wait`.  `do_target_wait` picks an inferior at random,
and thus a target at random (it could be the target whose `ready` flag
was cleared, or not), and pulls one event from it.

So it's possible that:

- the async event handler for a target A is called
- we end up consuming an event for target B
- all threads of target B are stopped, target_async(0) is called on it,
  so its async event handler is cleared (e.g.
  record_btrace_target::async)

As a result, target A still has events to report while its async event
handler is left unmarked, so these events are not consumed.  To counter
this, at the end of their async event handler callbacks, targets check
if they still have something to report and re-mark their async event
handler (e.g. remote_async_inferior_event_handler).

The linux_nat target does not suffer from this because it doesn't use an
async event handler at the moment.  It only uses a pipe registered with
the event loop.  It is written to in the SIGCHLD handler (and in other
spots that want to get target wait method called) and read from in
the target's wait method.  So if linux_nat happened to be target A in
the example above, the pipe would just stay readable, and the event loop
would wake up again, until linux_nat's wait method is finally called and
consumes the contents of the pipe.

I think it would be nicer if targets using async_event_handler worked in
a similar way, where the flag would stay set until the target's wait
method is actually called.  As a first step towards that, this patch
moves the responsibility of clearing the ready flags of async event
handlers to the invoked callback.

All async event handler callbacks are modified to clear their ready flag
before doing anything else.  So in practice, nothing changes with this
patch.  It's only the responsibility of clearing the flag that is
shifted toward the callee.

gdb/ChangeLog:

	* async-event.h (async_event_handler_func):  Add documentation.
	* async-event.c (check_async_event_handlers): Don't clear
	async_event_handler ready flag.
	* infrun.c (infrun_async_inferior_event_handler): Clear ready
	flag.
	* record-btrace.c (record_btrace_handle_async_inferior_event):
	Likewise.
	* record-full.c (record_full_async_inferior_event_handler):
	Likewise.
	* remote-notif.c (remote_async_get_pending_events_handler):
	Likewise.
	* remote.c (remote_async_inferior_event_handler): Likewise.

Change-Id: I179ef8e99580eae642d332846fd13664dbddc0c1
2021-02-04 13:13:30 -05:00
Pedro Alves
e87f0fe823 detach and breakpoint removal
A following patch will add a testcase that has a number of threads
constantly stepping over a breakpoint, and then has GDB detach the
process.  That testcase sometimes fails with the inferior crashing
with SIGTRAP after the detach because of the bug fixed by this patch,
when tested with the native target.

The problem is that target_detach removes breakpoints from the target
immediately, and that does not work with the native GNU/Linux target
(and probably no other native target) currently.  The test wouldn't
fail with this issue when testing against gdbserver, because gdbserver
does allow accessing memory while the current thread is running, by
transparently pausing all threads temporarily, without GDB noticing.
Implementing that in gdbserver was a lot of work, so I'm not looking
forward right now to do the same in the native target.  Instead, I
came up with a simpler solution -- push the breakpoints removal down
to the targets.  The Linux target conveniently already pauses all
threads before detaching them, since PTRACE_DETACH only works with
stopped threads, so we move removing breakpoints to after that.  Only
the remote and GNU/Linux targets support support async execution, so
no other target should really need this.

gdb/ChangeLog:

	* linux-nat.c (linux_nat_target::detach): Remove breakpoints
	here...
	* remote.c (remote_target::remote_detach_1): ... and here ...
	* target.c (target_detach): ... instead of here.
	* target.h (target_ops::detach): Add comment.
2021-02-03 01:15:12 +00:00
Pedro Alves
b0083dd72f Fix a couple vStopped pending ack bugs
A following patch will add a testcase that has two processes with
threads stepping over a breakpoint continuously, and then detaches
from one of the processes while threads are running.  The other
process continues stepping over its breakpoint.  And then the testcase
sends a SIGUSR1, expecting that GDB reports it.  That would sometimes
hang against gdbserver, due to the bugs fixed here.  Both bugs are
related, in that they're about remote protocol asynchronous Stop
notifications.  There's a bug in GDB, and another in GDBserver.

The GDB bug:

- when we detach from a process, the remote target discards any
  pending RSP notification related to that process, including the
  in-flight, yet-unacked notification.  Discarding the in-flight
  notification is the problem.  Until the in-flight notification is
  acked with a vStopped packet, the server won't send another %Stop
  notification.  As a result, the debug session gets messed up.  In
  the new testcase's case, GDB would hang inside stop_all_threads,
  waiting for a stop for one of the process'es threads, which never
  arrived -- its stop reply was permanently stuck in the stop reply
  queue, waiting for a vStopped packet that never arrived.

  In summary:

   1. GDBserver sends stop notification about thread X, the remote
      target receives it and stores it
   2. At the same time, GDB detaches thread X's inferior
   3. The remote target discards the received stop notification
   4. GDBserver waits forever for the ack

The GDBserver bug:

  GDBserver has the opposite bug.  It also discards notifications for
  the process being detached.  If that discards the head of the
  notification queue, when gdb sends an ack, it ends up acking the
  _next_ notification.  Meaning, gdb loses one notification.  In the
  testcase, this results in a similar hang in stop_all_threads.

So we have two very similar bugs in GDB and GDBserver, both resulting
in a similar symptom.  That's why I'm fixing them both at the same
time.

gdb/ChangeLog:

	* remote.c (remote_notif_stop_ack): Don't error out on
	TARGET_WAITKIND_IGNORE; instead, just ignore the notification.
	(remote_target::discard_pending_stop_replies): Don't delete
	in-flight notification; instead, clear its contents.

gdbserver/ChangeLog:

	* server.cc (discard_queued_stop_replies): Don't ever discard the
	notification at the head of the list.
2021-02-03 01:14:46 +00:00
Pedro Alves
621cc31071 Fix "target extended-remote" + "maint set target-non-stop" + "attach"
With "target extended-remote" + "maint set target-non-stop", attaching
hangs like so:

 (gdb) attach 1244450
 Attaching to process 1244450
 [New Thread 1244450.1244450]
 [New Thread 1244450.1244453]
 [New Thread 1244450.1244454]
 [New Thread 1244450.1244455]
 [New Thread 1244450.1244456]
 [New Thread 1244450.1244457]
 [New Thread 1244450.1244458]
 [New Thread 1244450.1244459]
 [New Thread 1244450.1244461]
 [New Thread 1244450.1244462]
 [New Thread 1244450.1244463]
 * hang *

Attaching to the hung GDB shows that GDB is busy in an infinite loop
in stop_all_threads:

 (top-gdb) bt
 #0  stop_all_threads () at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:4755
 #1  0x000055555597b424 in stop_waiting (ecs=0x7fffffffd930) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:7738
 #2  0x0000555555976fba in handle_signal_stop (ecs=0x7fffffffd930) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:5868
 #3  0x0000555555975f6a in handle_inferior_event (ecs=0x7fffffffd930) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:5527
 #4  0x0000555555971da4 in fetch_inferior_event () at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:3910
 #5  0x00005555559540b2 in inferior_event_handler (event_type=INF_REG_EVENT) at /home/pedro/gdb/binutils-gdb/src/gdb/inf-loop.c:42
 #6  0x000055555597e825 in infrun_async_inferior_event_handler (data=0x0) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:9162
 #7  0x0000555555687d1d in check_async_event_handlers () at /home/pedro/gdb/binutils-gdb/src/gdb/async-event.c:328
 #8  0x0000555555e48284 in gdb_do_one_event () at /home/pedro/gdb/binutils-gdb/src/gdbsupport/event-loop.cc:216
 #9  0x00005555559e7512 in start_event_loop () at /home/pedro/gdb/binutils-gdb/src/gdb/main.c:347
 #10 0x00005555559e765d in captured_command_loop () at /home/pedro/gdb/binutils-gdb/src/gdb/main.c:407
 #11 0x00005555559e8f80 in captured_main (data=0x7fffffffdb70) at /home/pedro/gdb/binutils-gdb/src/gdb/main.c:1239
 #12 0x00005555559e8ff2 in gdb_main (args=0x7fffffffdb70) at /home/pedro/gdb/binutils-gdb/src/gdb/main.c:1254
 #13 0x0000555555627c86 in main (argc=12, argv=0x7fffffffdc88) at /home/pedro/gdb/binutils-gdb/src/gdb/gdb.c:32

The problem is that the remote sends stops for all the threads:

 Packet received: l/home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.threads/attach-non-stop/attach-non-stop
 Sending packet: $vStopped#55...Packet received: T0006:f06e25edec7f0000;07:f06e25edec7f0000;10:f14190ccf4550000;thread:p12fd22.12fd2f;core:15;
 Sending packet: $vStopped#55...Packet received: T0006:f0dea5f0ec7f0000;07:f0dea5f0ec7f0000;10:e84190ccf4550000;thread:p12fd22.12fd27;core:4;
 Sending packet: $vStopped#55...Packet received: T0006:f0ee25f1ec7f0000;07:f0ee25f1ec7f0000;10:f14190ccf4550000;thread:p12fd22.12fd26;core:5;
 Sending packet: $vStopped#55...Packet received: T0006:f0bea5efec7f0000;07:f0bea5efec7f0000;10:f14190ccf4550000;thread:p12fd22.12fd29;core:1;
 Sending packet: $vStopped#55...Packet received: T0006:f0ce25f0ec7f0000;07:f0ce25f0ec7f0000;10:e84190ccf4550000;thread:p12fd22.12fd28;core:a;
 Sending packet: $vStopped#55...Packet received: T0006:f07ea5edec7f0000;07:f07ea5edec7f0000;10:e84190ccf4550000;thread:p12fd22.12fd2e;core:f;
 Sending packet: $vStopped#55...Packet received: T0006:f0ae25efec7f0000;07:f0ae25efec7f0000;10:df4190ccf4550000;thread:p12fd22.12fd2a;core:6;
 Sending packet: $vStopped#55...Packet received: T0006:0000000000000000;07:c0e8a381fe7f0000;10:bf43b4f1ec7f0000;thread:p12fd22.12fd22;core:2;
 Sending packet: $vStopped#55...Packet received: T0006:f0fea5f1ec7f0000;07:f0fea5f1ec7f0000;10:df4190ccf4550000;thread:p12fd22.12fd25;core:8;
 Sending packet: $vStopped#55...Packet received: T0006:f09ea5eeec7f0000;07:f09ea5eeec7f0000;10:e84190ccf4550000;thread:p12fd22.12fd2b;core:b;
 Sending packet: $vStopped#55...Packet received: OK

But then wait_one never consumes them, always hitting this path:

 4473          if (nfds == 0)
 4474            {
 4475              /* No waitable targets left.  All must be stopped.  */
 4476              return {NULL, minus_one_ptid, {TARGET_WAITKIND_NO_RESUMED}};
 4477            }

Resulting in GDB constanly calling target_stop to stop threads, but
the remote target never reporting back the stops to infrun.

That TARGET_WAITKIND_NO_RESUMED path shown above is always taken
because here, in wait_one too, just above:

 4428          for (inferior *inf : all_inferiors ())
 4429            {
 4430              process_stratum_target *target = inf->process_target ();
 4431              if (target == NULL
 4432                  || !target->is_async_p ()
                           ^^^^^^^^^^^^^^^^^^^^^
 4433                  || !target->threads_executing)
 4434                continue;

... the remote target is not async.

And in turn that happened because extended_remote_target::attach
misses enabling async in the target-non-stop path.

A testcase exercising this will be added in a following patch.

gdb/ChangeLog:

	* remote.c (extended_remote_target::attach): Set target async in
	the target-non-stop path too.
2021-02-03 01:04:28 +00:00
Simon Marchi
2189c31265 gdb: add remote_debug_printf
This is the next in the new-style debug macro series.

For this one, I decided to omit the function name from the "Sending packet" /
"Packet received" kind of prints, just because it's not very useful in that
context and hinders readability more than anything else.  This is completely
arbitrary.

This is with:

  [remote] putpkt_binary: Sending packet: $qTStatus#49...
  [remote] getpkt_or_notif_sane_1: Packet received: T0;tnotrun:0;tframes:0;tcreated:0;tfree:500000;tsize:500000;circular:0;disconn:0;starttime:0;stoptime:0;username:;notes::

and without:

  [remote] Sending packet: $qTStatus#49...
  [remote] Packet received: T0;tnotrun:0;tframes:0;tcreated:0;tfree:500000;tsize:500000;circular:0;disconn:0;starttime:0;stoptime:0;username:;notes::

A difference is that previously, the query packet and its reply would be
printed on the same line, like this:

  Sending packet: $qTStatus#49...Packet received: T0;tnotrun:0;tframes:0;tcreated:0;tfree:500000;tsize:500000;circular:0;disconn:0;starttime:0;stoptime:0;username:;notes::

Now, they are printed on two lines, since each remote_debug_printf{,_nofunc}
prints its own complete message including an end of line.  It's probably
a matter of taste, but I prefer the two-line version, it's easier to
follow, especially when the query packet is long.

As a result, lib/range-stepping-support.exp needs to be updated, as it
currently expects the vCont packet and the reply to be on the same line.
I think it's sufficient in that context to just expect the vCont packet
and not the reply, since the goal is just to count how many vCont;r GDB
sends.

gdb/ChangeLog:

	* remote.h (remote_debug_printf): New.
	(remote_debug_printf_nofunc): New.
	(REMOTE_SCOPED_DEBUG_ENTER_EXIT): New.
	* remote.c: Use above macros throughout file.

gdbsupport/ChangeLog:

	* common-debug.h (debug_prefixed_printf_cond_nofunc): New.
	* common-debug.c (debug_prefixed_vprintf): Handle a nullptr
	func.

gdb/testsuite/ChangeLog:

	* lib/range-stepping-support.exp (exec_cmd_expect_vCont_count):
	Adjust to "set debug remote" changes.

Change-Id: Ica6dead50d3f82e855c7d763f707cef74bed9fee
2021-01-22 12:43:27 -05:00
Simon Marchi
02349803fc gdb: change remote_debug to bool
As far as I can see, there are no more spots looking for a remote_debug
other than true/false.  If we ever want to revert to an int, we can
always change it back later, but this makes things simpler for now.

gdb/ChangeLog:

	* remote.h (remote_debug): Change to bool.
	* remote.c (remote_debug): Change to bool.
	(_initialize_remote): Adjust.

Change-Id: I21aac5b4cff9dc4f75c8efaf47c23583ecabd2a6
2021-01-22 12:40:48 -05:00
Simon Marchi
cda09ec9f9 gdb: move remote_debug to remote.{h,c}
remote_debug is currently declared in target.h and defined in top.c.
Move them to remote.h and remote.c.

Include remote.h in remote-sim.c, as it uses remote_debug.

gdb/ChangeLog:

	* target.h (remote_debug): Move to...
	* remote.h (remote_debug): ... here.
	* top.c (remote_debug): Move to...
	* remote.c (remote_debug): ... here.
	* remote-sim.c: Include remote.h.

Change-Id: Iae632d12ff8900b23eee6b2529d6a3cd339a8caa
2021-01-22 12:39:08 -05:00
Simon Marchi
baf2b57f18 gdb: move set remote commands to remote.c
Commands "set debug remote" and "set remotetimeout" are defined in
cli/cli-cmds.c, I think it would make more sense for them to be in
remote.c.

gdb/ChangeLog:

	* cli/cli-cmds.c (show_remote_debug): Remove.
	(show_remote_timeout): Remove.
	(_initialize_cli_cmds): Don't register commands.
	* remote.c (show_remote_debug): Move here.
	(show_remote_timeout): Move here.
	(_initialize_remote): Register commands.

Change-Id: Ic4d81888aa4f8dde89d1d29397ef19a08951b80b
2021-01-22 12:35:54 -05:00
Joel Sherrill
a6c11cbb14 gdb/remote.c: address conflicting enum and method name
When building with gcc 4.8, we get:

      CXX    remote.o
    cc1plus: warning: command line option '-Wmissing-prototypes' is valid for C/ObjC but not for C++ [enabled by default]
    /home/smarchi/src/binutils-gdb/gdb/remote.c:1157:38: error: 'resume_state' is not a class, namespace, or enumeration
       enum resume_state m_resume_state = resume_state::NOT_RESUMED;
                                          ^

It looks like gcc 4.8 doesn't like that there is an enum class named
resume_state as well as a method.  Since it's an easy fix, rename the method to
get_remote_state to avoid the clash.

gdb/ChangeLog:

	PR gdb/27219
	* remote.c (struct remote_thread_info) <resume_state>: Rename
	to...
	<get_resume_state>: ... this.
	(remote_target::resume): Adjust.
	(remote_target::commit_resume): Adjust.
	(remote_target::select_thread_for_ambiguous_stop_reply): Adjust.

Change-Id: Ib86c877a4c75ee671d69c27ed06cb8f57bc087db
2021-01-20 20:40:49 -05:00
Simon Marchi
aa2838ccc5 gdb: const-ify hostio methods parameter in remote.c
gdb/ChangeLog:

	* remote.c (class remote_target) <remote_hostio_send_command,
	remote_hostio_parse_result>: Constify parameter.
	(remote_hostio_parse_result): Likewise.
	(remote_target::remote_hostio_send_command): Adjust.
	(remote_target::remote_hostio_pread_vFile): Adjust.
	(remote_target::fileio_readlink): Adjust.
	(remote_target::fileio_fstat): Adjust.

Change-Id: I6b585b99937e6526a0a7e06261d2193114589912
2021-01-18 00:46:13 -05:00
Simon Marchi
b5c8f22d28 gdb: move remote_target::start_remote variable to narrower scope
The wait_status variable is only used when the target is in in all-stop
mode.  We can therefore move it in the !target_is_non_stop scope.  That
lets us remove the assert in the else, that checks that the wait status
is not set.  If the variable doesn't exist in that scope, it pretty much
guarantees that it is not set.

gdb/ChangeLog:

	* remote.c (remote_target::start_remote): Move wait_status to
	narrower scope.

Change-Id: I30979135e3f4f36d04178baa67575c4e58d3b648
2021-01-18 00:46:13 -05:00