mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-01 13:26:47 +08:00
I noticed the following behaviour:
$ gdb -q -i=mi /tmp/hello.x
=thread-group-added,id="i1"
=cmd-param-changed,param="print pretty",value="on"
~"Reading symbols from /tmp/hello.x...\n"
(gdb)
-break-insert -p 99 main
^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x0000000000401198",func="main",file="/tmp/hello.c",fullname="/tmp/hello.c",line="18",thread-groups=["i1"],thread="99",times="0",original-location="main"}
(gdb)
info breakpoints
&"info breakpoints\n"
~"Num Type Disp Enb Address What\n"
~"1 breakpoint keep y 0x0000000000401198 in main at /tmp/hello.c:18\n"
&"../../src/gdb/thread.c:1434: internal-error: print_thread_id: Assertion `thr != nullptr' failed.\nA problem internal to GDB has been detected,\nfurther debugging may prove unreliable."
&"\n"
&"----- Backtrace -----\n"
&"Backtrace unavailable\n"
&"---------------------\n"
&"\nThis is a bug, please report it."
&" For instructions, see:\n"
&"<https://www.gnu.org/software/gdb/bugs/>.\n\n"
Aborted (core dumped)
What we see here is that when using the MI a user can create
thread-specific breakpoints for non-existent threads. Then if we try
to use the CLI 'info breakpoints' command GDB throws an assertion.
The assert is a result of the print_thread_id call when trying to
build the 'stop only in thread xx.yy' line; print_thread_id requires a
valid thread_info pointer, which we can't have for a non-existent
thread.
In contrast, when using the CLI we see this behaviour:
$ gdb -q /tmp/hello.x
Reading symbols from /tmp/hello.x...
(gdb) break main thread 99
Unknown thread 99.
(gdb)
The CLI doesn't allow a breakpoint to be created for a non-existent
thread. So the 'info breakpoints' command is always fine.
Interestingly, the MI -break-info command doesn't crash, this is
because the MI uses global thread-ids, and so never calls
print_thread_id. However, GDB does support using CLI and MI in
parallel, so we need to solve this problem.
One option would be to change the CLI behaviour to allow printing
breakpoints for non-existent threads. This would preserve the current
MI behaviour.
The other option is to pull the MI into line with the CLI and prevent
breakpoints being created for non-existent threads. This is good for
consistency, but is a breaking change for the MI.
In the end I figured that it was probably better to retain the
consistent CLI behaviour, and just made the MI reject requests to
place a breakpoint on a non-existent thread. The only test we had
that depended on the old behaviour was
gdb.mi/mi-thread-specific-bp.exp, which was added by me in commit:
commit
|
||
---|---|---|
bfd | ||
binutils | ||
config | ||
contrib | ||
cpu | ||
elfcpp | ||
etc | ||
gas | ||
gdb | ||
gdbserver | ||
gdbsupport | ||
gnulib | ||
gold | ||
gprof | ||
gprofng | ||
include | ||
intl | ||
ld | ||
libbacktrace | ||
libctf | ||
libdecnumber | ||
libiberty | ||
libsframe | ||
opcodes | ||
readline | ||
sim | ||
texinfo | ||
zlib | ||
.cvsignore | ||
.editorconfig | ||
.gitattributes | ||
.gitignore | ||
ar-lib | ||
ChangeLog | ||
compile | ||
config-ml.in | ||
config.guess | ||
config.rpath | ||
config.sub | ||
configure | ||
configure.ac | ||
COPYING | ||
COPYING3 | ||
COPYING3.LIB | ||
COPYING.LIB | ||
COPYING.LIBGLOSS | ||
COPYING.NEWLIB | ||
depcomp | ||
djunpack.bat | ||
install-sh | ||
libtool.m4 | ||
lt~obsolete.m4 | ||
ltgcc.m4 | ||
ltmain.sh | ||
ltoptions.m4 | ||
ltsugar.m4 | ||
ltversion.m4 | ||
MAINTAINERS | ||
Makefile.def | ||
Makefile.in | ||
Makefile.tpl | ||
makefile.vms | ||
missing | ||
mkdep | ||
mkinstalldirs | ||
move-if-change | ||
multilib.am | ||
README | ||
README-maintainer-mode | ||
SECURITY.txt | ||
setup.com | ||
src-release.sh | ||
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.