diff options
author | Simon Marchi <simon.marchi@polymtl.ca> | 2020-07-13 22:27:00 -0400 |
---|---|---|
committer | Simon Marchi <simon.marchi@polymtl.ca> | 2020-07-13 22:27:01 -0400 |
commit | b315b67d7a57a0fd995cce5dfec77a4b61fa23d4 (patch) | |
tree | 9ef0b17812f0fdaa38e25cb683b206fe1db25cfe /gdbserver/linux-x86-low.cc | |
parent | 0a3a820f6ce861efa8c2a7aa5d0db11c6a7c3285 (diff) | |
download | binutils-b315b67d7a57a0fd995cce5dfec77a4b61fa23d4.zip binutils-b315b67d7a57a0fd995cce5dfec77a4b61fa23d4.tar.gz binutils-b315b67d7a57a0fd995cce5dfec77a4b61fa23d4.tar.bz2 |
gdbserver: fix memory leak when handling qsupported packet
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
Diffstat (limited to 'gdbserver/linux-x86-low.cc')
-rw-r--r-- | gdbserver/linux-x86-low.cc | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc index 7a65c1d..37d3626 100644 --- a/gdbserver/linux-x86-low.cc +++ b/gdbserver/linux-x86-low.cc @@ -106,7 +106,7 @@ public: bool supports_z_point_type (char z_type) override; - void process_qsupported (char **features, int count) override; + void process_qsupported (gdb::array_view<const char * const> features) override; bool supports_tracepoints () override; @@ -1003,18 +1003,15 @@ x86_target::update_xmltarget () PTRACE_GETREGSET. */ void -x86_target::process_qsupported (char **features, int count) +x86_target::process_qsupported (gdb::array_view<const char * const> features) { - int i; - /* Return if gdb doesn't support XML. If gdb sends "xmlRegisters=" with "i386" in qSupported query, it supports x86 XML target descriptions. */ use_xml = 0; - for (i = 0; i < count; i++) - { - const char *feature = features[i]; + for (const char *feature : features) + { if (startswith (feature, "xmlRegisters=")) { char *copy = xstrdup (feature + 13); @@ -1034,6 +1031,7 @@ x86_target::process_qsupported (char **features, int count) free (copy); } } + update_xmltarget (); } |