We have gdb::handle_eintr, which allows us to rewrite:
...
ssize_t ret;
do
{
errno = 0;
ret = ::write (pipe[1], "+", 1);
}
while (ret == -1 && errno == EINTR);
...
into:
...
ssize_t ret = gdb::handle_eintr (-1, ::write, pipe[1], "+", 1);
...
However, the call to write got a bit mangled, requiring effort to decode it
back to its original form.
Instead, add a new function gdb::write that allows us to write:
...
ssize_t ret = gdb::write (pipe[1], "+", 1);
...
Likewise for waitpid, read and close.
Tested on x86_64-linux.
When disassembling function symbols in C++ code, if GDB is asked to
disassemble a function by name then the function name in the header
line can be demangled by turning on `set print asm-demangle on`, e.g.:
(gdb) disassemble foo_type::some_function
Dump of assembler code for function _ZN8foo_type13some_functionE7my_type:
0x0000000000401142 <+0>: push %rbp
... etc ...
End of assembler dump.
(gdb) set print asm-demangle on
(gdb) disassemble foo_type::some_function
Dump of assembler code for function foo_type::some_function(my_type):
0x0000000000401142 <+0>: push %rbp
... etc ... │
End of assembler dump. │
However, if GDB is disassembling the current function, then this
demangling doesn't work, e.g.:
(gdb) break foo_type::some_function
Breakpoint 1 at 0x401152: file mangle.cc, line 16.
(gdb) run
Starting program: /tmp/mangle
Breakpoint 1, foo_type::some_function (this=0x7fffffffa597, obj=...) at mangle.cc:16
16 obj.update ();
(gdb) disassemble
Dump of assembler code for function _ZN8foo_type13some_functionE7my_type:
0x0000000000401142 <+0>: push %rbp
... etc ...
End of assembler dump.
(gdb) set print asm-demangle on
(gdb) disassemble
Dump of assembler code for function _ZN8foo_type13some_functionE7my_type:
0x0000000000401142 <+0>: push %rbp
... etc ...
End of assembler dump.
This commit fixes this issue, and extends gdb.cp/disasm-func-name.exp,
which was already testing the first case (disassemble by name) to also
cover disassembling the current function.
Approved-By: Tom Tromey <tom@tromey.com>
When building a help string, it's possible that the resulting options
will go over 80 columns. This patch changes this code to add line
wrapping where needed.
This can most be seen by looking "help bt" and in particular the
"-frame-info" help text.
This patch ensures that all ordinary help strings are wrapped at 80
columns. For the most part this consists of changing code like this
(note the embedded \n and the trailing backslash without a newline):
-Manage the space-separated list of debuginfod server URLs that GDB will query \
-when missing debuginfo, executables or source files.\nThe default value is \
-copied from the DEBUGINFOD_URLS environment variable."),
... to end each line with \n\, like:
+Manage the space-separated list of debuginfod server URLs that GDB will\n\
+query when missing debuginfo, executables or source files.\n\
+The default value is copied from the DEBUGINFOD_URLS environment variable."),
Approved-By: Eli Zaretskii <eliz@gnu.org>
This commit was inspired by this mailing list post:
https://inbox.sourceware.org/gdb-patches/osmtfvf5xe3yx4n7oirukidym4cik7lehhy4re5mxpset2qgwt@6qlboxhqiwgm
When reviewing that patch, the first thing I wanted to do was add some
tests for the 'edit' command because, as far as I can tell, there are
no real tests right now.
The approach I've taken for testing is to override the EDITOR
environment variable, setting this to just 'echo'. Now when the
'edit' command is run, instead of entering an interactive editor, the
shell instead echos back the arguments that GDB is trying to pass to
the editor. The output might look like this:
(gdb) edit
+22 /tmp/gdb/testsuite/gdb.base/edit-cmd.c
(gdb)
We can then test this like any other normal command. I then wrote
some basic tests covering a few situations like, using 'edit' before
the inferior is started. Using 'edit' without any arguments, and
using 'edit' with a line number argument.
There are plenty of cases that are still not tested, for example, the
test program only has a single source file for example. But we can
always add more tests later.
I then used these tests to validate the fix proposed in the above
patch.
The patch above does indeed fix some cases, specifically, when GDB
stops at a location (e.g. a breakpoint location) and then the 'edit'
command without any arguments is fixed. But using the 'list' command
to show some other location, and then 'edit' to edit the just listed
location broken before and after the above patch.
I am instead proposing this alternative patch which I think fixes more
cases. When GDB stops at a location then 'edit' with no arguments
should correctly edit the current line. And using 'list XX' to list a
specific location, followed by 'edit' should also now edit the just
listed location.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=17669
Co-Authored-By: Lluís Batlle i Rossell <viric@viric.name>
Approved-By: Tom Tromey <tom@tromey.com>
This commit adds support for filename options to GDB's option
sub-system (see cli/cli-option.{c,h}).
The new filename options support quoted and escaped filenames, and tab
completion is fully supported.
This commit adds the new option, and adds these options to the
'maintenance test-options' command as '-filename', along with some
tests that exercise this new option.
I've split the -filename testing into two. In gdb.base/options.exp we
use the -filename option with some arbitrary strings. This tests that
GDB can correctly extract the value from a filename option, and that
GDB can complete other options after a filename option. However,
these tests don't actually pass real filenames, nor do they test
filename completion.
In gdb.base/filename-completion.exp I have added some tests that test
the -filename option with real filenames, and exercise filename tab
completion.
This commit doesn't include any real uses of the new filename options,
that will come in the next commit.
When building gdb with -O2 -fsanitize=thread and running test-case
gdb.base/bg-exec-sigint-bp-cond.exp, I run into:
...
(gdb) c&^M
Continuing.^M
(gdb) Quit^M
(gdb) quit_count=1
^M
Breakpoint 2, foo () at bg-exec-sigint-bp-cond.c:23^M
23 return 0;^M
FAIL: $exp: no force memory write: \
SIGINT does not interrupt background execution
...
What happens is that:
- the breakpoint hits
- while evaluating the condition of the breakpoint,
$_shell("kill -INT <pid-of-gdb>") is called, handled by run_under_shell
- in run_under_shell, a vfork is issued
- in the vfork child, execl executes the kill command
- in the vfork parent, waitpid is called to wait for the result of the kill
command
- waitpid returns -1 with errno set to EINTR
- run_under_shell doesn't check the result of waitpid, and returns the
value of local variable status. Since waitpid returned -1, status was
not assigned a value, so it's uninitialized, and happens to be
non-zero
- the breakpoint condition evaluates to true, because
$_shell("kill -INT <pid-of-gdb>") != 0
- the breakpoint triggers a stop, which the test-case doesn't expect.
Fix this by using gdb::handle_eintr to call waitpid in run_under_shell.
Also handle the case that waitpid returns an error other than EINTR, using
perror_with_name.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR gdb/30695
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30695
I searched for spots using ".reset (new ...)" and replaced most of
these with std::make_unique. I think this is a bit cleaner and more
idiomatic.
Regression tested on x86-64 Fedora 40.
Reviewed-By: Klaus Gerlicher<klaus.gerlicher@intel.com>
Add two more separators in spellcheck.sh: colon and comma.
Doing so triggers the "inbetween->between" rule, which gives an incorrect
result. Override this with "inbetween->between, in between, in-between" [1],
in a new file gdb/contrib/common-misspellings.txt.
Fix the following common misspellings:
...
everytime -> every time
sucess -> success
thru -> through
transfered -> transferred
inbetween -> between, in between, in-between
...
Verified with spellcheck.sh. Tested on x86_64-linux.
[1] https://www.grammarly.com/blog/commonly-confused-words/in-between-or-inbetween/
While looking at the recent line number styling commit I noticed a few
places where we could add more file name styling. So lets do that.
Approved-By: Tom Tromey <tom@tromey.com>
This patch adds separate styling for line numbers. That is, whenever
gdb prints a source line number, it uses this style.
v2 includes a change to ensure that %ps works in query.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-by: Keith Seitz <keiths@redhat.com>
Some of the gdb and testsuite files double include some headers. While
all headers use include guards, it helps a bit keeping the code base
tidy.
No functional change.
Approved-by: Kevin Buettner <kevinb@redhat.com>
This commit moves the printing of the 'complete' command results out
of the 'complete_command' function. The printing is now done in a new
member function 'completion_result::print_matches'. At this point,
this is entirely a refactor.
The motivation for this refactor is how 'complete' should print the
completion of filename arguments. In some cases the filename results
need to have escaping added to the output. This escaping needs to be
done immediately prior to printing the result as adding too early will
result in multiple 'complete' results potentially being sorted
incorrectly. See the subsequent commits for more details.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
Following on from the previous commit, this commit marks the old
unquoted filename completion related functions as deprecated.
The aim of doing this is to make it more obvious to someone adding a
new command that they should not be using the older unquoted style
filename argument handling.
I split this change from the previous to make for an easier review.
This commit touches more files, but is _just_ function renaming.
Check out gdb/completer.{c,h} for what has been renamed. All the
other files have just been updated to use the new names.
There should be no user visible changes after this commit.
Make the current program space reference bubble up one level.
Change-Id: I6ba6dc4a2cb188720cbb61b84ab5c954aac105c6
Approved-By: Tom Tromey <tom@tromey.com>
Reviewed-By: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Make the current program space reference bubble up one level.
Change-Id: I19c4fc2ca955f9c828ef426a077b43983865697b
Approved-By: Tom Tromey <tom@tromey.com>
Reviewed-By: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Make the current program space reference bubble up one level.
Change-Id: I692554474d17e4f4708fd8ad662bf6c0bb964726
Approved-By: Tom Tromey <tom@tromey.com>
Reviewed-By: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Remove some includes reported as unused by clangd. Add some includes in
other files that were previously relying on the transitive include.
Change-Id: Ibdd0a998b04d21362a20d0ca8e5267e21e2e133e
This patch removes gdb_stdtargerr. There doesn't seem to be a need
for this -- it is always the same as stdtarg, and (I believe) has been
for many years.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Currently, when a user tries to list the current location, there are 2
different error messages that can happen, either:
(gdb) list .
No symbol table is loaded. Use the "file" command.
or
(gdb) list .
No debug information available to print source lines.
The difference here is if gdb can find any symtabs at all or not, which
is not something too important for end-users - and isn't informative at
all. This commit changes it so that the error always says that there
isn't debug information available, with these two variants:
(gdb) list .
Insufficient debug info for showing source lines at current PC (0x55555555511d).
or
(gdb) list .
Insufficient debug info for showing source lines at default location.
The difference now is if the inferior has started already, which is
controlled by the user and may be useful.
Unfortunately, it isn't as easy to differentiate if the symtab found for
other list parameters is correct, so other invocations, such as "list +"
still retain their original error message.
Co-Authored-By: Simon Marchi <simark@simark.ca>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
Most files including gdbcmd.h currently rely on it to access things
actually declared in cli/cli-cmds.h (setlist, showlist, etc). To make
things easy, replace all includes of gdbcmd.h with includes of
cli/cli-cmds.h. This might lead to some unused includes of
cli/cli-cmds.h, but it's harmless, and much faster than going through
the 170 or so files by hand.
Change-Id: I11f884d4d616c12c05f395c98bbc2892950fb00f
Approved-By: Tom Tromey <tom@tromey.com>
Move some declarations related to the "quit" machinery from defs.h to
event-top.h. Most of the definitions associated to these declarations
are in event-top.c. The exceptions are `quit()` and `maybe_quit()`,
that are defined in utils.c. For consistency, move these two
definitions to event-top.c.
Include "event-top.h" in many files that use these things.
Change-Id: I6594f6df9047a9a480e7b9934275d186afb14378
Approved-By: Tom Tromey <tom@tromey.com>
Move it out of defs.h, adjust the includes here and there.
Change-Id: I11901fdce55d54f5e51723e123cef154cfb1bbc5
Approved-By: John Baldwin <jhb@FreeBSD.org>
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>
Currently gdb.parameter doesn't raise an exception if an
ambiguous name is used, it instead returns the value of the
last partly matching parameter:
```
(gdb) show print sym
Ambiguous show print command "sym": symbol, symbol-filename, symbol-loading.
(gdb) show print symbol-loading
Printing of symbol loading messages is "full".
(gdb) py print(gdb.parameter("print sym"))
full
```
It's because lookup_cmd_composition_1 tries to detect
ambigous names by checking the return value of find_cmd
for CMD_LIST_AMBIGUOUS, which never happens, since only
lookup_cmd_1 returns CMD_LIST_AMBIGUOUS.
Instead the nfound argument contains the number of found
matches.
By using it instead, and by setting *CMD to the special value
CMD_LIST_AMBIGUOUS in this case, gdbpy_parameter can now show
the appropriate error message:
```
(gdb) py print(gdb.parameter("print sym"))
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Parameter `print sym' is ambiguous.
Error while executing Python code.
(gdb) py print(gdb.parameter("print symbol"))
True
(gdb) py print(gdb.parameter("print symbol-"))
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Parameter `print symbol-' is ambiguous.
Error while executing Python code.
(gdb) py print(gdb.parameter("print symbol-load"))
full
```
Since the document command also uses lookup_cmd_composition, it needed
to check for CMD_LIST_AMBIGUOUS as well, so it now also shows an
"Ambiguous command" error message in this case.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14639
Approved-By: Tom Tromey <tom@tromey.com>
When a user attempts to use the "list ." command with an inferior that
doesn't have debug symbols, GDB would crash. This was reported as PR
gdb/31256.
The crash would happen when attempting to get the current symtab_and_line
for the stop location, because the symtab would return a null pointer
and we'd attempt to dereference it to print the line.
This commit fixes that by checking for an empty symtab and erroring out
of the function if it happens.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31256
Approved-By: Tom Tromey <tom@tromey.com>
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.
Spotted what appears to be a copy&paste error in string_option_def,
the code for string handling writes the address fetching callback
function into the option_def::var_address::enumeration location,
rather than option_def::var_address::string.
Of course, this works just fine as option_def::var_address is a union,
and all of its members are function pointers, so they're going to be
the same size on every target GDB cares about.
But it doesn't hurt to be correct, so fixed in this commit.
There should be no user visible changes after this commit.
This changes gdb to use the C++17 [[fallthrough]] attribute rather
than special comments.
This was mostly done by script, but I neglected a few spellings and so
also fixed it up by hand.
I suspect this fixes the bug mentioned below, by switching to a
standard approach that, presumably, clang supports.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23159
Approved-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Luis Machado <luis.machado@arm.com>
Approved-By: Pedro Alves <pedro@palves.net>
Given that GDB now requires a C++17, replace all uses of
gdb::string_view with std::string_view.
This change has mostly been done automatically:
- gdb::string_view -> std::string_view
- #include "gdbsupport/gdb_string_view.h" -> #include <string_view>
One things which got brought up during review is that gdb::stging_view
does support being built from "nullptr" while std::sting_view does not.
Two places are manually adjusted to account for this difference:
gdb/tui/tui-io.c:tui_getc_1 and
gdbsupport/format.h:format_piece::format_piece.
The above automatic change transformed
"gdb::to_string (const gdb::string_view &)" into
"gdb::to_string (const std::string_view &)". The various direct users
of this function are now explicitly including
"gdbsupport/gdb_string_view.h". A later patch will remove the users of
gdb::to_string.
The implementation and tests of gdb::string_view are unchanged, they will
be removed in a following patch.
Change-Id: Ibb806a7e9c79eb16a55c87c6e41ad396fecf0207
Approved-By: Tom Tromey <tom@tromey.com>
Approved-By: Pedro Alves <pedro@palves.net>
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>
Add a new command completer function for the disassemble command.
There are two things that this completion function changes. First,
after the previous commit, the new function calls skip_over_slash_fmt,
which means that hitting tab after entering a /OPT flag now inserts a
space ready to start typing the address to disassemble at:
(gdb) disassemble /r<TAB>
(gdb) disassemble /r <CURSOR>
But also, we now get symbol completion after a /OPT option set,
previously this would do nothing:
(gdb) disassemble /r mai<TAB>
But now:
(gdb) disassemble /r mai<TAB>
(gdb) disassemble /r main <CURSOR>
Which was my main motivation for working on this commit.
However, I have made a second change in the completion function.
Currently, the disassemble command calls the generic
location_completer function, however, the disassemble docs say:
Note that the 'disassemble' command's address arguments are specified
using expressions in your programming language (*note Expressions:
Expressions.), not location specs (*note Location Specifications::).
So, for example, if you want to disassemble function 'bar' in file
'foo.c', you must type 'disassemble 'foo.c'::bar' and not 'disassemble
foo.c:bar'.
And indeed, if I try:
(gdb) disassemble hello.c:main
No symbol "hello" in current context.
(gdb) disassemble hello.c::main
No symbol "hello" in current context.
(gdb) disassemble 'hello.c'::main
Dump of assembler code for function main:
... snip ...
But, if I do this:
(gdb) disassemble hell<TAB>
(gdb) disassemble hello.c:<CURSOR>
which is a consequence of using the location_completer function. So
in this commit, after calling skip_over_slash_fmt, I forward the bulk
of the disassemble command completion to expression_completer. Now
when I try this:
(gdb) disassemble hell<TAB>
gives nothing, which I think is an improvement. There is one slight
disappointment, if I do:
(gdb) disassemble 'hell<TAB>
I still get nothing. I had hoped that this would expand to:
'hello.c':: but I guess this is a limitation of the current
expression_completer implementation, however, I don't think this is a
regression, the previous expansion was just wrong. Fixing
expression_completer is out of scope for this commit.
I've added some disassembler command completion tests, and also a test
that disassembling using 'FILE'::FUNC syntax works, as I don't think
that is tested anywhere.
The disassembler gained a new /b flag in this commit:
commit d4ce49b7ac
Date: Tue Jun 21 20:23:35 2022 +0100
gdb: disassembler opcode display formatting
The /b and /r flags result in the instruction opcodes displayed in
different formats, so it's not possible to have both at the same
time. Currently the /b flag overrides the /r flag.
We have a similar situation with the /m and /s flags, but here, if the
user tries to use both flags then they will get an error.
I think the error is clearer, so in this commit I propose that we add
an error if /r and /b are both used.
Obviously this change breaks backwards compatibility. I don't have a
compelling argument for why we should make the change beyond my
feeling that it was a mistake not to add this error from the start,
and that the new behaviour is better.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
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>
I noticed a comment by an include and remembered that I think these
don't really provide much value -- sometimes they are just editorial,
and sometimes they are obsolete. I think it's better to just remove
them. Tested by rebuilding.
Approved-By: Andrew Burgess <aburgess@redhat.com>
After the series that added this command was pushed, Pedro mentioned
that the news description could easily be misinterpreted, as well as
some code and test improvements that should be made.
While fixing the test, I realized that code repetition wasn't
happening as it should, so I took care of that too.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
The command 'list' has accepted the argument '+' for many years already,
but this option wasn't documented either in the texinfo docs or in the
help text for the command. This commit documents it.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
When using "list" with no arguments, GDB will first print the lines
around where the inferior is stopped, then print the next N lines until
reaching the end of file, at which point it warns the user "Line X out
of range, file Y only has X-1 lines.". This is usually desirable, but
if the user can no longer see the original line, they may have forgotten
the current line or that a list command was used at all, making GDB's
error message look cryptic. It was reported in bugzilla as PR cli/30497.
This commit improves the user experience by changing the behavior of
"list" slightly when a user passes no arguments. It now prints that the
end of the file has been reached and recommends that the user use the
command "list ." instead.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30497
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
Currently, after the user has used the list command once, there is no
self-contained way to ask GDB to print the location where the inferior is
stopped. The current best options require either using a separate
command to scope out where the inferior is stopped, or using "list *$pc"
requiring knowledge of GDB standard registers. This commit adds a way
to do that using '.' as a new argument for the 'list' command. If the
inferior isn't running, the command prints around the main function.
Because this necessitated having the inferior running and the test was
(seemingly unnecessarily) using printf in a non-essential way and it
would make the resulting log harder to read for no benefit, it was
replaced by a different statement.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
A future patch will add more situations that calculates "lines around a
certain point" to be printed using print_source_lines, and the logic
could be re-used. As a preparation for those commits, this one factors
out that part of the logic of the list command into its own function.
No functional changes are expected
Approved-By: Tom Tromey <tom@tromey.com>
do_set_command manually updates a string, only to copy it to a
std::string and free the working copy. This patch changes this code
to use std::string for everything, simplifying the code and removing a
copy.
Reviewed-by: John Baldwin <jhb@FreeBSD.org>
After this commit:
commit baab375361
Date: Tue Jul 13 14:44:27 2021 -0400
gdb: building inferior strings from within GDB
It was pointed out that a new ASan failure had been introduced which
was triggered by gdb.base/internal-string-values.exp:
(gdb) PASS: gdb.base/internal-string-values.exp: test_setting: all langs: lang=ada: ptype "foo"
print $_gdb_maint_setting("test-settings string")
=================================================================
==80377==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000068034 at pc 0x564785cba682 bp 0x7ffd20644620 sp 0x7ffd20644610
READ of size 1 at 0x603000068034 thread T0
#0 0x564785cba681 in find_command_name_length(char const*) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2129
#1 0x564785cbacb2 in lookup_cmd_1(char const**, cmd_list_element*, cmd_list_element**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, int, bool) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2186
#2 0x564785cbb539 in lookup_cmd_1(char const**, cmd_list_element*, cmd_list_element**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, int, bool) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2248
#3 0x564785cbbcf3 in lookup_cmd(char const**, cmd_list_element*, char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, int, int) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2339
#4 0x564785c82df2 in setting_cmd /tmp/src/binutils-gdb/gdb/cli/cli-cmds.c:2219
#5 0x564785c84274 in gdb_maint_setting_internal_fn /tmp/src/binutils-gdb/gdb/cli/cli-cmds.c:2348
#6 0x564788167b3b in call_internal_function(gdbarch*, language_defn const*, value*, int, value**) /tmp/src/binutils-gdb/gdb/value.c:2321
#7 0x5647854b6ebd in expr::ada_funcall_operation::evaluate(type*, expression*, noside) /tmp/src/binutils-gdb/gdb/ada-lang.c:11254
#8 0x564786658266 in expression::evaluate(type*, noside) /tmp/src/binutils-gdb/gdb/eval.c:111
#9 0x5647871242d6 in process_print_command_args /tmp/src/binutils-gdb/gdb/printcmd.c:1322
#10 0x5647871244b3 in print_command_1 /tmp/src/binutils-gdb/gdb/printcmd.c:1335
#11 0x564787125384 in print_command /tmp/src/binutils-gdb/gdb/printcmd.c:1468
#12 0x564785caac44 in do_simple_func /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:95
#13 0x564785cc18f0 in cmd_func(cmd_list_element*, char const*, int) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2735
#14 0x564787c70c68 in execute_command(char const*, int) /tmp/src/binutils-gdb/gdb/top.c:574
#15 0x564786686180 in command_handler(char const*) /tmp/src/binutils-gdb/gdb/event-top.c:543
#16 0x56478668752f in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /tmp/src/binutils-gdb/gdb/event-top.c:779
#17 0x564787dcb29a in tui_command_line_handler /tmp/src/binutils-gdb/gdb/tui/tui-interp.c:104
#18 0x56478668443d in gdb_rl_callback_handler /tmp/src/binutils-gdb/gdb/event-top.c:250
#19 0x7f4efd506246 in rl_callback_read_char (/usr/lib/libreadline.so.8+0x3b246) (BuildId: 092e91fc4361b0ef94561e3ae03a75f69398acbb)
#20 0x564786683dea in gdb_rl_callback_read_char_wrapper_noexcept /tmp/src/binutils-gdb/gdb/event-top.c:192
#21 0x564786684042 in gdb_rl_callback_read_char_wrapper /tmp/src/binutils-gdb/gdb/event-top.c:225
#22 0x564787f1b119 in stdin_event_handler /tmp/src/binutils-gdb/gdb/ui.c:155
#23 0x56478862438d in handle_file_event /tmp/src/binutils-gdb/gdbsupport/event-loop.cc:573
#24 0x564788624d23 in gdb_wait_for_event /tmp/src/binutils-gdb/gdbsupport/event-loop.cc:694
#25 0x56478862297c in gdb_do_one_event(int) /tmp/src/binutils-gdb/gdbsupport/event-loop.cc:264
#26 0x564786df99f0 in start_event_loop /tmp/src/binutils-gdb/gdb/main.c:412
#27 0x564786dfa069 in captured_command_loop /tmp/src/binutils-gdb/gdb/main.c:476
#28 0x564786dff61f in captured_main /tmp/src/binutils-gdb/gdb/main.c:1320
#29 0x564786dff75c in gdb_main(captured_main_args*) /tmp/src/binutils-gdb/gdb/main.c:1339
#30 0x564785381b6d in main /tmp/src/binutils-gdb/gdb/gdb.c:32
#31 0x7f4efbc3984f (/usr/lib/libc.so.6+0x2384f) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e)
#32 0x7f4efbc39909 in __libc_start_main (/usr/lib/libc.so.6+0x23909) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e)
#33 0x564785381934 in _start (/tmp/build/binutils-gdb/gdb/gdb+0xabc5934) (BuildId: 90de353ac158646e7dab501b76a18a76628fca33)
0x603000068034 is located 0 bytes after 20-byte region [0x603000068020,0x603000068034) allocated by thread T0 here:
#0 0x7f4efcee0cd1 in __interceptor_calloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x5647856265d8 in xcalloc /tmp/src/binutils-gdb/gdb/alloc.c:97
#2 0x564788610c6b in xzalloc(unsigned long) /tmp/src/binutils-gdb/gdbsupport/common-utils.cc:29
#3 0x56478815721a in value::allocate_contents(bool) /tmp/src/binutils-gdb/gdb/value.c:929
#4 0x564788157285 in value::allocate(type*, bool) /tmp/src/binutils-gdb/gdb/value.c:941
#5 0x56478815733a in value::allocate(type*) /tmp/src/binutils-gdb/gdb/value.c:951
#6 0x5647854ae81c in expr::ada_string_operation::evaluate(type*, expression*, noside) /tmp/src/binutils-gdb/gdb/ada-lang.c:10675
#7 0x5647854b63b8 in expr::ada_funcall_operation::evaluate(type*, expression*, noside) /tmp/src/binutils-gdb/gdb/ada-lang.c:11184
#8 0x564786658266 in expression::evaluate(type*, noside) /tmp/src/binutils-gdb/gdb/eval.c:111
#9 0x5647871242d6 in process_print_command_args /tmp/src/binutils-gdb/gdb/printcmd.c:1322
#10 0x5647871244b3 in print_command_1 /tmp/src/binutils-gdb/gdb/printcmd.c:1335
#11 0x564787125384 in print_command /tmp/src/binutils-gdb/gdb/printcmd.c:1468
#12 0x564785caac44 in do_simple_func /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:95
#13 0x564785cc18f0 in cmd_func(cmd_list_element*, char const*, int) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2735
#14 0x564787c70c68 in execute_command(char const*, int) /tmp/src/binutils-gdb/gdb/top.c:574
#15 0x564786686180 in command_handler(char const*) /tmp/src/binutils-gdb/gdb/event-top.c:543
#16 0x56478668752f in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /tmp/src/binutils-gdb/gdb/event-top.c:779
#17 0x564787dcb29a in tui_command_line_handler /tmp/src/binutils-gdb/gdb/tui/tui-interp.c:104
#18 0x56478668443d in gdb_rl_callback_handler /tmp/src/binutils-gdb/gdb/event-top.c:250
#19 0x7f4efd506246 in rl_callback_read_char (/usr/lib/libreadline.so.8+0x3b246) (BuildId: 092e91fc4361b0ef94561e3ae03a75f69398acbb)
The problem is in cli/cli-cmds.c, in the function setting_cmd, where
we do this:
const char *a0 = (const char *) argv[0]->contents ().data ();
Here argv[0] is a value* which we know is either a TYPE_CODE_ARRAY or
a TYPE_CODE_STRING. The problem is that the above line is casting the
value contents directly to a C-string, i.e. one that is assumed to
have a null-terminator at the end.
After the above commit this can no longer be assumed to be true. A
string value will be represented just as it would be in the current
language, so for Ada and Fortran the string will be an array of
characters with no null-terminator at the end.
My proposed solution is to copy the string contents into a std::string
object, and then use the std::string::c_str() value, this will ensure
that a null-terminator has been added.
I had a check through GDB at places TYPE_CODE_STRING was used and
couldn't see any other obvious places where this type of assumption
was being made, so hopefully this is the only offender.
Running the above test with ASan compiled in no longer gives an error.
Reviewed-By: Tom Tromey <tom@tromey.com>
History Of This Patch
=====================
This commit aims to address PR gdb/21699. There have now been a
couple of attempts to fix this issue. Simon originally posted two
patches back in 2021:
https://sourceware.org/pipermail/gdb-patches/2021-July/180894.htmlhttps://sourceware.org/pipermail/gdb-patches/2021-July/180896.html
Before Pedro then posted a version of his own:
https://sourceware.org/pipermail/gdb-patches/2021-July/180970.html
After this the conversation halted. Then in 2023 I (Andrew) also took
a look at this bug and posted two versions:
https://sourceware.org/pipermail/gdb-patches/2023-April/198570.htmlhttps://sourceware.org/pipermail/gdb-patches/2023-April/198680.html
The approach taken in my first patch was pretty similar to what Simon
originally posted back in 2021. My second attempt was only a slight
variation on the first.
Pedro then pointed out his older patch, and so we arrive at this
patch. The GDB changes here are mostly Pedro's work, but updated by
me (Andrew), any mistakes are mine.
The tests here are a combinations of everyone's work, and the commit
message is new, but copies bits from everyone's earlier work.
Problem Description
===================
Bug PR gdb/21699 makes the observation that using $_as_string with
GDB's printf can cause GDB to print unexpected data from the
inferior. The reproducer is pretty simple:
#include <stddef.h>
static char arena[100];
/* Override malloc() so value_coerce_to_target() gets a known
pointer, and we know we"ll see an error if $_as_string() gives
a string that isn't null terminated. */
void
*malloc (size_t size)
{
memset (arena, 'x', sizeof (arena));
if (size > sizeof (arena))
return NULL;
return arena;
}
int
main ()
{
return 0;
}
And then in a GDB session:
$ gdb -q test
Reading symbols from /tmp/test...
(gdb) start
Temporary breakpoint 1 at 0x4004c8: file test.c, line 17.
Starting program: /tmp/test
Temporary breakpoint 1, main () at test.c:17
17 return 0;
(gdb) printf "%s\n", $_as_string("hello")
"hello"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(gdb) quit
The problem above is caused by how value_cstring is used within
py-value.c, but once we understand the issue then it turns out that
value_cstring is used in an unexpected way in many places within GDB.
Within py-value.c we have a null-terminated C-style string. We then
pass a pointer to this string, along with the length of this
string (so not including the null-character) to value_cstring.
In value_cstring GDB allocates an array value of the given character
type, and copies in requested number of characters. However
value_cstring does not add a null-character of its own. This means
that the value created by calling value_cstring is only
null-terminated if the null-character is included in the passed in
length. In py-value.c this is not the case, and indeed, in most uses
of value_cstring, this is not the case.
When GDB tries to print one of these strings the value contents are
pushed to the inferior, and then read back as a C-style string, that
is, GDB reads inferior memory until it finds a null-terminator. For
the py-value.c case, no null-terminator is pushed into the inferior,
so GDB will continue reading inferior memory until a null-terminator
is found, with unpredictable results.
Patch Description
=================
The first thing this patch does is better define what the arguments
for the two function value_cstring and value_string should represent.
The comments in the header file are updated to describe whether the
length argument should, or should not, include a null-character.
Also, the data argument is changed to type gdb_byte. The functions as
they currently exist will handle wide-characters, in which case more
than one 'char' would be needed for each character. As such using
gdb_byte seems to make more sense.
To avoid adding casts throughout GDB, I've also added an overload that
still takes a 'char *', but asserts that the character type being used
is of size '1'.
The value_cstring function is now responsible for adding a null
character at the end of the string value it creates.
However, once we start looking at how value_cstring is used, we
realise there's another, related, problem. Not every language's
strings are null terminated. Fortran and Ada strings, for example,
are just an array of characters, GDB already has the function
value_string which can be used to create such values.
Consider this example using current GDB:
(gdb) set language ada
(gdb) p $_gdb_setting("arch")
$1 = (97, 117, 116, 111)
(gdb) ptype $
type = array (1 .. 4) of char
(gdb) p $_gdb_maint_setting("test-settings string")
$2 = (0)
(gdb) ptype $
type = array (1 .. 1) of char
This shows two problems, first, the $_gdb_setting and
$_gdb_maint_setting functions are calling value_cstring using the
builtin_char character, rather than a language appropriate type. In
the first call, the 'arch' case, the value_cstring call doesn't
include the null character, so the returned array only contains the
expected characters. But, in the $_gdb_maint_setting example we do
end up including the null-character, even though this is not expected
for Ada strings.
This commit adds a new language method language_defn::value_string,
this function takes a pointer and length and creates a language
appropriate value that represents the string. For C, C++, etc this
will be a null-terminated string (by calling value_cstring), and for
Fortran and Ada this can be a bounded array of characters with no null
terminator. Additionally, this new language_defn::value_string
function is responsible for selecting a language appropriate character
type.
After this commit the only calls to value_cstring are from the C
expression evaluator and from the default language_defn::value_string.
And the only calls to value_string are from Fortan, Ada, and ObjectC
related code.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=21699
Co-Authored-By: Simon Marchi <simon.marchi@efficios.com>
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Co-Authored-By: Pedro Alves <pedro@palves.net>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Same as previous patches, but for sync_execution_done. Except that
here, we only want to notify the interpreter that is executing the
command, not all interpreters.
Change-Id: I729c719447b5c5f29af65dbf6fed9132e2cd308b