Co-workers who work on a program that uses DAP asked for the ability
to have gdb stop at the main subprogram when launching. This patch
implements this extension.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
This adds a new "target" to the DAP attach request. This is passed to
"target remote". I thought "attach" made the most sense for this,
because in some sense gdb is attaching to a running process. It's
worth noting that all DAP "attach" parameters are defined by the
implementation.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
A DAP client can report the supportsVariableType capability in the
initialize request. In this case, gdb can include the type of a
variable or expression in various results.
This adds an 'assign' method to gdb.Value. This allows for assignment
without requiring the use of parse_and_eval.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
It occurred to me recently that gdb's DAP implementation should
probably check the types of objects coming from the client. This
patch implements this idea by reusing Python's existing type
annotations, and supplying a decorator that verifies these at runtime.
Python doesn't make it very easy to do runtime type-checking, so the
core of the checker is written by hand. I haven't tried to make a
fully generic runtime type checker. Instead, this only checks the
subset that is needed by DAP. For example, only keyword-only
functions are handled.
Furthermore, in a few spots, it wasn't convenient to spell out the
type that is accepted. I've added a couple of comments to this effect
in breakpoint.py.
I've tried to make this code compatible with older versions of Python,
but I've only been able to try it with 3.9 and 3.10.
My co-worker Kévin taught me that using a mutable object as a default
argument in Python is somewhat dangerous, because the object is
created a single time (when the function is defined), and so if it is
mutated in the body of the function, the changes will stick around.
This patch changes the cases like this in DAP to use () rather than []
as the default. This patch is merely preventative, as no bugs like
this are in the code.
The 'request' decorator is intended to also ensure that the request
function runs in the DAP thread. However, the unwrapped function is
installed in the global request map, so the wrapped version is never
called. This patch fixes the bug.
When I first started implementing DAP, I had some vague plan of having
the implementation functions use the same name as the request. I
abandoned this idea, but one vestige remained. This patch renames the
one remaining function to be gdb-ish.
This implements the DAP "attach" request.
Note that the copyright dates on the new test source file are not
incorrect -- this was copied verbatim from another directory.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
This implements the DAP setExceptionBreakpoints request for Ada. This
is a somewhat minimal implementation, in that "exceptionOptions" are
not implemented (or advertised) -- I wasn't completely sure how this
feature is supposed to work.
I haven't added C++ exception handling here, but it's easy to do if
needed.
This patch relies on the new MI command execution support to do its
work.
Currently, Ada catchpoints require that the inferior be running.
However, there's no deep reason for this -- for example, C++ exception
catchpoints do not have this requirement. Instead, those work like
ordinary breakpoints: they are pending until the needed runtime
locations are seen.
This patch changes Ada catchpoints to work the same way.
This patch merges create_excep_cond_exprs into ada_catchpoint::re_set.
This is less verbose and is also a step toward making ada_catchpoint
work more like the other code_breakpoint-based exception catchpoints.
gnat_runtime_has_debug_info starts a new gdb to do its work. However,
it also leaves this gdb running, which can potentially confuse the
calling test -- I encountered this when writing a new DAP test. This
patch changes the proc to shut down gdb.
With a gdb 13.2 based package on SLE-15 aarch64, I run into:
...
(gdb) PASS: gdb.python/py-rbreak.exp: nosharedlibrary
py sl = gdb.rbreak("^[^_]",minsyms=False)^M
Breakpoint 2 at 0x4004ac: file ../sysdeps/aarch64/crti.S, line 63.^M
...
(gdb) py print(len(sl))^M
12^M
(gdb) FAIL: gdb.python/py-rbreak.exp: check number of returned breakpoints is 11
...
The FAIL is due to:
- the glibc object crti.o containing debug information for function
call_weak_fn, and
- the test-case not expecting this.
The debug information is there due to compiling glibc using a binutils which
contains commit 591cc9fbbf ("gas/Dwarf: record functions").
I've run into a similar issue before, see commit 3fbbcf473a ("[gdb/testsuite]
Fix regexp in py-rbreak.exp").
The fix I applied there was to use a regexp "^[^_]" to filter out
__libc_csu_fini and __libc_csu_init, but that doesn't work for call_weak_fn.
Fix this by:
- reverting the regexp to "", and
- rewriting the check to require at least 11 functions, rather than a precise
match.
Tested on x86_64-linux.
PR testsuite/30538
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30538
With a gdb 13.2 based package on openSUSE Tumbleweed i586, I ran into:
...
(gdb) run ^M
Starting program: out_of_line_in_inlined/foo_o224_021-all ^M
[Thread debugging using libthread_db enabled]^M
Using host libthread_db library "/lib/libthread_db.so.1".^M
^M
Breakpoint 1.1, foo_o224_021.child1.child2 (s=...) at foo_o224_021.adb:26^M
26 for C of S loop^M
(gdb) FAIL: gdb.ada/out_of_line_in_inlined.exp: scenario=all: \
run to foo_o224_021.child1.child2
...
I can reproduce the same issue with gdb trunk on x86_64, by using optimize=-O3
instead of optimize=-O2.
Fix this by using $bkptno_num_re.
Tested on x86_64-linux.
PR testsuite/30539
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30539
Replace macro HELP_ATTRIBUTE_MODE with a std::string.
Tested on x86_64-linux.
Reviewed-By: Bruno Larsen <blarsen@redhat.com>
Reviewed-By: Tom Tromey <tom@tromey.com>
This commit implements a fix for a bug reported against GDB on
Fedora bugzilla...
https://bugzilla.redhat.com/show_bug.cgi?id=2166796
The test case in that bug report involved running gdb against the 'jq'
program (which is a command-line JSON processor) on Fedora 37. Since
the debug info is compiler (and compile-time option) dependent, it
won't necessarily show up in other distributions or even past or
future versions of Fedora. (E.g. when trying the example shown below
on Fedora 38, GDB says that the value of 'value' has been optimized
out. I.e. it does not demonstrate the same DWARF error that can be
see when using Fedora 37.)
That said, on Fedora 37, the bug could be reproduced as follows:
[kev@f37-1 ~]$ gdb jq -q -ex 'b src/util.c:415' -ex 'r </dev/null'
Reading symbols from jq...
This GDB supports auto-downloading debuginfo from the following URLs:
<https://debuginfod.fedoraproject.org/>
Enable debuginfod for this session? (y or [n]) y
Debuginfod has been enabled.
To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
Reading symbols from /home/kev/.cache/debuginfod_client/9d3c8b4197350a190a74972d481de32abf641aa4/debuginfo...
No source file named src/util.c.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (src/util.c:415) pending.
Starting program: /usr/bin/jq </dev/null
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Breakpoint 1, jq_util_input_next_input (state=0x55555555d7f0) at src/util.c:416
416 if (state->parser == NULL) {
(gdb) p value
DWARF-2 expression error: DW_OP_GNU_uninit must always be the very last op.
This is undesirable - rather than output an error about the DWARF
info, we'd prefer to see a value, even if it is uninitialized.
Examination of the debuginfo showed the following:
<1><468f1>: Abbrev Number: 112 (DW_TAG_subprogram)
<468f2> DW_AT_external : 1
<468f2> DW_AT_name : (indirect string, offset: 0x4781): jq_util_input_next_input
<468f6> DW_AT_decl_file : 10
<468f6> DW_AT_decl_line : 411
<468f8> DW_AT_decl_column : 4
<468f9> DW_AT_prototyped : 1
<468f9> DW_AT_type : <0x3f2>
<468fd> DW_AT_sibling : <0x4692e>
...
<2><46921>: Abbrev Number: 102 (DW_TAG_variable)
<46922> DW_AT_name : (indirect string, offset: 0x8cb): value
<46926> DW_AT_decl_file : 10
<46926> DW_AT_decl_line : 414
<46928> DW_AT_decl_column : 6
<46929> DW_AT_type : <0x3f2>
Note that there's no DW_AT_location, so I looked for an abstract origin entry:
<2><2dfa0>: Abbrev Number: 90 (DW_TAG_variable)
<2dfa1> DW_AT_abstract_origin: <0x46921>
<2dfa5> DW_AT_location : 0x27cf1 (location list)
<2dfa9> DW_AT_GNU_locviews: 0x27ce1
(Note that the DW_AT_abstract_origin attribute's value is 0x46921 which
is the DIE for the local variable "value".)
Looking at the location list, I see:
00027cf1 v000000000000000 v000000000000000 views at 00027ce1 for:
000000000002f8fe 000000000002f92e (DW_OP_reg13 (r13); DW_OP_GNU_uninit; DW_OP_piece: 8; DW_OP_reg12 (r12); DW_OP_GNU_uninit; DW_OP_piece: 8)
While DW_OP_GNU_uninit is not the very last op, it is the last op
prior to DW_OP_piece. The fix involved changing the DW_OP_GNU_uninit
case in dwarf_expr_context::execute_stack_op in gdb/dwarf2/expr.c so
that DW_OP_GNU_uninit may appear just before DW_OP_piece.
With the fix in place, attempting to print 'value' now looks like
this:
(gdb) p value
$1 = [uninitialized] {kind_flags = 0 '\000', pad_ = 0 '\000', offset = 0,
size = 0, u = {ptr = 0x0, number = 0}}
Note that "[uninitialized]" is part of the output. (But also note
that there's an extra space character.)
I've made a new test case,
gdb.dwarf2/DW_OP_piece_with_DW_OP_GNU_uninit.exp, by adapting an
existing one, gdb.dwarf2/opt-out-not-implptr.exp. Since it uses the
DWARF assembler, the test case does not depend on a specific compiler
version or compiler options.
Tested on Fedora 37 and Fedora 38.
Add a new test plt-findfre-1 to ensure lookup of SFrame stack trace
information for pltN entries is correct.
In this test, a dummy SFrame FDE of type SFRAME_FDE_TYPE_PCMASK is
created. The size of the 'function code block' covered by the SFrame
FDE is equivalent to 5 pltN entries of 16 bytes each.
The test first looks up SFrame FREs for some addresses in the first pltN
entry, followed by lookups for some addresses in the fourth pltN entry.
libsframe/
* Makefile.in: Regenerated.
* testsuite/libsframe.find/find.exp: Add new test.
* testsuite/libsframe.find/local.mk: Likewise.
* testsuite/libsframe.find/plt-findfre-1.c: New test.
To find SFrame stack trace information from an FDE of type
SFRAME_FDE_TYPE_PCMASK, sframe_find_fre () was doing an operation
like,
(start_ip_offset & 0xff) >= (pc & 0xff), etc.
This is buggy and needs correction. The mask 0xff should be 0xf (to
work for a pltN entry of size say, 16 bytes).
At this time, the size of the pltN entry is implicitly assumed to be 16
bytes by libsframe. In next version of the SFrame format, we can encode
this information explicitly in the SFrame FDE.
For now, we should fix the code to at least behave correctly for the
generated code and the generated SFrame stack trace information for the
pltN entries on x86_64.
libsframe/
* sframe.c (sframe_find_fre): Correct the bitmask used for
SFrame FDEs of type SFRAME_FDE_TYPE_PCMASK.
As noted by Tom Tromey, there are some formatting issues with the ternary
operator in the aarch64/arm codebase. This patch fixes those.
Reviewed-By: Tom Tromey <tom@tromey.com>
Say we're in TUI mode, and type "sun":
...
(gdb) sun
...
After switching to SingleKey mode using C-x s, we have just:
...
sun
...
After typing "d", we get:
...
sun
Undefined command: "sundown". Try "help".
...
The SingleKey "d" is supposed run the "down" command.
Fix this by clearing the readline line buffer when switching to SingleKey
mode.
Tested on x86_64-linux.
PR tui/30522
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30522
Reviewed-By: Tom Tromey <tom@tromey.com>
A GDB crash was discovered on Fedora GDB that was tracked back to an
issue with the way that debuginfod is cleaned up.
The bug was reported on Fedora 37, 38, and 39. Here are the steps to
reproduce:
1. The file /etc/ssl/openssl.cnf contains the following lines:
[provider_sect]
default = default_sect
##legacy = legacy_sect
##
[default_sect]
activate = 1
##[legacy_sect]
##activate = 1
The bug will occur when the '##' characters are removed so that the
lines in question look like this:
[provider_sect]
default = default_sect
legacy = legacy_sect
[default_sect]
activate = 1
[legacy_sect]
activate = 1
2. Clean up any existing debuginfod cache data:
> rm -rf $HOME/.cache/debuginfod_client
3. Run GDB:
> gdb -nx -q -iex 'set trace-commands on' \
-iex 'set debuginfod enabled on' \
-iex 'set confirm off' \
-ex 'start' -ex 'quit' /bin/ls
+set debuginfod enabled on
+set confirm off
Reading symbols from /bin/ls...
Downloading separate debug info for /usr/bin/ls
... snip ...
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffde38) at ../src/ls.c:1646
1646 {
+quit
Fatal signal: Segmentation fault
----- Backtrace -----
... snip ...
So GDB ends up crashing during exit.
What's happening is that when debuginfod is initialised
debuginfod_begin is called (this is in the debuginfod library), this
in turn sets up libcurl, which makes use of openssl. Somewhere during
this setup process an at_exit function is registered to cleanup some
state.
Back in GDB the debuginfod_client object is managed using this code:
/* Deleter for a debuginfod_client. */
struct debuginfod_client_deleter
{
void operator() (debuginfod_client *c)
{
debuginfod_end (c);
}
};
using debuginfod_client_up
= std::unique_ptr<debuginfod_client, debuginfod_client_deleter>;
And then a global debuginfod_client_up is created to hold a pointer to
the debuginfod_client object. As a global this will be cleaned up
using the standard C++ global object destructor mechanism, which is
run after the at_exit handlers.
However, it is expected that when debuginfod_end is called the
debuginfod_client object will still be in a usable state, that is, we
don't expect the at_exit handlers to have run and started cleaning up
the library state.
To fix this issue we need to ensure that debuginfod_end is called
before the at_exit handlers have a chance to run.
This commit removes the debuginfod_client_up type, and instead has GDB
hold a raw pointer to the debuginfod_client object. We then make use
of GDB's make_final_cleanup to register a function that will call
debuginfod_end.
As GDB's final cleanups are called before exit is called, this means
that debuginfod_end will be called before the at_exit handlers are
called, and the crash identified above is resolved.
It's not obvious how this issue can easily be tested for. The bug does
not appear to manifest when using a local debuginfod server, so we'd
need to setup something more involved. For now I'm proposing this
patch without any associated tests.
Co-Authored-By: Mark Wielaard <mark@klomp.org>
Co-Authored-By: Simon Marchi <simark@simark.ca>
Reviewed-By: Tom Tromey <tom@tromey.com>
Reviewed-By: Aaron Merey <amerey@redhat.com>
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>
I found a couple of spots that could use scoped_value_mark. One of
them is a spot that didn't consider the possibility that value_mark
can return NULL. I tend to doubt this can be seen in this context,
but nevertheless this is safer.
Regression tested on x86-64 Fedora 36.
Freeing ecoff_debug_info "pointers to the unswapped symbolic info"
isn't a simple matter, due to differing allocation strategies. In
_bfd_ecoff_slurp_symbolic_info the pointers are to objalloc memory.
In the ecoff linker they are to separately malloc'd memory. In gas we
have most (obj-elf) or all (obj-ecoff) into a single malloc'd buffer.
This patch fixes the leaks for binutils and ld, leaving the gas leaks
for another day. The mips elf backend already had this covered, and
the ecoff backend had a pointer, raw_syments used as a flag, so most
of the patch is moving these around a little so they are accessible
for both ecoff and elf.
include/
* coff/ecoff.h (struct ecoff_debug_info): Add alloc_syments.
bfd/
* libecoff.h (struct ecoff_tdata): Delete raw_syments.
* elfxx-mips.c (free_ecoff_debug): Delete. Replace uses with
_bfd_ecoff_free_ecoff_debug_info.
(_bfd_mips_elf_final_link): Init debug.alloc_syments.
* ecofflink.c (_bfd_ecoff_free_ecoff_debug_info): New function.
* ecoff.c (_bfd_ecoff_bfd_free_cached_info): Call
_bfd_ecoff_free_ecoff_debug_info.
(_bfd_ecoff_slurp_symbolic_info): Replace uses of raw_syments
with alloc_syments.
(ecoff_final_link_debug_accumulate): Likewise. Use
_bfd_ecoff_free_ecoff_debug_info.
(_bfd_ecoff_bfd_copy_private_bfd_data): Set alloc_syments for
copied output.
* elf64-alpha.c (elf64_alpha_read_ecoff_info): Use
_bfd_ecoff_free_ecoff_debug_info.
* libbfd-in.h (_bfd_ecoff_free_ecoff_debug_info): Declare.
* libbfd.h: Regenerate.
gas/
* config/obj-ecoff.c (ecoff_frob_file): Set alloc_syments.
* config/obj-elf.c (elf_frob_file_after_relocs): Likewise.
I noticed that the test-suite doesn't excercise the case in
tui_redisplay_readline that height (initially 1) is changed by this call:
...
tui_puts_internal (w, prompt, &height);
...
Add a test-case that excercises this.
Tested on x86_64-linux.
In the current implementation, core_target::build_file_mappings will try
to locate and open files which were mapped in the process for which the
core dump was produced. If the file cannot be found or cannot be
opened, GDB will re-try to open it once for each time it was mapped in
the process's address space.
This patch makes it so GDB recognizes that it has already failed to open
a given file once and does not re-try the process for each mapping.
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
When GDB opens a coredump it tries to locate and then open all files
which were mapped in the process.
If a file is found but cannot be opened with BFD (bfd_open /
bfd_check_format fails), then a warning is printed to the user. If the
same file was mapped multiple times in the process's address space, the
warning is printed once for each time the file was mapped. I find this
un-necessarily noisy.
This patch makes it so the warning message is printed only once per
file.
There was a comment in the code assuming that if the file was found on
the system, opening it (bfd_open + bfd_check_format) should always
succeed. A recent change in BFD (014a602b86 "Don't optimise bfd_seek
to same position") showed that this assumption is not valid. For
example, it is possible to have a core dump of a process which had
mmaped an IO page from a DRI render node (/dev/dri/runderD$NUM). In
such case the core dump does contain the information that portions of
this special file were mapped in the host process, but trying to seek to
position 0 will fail, making bfd_check_format fail. This patch removes
this comment.
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
In core_target::build_file_mappings, GDB tries to open files referenced
in the core dump.
The process goes like this:
struct bfd *bfd = bfd_map[filename];
if (bfd == nullptr)
{
bfd = bfd_map[filename]
= bfd_openr (expanded_fname.get (), "binary");
if (bfd == nullptr || !bfd_check_format (bfd, bfd_object))
{
if (bfd != nullptr)
bfd_close (bfd);
return;
}
}
asection *sec = bfd_make_section_anyway (bfd, "load");
...
The problem is that if bfd_check_format fails, we close the bfd but keep
a reference to it in the bfd_map.
If the same filename appears another time in the NT_FILE note, we enter
this code again. The second time, bfd_map[filename] is not nullptr and
we try to call bfd_make_section_anyway on an already closed BFD, which
is a use-after-free error.
This patch makes sure that the bfd is only saved in the bfd_map if it
got opened successfully.
This error got exposed by a recent change in BFD (014a602b86 "Don't
optimise bfd_seek to same position"). Since this change, opening a
coredump which contains mapping to some special files such as a DRI
render node (/dev/dri/renderD$NUM) exposes the issue. This happens for
example for processes using AMDGPU devices to offload compute tasks.
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>