Commit Graph

1558 Commits

Author SHA1 Message Date
Simon Marchi
18d2988e5d gdb, gdbserver, gdbsupport: remove includes of early headers
Now that defs.h, server.h and common-defs.h are included via the
`-include` option, it is no longer necessary for source files to include
them.  Remove all the inclusions of these files I could find.  Update
the generation scripts where relevant.

Change-Id: Ia026cff269c1b7ae7386dd3619bc9bb6a5332837
Approved-By: Pedro Alves <pedro@palves.net>
2024-03-26 21:13:22 -04:00
Andrew Burgess
3df7843699 gdb: fix b/p conditions with infcalls in multi-threaded inferiors
This commit fixes bug PR 28942, that is, creating a conditional
breakpoint in a multi-threaded inferior, where the breakpoint
condition includes an inferior function call.

Currently, when a user tries to create such a breakpoint, then GDB
will fail with:

  (gdb) break infcall-from-bp-cond-single.c:61 if (return_true ())
  Breakpoint 2 at 0x4011fa: file /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.threads/infcall-from-bp-cond-single.c, line 61.
  (gdb) continue
  Continuing.
  [New Thread 0x7ffff7c5d700 (LWP 2460150)]
  [New Thread 0x7ffff745c700 (LWP 2460151)]
  [New Thread 0x7ffff6c5b700 (LWP 2460152)]
  [New Thread 0x7ffff645a700 (LWP 2460153)]
  [New Thread 0x7ffff5c59700 (LWP 2460154)]
  Error in testing breakpoint condition:
  Couldn't get registers: No such process.
  An error occurred while in a function called from GDB.
  Evaluation of the expression containing the function
  (return_true) will be abandoned.
  When the function is done executing, GDB will silently stop.
  Selected thread is running.
  (gdb)

Or, in some cases, like this:

  (gdb) break infcall-from-bp-cond-simple.c:56 if (is_matching_tid (arg, 1))
  Breakpoint 2 at 0x401194: file /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.threads/infcall-from-bp-cond-simple.c, line 56.
  (gdb) continue
  Continuing.
  [New Thread 0x7ffff7c5d700 (LWP 2461106)]
  [New Thread 0x7ffff745c700 (LWP 2461107)]
  ../../src.release/gdb/nat/x86-linux-dregs.c:146: internal-error: x86_linux_update_debug_registers: Assertion `lwp_is_stopped (lwp)' failed.
  A problem internal to GDB has been detected,
  further debugging may prove unreliable.

The precise error depends on the exact thread state; so there's race
conditions depending on which threads have fully started, and which
have not.  But the underlying problem is always the same; when GDB
tries to execute the inferior function call from within the breakpoint
condition, GDB will, incorrectly, try to resume threads that are
already running - GDB doesn't realise that some threads might already
be running.

The solution proposed in this patch requires an additional member
variable thread_info::in_cond_eval.  This flag is set to true (in
breakpoint.c) when GDB is evaluating a breakpoint condition.

In user_visible_resume_ptid (infrun.c), when the in_cond_eval flag is
true, then GDB will only try to resume the current thread, that is,
the thread for which the breakpoint condition is being evaluated.
This solves the problem of GDB trying to resume threads that are
already running.

The next problem is that inferior function calls are assumed to be
synchronous, that is, GDB doesn't expect to start an inferior function
call in thread #1, then receive a stop from thread #2 for some other,
unrelated reason.  To prevent GDB responding to an event from another
thread, we update fetch_inferior_event and do_target_wait in infrun.c,
so that, when an inferior function call (on behalf of a breakpoint
condition) is in progress, we only wait for events from the current
thread (the one evaluating the condition).

In do_target_wait I had to change the inferior_matches lambda
function, which is used to select which inferior to wait on.
Previously the logic was this:

   auto inferior_matches = [&wait_ptid] (inferior *inf)
     {
       return (inf->process_target () != nullptr
               && ptid_t (inf->pid).matches (wait_ptid));
     };

This compares the pid of the inferior against the complete ptid we
want to wait on.  Before this commit wait_ptid was only ever
minus_one_ptid (which is special, and means any process), and so every
inferior would match.

After this commit though wait_ptid might represent a specific thread
in a specific inferior.  If we compare the pid of the inferior to a
specific ptid then these will not match.  The fix is to compare
against the pid extracted from the wait_ptid, not against the complete
wait_ptid itself.

In fetch_inferior_event, after receiving the event, we only want to
stop all the other threads, and call inferior_event_handler with
INF_EXEC_COMPLETE, if we are not evaluating a conditional breakpoint.
If we are, then all the other threads should be left doing whatever
they were before.  The inferior_event_handler call will be performed
once the breakpoint condition has finished being evaluated, and GDB
decides to stop or not.

The final problem that needs solving relates to GDB's commit-resume
mechanism, which allows GDB to collect resume requests into a single
packet in order to reduce traffic to a remote target.

The problem is that the commit-resume mechanism will not send any
resume requests for an inferior if there are already events pending on
the GDB side.

Imagine an inferior with two threads.  Both threads hit a breakpoint,
maybe the same conditional breakpoint.  At this point there are two
pending events, one for each thread.

GDB selects one of the events and spots that this is a conditional
breakpoint, GDB evaluates the condition.

The condition includes an inferior function call, so GDB sets up for
the call and resumes the one thread, the resume request is added to
the commit-resume queue.

When the commit-resume queue is committed GDB sees that there is a
pending event from another thread, and so doesn't send any resume
requests to the actual target, GDB is assuming that when we wait we
will select the event from the other thread.

However, as this is an inferior function call for a condition
evaluation, we will not select the event from the other thread, we
only care about events from the thread that is evaluating the
condition - and the resume for this thread was never sent to the
target.

And so, GDB hangs, waiting for an event from a thread that was never
fully resumed.

To fix this issue I have added the concept of "forcing" the
commit-resume queue.  When enabling commit resume, if the force flag
is true, then any resumes will be committed to the target, even if
there are other threads with pending events.

A note on authorship: this patch was based on some work done by
Natalia Saiapova and Tankut Baris Aktemur from Intel[1].  I have made
some changes to their work in this version.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28942

[1] https://sourceware.org/pipermail/gdb-patches/2020-October/172454.html

Co-authored-by: Natalia Saiapova <natalia.saiapova@intel.com>
Co-authored-by: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Reviewed-By: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Tested-By: Luis Machado <luis.machado@arm.com>
Tested-By: Keith Seitz <keiths@redhat.com>
2024-03-25 17:25:06 +00:00
Tiezhu Yang
4a4fd10d17 gdb: Modify the output of "info breakpoints" and "delete breakpoints"
The output of "info breakpoints" includes breakpoint, watchpoint,
tracepoint, and catchpoint if they are created, so it should show
all the four types are deleted in the output of "info breakpoints"
to report empty list after "delete breakpoints".

It should also change the output of "delete breakpoints" to make it
clear that watchpoints, tracepoints, and catchpoints are also being
deleted. This is suggested by Guinevere Larsen, thank you.

$ make check-gdb TESTS="gdb.base/access-mem-running.exp"
$ gdb/gdb gdb/testsuite/outputs/gdb.base/access-mem-running/access-mem-running
[...]
(gdb) break main
Breakpoint 1 at 0x12000073c: file /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c, line 32.
(gdb) watch global_counter
Hardware watchpoint 2: global_counter
(gdb) trace maybe_stop_here
Tracepoint 3 at 0x12000071c: file /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c, line 27.
(gdb) catch fork
Catchpoint 4 (fork)
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000012000073c in main at /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c:32
2       hw watchpoint  keep y                      global_counter
3       tracepoint     keep y   0x000000012000071c in maybe_stop_here at /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c:27
	not installed on target
4       catchpoint     keep y                      fork

Without this patch:

(gdb) delete breakpoints
Delete all breakpoints? (y or n) y
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb) info breakpoints 3
No breakpoint or watchpoint matching '3'.

With this patch:

(gdb) delete breakpoints
Delete all breakpoints, watchpoints, tracepoints, and catchpoints? (y or n) y
(gdb) info breakpoints
No breakpoints, watchpoints, tracepoints, or catchpoints.
(gdb) info breakpoints 3
No breakpoint, watchpoint, tracepoint, or catchpoint matching '3'.

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Approved-by: Kevin Buettner <kevinb@redhat.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-02-26 19:19:58 +08:00
Simon Marchi
85e8a786f4 gdb: add program_space parameter to disable_breakpoints_in_shlibs
Make the current_program_space reference bubble up one level.

Change-Id: Ide917aa306bff1872d961244901d79f65d2da62e
Approved-By: Andrew Burgess <aburgess@redhat.com>
2024-02-09 11:09:55 -05:00
Simon Marchi
f592870204 gdb: add inferior parameter to breakpoint_init_inferior
By inspection, I believe that breakpoint_init_inferior doesn't call
anything that relies on the current program space or inferior.  So,
add an inferior parameter, to make the current inferior / program space
references bubble up one level.

Change-Id: Ib07b7a6d360e324f6ae1aa502dd314b8cce421b7
Approved-By: Andrew Burgess <aburgess@redhat.com>
2024-02-09 11:09:55 -05:00
Simon Marchi
c72348e3b4 gdb: add program_space parameter to mark_breakpoints_out
Make the current_program_space reference bubble up one level.

Change-Id: Idc8ed78d23bf3bb2969f6963d8cc049f26901c29
Approved-By: Andrew Burgess <aburgess@redhat.com>
2024-02-09 11:09:55 -05:00
Simon Marchi
7b323785ef gdb: rename struct shobj -> struct solib
`struct so_list` was recently renamed to `struct shobj` (in 3fe0dfd160
("gdb: rename struct so_list to shobj")).  In hindsight, `solib` would
have been a better name.  We have solib.c, the implementations in
solib-*.c, many functions with solib in their name, the solib_loaded /
solib_unloaded observables, etc.

Rename shobj to solib.

Change-Id: I0af1c7a9b29bdda027e9af633f6d37e1cfcacd5d
Approved-By: Tom Tromey <tom@tromey.com>
2024-02-05 16:10:15 -05:00
Andrew Burgess
1d506c26d9 Update copyright year range in header of all files managed by GDB
This commit is the result of the following actions:

  - Running gdb/copyright.py to update all of the copyright headers to
    include 2024,

  - Manually updating a few files the copyright.py script told me to
    update, these files had copyright headers embedded within the
    file,

  - Regenerating gdbsupport/Makefile.in to refresh it's copyright
    date,

  - Using grep to find other files that still mentioned 2023.  If
    these files were updated last year from 2022 to 2023 then I've
    updated them this year to 2024.

I'm sure I've probably missed some dates.  Feel free to fix them up as
you spot them.
2024-01-12 15:49:57 +00:00
Tom Tromey
667ed4b14d Avoid language-based lookups in startup path
The previous patches are nearly enough to enable background DWARF
reading.  However, this hack in language_defn::get_symbol_name_matcher
causes an early computation of current_language:

  /* If currently in Ada mode, and the lookup name is wrapped in
     '<...>', hijack all symbol name comparisons using the Ada
     matcher, which handles the verbatim matching.  */
  if (current_language->la_language == language_ada
      && lookup_name.ada ().verbatim_p ())
    return current_language->get_symbol_name_matcher_inner (lookup_name);

I considered various options here -- reversing the order of the
checks, or promoting the verbatim mode to not be a purely Ada feature
-- but in the end found that the few calls to this during startup
could be handled more directly.

In the JIT code, and in create_exception_master_breakpoint_hook, gdb
is really looking for a certain kind of symbol (text or data) using a
linkage name.  Changing the lookup here is clearer and probably more
efficient as well.

In create_std_terminate_master_breakpoint, the lookup can't really be
done by linkage name (it would require relying on a certain mangling
scheme, and also may trip over versioned symbols) -- but we know that
this spot is C++-specific, and so the language ought to be temporarily
set to C++ here.

After this patch, the "file" case is much faster:

    (gdb) file /tmp/gdb
    2023-10-23 13:16:54.456 - command started
    Reading symbols from /tmp/gdb...
    2023-10-23 13:16:54.520 - command finished
    Command execution time: 0.225906 (cpu), 0.064313 (wall)
2024-01-08 18:40:22 -07:00
Tom Tromey
fde841947e Use unique_xmalloc_ptr in explicit_location_spec
This changes explicit_location_spec to use unique_xmalloc_ptr,
removing some manual memory management.

Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-13 14:12:52 -07:00
Tom Tromey
e7cdec6605 Use unique_xmalloc_ptr in linespec_location_spec
This changes linespec_location_spec to use unique_xmalloc_ptr,
removing some manual memory management.

Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-13 14:12:52 -07:00
Tom de Vries
f9582a22db [gdb] Fix segfault in for_each_block, part 1
When running test-case gdb.base/vfork-follow-parent.exp on powerpc64 (likewise
on s390x), I run into:
...
(gdb) PASS: gdb.base/vfork-follow-parent.exp: \
  exec_file=vfork-follow-parent-exit: target-non-stop=on: non-stop=off: \
  resolution_method=schedule-multiple: print unblock_parent = 1
continue^M
Continuing.^M
Reading symbols from vfork-follow-parent-exit...^M
^M
^M
Fatal signal: Segmentation fault^M
----- Backtrace -----^M
0x1027d3e7 gdb_internal_backtrace_1^M
        src/gdb/bt-utils.c:122^M
0x1027d54f _Z22gdb_internal_backtracev^M
        src/gdb/bt-utils.c:168^M
0x1057643f handle_fatal_signal^M
        src/gdb/event-top.c:889^M
0x10576677 handle_sigsegv^M
        src/gdb/event-top.c:962^M
0x3fffa7610477 ???^M
0x103f2144 for_each_block^M
        src/gdb/dcache.c:199^M
0x103f235b _Z17dcache_invalidateP13dcache_struct^M
        src/gdb/dcache.c:251^M
0x10bde8c7 _Z24target_dcache_invalidatev^M
        src/gdb/target-dcache.c:50^M
...
or similar.

The root cause for the segmentation fault is that linux_is_uclinux gives an
incorrect result: it should always return false, given that we're running on a
regular linux system, but instead it returns first true, then false.

In more detail, the segmentation fault happens as follows:
- a program space with an address space is created
- a second program space is about to be created. maybe_new_address_space
  is called, and because linux_is_uclinux returns true, maybe_new_address_space
  returns false, and no new address space is created
- a second program space with the same address space is created
- a program space is deleted. Because linux_is_uclinux now returns false,
  gdbarch_has_shared_address_space (current_inferior ()->arch ()) returns
  false, and the address space is deleted
- when gdb uses the address space of the remaining program space, we run into
  the segfault, because the address space is deleted.

Hardcoding linux_is_uclinux to false makes the test-case pass.

We leave addressing the root cause for the following commit in this series.

For now, prevent the segmentation fault by making the address space a refcounted
object.

This was already suggested here [1]:
...
A better solution might be to have the address spaces be reference counted
...

Tested on top of trunk on x86_64-linux and ppc64le-linux.
Tested on top of gdb-14-branch on ppc64-linux.

Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>

PR gdb/30547
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30547

[1] https://sourceware.org/pipermail/gdb-patches/2023-October/202928.html
2023-11-28 10:31:25 +01:00
Lancelot Six
6b09f1342c gdb: Replace gdb::optional with std::optional
Since GDB now requires C++17, we don't need the internally maintained
gdb::optional implementation.  This patch does the following replacing:
  - gdb::optional -> std::optional
  - gdb::in_place -> std::in_place
  - #include "gdbsupport/gdb_optional.h" -> #include <optional>

This change has mostly been done automatically.  One exception is
gdbsupport/thread-pool.* which did not use the gdb:: prefix as it
already lives in the gdb namespace.

Change-Id: I19a92fa03e89637bab136c72e34fd351524f65e9
Approved-By: Tom Tromey <tom@tromey.com>
Approved-By: Pedro Alves <pedro@palves.net>
2023-11-21 11:52:35 +00:00
Simon Marchi
9c742269ec gdb: remove get_current_regcache
Remove get_current_regcache, inlining the call to get_thread_regcache in
callers.  When possible, pass the right thread_info object known from
the local context.  Otherwise, fall back to passing `inferior_thread ()`.

This makes the reference to global context bubble up one level, a small
step towards the long term goal of reducing the number of references to
global context (or rather, moving those references as close as possible
to the top of the call tree).

No behavior change expected.

Change-Id: Ifa6980c88825d803ea586546b6b4c633c33be8d6
2023-11-17 20:01:37 +00:00
Tom Tromey
c748dbd95b Remove some redundant "break"s
I found some "break" statements that follow "return" or a call to a
noreturn function.  These aren't needed, and the compiler would warn
if they were.  So, this patch removes them.

Tested by rebuilding.
2023-11-14 10:37:55 -07:00
Tom Tromey
1f9e9ea5b7 Remove some frame invalidation code
I stumbled across a few spots that mention that a function
"invalidates frame" and also assignments of NULL to a frame_info_ptr.
This code isn't harmful, but is also unnecessary since the
introduction of frame_info_ptr -- nowadays frame invalidations are
handled automatically.

Regression tested on x86-64 Fedora 38.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-10-30 21:47:36 -06:00
Simon Marchi
3fe0dfd160 gdb: rename struct so_list to shobj
Now that so_list lists are implemented using intrusive_list, it doesn't
really make sense for the element type to be named "_list".  Rename to
just `struct shobj` (`struct so` was deemed to be not greppable enough).

Change-Id: I1063061901298bb40fee73bf0cce44cd12154c0e
Approved-By: Pedro Alves <pedro@palves.net>
Reviewed-By: Reviewed-By: Lancelot Six <lancelot.six@amd.com>
2023-10-19 11:14:26 -04:00
Simon Marchi
98107b0b17 gdb: make so_list::{so_original_name,so_name} std::strings
Change these two fields, simplifying memory management and copying.

Change-Id: If2559284c515721e71e1ef56ada8b64667eebe55
Approved-By: Pedro Alves <pedro@palves.net>
Reviewed-By: Reviewed-By: Lancelot Six <lancelot.six@amd.com>
2023-10-19 10:57:51 -04:00
Simon Marchi
bb86ab837e gdb: replace some so_list parameters to use references
A subsequent patch changes so_list to be linked using
intrusive_list.  Iterating an intrusive_list yields some references to
the list elements.  Convert some functions accepting so_list objects to
take references, to make things easier and more natural.  Add const
where possible and convenient.

Change-Id: Id5ab5339c3eb6432e809ad14782952d6a45806f3
Approved-By: Pedro Alves <pedro@palves.net>
Reviewed-By: Reviewed-By: Lancelot Six <lancelot.six@amd.com>
2023-10-19 10:57:51 -04:00
Simon Marchi
99d9c3b92c gdb: remove target_gdbarch
This function is just a wrapper around the current inferior's gdbarch.
I find that having that wrapper just obscures where the arch is coming
from, and that it's often used as "I don't know which arch to use so
I'll use this magical target_gdbarch function that gets me an arch" when
the arch should in fact come from something in the context (a thread,
objfile, symbol, etc).  I think that removing it and inlining
`current_inferior ()->arch ()` everywhere will make it a bit clearer
where that arch comes from and will trigger people into reflecting
whether this is the right place to get the arch or not.

Change-Id: I79f14b4e4934c88f91ca3a3155f5fc3ea2fadf6b
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-10-10 10:44:35 -04:00
Simon Marchi
e0322c6a7b gdb: remove unnecessary nullptr check in free_objfile observers
The free_objfile observable is never called with a nullptr objfile.

Change-Id: I1e990edeb45bc38009ccb129c623911097ab65fe
Approved-By: Tom Tromey <tom@tromey.com>
2023-10-05 13:20:50 -04:00
Simon Marchi
bd93891c9a gdb: remove solib::pspace field
This backlink is not necessary, we always know the program space from
the context.  Pass it down the solib_unloaded observer.

Change-Id: I45a503472dc791f517558b8141901472634e0556
Approved-By: Tom Tromey <tom@tromey.com>
2023-10-02 11:53:21 -04:00
Tom Tromey
0128542673 Use string_file::release in some places
I found a few spots like:

    string_file f;
    std::string x = f.string ();

However, string_file::string returns a 'const std::string &'...  so it
seems to me that this must be copying the string (? I find it hard to
reason about this in C++).

This patch changes these spots to use release() instead, which moves
the string.

Reviewed-by: Keith Seitz <keiths@redhat.com>
Reviewed-by: Lancelot Six <lancelot.six@amd.com>
2023-09-26 06:56:27 -06:00
Tom Tromey
6a9196a65f Use gdb::checked_static_cast for code_breakpoint
This replaces some casts to 'code_breakpoint *' with
checked_static_cast.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-09-19 08:14:01 -06:00
Tom Tromey
01bccc56af Use gdb::checked_static_cast for tracepoints
This replaces some casts to 'tracepoint *' with checked_static_cast.
Some functions are changed to accept a 'tracepoint *' now, for better
type safety.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-09-19 08:14:00 -06:00
Tom Tromey
bcafd1c19e Use gdb::checked_static_cast for watchpoints
This replaces some casts to 'watchpoint *' with checked_static_cast.
In one spot, an unnecessary block is also removed.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-09-19 08:14:00 -06:00
Mohamed Bouhaouel
093da43d2a gdb, breakpoint: add a destructor to the watchpoint struct
Make sure to unlink the related breakpoint when the watchpoint instance
is deleted.  This prevents having a wp-related breakpoint that is
linked to a NULL watchpoint (e.g.  the watchpoint instance is being
deleted when the 'watch' command fails).  With the below scenario,
having such a left out breakpoint will lead to a GDB hang, and this
is due to an infinite loop when deleting all inferior breakpoints.

Scenario:
	(gdb) set can-use-hw-watchpoints 0
	(gdb) awatch <SCOPE VAR>
	Can't set read/access watchpoint when hardware watchpoints are disabled.
	(gdb) rwatch <SCOPE VAR>
	Can't set read/access watchpoint when hardware watchpoints are disabled.
	(gdb) <continue the program until the end>
	>> HANG <<

Signed-off-by: Mohamed Bouhaouel <mohamed.bouhaouel@intel.com>
Reviewed-by: Bruno Larsen <blarsen@redhat.com>
2023-09-19 06:56:53 -06:00
Pedro Alves
9d7d58e726 gdb: centralize "[Thread ...exited]" notifications
Currently, each target backend is responsible for printing "[Thread
...exited]" before deleting a thread.  This leads to unnecessary
differences between targets, like e.g. with the remote target, we
never print such messages, even though we do print "[New Thread ...]".

E.g., debugging the gdb.threads/attach-many-short-lived-threads.exp
with gdbserver, letting it run for a bit, and then pressing Ctrl-C, we
currently see:

 (gdb) c
 Continuing.
 ^C[New Thread 3850398.3887449]
 [New Thread 3850398.3887500]
 [New Thread 3850398.3887551]
 [New Thread 3850398.3887602]
 [New Thread 3850398.3887653]
 ...

 Thread 1 "attach-many-sho" received signal SIGINT, Interrupt.
 0x00007ffff7e6a23f in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=req@entry=0x7fffffffda80, rem=rem@entry=0x7fffffffda80)
     at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78
 78      in ../sysdeps/unix/sysv/linux/clock_nanosleep.c
 (gdb)

Above, we only see "New Thread" notifications, even though threads
were deleted.

After this patch, we'll see:

 (gdb) c
 Continuing.
 ^C[Thread 3558643.3577053 exited]
 [Thread 3558643.3577104 exited]
 [Thread 3558643.3577155 exited]
 [Thread 3558643.3579603 exited]
 ...
 [New Thread 3558643.3597415]
 [New Thread 3558643.3600015]
 [New Thread 3558643.3599965]
 ...

 Thread 1 "attach-many-sho" received signal SIGINT, Interrupt.
 0x00007ffff7e6a23f in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=req@entry=0x7fffffffda80, rem=rem@entry=0x7fffffffda80)
     at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78
 78      in ../sysdeps/unix/sysv/linux/clock_nanosleep.c
 (gdb) q

This commit fixes this by moving the thread exit printing to common
code instead, triggered from within delete_thread (or rather,
set_thread_exited).

There's one wrinkle, though.  While most targest want to print:

 [Thread ... exited]

the Windows target wants to print:

 [Thread ... exited with code <exit_code>]

... and sometimes wants to suppress the notification for the main
thread.  To address that, this commits adds a delete_thread_with_code
function, only used by that target (so far).

This fix was originally posted as part of a larger series:

  https://inbox.sourceware.org/gdb-patches/20221212203101.1034916-1-pedro@palves.net/

But didn't really need to be part of that series.  In order to get
this fix merged sooner, I (Andrew Burgess) have rebased this commit
outside of the original series.  Any bugs introduced while splitting
this patch out and rebasing, are entirely my own.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30129
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
2023-08-23 09:57:38 +01:00
Andrew Burgess
f29ab2e0e3 gdb: add missing notify_breakpoint_modified call
The commit:

  commit b080fe54fb
  Date:   Tue Nov 8 12:32:51 2022 +0000

      gdb: add inferior-specific breakpoints

introduced a bug in the function breakpoint_set_inferior. The above
commit includes this line:

  gdb::observers::breakpoint_modified.notify (b);

when it should have instead used this line:

  notify_breakpoint_modified (b);

The change to use notify_breakpoint_modified was introduced to GDB
after commit b080fe54fb was written, but before it was merged, and I
failed to update this part of the code during the rebase.

The consequence of this error is that the MI interpreter will not emit
breakpoint-modified notifications when breakpoint_set_inferior is
called.

In this commit I update the code to call notify_breakpoint_modified,
and add a test that checks the MI events are being emitted correctly
in this case.
2023-08-23 09:04:45 +01:00
Andrew Burgess
b080fe54fb gdb: add inferior-specific breakpoints
This commit extends the breakpoint mechanism to allow for inferior
specific breakpoints (but not watchpoints in this commit).

As GDB gains better support for multiple connections, and so for
running multiple (possibly unrelated) inferiors, then it is not hard
to imagine that a user might wish to create breakpoints that apply to
any thread in a single inferior.  To achieve this currently, the user
would need to create a condition possibly making use of the $_inferior
convenience variable, which, though functional, isn't the most user
friendly.

This commit adds a new 'inferior' keyword that allows for the creation
of inferior specific breakpoints.

Inferior specific breakpoints are automatically deleted when the
associated inferior is removed from GDB, this is similar to how
thread-specific breakpoints are deleted when the associated thread is
deleted.

Watchpoints are already per-program-space, which in most cases mean
watchpoints are already inferior specific.  There is a small window
where inferior-specific watchpoints might make sense, which is after a
vfork, when two processes are sharing the same address space.
However, I'm leaving that as an exercise for another day.  For now,
attempting to use the inferior keyword with a watchpoint will give an
error, like this:

  (gdb) watch a8 inferior 1
  Cannot use 'inferior' keyword with watchpoints

A final note on the implementation: currently, inferior specific
breakpoints, like thread-specific breakpoints, are inserted into every
inferior, GDB then checks once the inferior stops if we are in the
correct thread or inferior, and resumes automatically if we stopped in
the wrong thread/inferior.

An obvious optimisation here is to only insert breakpoint locations
into the specific program space (which mostly means inferior) that
contains either the inferior or thread we are interested in.  This
would reduce the number times GDB has to stop and then resume again in
a multi-inferior setup.

I have a series on the mailing list[1] that implements this
optimisation for thread-specific breakpoints.  Once this series has
landed I'll update that series to also handle inferior specific
breakpoints in the same way.  For now, inferior specific breakpoints
are just slightly less optimal, but this is no different to
thread-specific breakpoints in a multi-inferior debug session, so I
don't see this as a huge problem.

[1] https://inbox.sourceware.org/gdb-patches/cover.1685479504.git.aburgess@redhat.com/
2023-08-17 16:42:39 +01:00
Mihails Strasuns
3cdc2d7e66 gdb, breakpoint: add breakpoint location debugging logs
Add new commands:

  set debug breakpoint on|off
  show debug breakpoint

This patch introduces new debugging information that prints
breakpoint location insertion and removal flow.

The debug output looks like:
~~~
(gdb) set debug breakpoint on
(gdb) disassemble main
Dump of assembler code for function main:
   0x0000555555555129 <+0>:	endbr64
   0x000055555555512d <+4>:	push   %rbp
   0x000055555555512e <+5>:	mov    %rsp,%rbp
=> 0x0000555555555131 <+8>:	mov    $0x0,%eax
   0x0000555555555136 <+13>:	pop    %rbp
   0x0000555555555137 <+14>:	ret
End of assembler dump.
(gdb) break *0x0000555555555137
Breakpoint 2 at 0x555555555137: file main.c, line 4.
[breakpoint] update_global_location_list: insert_mode = UGLL_MAY_INSERT
(gdb) c
Continuing.
[breakpoint] update_global_location_list: insert_mode = UGLL_INSERT
[breakpoint] insert_bp_location: Breakpoint 2 (0x5565daddb1e0) at address 0x555555555137 in main at main.c:4
[breakpoint] insert_bp_location: Breakpoint -2 (0x5565dab51c10) at address 0x7ffff7fd37b5
[breakpoint] insert_bp_location: Breakpoint -5 (0x5565dab68f30) at address 0x7ffff7fe509e
[breakpoint] insert_bp_location: Breakpoint -7 (0x5565dab694f0) at address 0x7ffff7fe63f4
[breakpoint] remove_breakpoint_1: Breakpoint 2 (0x5565daddb1e0) at address 0x555555555137 in main at main.c:4 due to regular remove
[breakpoint] remove_breakpoint_1: Breakpoint -2 (0x5565dab51c10) at address 0x7ffff7fd37b5 due to regular remove
[breakpoint] remove_breakpoint_1: Breakpoint -5 (0x5565dab68f30) at address 0x7ffff7fe509e due to regular remove
[breakpoint] remove_breakpoint_1: Breakpoint -7 (0x5565dab694f0) at address 0x7ffff7fe63f4 due to regular remove

Breakpoint 2, 0x0000555555555137 in main () at main.c:4
4	}
~~~

Co-Authored-By: Christina Schimpe <christina.schimpe@intel.com>
2023-08-09 07:38:57 +00:00
Andrew Burgess
b1c0ab2080 gdb: avoid double stop after failed breakpoint condition check
This commit replaces this earlier commit:

  commit 2e411b8c68
  Date:   Fri Oct 14 14:53:15 2022 +0100

      gdb: don't always print breakpoint location after failed condition check

and is a result of feedback received here[1].

The original commit addressed a problem where, if a breakpoint
condition included an inferior function call, and if the inferior
function call failed, then GDB would announce the stop twice.  Here's
an example of GDB's output before the above commit that shows the
problem being addressed:

  (gdb) break foo if (some_func ())
  Breakpoint 1 at 0x40111e: file bpcond.c, line 11.
  (gdb) r
  Starting program: /tmp/bpcond

  Program received signal SIGSEGV, Segmentation fault.
  0x0000000000401116 in some_func () at bpcond.c:5
  5       return *p;
  Error in testing condition for breakpoint 1:
  The program being debugged stopped while in a function called from GDB.
  Evaluation of the expression containing the function
  (some_func) will be abandoned.
  When the function is done executing, GDB will silently stop.

  Breakpoint 1, 0x0000000000401116 in some_func () at bpcond.c:5
  5       return *p;
  (gdb)

The original commit addressed this issue in breakpoint.c, by spotting
that the $pc had changed while evaluating the breakpoint condition,
and inferring from this that GDB must have stopped elsewhere.

However, the way in which the original commit suppressed the second
stop announcement was to set bpstat::print to true -- this tells GDB
not to print the frame during the stop announcement, and for the CLI
this is fine, however, it was pointed out that for the MI this still
isn't really enough.  Below is an example from an MI session after the
above commit was applied, this shows the problem with the above
commit:

  -break-insert -c "cond_fail()" foo
  ^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x000000000040111e",func="foo",file="/tmp/mi-condbreak-fail.c",line="30",thread-groups=["i1"],cond="cond_fail()",times="0",original-location="foo"}
  (gdb)
  -exec-run
  =thread-group-started,id="i1",pid="2636270"
  =thread-created,id="1",group-id="i1"
  =library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1",ranges=[{from="0x00007ffff7fd3110",to="0x00007ffff7ff2bb4"}]
  ^running
  *running,thread-id="all"
  (gdb)
  =library-loaded,id="/lib64/libm.so.6",target-name="/lib64/libm.so.6",host-name="/lib64/libm.so.6",symbols-loaded="0",thread-group="i1",ranges=[{from="0x00007ffff7e59390",to="0x00007ffff7ef4f98"}]
  =library-loaded,id="/lib64/libc.so.6",target-name="/lib64/libc.so.6",host-name="/lib64/libc.so.6",symbols-loaded="0",thread-group="i1",ranges=[{from="0x00007ffff7ca66b0",to="0x00007ffff7df3c5f"}]
  ~"\nProgram"
  ~" received signal SIGSEGV, Segmentation fault.\n"
  ~"0x0000000000401116 in cond_fail () at /tmp/mi-condbreak-fail.c:24\n"
  ~"24\t  return *p;\t\t\t/* Crash here.  */\n"
  *stopped,reason="signal-received",signal-name="SIGSEGV",signal-meaning="Segmentation fault",frame={addr="0x0000000000401116",func="cond_fail",args=[],file="/tmp/mi-condbreak-fail.c",fullname="/tmp/mi-condbreak-fail.c",line="24",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="9"
  &"Error in testing condition for breakpoint 1:\n"
  &"The program being debugged was signaled while in a function called from GDB.\n"
  &"GDB remains in the frame where the signal was received.\n"
  &"To change this behavior use \"set unwindonsignal on\".\n"
  &"Evaluation of the expression containing the function\n"
  &"(cond_fail) will be abandoned.\n"
  &"When the function is done executing, GDB will silently stop.\n"
  =breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x000000000040111e",func="foo",file="/tmp/mi-condbreak-fail.c",fullname="/tmp/mi-condbreak-fail.c",line="30",thread-groups=["i1"],cond="cond_fail()",times="1",original-location="foo"}
  *stopped
  (gdb)

Notice that we still see two '*stopped' lines, the first includes the
full frame information, while the second has no frame information,
this is a result of bpstat::print having been set.  Ideally, the
second '*stopped' line should not be present.

By setting bpstat::print I was addressing the problem too late, this
flag really only changes how interp::on_normal_stop prints the stop
event, and interp::on_normal_stop is called (indirectly) from the
normal_stop function in infrun.c.  A better solution is to avoid
calling normal_stop at all for the stops which should not be reported
to the user, and this is what I do in this commit.

This commit has 3 parts:

  1. In breakpoint.c, revert the above commit,

  2. In fetch_inferior_event (infrun.c), capture the stop-id before
  calling handle_inferior_event.  If, after calling
  handle_inferior_event, the stop-id has changed, then this indicates
  that somewhere within handle_inferior_event, a stop was announced to
  the user.  If this is the case then GDB should not call normal_stop,
  and we should rely on whoever announced the stop to ensure that we
  are in a PROMPT_NEEDED state, which means the prompt will be
  displayed once fetch_inferior_event returns.  And,

  3. In infcall.c, do two things:

     (a) In run_inferior_call, after making the inferior call, ensure
     that either async_disable_stdin or async_enable_stdin is called
     to put the prompt state, and stdin handling into the correct
     state based on whether the inferior call completed successfully
     or not, and

     (b) In call_thread_fsm::should_stop, call async_enable_stdin
     rather than changing the prompt state directly.  This isn't
     strictly necessary, but helped me understand this code more.
     This async_enable_stdin call is only reached if normal_stop is
     not going to be called, and replaces the async_enable_stdin call
     that exists in normal_stop.  Though we could just adjust the
     prompt state if felt (to me) much easier to understand when I
     could see this call and the corresponding call in normal_stop.

With these changes in place now, when the inferior call (from the
breakpoint condition) fails, infcall.c leaves the prompt state as
PROMPT_NEEDED, and leaves stdin registered with the event loop.

Back in fetch_inferior_event GDB notices that the stop-id has changed
and so avoids calling normal_stop.

And on return from fetch_inferior_event GDB will display the prompt
and handle input from stdin.

As normal_stop is not called the MI problem is solved, and the test
added in the earlier mentioned commit still passes just fine, so the
CLI has not regressed.

[1] https://inbox.sourceware.org/gdb-patches/6fd4aa13-6003-2563-5841-e80d5a55d59e@palves.net/
2023-08-03 14:55:31 +01:00
Andrew Burgess
3f3ffaca04 gdb: include location number in breakpoint error message
This commit improves the output of this previous commit:

  commit 2dc3457a45
  Date:   Fri Oct 14 13:22:55 2022 +0100

      gdb: include breakpoint number in testing condition error message

The earlier commit extended the error message:

  Error in testing breakpoint condition:

to include the breakpoint number, e.g.:

  Error in testing breakpoint condition 3:

This commit extends takes this further, and includes the location
number if the breakpoint has multiple locations, so we might now see:

  Error in testing breakpoint condition 3.2:

Just as with how GDB reports a normal breakpoint stop, if a breakpoint
only has a single location then the location number is not included,
this keeps things nice and consistent.

I've extended one of the tests to cover the new functionality.

Approved-By: Pedro Alves <pedro@palves.net>
2023-07-10 10:49:59 +01:00
Tom de Vries
3bfdcabbc2 [gdb] Fix more typos
Fix some more typos:
- distinquish -> distinguish
- actualy -> actually
- singe -> single
- frash -> frame
- chid -> child
- dissassembler -> disassembler
- uninitalized -> uninitialized
- precontidion -> precondition
- regsiters -> registers
- marge -> merge
- sate -> state
- garanteed -> guaranteed
- explictly -> explicitly
- prefices (nonstandard plural) -> prefixes
- bondary -> boundary
- formated -> formatted
- ithe -> the
- arrav -> array
- coresponding -> corresponding
- owend -> owned
- fials -> fails
- diasm -> disasm
- ture -> true
- tpye -> type

There's one code change, the name of macro SIG_CODE_BONDARY_FAULT changed to
SIG_CODE_BOUNDARY_FAULT.

Tested on x86_64-linux.
2023-06-05 12:53:15 +02:00
Tom de Vries
33b5899fc0 [gdb] Fix typos
Fix a few typos:
- implemention -> implementation
- convertion(s) -> conversion(s)
- backlashes -> backslashes
- signoring -> ignoring
- (un)ambigious -> (un)ambiguous
- occured -> occurred
- hidding -> hiding
- temporarilly -> temporarily
- immediatelly -> immediately
- sillyness -> silliness
- similiar -> similar
- porkuser -> pokeuser
- thats -> that
- alway -> always
- supercede -> supersede
- accomodate -> accommodate
- aquire -> acquire
- priveleged -> privileged
- priviliged -> privileged
- priviledges -> privileges
- privilige -> privilege
- recieve -> receive
- (p)refered -> (p)referred
- succesfully -> successfully
- successfuly -> successfully
- responsability -> responsibility
- wether -> whether
- wich -> which
- disasbleable -> disableable
- descriminant -> discriminant
- construcstor -> constructor
- underlaying -> underlying
- underyling -> underlying
- structureal -> structural
- appearences -> appearances
- terciarily -> tertiarily
- resgisters -> registers
- reacheable -> reachable
- likelyhood -> likelihood
- intepreter -> interpreter
- disassemly -> disassembly
- covnersion -> conversion
- conviently -> conveniently
- atttribute -> attribute
- struction -> struct
- resonable -> reasonable
- popupated -> populated
- namespaxe -> namespace
- intialize -> initialize
- identifer(s) -> identifier(s)
- expection -> exception
- exectuted -> executed
- dungerous -> dangerous
- dissapear -> disappear
- completly -> completely
- (inter)changable -> (inter)changeable
- beakpoint -> breakpoint
- automativ -> automatic
- alocating -> allocating
- agressive -> aggressive
- writting -> writing
- reguires -> requires
- registed -> registered
- recuding -> reducing
- opeartor -> operator
- ommitted -> omitted
- modifing -> modifying
- intances -> instances
- imbedded -> embedded
- gdbaarch -> gdbarch
- exection -> execution
- direcive -> directive
- demanged -> demangled
- decidely -> decidedly
- argments -> arguments
- agrument -> argument
- amespace -> namespace
- targtet -> target
- supress(ed) -> suppress(ed)
- startum -> stratum
- squence -> sequence
- prompty -> prompt
- overlow -> overflow
- memember -> member
- languge -> language
- geneate -> generate
- funcion -> function
- exising -> existing
- dinking -> syncing
- destroh -> destroy
- clenaed -> cleaned
- changep -> changedp (name of variable)
- arround -> around
- aproach -> approach
- whould -> would
- symobl -> symbol
- recuse -> recurse
- outter -> outer
- freeds -> frees
- contex -> context

Tested on x86_64-linux.

Reviewed-By: Tom Tromey <tom@tromey.com>
2023-06-03 22:43:57 +02:00
Simon Marchi
19081eb5f1 gdb: add interp::on_breakpoint_modified method
Same idea as previous patches, but for breakpoint_modified.

Change-Id: I4f0a9edea912de431e32451d74224b2022a7c328
2023-05-30 15:07:26 -04:00
Simon Marchi
e4239559f4 gdb: add interp::on_breakpoint_deleted method
Same idea as previous patches, but for breakpoint_deleted.

Change-Id: I59c231ce963491bb1eee1432ee1090138f09e19c
2023-05-30 15:07:26 -04:00
Simon Marchi
e7692320db gdb: add interp::on_breakpoint_created method
Same idea as previous patches, but for breakpoint_created.

Change-Id: I614113c924edc243590018b8fb3bf69cb62215ef
2023-05-30 15:07:26 -04:00
Simon Marchi
a1decfc1df gdb: remove breakpoint_pointer_iterator
Remove the breakpoint_pointer_iterator layer.  Adjust all users of
all_breakpoints and all_tracepoints to use references instead of
pointers.

Change-Id: I376826f812117cee1e6b199c384a10376973af5d
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-05-25 09:52:22 -04:00
Simon Marchi
e2a1578868 gdb: link breakpoints with intrusive_list
Change-Id: I043d8d6f3dd864d80d5088f6ffc2c098337249ea
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-05-25 09:41:16 -04:00
Simon Marchi
b00b30b298 gdb: remove bp_location_pointer_iterator
Remove the bp_location_pointer_iterator layer.  Adjust all users of
breakpoint::locations to use references instead of pointers.

Change-Id: Iceed34f5e0f5790a9cf44736aa658be6d1ba1afa
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-05-25 09:40:58 -04:00
Simon Marchi
20afe380e8 gdb: use intrusive_list for breakpoint locations
Replace the hand-maintained linked lists of breakpoint locations with
and intrusive list.

 - Remove breakpoint::loc, add breakpoint::m_locations.

 - Add methods for the various manipulations that need to be done on the
   location list, while maintaining reasonably good encapsulation.

 - bp_location currently has a default constructor because of one use
   in hoist_existing_locations.  hoist_existing_locations now returns a
   bp_location_list, and doesn't need the default-constructor
   bp_location anymore, so remove the bp_location default constructor.

 - I needed to add a call to clear_locations in delete_breakpoint to
   avoid a use-after-free.

 - Add a breakpoint::last_loc method, for use in
   set_breakpoint_condition.

bp_location_range uses reference_to_pointer_iterator, so that all
existing callers of breakpoint::locations don't need to change right
now.  It will be removed in the next patch.

The rest of the changes are to adapt the call sites to use the new
methods, of breakpoint::locations, rather than breakpoint::loc directly.

Change-Id: I25f7ee3d66a4e914a0540589ac414b3b820b6e70
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-05-25 08:47:12 -04:00
Simon Marchi
f5951b9ff8 gdb: add breakpoint::first_loc methods
Add convenience first_loc methods to struct breakpoint (const and
non-const overloads).  A subsequent patch changes the list of locations
to be an intrusive_list and makes the actual list private, so these
spots would need to change from:

    b->loc

to something ugly like:

    *b->locations ().begin ()

That would make the code much heavier and not readable.  There is a
surprisingly big number of places that access the first location of
breakpoints.  Whether this is correct, or these spots fail to consider
the possibility of multi-location breakpoints, I don't know.  But
anyhow, I think that using this instead:

 b->first_loc ()

conveys the intention better than the other two forms.

Change-Id: Ibbefe3e4ca6cdfe570351fe7e2725f2ce11d1e95
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-05-25 08:47:00 -04:00
Simon Marchi
9dc1523b57 gdb: add breakpoint "has locations" methods
Add three convenience methods to struct breakpoint:

 - has_locations: returns true if the breakpoint has at least one
   location
 - has_single_location: returns true if the breakpoint has exactly one
   location
 - has_multiple_locations: returns true if the breakpoint has more than
   one location

A subsequent patch changes the list of breakpoints to be an
intrusive_list, so all these spots would need to change.  But in any
case, I think that this:

  if (b->has_multiple_locations ())

conveys the intention better than:

  if (b->loc != nullptr && b->loc->next != nullptr)

Change-Id: Ib18c3605fd35d425ef9df82cb7aacff1606c6747
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-05-25 08:46:23 -04:00
Simon Marchi
5e632eca05 gdb: constify breakpoint::print_it parameter
The print_it method itself is const.  In a subsequent patch, the
locations that come out of a const breakpoint will be const as well.  It
will therefore be needed to make the last_loc output parameter const as
well.  Make that change now to reduce the size of the following patches.

Change-Id: I7ed962950bc9582646e31e2e42beca2a1c9c5105
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-05-25 08:46:23 -04:00
Simon Marchi
dbaa3bf640 gdb: make some breakpoint methods use this
Some implementations of breakpoint::check_status and
breakpoint::print_it do this:

    struct breakpoint *b = bs->breakpoint_at;

bs->breakpoint_at is always the same as `this` (we can get convinced by
looking at the call sites of check_status and print_it), so it would
just be clearer to access fields through `this` instead.

Change-Id: Ic542a64fcd88e31ae2aad6feff1da278c7086891
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-05-25 08:46:23 -04:00
Tom Tromey
b8c03634d6 Introduce and use parser flags
This patch adds a new parser_flags type and changes the parser APIs to
use it rather than a collection of 'int' and 'bool'.  More flags will
be added in subsquent patches.
2023-05-23 13:57:54 -06:00
Andrew Burgess
a500c3d8e0 gdb/breakpoint: use warning function instead of gdb_printf
Noticed that in breakpoint.c, in one place, we do this:

  gdb_printf (_("warning: Error removing "
                "breakpoint %d\n"),
                old_loc->owner->number);

Instead of using the `warning` function.  There are a number of
differences between using gdb_printf like this and calling `warning`,
the main one is probably that real warnings are sent to gdb_stderr,
while the above gdb_printf call will go to gdb_stdout.

In this commit I:

  1. Change to call `warning`, we can drop the "warning: " prefix from
  the string in breakpoint.c,

  2. Update the warning text, I now start with a lower case 'e', which
  I believe is the GDB style for warnings,

  3. And I have included the address of the bp_location in the warning
  messsage,

  4. Finally, I update all the tests (2) that include this error
  message.

Reviewed-By: Tom Tromey <tom@tromey.com>
2023-05-19 10:15:01 +01:00
Johnson Sun
6e96d8a970 Disable out-of-scope watchpoints
Currently, when a local software watchpoint goes out of scope, GDB sets
the watchpoint's disposition to `delete at next stop' and then normal
stops (i.e., stop and wait for the next GDB command). When GDB normal
stops, it automatically deletes the breakpoints with their disposition
set to `delete at next stop'.

Suppose a Python script decides not to normal stop when a local
software watchpoint goes out of scope, the watchpoint will not be
automatically deleted even when its disposition is set to
`delete at next stop'.

Since GDB single-steps the program and tests the watched expression
after each instruction, not deleting the watchpoint causes the
watchpoint to be hit many more times than it should, as reported in
PR python/29603.

This was happening because the watchpoint is not deleted or disabled
when going out of scope.

This commit fixes this issue by disabling the watchpoint when going out
of scope. It also adds a test to ensure this feature isn't regressed in
the future.

Calling `breakpoint_auto_delete' on all kinds of stops (in
`fetch_inferior_event') seem to solve this issue, but is in fact
inappropriate, since `breakpoint_auto_delete' goes over all breakpoints
instead of just going through the bpstat chain (which only contains the
breakpoints that were hit right now).

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29603
Change-Id: Ia85e670b2bcba2799219abe4b6be3b582387e383
2023-05-11 12:09:10 -04:00
Simon Marchi
1fba7b3ac5 gdb: fix use-after-free in check_longjmp_breakpoint_for_call_dummy
Commit 7a8de0c330 ("Remove ALL_BREAKPOINTS_SAFE") introduced a
use-after-free in the breakpoints iterations (see below for full ASan
report).  This makes gdb.base/stale-infcall.exp fail when GDB is build
with ASan.

check_longjmp_breakpoint_for_call_dummy iterates on all breakpoints,
possibly deleting the current breakpoint as well as related breakpoints.
The problem arises when a breakpoint in the B->related_breakpoint chain
is also B->next.  In that case, deleting that related breakpoint frees
the breakpoint that all_breakpoints_safe has saved.

The old code worked around that by manually changing B_TMP, which was
the next breakpoint saved by the "safe iterator":

	while (b->related_breakpoint != b)
	  {
	    if (b_tmp == b->related_breakpoint)
	      b_tmp = b->related_breakpoint->next;
	    delete_breakpoint (b->related_breakpoint);
	  }

(Note that this seemed to assume that b->related_breakpoint->next was
the same as b->next->next, not sure this is guaranteed.)

The new code kept the B_TMP variable, but it's not useful in that
context.  We can't go change the next breakpoint as saved by the safe
iterator, like we did before.  I suggest fixing that by saving the
breakpoints to delete in a map and deleting them all at the end.

Here's the full ASan report:

    (gdb) PASS: gdb.base/stale-infcall.exp: continue to breakpoint: break-run1
    print infcall ()
    =================================================================
    ==47472==ERROR: AddressSanitizer: heap-use-after-free on address 0x611000034980 at pc 0x563f7012c7bc bp 0x7ffdf3804d70 sp 0x7ffdf3804d60
    READ of size 8 at 0x611000034980 thread T0
        #0 0x563f7012c7bb in next_iterator<breakpoint>::operator++() /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/next-iterator.h:66
        #1 0x563f702ce8c0 in basic_safe_iterator<next_iterator<breakpoint> >::operator++() /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/safe-iterator.h:84
        #2 0x563f7021522a in check_longjmp_breakpoint_for_call_dummy(thread_info*) /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:7611
        #3 0x563f714567b1 in process_event_stop_test /home/smarchi/src/binutils-gdb/gdb/infrun.c:6881
        #4 0x563f71454e07 in handle_signal_stop /home/smarchi/src/binutils-gdb/gdb/infrun.c:6769
        #5 0x563f7144b680 in handle_inferior_event /home/smarchi/src/binutils-gdb/gdb/infrun.c:6023
        #6 0x563f71436165 in fetch_inferior_event() /home/smarchi/src/binutils-gdb/gdb/infrun.c:4387
        #7 0x563f7136ff51 in inferior_event_handler(inferior_event_type) /home/smarchi/src/binutils-gdb/gdb/inf-loop.c:42
        #8 0x563f7168038d in handle_target_event /home/smarchi/src/binutils-gdb/gdb/linux-nat.c:4219
        #9 0x563f72fccb6d in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:573
        #10 0x563f72fcd503 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:694
        #11 0x563f72fcaf2b in gdb_do_one_event(int) /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:217
        #12 0x563f7262b9bb in wait_sync_command_done() /home/smarchi/src/binutils-gdb/gdb/top.c:426
        #13 0x563f7137a7c3 in run_inferior_call /home/smarchi/src/binutils-gdb/gdb/infcall.c:650
        #14 0x563f71381295 in call_function_by_hand_dummy(value*, type*, gdb::array_view<value*>, void (*)(void*, int), void*) /home/smarchi/src/binutils-gdb/gdb/infcall.c:1332
        #15 0x563f7137c0e2 in call_function_by_hand(value*, type*, gdb::array_view<value*>) /home/smarchi/src/binutils-gdb/gdb/infcall.c:780
        #16 0x563f70fe5960 in evaluate_subexp_do_call(expression*, noside, value*, gdb::array_view<value*>, char const*, type*) /home/smarchi/src/binutils-gdb/gdb/eval.c:649
        #17 0x563f70fe6617 in expr::operation::evaluate_funcall(type*, expression*, noside, char const*, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:677
        #18 0x563f6fd19668 in expr::operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/expression.h:136
        #19 0x563f70fe6bba in expr::var_value_operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:689
        #20 0x563f704b71dc in expr::funcall_operation::evaluate(type*, expression*, noside) /home/smarchi/src/binutils-gdb/gdb/expop.h:2219
        #21 0x563f70fe0f02 in expression::evaluate(type*, noside) /home/smarchi/src/binutils-gdb/gdb/eval.c:110
        #22 0x563f71b1373e in process_print_command_args /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1319
        #23 0x563f71b1391b in print_command_1 /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1332
        #24 0x563f71b147ec in print_command /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1465
        #25 0x563f706029b8 in do_simple_func /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:95
        #26 0x563f7061972a in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2735
        #27 0x563f7262d0ef in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:572
        #28 0x563f7100ed9c in command_handler(char const*) /home/smarchi/src/binutils-gdb/gdb/event-top.c:543
        #29 0x563f7101014b in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /home/smarchi/src/binutils-gdb/gdb/event-top.c:779
        #30 0x563f72777942 in tui_command_line_handler /home/smarchi/src/binutils-gdb/gdb/tui/tui-interp.c:104
        #31 0x563f7100d059 in gdb_rl_callback_handler /home/smarchi/src/binutils-gdb/gdb/event-top.c:250
        #32 0x7f5a80418246 in rl_callback_read_char (/usr/lib/libreadline.so.8+0x3b246) (BuildId: 092e91fc4361b0ef94561e3ae03a75f69398acbb)
        #33 0x563f7100ca06 in gdb_rl_callback_read_char_wrapper_noexcept /home/smarchi/src/binutils-gdb/gdb/event-top.c:192
        #34 0x563f7100cc5e in gdb_rl_callback_read_char_wrapper /home/smarchi/src/binutils-gdb/gdb/event-top.c:225
        #35 0x563f728c70db in stdin_event_handler /home/smarchi/src/binutils-gdb/gdb/ui.c:155
        #36 0x563f72fccb6d in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:573
        #37 0x563f72fcd503 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:694
        #38 0x563f72fcb15c in gdb_do_one_event(int) /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:264
        #39 0x563f7177ec1c in start_event_loop /home/smarchi/src/binutils-gdb/gdb/main.c:412
        #40 0x563f7177f12e in captured_command_loop /home/smarchi/src/binutils-gdb/gdb/main.c:476
        #41 0x563f717846e4 in captured_main /home/smarchi/src/binutils-gdb/gdb/main.c:1320
        #42 0x563f71784821 in gdb_main(captured_main_args*) /home/smarchi/src/binutils-gdb/gdb/main.c:1339
        #43 0x563f6fcedfbd in main /home/smarchi/src/binutils-gdb/gdb/gdb.c:32
        #44 0x7f5a7e43984f  (/usr/lib/libc.so.6+0x2384f) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e)
        #45 0x7f5a7e439909 in __libc_start_main (/usr/lib/libc.so.6+0x23909) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e)
        #46 0x563f6fcedd84 in _start (/home/smarchi/build/binutils-gdb/gdb/gdb+0xafb0d84) (BuildId: 50bd32e6e9d5e84543e9897b8faca34858ca3995)

    0x611000034980 is located 0 bytes inside of 208-byte region [0x611000034980,0x611000034a50)
    freed by thread T0 here:
        #0 0x7f5a7fce312a in operator delete(void*, unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:164
        #1 0x563f702bd1fa in momentary_breakpoint::~momentary_breakpoint() /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:304
        #2 0x563f702771c5 in delete_breakpoint(breakpoint*) /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:12404
        #3 0x563f702150a7 in check_longjmp_breakpoint_for_call_dummy(thread_info*) /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:7673
        #4 0x563f714567b1 in process_event_stop_test /home/smarchi/src/binutils-gdb/gdb/infrun.c:6881
        #5 0x563f71454e07 in handle_signal_stop /home/smarchi/src/binutils-gdb/gdb/infrun.c:6769
        #6 0x563f7144b680 in handle_inferior_event /home/smarchi/src/binutils-gdb/gdb/infrun.c:6023
        #7 0x563f71436165 in fetch_inferior_event() /home/smarchi/src/binutils-gdb/gdb/infrun.c:4387
        #8 0x563f7136ff51 in inferior_event_handler(inferior_event_type) /home/smarchi/src/binutils-gdb/gdb/inf-loop.c:42
        #9 0x563f7168038d in handle_target_event /home/smarchi/src/binutils-gdb/gdb/linux-nat.c:4219
        #10 0x563f72fccb6d in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:573
        #11 0x563f72fcd503 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:694
        #12 0x563f72fcaf2b in gdb_do_one_event(int) /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:217
        #13 0x563f7262b9bb in wait_sync_command_done() /home/smarchi/src/binutils-gdb/gdb/top.c:426
        #14 0x563f7137a7c3 in run_inferior_call /home/smarchi/src/binutils-gdb/gdb/infcall.c:650
        #15 0x563f71381295 in call_function_by_hand_dummy(value*, type*, gdb::array_view<value*>, void (*)(void*, int), void*) /home/smarchi/src/binutils-gdb/gdb/infcall.c:1332
        #16 0x563f7137c0e2 in call_function_by_hand(value*, type*, gdb::array_view<value*>) /home/smarchi/src/binutils-gdb/gdb/infcall.c:780
        #17 0x563f70fe5960 in evaluate_subexp_do_call(expression*, noside, value*, gdb::array_view<value*>, char const*, type*) /home/smarchi/src/binutils-gdb/gdb/eval.c:649
        #18 0x563f70fe6617 in expr::operation::evaluate_funcall(type*, expression*, noside, char const*, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:677
        #19 0x563f6fd19668 in expr::operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/expression.h:136
        #20 0x563f70fe6bba in expr::var_value_operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:689
        #21 0x563f704b71dc in expr::funcall_operation::evaluate(type*, expression*, noside) /home/smarchi/src/binutils-gdb/gdb/expop.h:2219
        #22 0x563f70fe0f02 in expression::evaluate(type*, noside) /home/smarchi/src/binutils-gdb/gdb/eval.c:110
        #23 0x563f71b1373e in process_print_command_args /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1319
        #24 0x563f71b1391b in print_command_1 /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1332
        #25 0x563f71b147ec in print_command /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1465
        #26 0x563f706029b8 in do_simple_func /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:95
        #27 0x563f7061972a in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2735
        #28 0x563f7262d0ef in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:572
        #29 0x563f7100ed9c in command_handler(char const*) /home/smarchi/src/binutils-gdb/gdb/event-top.c:543

    previously allocated by thread T0 here:
        #0 0x7f5a7fce2012 in operator new(unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:95
        #1 0x563f7029a9a3 in new_momentary_breakpoint<program_space*&, frame_id&, int&> /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:8129
        #2 0x563f702212f6 in momentary_breakpoint_from_master /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:8169
        #3 0x563f70212db1 in set_longjmp_breakpoint_for_call_dummy() /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:7582
        #4 0x563f713804db in call_function_by_hand_dummy(value*, type*, gdb::array_view<value*>, void (*)(void*, int), void*) /home/smarchi/src/binutils-gdb/gdb/infcall.c:1260
        #5 0x563f7137c0e2 in call_function_by_hand(value*, type*, gdb::array_view<value*>) /home/smarchi/src/binutils-gdb/gdb/infcall.c:780
        #6 0x563f70fe5960 in evaluate_subexp_do_call(expression*, noside, value*, gdb::array_view<value*>, char const*, type*) /home/smarchi/src/binutils-gdb/gdb/eval.c:649
        #7 0x563f70fe6617 in expr::operation::evaluate_funcall(type*, expression*, noside, char const*, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:677
        #8 0x563f6fd19668 in expr::operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/expression.h:136
        #9 0x563f70fe6bba in expr::var_value_operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:689
        #10 0x563f704b71dc in expr::funcall_operation::evaluate(type*, expression*, noside) /home/smarchi/src/binutils-gdb/gdb/expop.h:2219
        #11 0x563f70fe0f02 in expression::evaluate(type*, noside) /home/smarchi/src/binutils-gdb/gdb/eval.c:110
        #12 0x563f71b1373e in process_print_command_args /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1319
        #13 0x563f71b1391b in print_command_1 /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1332
        #14 0x563f71b147ec in print_command /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1465
        #15 0x563f706029b8 in do_simple_func /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:95
        #16 0x563f7061972a in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2735
        #17 0x563f7262d0ef in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:572
        #18 0x563f7100ed9c in command_handler(char const*) /home/smarchi/src/binutils-gdb/gdb/event-top.c:543
        #19 0x563f7101014b in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /home/smarchi/src/binutils-gdb/gdb/event-top.c:779
        #20 0x563f72777942 in tui_command_line_handler /home/smarchi/src/binutils-gdb/gdb/tui/tui-interp.c:104
        #21 0x563f7100d059 in gdb_rl_callback_handler /home/smarchi/src/binutils-gdb/gdb/event-top.c:250
        #22 0x7f5a80418246 in rl_callback_read_char (/usr/lib/libreadline.so.8+0x3b246) (BuildId: 092e91fc4361b0ef94561e3ae03a75f69398acbb)

Change-Id: Id00c17ab677f847fbf4efdf0f4038373668d3d88
Approved-By: Tom Tromey <tom@tromey.com>
2023-05-09 13:48:14 -04:00