binutils-gdb modified for the FreeChainXenon project
Find a file
Andrew Burgess 3ce8f906be gdb: MI stopped events when unwindonsignal is on
This recent commit:

  commit b1c0ab2080
  Date:   Wed Jul 12 21:56:50 2023 +0100

      gdb: avoid double stop after failed breakpoint condition check

Addressed a problem where two MI stopped events would be reported if a
breakpoint condition failed due to a signal, this commit was a
replacement for this commit:

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

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

which solved the two stop problem, but only for the CLI.  Before both
of these commits, if a b/p condition failed due to a signal then the
user would see two stops reported, the first at the location where the
signal occurred, and the second at the location of the breakpoint.

By default GDB remains at the location where the signal occurred, so
the second reported stop can be confusing, this is the problem that
commit 2e411b8c68 tried to solve (for the CLI) and b1c0ab2080
extended also address the issue for MI too.

However, while working on another patch I realised that there was a
problem with GDB after the above commits.  Neither of the above
commits considered 'set unwindonsignal on'.  With this setting on,
when an inferior function call fails with a signal GDB will unwind the
stack back to the location where the inferior function call started.
In the b/p case we're looking at, the stop should be reported at the
location of the breakpoint, not at the location where the signal
occurred, and this isn't what happens.

This commit fixes this by ensuring that when unwindonsignal is 'on',
GDB reports a single stop event at the location of the breakpoint,
this fixes things for both CLI and MI.

The function call_thread_fsm::should_notify_stop is called when the
inferior function call completes and GDB is figuring out if the user
should be notified about this stop event by calling normal_stop from
fetch_inferior_event in infrun.c.  If normal_stop is called, then this
notification will be for the location where the inferior call stopped,
which will be the location at which the signal occurred.

Prior to this commit, the only time that normal_stop was not called,
was if the inferior function call completed successfully, this was
controlled by ::should_notify_stop, which only turns false when the
inferior function call has completed successfully.

In this commit I have extended the logic in ::should_notify_stop.  Now
there are three cases in which ::should_notify_stop will return false,
and we will not announce the first stop (by calling normal_stop).
These three reasons are:

  1. If the inferior function call completes successfully, this is
  unchanged behaviour,

  2. If the inferior function call stopped due to a signal and 'set
  unwindonsignal on' is in effect, and

  3. If the inferior function call stopped due to an uncaught C++
  exception, and 'set unwind-on-terminating-exception on' is in
  effect.

However, if we don't call normal_stop then we need to call
async_enable_stdin in call_thread_fsm::should_stop.  Prior to this
commit this was only done for the case where the inferior function
call completed successfully.

In this commit I now call ::should_notify_stop and use this to
determine if we need to call async_enable_stdin.  With this done we
now call async_enable_stdin for each of the three cases listed above,
which means that GDB will exit wait_sync_command_done correctly (see
run_inferior_call in infcall.c).

With these two changes the problem is mostly resolved.  However, the
solution isn't ideal, we've still lost some information.

Here is how GDB 13.1 behaves, this is before commits b1c0ab2080 and
2e411b8c68:

  $ gdb -q /tmp/mi-condbreak-fail \
        -ex 'set unwindonsignal on' \
        -ex 'break 30 if (cond_fail())' \
        -ex 'run'
  Reading symbols from /tmp/mi-condbreak-fail...
  Breakpoint 1 at 0x40111e: file /tmp/mi-condbreak-fail.c, line 30.
  Starting program: /tmp/mi-condbreak-fail

  Program received signal SIGSEGV, Segmentation fault.
  0x0000000000401116 in cond_fail () at /tmp/mi-condbreak-fail.c:24
  24	  return *p;			/* Crash here.  */
  Error in testing breakpoint condition:
  The program being debugged was signaled while in a function called from GDB.
  GDB has restored the context to what it was before the call.
  To change this behavior use "set unwindonsignal off".
  Evaluation of the expression containing the function
  (cond_fail) will be abandoned.

  Breakpoint 1, foo () at /tmp/mi-condbreak-fail.c:30
  30	  global_counter += 1;		/* Set breakpoint here.  */
  (gdb)

In this state we see two stop notifications, the first is where the
signal occurred, while the second is where the breakpoint is located.
As GDB has unwound the stack (thanks to unwindonsignal) the second
stop notification reflects where the inferior is actually located.

Then after commits b1c0ab2080 and 2e411b8c68 the behaviour changed
to this:

  $ gdb -q /tmp/mi-condbreak-fail \
        -ex 'set unwindonsignal on' \
	-ex 'break 30 if (cond_fail())' \
	-ex 'run'
  Reading symbols from /tmp/mi-condbreak-fail...
  Breakpoint 1 at 0x40111e: file /tmp/mi-condbreak-fail.c, line 30.
  Starting program: /tmp/mi-condbreak-fail

  Program received signal SIGSEGV, Segmentation fault.
  0x0000000000401116 in cond_fail () at /tmp/mi-condbreak-fail.c:24
  24	  return *p;			/* Crash here.  */
  Error in testing condition for breakpoint 1:
  The program being debugged was signaled while in a function called from GDB.
  GDB has restored the context to what it was before the call.
  To change this behavior use "set unwindonsignal off".
  Evaluation of the expression containing the function
  (cond_fail) will be abandoned.
  (gdb) bt 1
  #0  foo () at /tmp/mi-condbreak-fail.c:30
  (More stack frames follow...)
  (gdb)

This is the broken state.  GDB is reports the SIGSEGV location, but
not the unwound breakpoint location.  The final 'bt 1' shows that the
inferior is not located in cond_fail, which is the only location GDB
reported, so this is clearly wrong.

After implementing the fixes described above we now get this
behaviour:

  $ gdb -q /tmp/mi-condbreak-fail \
        -ex 'set unwindonsignal on' \
        -ex 'break 30 if (cond_fail())' \
        -ex 'run'
  Reading symbols from /tmp/mi-condbreak-fail...
  Breakpoint 1 at 0x40111e: file /tmp/mi-condbreak-fail.c, line 30.
  Starting program: /tmp/mi-condbreak-fail
  Error in testing breakpoint condition for breakpoint 1:
  The program being debugged was signaled while in a function called from GDB.
  GDB has restored the context to what it was before the call.
  To change this behavior use "set unwindonsignal off".
  Evaluation of the expression containing the function
  (cond_fail) will be abandoned.

  Breakpoint 1, foo () at /tmp/mi-condbreak-fail.c:30
  30	  global_counter += 1;		/* Set breakpoint here.  */
  (gdb)

This is better.  GDB now reports a single stop at the location of the
breakpoint, which is where the inferior is actually located.  However,
by removing the first stop notification we have lost some potentially
useful information about which signal caused the inferior to stop.

To address this I've reworked the message that is printed to include
the signal information.  GDB now reports this:

  $ gdb -q /tmp/mi-condbreak-fail \
        -ex 'set unwindonsignal on' \
        -ex 'break 30 if (cond_fail())' \
        -ex 'run'
  Reading symbols from /tmp/mi-condbreak-fail...
  Breakpoint 1 at 0x40111e: file /tmp/mi-condbreak-fail.c, line 30.
  Starting program: /tmp/mi-condbreak-fail
  Error in testing condition for breakpoint 1:
  The program being debugged received signal SIGSEGV, Segmentation fault
  while in a function called from GDB.  GDB has restored the context
  to what it was before the call.  To change this behavior use
  "set unwindonsignal off".  Evaluation of the expression containing
  the function (cond_fail) will be abandoned.

  Breakpoint 1, foo () at /tmp/mi-condbreak-fail.c:30
  30	  global_counter += 1;		/* Set breakpoint here.  */
  (gdb)

This is better, the user now sees a single stop notification at the
correct location, and the error message describes which signal caused
the inferior function call to stop.

However, we have lost the information about where the signal
occurred.  I did consider trying to include this information in the
error message, but, in the end, I opted not too.  I wasn't sure it was
worth the effort.  If the user has selected to unwind on signal, then
surely this implies they maybe aren't interested in debugging failed
inferior calls, so, hopefully, just knowing the signal name will be
enough.  I figure we can always add this information in later if
there's a demand for it.
2023-08-23 10:29:17 +01:00
bfd kvx: fix 32-bit build 2023-08-23 12:38:58 +09:30
binutils bfd_get_symbol_leading_char vs. "" 2023-08-23 10:07:45 +09:30
config mh-mingw: drop unused BOOT_CXXFLAGS variable 2023-08-12 10:24:26 +09:30
contrib Import mklog.py from gcc repo 2020-09-25 10:24:44 -04:00
cpu sim --enable-cgen-maint 2023-08-19 12:41:32 +09:30
elfcpp Add markers for the 2.41 branch 2023-07-03 11:12:15 +01:00
etc Update year range in gprofng copyright notices 2023-01-01 23:26:30 +10:30
gas kvx: O_pseudo_fixup 2023-08-23 11:03:52 +09:30
gdb gdb: MI stopped events when unwindonsignal is on 2023-08-23 10:29:17 +01:00
gdbserver gdbserver: Reinstall software single-step breakpoints in resume_stopped_resumed_lwps 2023-08-11 20:54:09 -07:00
gdbsupport gdb: add gdb::make_unique function 2023-08-23 09:50:30 +01:00
gnulib Add missing backslash to update-gnulib.sh 2023-06-21 08:47:05 -06:00
gold Revert "2.41 Release sources" 2023-08-02 12:06:23 +01:00
gprof regen config 2023-08-12 10:27:57 +09:30
gprofng gprofng: Use execvp instead of execv 2023-08-17 13:15:10 -07:00
include aarch64: Improve naming conventions for A and R-profile architecture 2023-08-22 16:46:33 +01:00
intl regen config 2023-08-12 10:27:57 +09:30
ld kvx: fix 32-bit build 2023-08-23 12:38:58 +09:30
libbacktrace regen config 2023-08-12 10:27:57 +09:30
libctf regen config 2023-08-12 10:27:57 +09:30
libdecnumber regen config 2023-08-12 10:27:57 +09:30
libiberty Synchromize libiberty sources with master version in gcc repository 2023-06-26 15:47:15 +01:00
libsframe regen config 2023-08-12 10:27:57 +09:30
opcodes aarch64: Improve naming conventions for A and R-profile architecture 2023-08-22 16:46:33 +01:00
readline [readline] Fix double free in _rl_scxt_dispose 2023-05-28 10:17:57 +02:00
sim sim: bpf: remove negi, neg32i insns 2023-08-21 10:07:25 -07:00
texinfo
zlib regen config 2023-08-12 10:27:57 +09:30
.cvsignore
.editorconfig Add top-level .editorconfig file 2022-01-28 08:25:42 -05:00
.gitattributes binutils-gdb/git: highlight whitespace errors in source files 2022-07-25 14:35:41 +01:00
.gitignore Add gnu global outputs to .gitignore 2020-12-02 10:00:27 -05:00
ar-lib
ChangeLog Revert "2.41 Release sources" 2023-08-02 12:06:23 +01:00
compile
config-ml.in MSP430: Add -fno-exceptions multilib 2023-08-12 10:24:26 +09:30
config.guess kvx: New port. 2023-08-16 14:22:54 +01:00
config.rpath
config.sub kvx: New port. 2023-08-16 14:22:54 +01:00
configure generated bfd files, and kvx regen 2023-08-17 21:44:04 +09:30
configure.ac kvx: New port. 2023-08-16 14:22:54 +01:00
COPYING
COPYING.LIB
COPYING.LIBGLOSS
COPYING.NEWLIB
COPYING3
COPYING3.LIB
depcomp
djunpack.bat
install-sh
libtool.m4 FDPIC: Handle arm*-*-uclinuxfdpiceabi in configure scripts 2023-08-12 10:25:06 +09:30
ltgcc.m4
ltmain.sh Do not use HAVE_DOS_BASED_FILE_SYSTEM for Cygwin. 2023-08-12 10:25:06 +09:30
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
MAINTAINERS MAINTAINERS: Update path to readline config.{sub,guess} files 2021-05-24 18:11:49 +02:00
Makefile.def gccrs: Add gcc-check-target check-rust 2023-08-12 10:25:06 +09:30
Makefile.in regen config 2023-08-12 10:27:57 +09:30
Makefile.tpl toplevel: Substitute GDCFLAGS instead of using CFLAGS 2023-08-12 10:27:44 +09:30
makefile.vms
missing
mkdep
mkinstalldirs
move-if-change
multilib.am
README
README-maintainer-mode Note that at least dejagnu version 1.5.3 is required in order to be ale to run the testsuites. 2022-10-04 10:54:19 +01:00
SECURITY.txt Add a SECURITY.txt file describing the GNU Binutils' project's stance on security related bugs. 2023-04-20 16:52:11 +01:00
setup.com
src-release.sh Revert "2.41 Release sources" 2023-08-02 12:06:23 +01:00
symlink-tree
test-driver
ylwrap

		   README for GNU development tools

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

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

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

	./configure 
	make

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

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

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

	CC=gcc ./configure
	make

A similar example using csh:

	setenv CC gcc
	./configure
	make

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

REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info
on where and how to report problems.