While trying to build on Cygwin (gcc 10.2.0), I got:
CXX server.o
/home/Baube/src/binutils-gdb/gdbserver/server.cc: In function 'void handle_general_set(char*)':
/home/Baube/src/binutils-gdb/gdbserver/server.cc:832:12: error: 'sprintf' argument 3 overlaps destination object 'own_buf' [-Werror=restrict]
832 | sprintf (own_buf, "E.Unknown thread-events mode requested: %s\n",
| ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
833 | mode);
| ~~~~~
/home/Baube/src/binutils-gdb/gdbserver/server.cc:553:27: note: destination object referenced by 'restrict'-qualified argument 1 was declared here
553 | handle_general_set (char *own_buf)
| ~~~~~~^~~~~~~
There is indeed a problem: mode points somewhere into own_buf. And by
the time mode gets formatted as a %s, whatever it points to has been
overwritten. I hacked gdbserver to coerce it into that error path, and
this is the resulting message:
(gdb) p own_buf
$1 = 0x629000000200 "E.Unknown thread-events mode requested: ad-events mode requested: 00;10:9020fdf7ff7f0000;thread:p49388.49388;core:e;\n"
Fix it by formatting the error string in an std::string first.
gdbserver/ChangeLog:
* server.cc (handle_general_set): Don't use sprintf with
argument overlapping buffer.
Change-Id: I4fdf05c0117f63739413dd67ddae7bd6ee414824
handle_search_memory had some code after a call to error. This code
is dead, and this patch removes it.
gdbserver/ChangeLog
2020-10-07 Tom Tromey <tromey@adacore.com>
* server.cc (handle_search_memory): Remove dead code.
This replaces gdbserver's memory-searching function with
simple_search_memory.
gdbserver/ChangeLog
2020-10-07 Tom Tromey <tromey@adacore.com>
* server.cc (handle_search_memory_1): Remove.
(handle_search_memory): Use simple_search_memory.
I found myself wanting to run a few specific selftests while developing.
I thought it would be nice to be able to provide multiple test names
when running `maintenant selftests`. The arguments to that command is
currently interpreted as a single filter (not split by spaces), it now
becomes a list a filters, split by spaces. A test is executed when it
matches at least one filter.
Here's an example of the result in GDB:
(gdb) maintenance selftest xml
Running selftest xml_escape_text.
Running selftest xml_escape_text_append.
Ran 2 unit tests, 0 failed
(gdb) maintenance selftest xml unord
Running selftest unordered_remove.
Running selftest xml_escape_text.
Running selftest xml_escape_text_append.
Ran 3 unit tests, 0 failed
(gdb) maintenance selftest xml unord foobar
Running selftest unordered_remove.
Running selftest xml_escape_text.
Running selftest xml_escape_text_append.
Ran 3 unit tests, 0 failed
Since the selftest machinery is also shared with gdbserver, I also
adapted gdbserver. It accepts a `--selftest` switch, which accepts an
optional filter argument. I made it so you can now pass `--selftest`
multiple time to add filters.
It's not so useful right now though: there's only a single selftest
right now in GDB and it's for an architecture I can't compile. So I
tested by adding dummy tests, here's an example of the result:
$ ./gdbserver --selftest=foo
Running selftest foo.
foo
Running selftest foobar.
foobar
Ran 2 unit tests, 0 failed
$ ./gdbserver --selftest=foo --selftest=bar
Running selftest bar.
bar
Running selftest foo.
foo
Running selftest foobar.
foobar
Ran 3 unit tests, 0 failed
gdbsupport/ChangeLog:
* selftest.h (run_tests): Change parameter to array_view.
* selftest.c (run_tests): Change parameter to array_view and use
it.
gdb/ChangeLog:
* maint.c (maintenance_selftest): Split args and pass array_view
to run_tests.
gdbserver/ChangeLog:
* server.cc (captured_main): Accept multiple `--selftest=`
options. Pass all `--selftest=` arguments to run_tests.
Change-Id: I422bd49f08ea8095ae174c5d66a2dd502a59613a
On some systems, the gdb.multi/multi-target.exp testcase occasionally
fails like so:
Running src/gdb/testsuite/gdb.multi/multi-target.exp ...
FAIL: gdb.multi/multi-target.exp: info-inferiors: multi_process=on: inferior 1: info connections
FAIL: gdb.multi/multi-target.exp: info-inferiors: multi_process=on: inferior 1: info inferiors
FAIL: gdb.multi/multi-target.exp: info-inferiors: multi_process=on: inferior 2: info connections
FAIL: gdb.multi/multi-target.exp: info-inferiors: multi_process=on: inferior 2: info inferiors
FAIL: gdb.multi/multi-target.exp: info-inferiors: multi_process=on: inferior 3: inferior 3
... many more cascading fails.
The problem starts when the testcase runs an inferior against GDBserver:
(gdb) run
Starting program: build/gdb/testsuite/outputs/gdb.multi/multi-target/multi-target
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
Reading /lib64/ld-2.31.so from remote target...
Reading /lib64/.debug/ld-2.31.so from remote target...
Reading /usr/lib/debug//lib64/ld-2.31.so from remote target...
Reading /usr/lib/debug/lib64//ld-2.31.so from remote target...
Reading target:/usr/lib/debug/lib64//ld-2.31.so from remote target...
Reading /lib/x86_64-linux-gnu/libpthread.so.0 from remote target...
Reading /lib/x86_64-linux-gnu/libc.so.6 from remote target...
Reading /lib/x86_64-linux-gnu/libc-2.31.so from remote target...
Reading /lib/x86_64-linux-gnu/.debug/libc-2.31.so from remote target...
Reading /usr/lib/debug//lib/x86_64-linux-gnu/libc-2.31.so from remote target...
Reading /usr/lib/debug//lib/x86_64-linux-gnu/libc-2.31.so from remote target...
Remote connection closed
...
Note the "Remote connection closed" message. That means GDBserver
exited abruptly.
I traced it down to the fact that GDB fetches the thread list from
GDBserver while the main thread of the process is still running. On
my main system where I wrote the testcase, I have not observed the
failure because it is slow enough that the thread stops before
GDBserver fetches the thread list in the problem scenario which I'll
describe below.
With some --remote-debug logging from GDBserver side, we see the last
packets before the connection closes:
...
getpkt ("vCont;c"); [no ack sent]
putpkt ("$OK#9a"); [noack mode]
getpkt ("Tp10f9a.10f9a"); [no ack sent]
putpkt ("$OK#9a"); [noack mode]
getpkt ("Hgp0.0"); [no ack sent]
putpkt ("$OK#9a"); [noack mode]
getpkt ("qXfer:threads:read::0,1000"); [no ack sent]
Note the vCont;c , which sets the program running, and then a
qXfer:threads:read packet at the end.
The problem happens when the thread list refresh (qXfer:threads:read)
is sent just while the main thread is running and it still hasn't
initialized its libpthread id internally. In that state, the main
thread's lwp will remain with the thread_known flag clear. See in
find_one_thread:
/* If the new thread ID is zero, a final thread ID will be available
later. Do not enable thread debugging yet. */
if (ti.ti_tid == 0)
return 0;
Now, back in server.cc, to handle the qXfer:threads:read, we reach
handle_qxfer_threads -> handle_qxfer_threads_proper, and the latter
then calls handle_qxfer_threads_worker for each known thread. In
handle_qxfer_threads_worker, we call target_thread_handle. This ends
up in thread_db_thread_handle, here:
if (!lwp->thread_known && !find_one_thread (thread->id))
return false;
Since the thread ID isn't known yet, we call find_one_thread. This
calls into libthread_db.so, which accesses memory. Because the
current thread is running, that fails and we throw an error, here:
/* Get information about this thread. */
err = thread_db->td_ta_map_lwp2thr_p (thread_db->thread_agent, lwpid, &th);
if (err != TD_OK)
error ("Cannot get thread handle for LWP %d: %s",
lwpid, thread_db_err_str (err));
The current design is that whenever GDB-facing packets/requests need
to accesses memory, server.cc is supposed to prepare the target for
the access. See gdb_read_memory / gdb_write_memory. This preparation
means pausing threads if in non-stop mode (someday we could lift this
requirement, but we will still need to pause to access registers or do
other related ptrace accesses like PTRACE_GET_THREAD_AREA). Note that
the multi-target.exp testcase forces "maint set target-non-stop on".
So the fix here is to prepare the target to access memory when
handling qXfer:threads:read too.
gdbserver/ChangeLog:
* inferiors.cc (switch_to_process): New, moved here from
thread-db.cc, and made extern.
* inferiors.h (switch_to_process): Declare.
* server.cc: Include "gdbsupport/scoped_restore.h".
(handle_qxfer_threads_proper): Now returns bool. Prepare to
access memory around target calls.
(handle_qxfer_threads): Handle errors.
* thread-db.cc (switch_to_process): Moved to inferiors.cc.
When building gdbserver with AddressSanitizer, I get this annoying
little leak when gdbserver exits:
==307817==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 14 byte(s) in 1 object(s) allocated from:
#0 0x7f7fd4256459 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x563bef981b80 in xmalloc /home/simark/src/binutils-gdb/gdbserver/../gdb/alloc.c:60
#2 0x563befb53301 in xstrdup /home/simark/src/binutils-gdb/libiberty/xstrdup.c:34
#3 0x563bef9d742b in handle_query /home/simark/src/binutils-gdb/gdbserver/server.cc:2286
#4 0x563bef9ed0b7 in process_serial_event /home/simark/src/binutils-gdb/gdbserver/server.cc:4061
#5 0x563bef9f1d9e in handle_serial_event(int, void*) /home/simark/src/binutils-gdb/gdbserver/server.cc:4402
#6 0x563befb0ec65 in handle_file_event /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:548
#7 0x563befb0f49f in gdb_wait_for_event /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:673
#8 0x563befb0d4a1 in gdb_do_one_event() /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:215
#9 0x563bef9e721a in start_event_loop /home/simark/src/binutils-gdb/gdbserver/server.cc:3484
#10 0x563bef9eb90a in captured_main /home/simark/src/binutils-gdb/gdbserver/server.cc:3875
#11 0x563bef9ec2c7 in main /home/simark/src/binutils-gdb/gdbserver/server.cc:3961
#12 0x7f7fd3330001 in __libc_start_main (/usr/lib/libc.so.6+0x27001)
SUMMARY: AddressSanitizer: 14 byte(s) leaked in 1 allocation(s).
This is due to the handling of unknown qsupported features in
handle_query. The `qsupported` vector is built, containing all the
feature names received from GDB. As we iterate on them, when we
encounter unknown ones, we move them at the beginning of the vector, in
preparation of passing this vector of unknown features down to the
target (which may know about them).
When moving these unknown features to other slots in the vector, we
overwrite other pointers without freeing them, which therefore leak.
An easy fix would be to add a `free` when doing the move. However, I
think this is a good opportunity to sprinkle a bit of automatic memory
management in this code.
So, use a vector of std::string which owns all the entries. And use a
separate vector (that doesn't own the entries) for the unknown ones,
which is then passed to target_process_qsupported.
Given that the `c_str` method of std::string returns a `const char *`,
it follows that process_stratum_target::process_qsupported must accept a
`const char **` instead of a `char **`. And while at it, change the
pointer + size paramters to use an array_view instead.
gdbserver/ChangeLog:
* server.cc (handle_query): Use std::vector of
std::string for `qsupported` vector. Use separate
vector for unknowns.
* target.h (class process_stratum_target) <process_qsupported>:
Change parameters to array_view of const char *.
(target_process_qsupported): Remove `count` parameter.
* target.cc (process_stratum_target::process_qsupported): Change
parameters to array_view of const char *.
* linux-x86-low.cc (class x86_target) <process_qsupported>:
Likewise.
Change-Id: I97f133825faa6d7abbf83a58504eb0ba77462812
Use the construct_inferior_arguments function instead of
stringify_argv to construct a string from the program
arguments in those places where that one is then passed
to fork_inferior (linux-low, lyn-low), since
construct_inferior_arguments properly takes care of
special characters, while stringify_argv does not.
Using construct_inferior_arguments seems "natural", since its
documentation also mentions that it "does the
same shell processing as fork_inferior".
Since construct_inferior_args has been extended to do
proper quoting for Windows shells in commit
5d60742e2d
("Fix quoting of special characters for the MinGW build.",
2012-06-12), use it for the Windows case as well.
(I could not test that case myself, though.)
Adapt handling of empty args in function 'handle_v_run'
in gdbserver/server.cc to just insert an empty string
for an empty arg, since that one is now properly handled
in 'construct_inferior_arguments' already (and inserting
a "''" string in 'handle_v_run' would otherwise
cause that one to be treated as a string literally
containing two quote characters, which
'construct_inferior_args' would preserve by adding
extra escaping).
This makes gdbserver properly handle program args containing special
characters (like spaces), e.g. (example from PR25893)
$ gdbserver localhost:50505 myprogram "hello world"
now properly handles "hello world" as a single arg, not two separate
ones ("hello", "world").
gdbserver/ChangeLog:
PR gdbserver/25893
* linux-low.cc (linux_process_target::create_inferior),
lynx-low.cc (lynx_process_target::create_inferior),
win32-low.cc (win32_process_target::create_inferior): Use
construct_inferior_arguments instead of stringify_argv
to get string representation which properly escapes
special characters.
* server.cc (handle_v_run): Just pass empty program arg
as such, since any further processing is now handled via
construct_inferior_arguments.
Change-Id: Ibf963fcd51415c948840fb463289516b3479b0c3
The vector holding the program args is passed as a parameter
to target_create_inferior, which then passes it to
stringify_argv for all platforms, where any NULL entry in
the vector is ignored, so there seems to be no reason
to actually add one after all.
(Since the intention is to replace uses of stringify_argv with
construct_inferior_arguments in a follow-up commit and that
function doesn't currently handle such NULL arguments, it
would otherwise have to be extended.)
gdbserver/ChangeLog:
* server.cc (captured_main), (handle_v_run): No longer
insert extra NULL element to args vector.
Change-Id: Ia2ef6d36814a6b11ce8b0d6e3b33248a7945e825
If the search area is bigger than SEARCH_CHUNK_SIZE (16000), then you get
an error in gdbserver:
gdb: (gdb) find /w 0x3c43f0,+20000,0x04030201
gdb: Pattern not found.
gdbserver: Unable to access 3997 bytes of target memory at 0x3c8273, halting search.
The return value of any additional gdb_read_memory calls were compared with the
wrong value, this fixes it.
gdbserver/ChangeLog:
2020-04-22 Hannes Domani <ssbssa@yahoo.de>
* server.cc (handle_search_memory_1): Fix gdb_read_memory return value
comparison.
event-loop.c requires the client to provide some functions. This
patch implements these functions for gdbserver.
gdbserver/ChangeLog
2020-04-13 Tom Tromey <tom@tromey.com>
* server.c (invoke_async_signal_handlers)
(check_async_event_handlers, flush_streams, gdb_select): New
functions.
There is a developer only feature in gdbserver that provides a
command line option --disable-packet that prevents some packets from
being sent, which is used to increase test coverage within GDB.
This commit extends this mechanism to prevent GDBserver from sending
the T stop reply packets, instead limiting GDBserver to only send the
S stop reply packets.
The S stop reply packet is part of the older target control mechanism,
which has design flaws that were worked around with the introduction
of the newer target control mechanism, which uses the T stop reply
packet.
Limiting GDBserver to use S stop packets instead of T stop packets
will, inevitably, mean that GDBserver doesn't function correctly in
many cases involving multiple threads, however, I don't think this is
too important, this is a developer only feature, intended to allow us
to test GDB.
A new test that makes use of this feature will be added in the next
commit.
gdbserver/ChangeLog:
* remote-utils.cc (prepare_resume_reply): Add ability to convert T
reply into an S reply.
* server.cc (disable_packet_T): New global.
(captured_main): Set new global when appropriate.
* server.h (disable_packet_T): Declare.
For the same reasons outlined in the previous patch, this patch renames
gdbserver source files to .cc.
I have moved the "-x c++" switch to only those rules that require it.
gdbserver/ChangeLog:
* Makefile.in: Rename source files from .c to .cc.
* %.c: Rename to %.cc.
* configure.ac: Rename server.c to server.cc.
* configure: Re-generate.