Age | Commit message (Collapse) | Author | Files | Lines |
|
For the Rust language, to avoid segmentation fault in case of an empty
array, do not try to copy any elements, but allocate and return
the empty array immediately.
With the command before the change, gdb crashes with message:
(gdb) set lang rust
(gdb) p [1;0]
Fatal signal: Segmentation fault
After the fix in this commit, gdb shows following message:
(gdb) set lang rust
(gdb) p [1;0]
$1 = []
Update the existing test case gdb.rust/expr.exp to verify the change.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
"Check we have ..." --> "Check if we have ..."
This is for consistency with the previous comment and
the code downstream.
|
|
For background reading, please see the previous patch, and the patch
before that!
After the last two patches, internal breakpoints can now be marked as
shlib_disabled if the library in which they are placed is unloaded.
The patch before last discusses a situation related to the
gdb.base/nostdlib.exp test, when run on a GNU/Linux glibc based system
where executables are compiled as PIE by default.
In this case it is observed that the dynamic linker will actually
report itself as unloaded (i.e. remove itself from the list of
currently loaded shared libraries). This behaviour is likely a bug in
the dynamic linker, but this behaviour exists in released versions of
the dynamic linker, so GDB should (if the cost is not too great) be
changed to handle this situation.
This commit handles a problem with the 'maint info breakpoints'
command.
When the dynamic linker is unloaded the 'shlib event' breakpoint is
marked as shlib_disabled (i.e. placed into the pending state). When
displaying the breakpoint in the 'maint info breakpoints' output, GDB
will try to print the locspec (location_spec *) as a string
Unfortunately, the locspec will be nullptr as the internal breakpoints
are not created via a location_spec, this means that GDB ends up
trying to call location_sepc::to_string() on a nullptr, resulting in
undefined behaviour (and a crash).
For most internal breakpoint types this is not a problem. If we
consider bp_longjmp_master for example, if the shared library
containing a breakpoint of this type is unloaded then first GDB marks
the breakpoint as shlib_disabled, then after unloading the shared
library breakpoint_re_set is called, which will delete the internal
breakpoint, and then try to re-create it (if needed). As a result,
the user never gets a change to run 'maint info breakpoints' on a
bp_longjmp_master breakpoint in the shlib_disabled state.
But bp_shlib_event and bp_thread_event breakpoints are not deleted and
recreated like this (see internal_breakpoint::re_set), so it is
possible, in rare cases, that we could end up trying to view one of
these breakpoint in a shlib_disabled state, and it would be nice if
GDB didn't crash as a result.
I've updated the printing code to check for and handle this case, and
I've updated the docs to mention this (rare) case.
For testing, I've extended gdb.base/nostdlib.exp to compile as
pie and nopie, and then run 'maint info breakpoints'. If we're
running on a buggy glibc then this will trigger the crash. I don't
know how I can trigger this problem without a buggy glibc as this
would require forcing the dynamic linker to be unloaded.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Bug PR gdb/32079 highlights an issue where GDB will try to remove a
breakpoint for a shared library that has been unloaded. This will
trigger an error from GDB like:
(gdb) next
61 dlclose (handle[dl]);
(gdb) next
warning: error removing breakpoint 0 at 0x7ffff78169b9
warning: error removing breakpoint 0 at 0x7ffff7730b57
warning: error removing breakpoint 0 at 0x7ffff7730ad3
54 for (dl = 0; dl < 4; ++dl)
(gdb)
What happens is that as the inferior steps over the dlclose() call,
GDB notices that the library has been unloaded and calls
disable_breakpoints_in_unloaded_shlib. However, this function only
operates on user breakpoints and tracepoints.
In the example above what is happening is that the test loads multiple
copies of libc into different linker namespsaces. When we 'next' over
the dlclose call one of the copies of libc is unloaded. As GDB placed
longjmp master breakpoints within the copy of libc that was just
unloaded, the warnings we see are GDB trying (and failing) to remove
these breakpoints.
I think the solution is for disable_breakpoints_in_unloaded_shlib to
handle all breakpoints, even internal ones like the longjmp master
breakpoints.
If we do this then the breakpoint will be marked as shlib_disabled and
also will be marked as not inserted. Later when we call
breakpoint_re_set() and the longjmp breakpoints are deleted we will no
longer try to remove them.
This solution is inspired by a patch suggested in the bug report:
https://sourceware.org/bugzilla/show_bug.cgi?id=32079#c3
There are some differences with my approach compared to the patch
suggested in the bug. First I have no need to delete the breakpoint
inside disable_breakpoints_in_unloaded_shlib as an earlier patch in
this series arranged for breakpoint_re_set to be called when shared
libraries are removed. Calling breakpoint_re_set will take care of
deleting the breakpoint for us. For details see the earlier commit
titled:
gdb: fixes for code_breakpoint::disabled_by_cond logic
Next, rather than only handling bp_longjmp and bp_longjmp_master, I
allow all breakpoints to be handled. I also only give the warning
about disabling breakpoints for user breakpoints, I don't see the
point of warning the user about internal b/p changes.
With this done the issues in PR gdb/32079 are resolved.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32079
Tested-By: Hannes Domani <ssbssa@yahoo.de>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
While working on the previous commit I realised that GDB would not
handle dprintf breakpoints correctly when a shared library was
unloaded.
Consider this example using the test binary from shlib-unload.exp. In
the function 'foo' we create a dprintf is in a shared library:
(gdb) b 59
Breakpoint 1 at 0x401215: file /tmp/projects/binutils-gdb/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/shlib-unload.c, line 59.
(gdb) r
Starting program: /tmp/projects/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/shlib-unload/shlib-unload
Breakpoint 1, main () at /tmp/projects/binutils-gdb/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/shlib-unload.c:59
59 res = dlclose (handle); /* Break here. */
(gdb) dprintf foo,"In foo"
Dprintf 2 at 0x7ffff7fc50fd: file /tmp/projects/binutils-gdb/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/shlib-unload-lib.c, line 23.
(gdb) n
Error in re-setting breakpoint 2: Function "foo" not defined.
warning: error removing breakpoint 2 at 0x7ffff7fc50fd
warning: error removing breakpoint 2 at 0x7ffff7fc50fd
warning: error removing breakpoint 2 at 0x7ffff7fc50fd
warning: error removing breakpoint 2 at 0x7ffff7fc50fd
warning: error removing breakpoint 2 at 0x7ffff7fc50fd
warning: error removing breakpoint 2 at 0x7ffff7fc50fd
warning: error removing breakpoint 2 at 0x7ffff7fc50fd
warning: error removing breakpoint 2 at 0x7ffff7fc50fd
Cannot remove breakpoints because program is no longer writable.
Further execution is probably impossible.
60 assert (res == 0);
(gdb)
What happens here is that as the inferior steps over the dlclose call
the shared library containing 'foo' is unloaded and
disable_breakpoints_in_unloaded_shlib is called. However in
disable_breakpoints_in_unloaded_shlib we have this check:
if (b.type != bp_breakpoint
&& b.type != bp_jit_event
&& b.type != bp_hardware_breakpoint
&& !is_tracepoint (&b))
continue;
As the dprintf has type bp_dprintf then this check triggers and we
ignore the dprintf, meaning the dprintf is not disabled. When the
inferior stops after the 'next' GDB tries to remove all breakpoints
but the dprintf can no longer be removed, the memory in which it was
placed has been unmapped from the inferior.
The fix is to start using is_breakpoint() in
disable_breakpoints_in_unloaded_shlib instead of the bp_breakpoint and
bp_hardware_breakpoint checks. The is_breakpoint() function also
checks for bp_dprintf.
With this fix in place GDB now correctly disables the breakpoint and
we no longer see the warning about removing the breakpoint.
During review it was pointed out that PR gdb/23149 and PR gdb/20208
both describe something similar, though for these bugs, the inferior
is restarted (which unloads all currently loaded shlib) rather than
passing over the dlclose. But the consequences are pretty similar.
I've included a test which covers this case.
One additional thing that these two bugs did show though is that
disable_breakpoints_in_shlibs also needs to start using is_breakpoint
for the same reason. Without this change, when an inferior is
restarted we get a warning like this for dprintf breakpoints:
warning: Temporarily disabling breakpoints for unloaded shared library "..."
but we don't get a similar warning for "normal" breakpoints. This is
because disable_breakpoints_in_shlibs is called from clear_solib,
which is called when an inferior is restarted.
It is best not to think too hard about disable_breakpoints_in_shlibs,
as this function is pretty broken, e.g. it doesn't call
notify_breakpoint_modified, despite modifying the breakpoints. But
for now I'm ignoring that, but fixing this is definitely on my list
for my next set of breakpoint related fixes, it's just that a lot of
these breakpoint fixes end up being depending on one another, but I
want to avoid making this series too long. So for now, I'm ignoring
the existing bug (missing breakpoint modified events), and fixing
disable_breakpoints_in_shlibs to cover dprintf.
With these fixes in place, the two bugs mentioned above should be
fixed.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23149
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20208
Tested-By: Hannes Domani <ssbssa@yahoo.de>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This commit rewrites disable_breakpoints_in_unloaded_shlib to be more
like disable_breakpoints_in_freed_objfile. Instead of looping over
all b/p locations, we instead loop over all b/p and then over all
locations for each b/p.
The advantage of doing this is that we can fix the small bug that was
documented in a comment in the code:
/* This may cause duplicate notifications for the same breakpoint. */
notify_breakpoint_modified (b);
By calling notify_breakpoint_modified() as we modify each location we
can potentially send multiple notifications for a single b/p.
Is this a bug? Maybe not. After all, at each notification one of the
locations will have changed, so its probably fine. But it's not
ideal, and we can easily do better, so lets do that.
There's a new test which checks that we only get a single notification
when the shared library is unloaded. Note that the test is written as
if there are multiple related but different tests within the same test
file ... but there aren't currently! The next commit will add another
test proc to this test script at which point the comments will make
sense. I've done this to avoid unnecessary churn in the next commit.
Tested-By: Hannes Domani <ssbssa@yahoo.de>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
I spotted that the code_breakpoint::disabled_by_cond flag doesn't work
how I'd expect it too. The flag appears to be "sticky" in some
situations; once a code_breakpoint::disabled_by_cond flag is marked
true, then, in some cases the flag wont automatically become false
again, even when you'd think it should.
The problem is in update_breakpoint_locations. In this function,
which is called as a worker of code_breakpoint::re_set, GDB computes a
new set of locations for a breakpoint, the new locations are then
installed into the breakpoint.
However, before installing the new locations GDB attempts to copy the
bp_location::enabled and bp_location::disabled_by_cond flag from the
old locations into the new locations.
The reason for copying the ::enabled flag makes sense. This flag is
controlled by the user. When we create the new locations if GDB can
see that a new location is equivalent to one of the old locations, and
if the old location was disabled by the user, then the new location
should also be disabled.
However, I think the logic behind copying the ::disabled_by_cond flag
is wrong. The disabled_by_cond flag is controlled by GDB and should
toggle automatically. If the condition string can be parsed then the
flag should be false (b/p enabled), if the condition string can't be
parsed then the flag should be true (b/p disabled).
As we always parse the condition string in update_breakpoint_locations
before we try to copy the ::enabled flag value then the
::disabled_by_cond flag should already be correct, there's no need to
copy over the ::disabled_by_cond value from the old location.
As a concrete example, consider a b/p placed within the main
executable, but with a condition that depends on a variable within a
shared library.
When the b/p is initially created the b/p will be disabled as the
condition string will be invalid (the shared library variable isn't
available yet).
When the inferior starts the shared library is loaded and the
condition variable becomes available to GDB. When the shared library
is loaded breakpoint_re_set is called which (eventually) calls
update_breakpoint_locations.
A new location is computed for the breakpoint and the condition string
is parsed. As the shared library variable is now know the expression
parses correctly and ::disabled_by_cond is left false for the new
location.
But currently GDB spots that the new location is at the same address
as the old location and copies disabled_by_cond over from the old
location, which marks the b/p location as disabled. This is not what
I would expect.
The solution is simple, don't copy over disabled_by_cond.
While writing a test I found another problem though. The
disabled_by_cond flag doesn't get set true when it should! This is
the exact opposite of the above.
The problem here is in solib_add which is (despite the name) called
whenever the shared library set changes, including when a shared
library is unloaded.
Imagine an executable that uses dlopen/dlclose to load a shared
library. Given an example of a b/p in the main executable that has a
condition that uses a variable from our shared library, a library
which might be unloaded with dlclose.
My expectation is that, when the library is unloaded, GDB will
automatically mark the breakpoint as disabled_by_cond, however, this
was not happening.
The problem is that in solib_add we only call breakpoint_re_set when
shared libraries are added, not when shared libraries are removed.
The solution I think is to just call breakpoint_re_set in both cases,
now the disabled_by_cond flag is updated as I'd expect.
Unfortunately, making this change causes a regression when running:
make check-gdb \
TESTS="gdb.trace/change-loc.exp" \
RUNTESTFLAGS="--target_board=native-gdbserver"
This test unloads a shared library and expects breakpoints within the
shared library to enter the PENDING state (because the bp_location's
shlib_disabled flag will be set). However, the new call to
breakpoint_re_set means that this is no longer the case.
The breakpoint_re_set call means that update_breakpoint_locations is
called, which then checks if all locations for a breakpoint are
pending or not. In this test not all locations are pending, and so
GDB recalculates the locations of each breakpoint, this means that
pending locations are discarded.
There is a but report PR gdb/32404 which mentions the problems with
shlib_disabled pending breakpoints, and how they are prone to being
randomly deleted if the user can cause GDB to trigger a call to
breakpoint_re_set. This patch just adds another call to
breakpoint_re_set, which triggers this bug in this one test case.
For now I have marked this test as KFAIL. I do plan to try and
address the pending (shlib_disabled) breakpoint problem in the future,
but I'm not sure when that will be right now.
There are, of course, tests to cover all these cases.
During review I was pointed at bug PR gdb/32079 as something that this
commit might fix, or help in fixing.
And this commit is part of the fix for that bug, but is not the
complete solution. However, the remaining parts of the fix for that
bug are not really related to the content of this commit.
The problem in PR gdb/32079 is that the inferior maps multiple copies
of libc in different linker namespaces using dlmopen (actually libc is
loaded as a consequence of loading some other library into a different
namespace, but that's just a detail). The user then uses a 'next'
command to move the inferior forward.
GDB sets up internal breakpoints on the longjmp symbols, of which
there are multiple copies (there is a copy in every loaded libc).
However, the 'next' command is, in the problem case, stepping over a
dlclose call which unloads one of the loaded libc libraries.
In current HEAD GDB in solib_add we fail to call breakpoint_re_set()
when the library is unloaded; breakpoint_re_set() would delete and
then recreate the longjmp breakpoints. As breakpoint_re_set() is not
called GDB thinks that the the longjmp breakpoint in the now unloaded
libc still exists, and is still inserted.
When the inferior stops after the 'next' GDB tries to delete and
remove the longjmp breakpoint which fails as the libc in which the
breakpoint was inserted is no longer mapped in.
When the user tries to 'next' again GDB tries to re-insert the still
existing longjmp breakpoint which again fails as the memory in which
the b/p should be inserted is no longer part of the inferior memory
space.
This commit helps a little. Now when the libc library is unmapped GDB
does call breakpoint_re_set(). This deletes the longjmp breakpoints
including the one in the unmapped library, then, when we try to
recreate the longjmp breakpoints (at the end of breakpoint_re_set) we
don't create a b/p in the now unmapped copy of libc.
However GDB does still think that the deleted breakpoint is inserted.
The breakpoint location remains in GDB's data structures until the
next time the inferior stops, at which point GDB tries to remove the
breakpoint .... and fails.
However, as the b/p is now deleted, when the user tries to 'next' GDB
no longer tries to re-insert the b/p, and so one of the problems
reported in PR gdb/32079 is resolved.
I'll fix the remaining issues from PR gdb/32079 in a later commit in
this series.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32079
Tested-By: Hannes Domani <ssbssa@yahoo.de>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
gdb/testsuite/rocm.exp: Use system GPU(s) to detect features
Background
----------
This patch revisits the purpose of hcc_amdgpu_targets{} in
order to address the separation of concerns between:
- GPU targets passed to the compiler. This kind of target
is passed as an argument to flags like "--offload-arch=...",
"--targets=...", etc.
- GPU targets as in available GPU devices on the system. This
is crucial for finding which capabilities are available,
and therefore which tests should be executed or skipped.
Code change
-----------
- A new "find_amdgpu_devices{}" procedure is added. It is
responsible for listing the GPU devices that are available
on the system.
- "hcc_amdgpu_targets{}" is rewritten to use the newly added
"find_amdgpu_devices{}" when there's no environment variable
(HCC_AMDGPU_TARGET) set.
- The output of "hcc_amdgpu_targets{}" is now only used in
places that set the target for the building toolchains.
- The output of "find_amdgpu_devices{}" is used anywhere that
needs to evaluate the GPU features.
Approved-By: Lancelot Six <lancelot.six@amd.com> (amdgpu)
Change-Id: Ib11021dbe674aa40192737ede78284a1bc531513
|
|
While working on another series, I discovered that the existing code
in gdb.ada/complete.exp that conditionally accepts a completion does
not work correctly. The code assumes that wrapping a line in "(...)?"
will make the entire line optional, but really this will only match a
blank line.
Meanwhile, I needed this same patch for a second series I'm working
on, so I've pulled this out. As it only affects Ada, I am going to
check it in.
|
|
Now that stabs is deprecated, we should probably warn our users of it
before removing support, so that they have time to react and either make
themselves heard, or fix things on their end so that they can still debug
their applications.
This commit adds a new function that emits a warning whenever GDB does
stabs reading. Since there are several places where stabs is
re-invented, this warning had to be added to many places, but I think I
managed to warn everywhere relevant without duplicating warnings.
Also, the test gdb.stabs/weird.exp explicitly checks for GDB warnings
when reading stabs, so it had to be updated to account for the
deprecation warning. It is done generically, since it will be removed in
the next release anyway.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
When using the MI interpreter, if someone was to attach to a ROCm
process which has active GPU waves, GDB would issue a segfault as
follows:
attach 1994813
&"attach 1994813\n"
~"Attaching to process 1994813\n"
=thread-group-started,id="i1",pid="1994813"
=thread-created,id="1",group-id="i1"
=thread-created,id="2",group-id="i1"
~"[New LWP 1994828]\n"
*running,thread-id="2"
=thread-created,id="3",group-id="i1"
~"[New LWP 1994825]\n"
*running,thread-id="3"
=thread-created,id="4",group-id="i1"
~"[New LWP 1994823]\n"
*running,thread-id="4"
^done
=library-loaded,...
[...]
~"[Thread debugging using libthread_db enabled]\n"
~"Using host libthread_db library \"/lib/x86_64-linux-gnu/libthread_db.so.1\".\n"
=thread-created,id="5",group-id="i1"
&"\n\n"
&"Fatal signal: "
&"Segmentation fault"
&"\n"
&"----- Backtrace -----\n"
&"Backtrace unavailable\n"
&"---------------------\n"
&"A fatal error internal to GDB has been detected, further\ndebugging is not possible. GDB will now terminate.\n\n"
&"This is a bug, please report it."
&" For instructions, see:\n"
&"<https://github.com/ROCm-Developer-Tools/ROCgdb/issues>"
&"."
&"\n\n"
Segmentation fault
The issue comes from using a non-initialized pointer in mi_on_resume_1:
if (!mi->running_result_record_printed && mi->mi_proceeded)
{
gdb_printf (mi->raw_stdout, "%s^running\n",
mi->current_token ? mi->current_token : "");
}
In this instance, "mi->current_token" has an uninitialized value. This is a
regression introduced by:
commit def2803789208a617c429b5dcf2026decb25ce0c
Date: Wed Sep 6 11:02:00 2023 -0400
gdb/mi: make current_token a field of mi_interp
Before this patch, current_token was a global implicitly 0-initialized. Since
it is now a class field, it is not 0-initialized by default anymore. This
patch changes this.
Change-Id: I3f00b080318a70405d881ff0abe02b2c5cb1f9d8
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Approved-By: Tom Tromey <tom@tromey.com>
|
|
If there is a large number of threads in the input program, the expect
buffer in `get_mi_thread_list` would become full. Prevent this by
consuming the buffer in small pieces.
Regression-tested using the gdb.mi tests.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
|
In test-case gdb.base/gstack.exp we start a gdb implicitly using
prepare_for_testing.
The gdb is not really used, but its spawn_id (available in variable
gdb_spawn_id) is used in a gdb_test_multiple, which is used to interact with
the gstack process.
Usually, a running gdb is cleaned up at test-case exit in gdb_finish, which
calls gdb_exit, which by default calls gdb_default_exit, which does
'send_gdb "quit\n"'.
However, this sends a quit to the host process expect is currently talking to,
defined by board_info(host,fileid), and after spawning gstack that's gstack, not
gdb.
Fix this by:
- using build_executable instead of prepare_for_testing to not spawn an unused
gdb, and
- changing the gdb_test_multiple into a gdb_expect, eliminating the implicit use
of gdb_spawn_id.
Tested on x86_64-linux.
Reviewed-By: Keith Seitz <keiths@redhat.com>
PR testsuite/32709
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32709
|
|
Fix typos:
...
overriden -> overridden
reate -> create
...
Tested on x86_64-linux.
I
|
|
The `get_mi_thread_list` procedure's body is incorrectly indented.
Fix it.
There is one line that was already long. Consider it an exception and
don't bother breaking it.
|
|
The -taso switch was quite useful 25 years ago for porting 32-bit
code with broken integer-pointer casting. Not anymore. The EF_ALPHA_32BIT
Linux support is going to be dropped in kernel v6.14 [1], NetBSD and OpenBSD
never had it, so there is no point in keeping the -taso option around.
Also remove alpha special case that uses -taso from gdb.base/dump.exp
in gdb testsuite.
[1] https://lore.kernel.org/all/87jzb2tdb7.fsf_-_@email.froward.int.ebiederm.org
Signed-off-by: Ivan Kokshaysky <ink@unseen.parts>
Reviewed-By: Maciej W. Rozycki <macro@orcam.me.uk>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
The top comment in gdb.python/py-source-styling.exp was completely
wrong, clearly a cut&paste job from elsewhere. Write a comment that
actually reflects what the test does.
I've also moved the allow_python_tests check earlier in the file.
And I changed some 'return -1' into just 'return'. I'm not aware that
the '-1' adds any value.
I also folded a 'pass $gdb_test_name' into the preceding gdb_assert,
which I think is neater.
There is no change in what is actually being tested after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
I noticed that, with recent versions of GDB, when the TUI is enabled
before the inferior is started, the source code display is not as
helpful as it used to be. Here's a simple test program being
displayed using GDB 15.2, at this point the inferior has not started,
all I've done is 'tui enable':
┌─hello.c────────────────────────────────────────────────┐
│ 10 return 0; │
│ 11 } │
│ 12 │
│ 13 /* The main function. */ │
│ 14 │
│ 15 int │
│ 16 main () │
│ 17 { │
│ 18 printf ("Hello World\n"); │
│ 19 call_me ( 0, 1, 2, 3, 4, 5, 6, 7 ); │
│ 20 return 0; │
│ 21 } │
│ │
│ │
└────────────────────────────────────────────────────────┘
Compare this to GDB 16.2:
┌─hello.c────────────────────────────────────────────────┐
│ 17 { │
│ 18 printf ("Hello World\n"); │
│ 19 call_me ( 0, 1, 2, 3, 4, 5, 6, 7 ); │
│ 20 return 0; │
│ 21 } │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
└────────────────────────────────────────────────────────┘
I think the new layout is not as good because it is missing the
context of the function name. The new behaviour started with the
commit:
commit 49e607f511c1fab82a0116990a72d1915c74bb4a
Author: Stephan Rohr <stephan.rohr@intel.com>
Date: Sat Aug 3 02:07:42 2024 -0700
gdb: adjust the default place of 'list' to main's prologue
I don't think the new behaviour is really a problem with that commit,
rather, when using 'tui enable' before the inferior has started GDB
ends up calling tui_source_window_base::rerender(), and then passes
through the code path which calls update_source_window_with_addr().
When using 'tui enable' after the inferior has started, GDB again
calls tui_source_window_base::rerender(), but this time has a frame,
and so takes the second code path, which centres the selected source
line, and then calls update_source_window.
The point is that the update_source_window_with_addr() path doesn't
include the logic to centre the source line.
Before the above commit this was fine as GDB's default location would
be prior to main, and so we got the "good" TUI output. After the
above commit the default location is now main's prologue, and without
the centring logic, the first line shown is main's prologue.
I propose fixing this by having update_source_window_with_addr() call
maybe_update(). This will first check if the requested line is
already visible, and if not, show the requested line with centring
applied.
After this commit, the 'tui enable' state is now:
┌─hello.c─────────────────────────────────────────────────────┐
│ 11 } │
│ 12 │
│ 13 /* The main function. */ │
│ 14 │
│ 15 int │
│ 16 main () │
│ 17 { │
│ 18 printf ("Hello World\n"); │
│ 19 call_me ( 0, 1, 2, 3, 4, 5, 6, 7 ); │
│ 20 return 0; │
│ 21 } │
│ │
│ │
│ │
└─────────────────────────────────────────────────────────────┘
It's not identical to the old behaviour, but that was never the
objective, we do however, see the context around main's prologue,
which will usually be enough to see the function name and return type,
which I think is useful.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
While working on another patch which changes how we parse the line
DWARF line tables I noticed what I think is a minor bug in how we
process the line tables.
What I noticed is that my new line table parser was adding more END
markers into the parsed table than GDB's current approach. This
difference was observed when processing the debug information for
libstdc++.
Here is the line table from the new test, this is a reasonable
reproduction of the problem case that I observed in the actual debug
line table:
Contents of the .debug_line section:
dw2-skipped-line-entries-1.c:
File name Line number Starting address View Stmt
dw2-skipped-line-entries-1.c 101 0x40110a x
/tmp/dw2-skipped-line-entries-2.c:
dw2-skipped-line-entries-2.c 201 0x401114 x
/tmp/dw2-skipped-line-entries-3.c:
dw2-skipped-line-entries-3.c 301 0x40111e x
/tmp/dw2-skipped-line-entries-1.c:
dw2-skipped-line-entries-1.c 102 0x401128 x
dw2-skipped-line-entries-1.c 103 0x401128 x
dw2-skipped-line-entries-1.c 104 0x401128 x
/tmp/dw2-skipped-line-entries-2.c:
dw2-skipped-line-entries-2.c 211 0x401128
/tmp/dw2-skipped-line-entries-3.c:
dw2-skipped-line-entries-3.c 311 0x401132
/tmp/dw2-skipped-line-entries-1.c:
dw2-skipped-line-entries-1.c 104 0x40113c
dw2-skipped-line-entries-1.c 105 0x401146 x
dw2-skipped-line-entries-1.c - 0x401150
The problem is caused by the entry for line 211. Notice that this
entry is at the same address as the previous entries. Further, the
entry for 211 is a non-statement entry, while the previous entries are
statement entries.
As the entry for line 211 is a non-statement entry, and the previous
entries at that address are statement entries in a different symtab,
it is thought that it is better to prefer the earlier entries (in
dw2-skipped-line-entries-1.c), and so the entry for line 211 will be
discarded.
As GDB parses the line table it switches between the 3 symtabs (based
on source filename) adding the relevant entries to each symtab.
Additionally, as GDB switches symtabs, it adds an END entry to the
previous symtab.
The problem then is that, for the line 211 entry, this is the only
entry in dw2-skipped-line-entries-2.c before we switch symtab again.
But the line 211 entry is discarded. This means that GDB switches
from dw2-skipped-line-entries-1.c to dw2-skipped-line-entries-2.c, and
then on to dw2-skipped-line-entries-3.c without ever adding an entry
to dw2-skipped-line-entries-2.c.
And here then is the bug. GDB updates its idea of the previous symtab
not when an entry is written into a symtab, but every time we change
symtab.
In this case, when we switch to dw2-skipped-line-entries-3.c we add
the END marker to dw2-skipped-line-entries-2.c, even though no entries
were written to dw2-skipped-line-entries-2.c. At the same time, no
END marker is ever written into dw2-skipped-line-entries-1.c as the
dw2-skipped-line-entries-2.c entry (for line 211) was discarded.
Here is the 'maint info line-table' for dw2-skipped-line-entries-1.c
before this patch:
INDEX LINE REL-ADDRESS UNREL-ADDRESS IS-STMT PROLOGUE-END EPILOGUE-BEGIN
0 101 0x000000000040110a 0x000000000040110a Y
1 END 0x0000000000401114 0x0000000000401114 Y
2 102 0x0000000000401128 0x0000000000401128 Y
3 103 0x0000000000401128 0x0000000000401128 Y
4 104 0x0000000000401128 0x0000000000401128 Y
5 104 0x000000000040113c 0x000000000040113c
6 105 0x0000000000401146 0x0000000000401146 Y
7 END 0x0000000000401150 0x0000000000401150 Y
And after this patch:
INDEX LINE REL-ADDRESS UNREL-ADDRESS IS-STMT PROLOGUE-END EPILOGUE-BEGIN
0 101 0x000000000040110a 0x000000000040110a Y
1 END 0x0000000000401114 0x0000000000401114 Y
2 102 0x0000000000401128 0x0000000000401128 Y
3 103 0x0000000000401128 0x0000000000401128 Y
4 104 0x0000000000401128 0x0000000000401128 Y
5 END 0x0000000000401132 0x0000000000401132 Y
6 104 0x000000000040113c 0x000000000040113c
7 105 0x0000000000401146 0x0000000000401146 Y
8 END 0x0000000000401150 0x0000000000401150 Y
Notice that we gained an extra entry, the END marker that was added at
position #5 in the table.
Now, does this matter? I cannot find any bugs that trigger because of
this behaviour.
So why fix it? First, the current behaviour is inconsistent, as we
switch symtabs, we usually get an END marker in the previous symtab.
But occasionally we don't. I don't like things that are inconsistent
for no good reason. And second, as I said, I want to change the line
table parsing. To do this I want to check that my new parser creates
an identical table to the current parser. But my new parser naturally
"fixes" this inconsistency, so I have two choices, do extra work to
make my new parser bug-compatible with the current one, or fix the
current one. I'd prefer to just fix the current line table parser.
There's a test that includes the above example and checks that the END
markers are put in the correct place. But as I said, I've not been
able to trigger any negative behaviour from the current solution, so
there's no test that exposes any broken behaviour.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
The current py-symbol.exp test makes an assumption about which symbol
will be returned first. I don't think gdb should really make promises
about the order in which the symbols are listed, though, and a series
I am working on changes this behavior. This patch changes the test to
merely ensure that both symbols are returned.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
|
The procedures set_sanitizer_1, set_sanitizer and set_sanitizer_default
are used for the configuration of ASAN specific environment variables.
However, they are actually generic. Rename them to append_environment*
so that their purpose is more clear.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
Tom de Vries pointed out that commit 8cfa1fc4 ("Reorder gnatmake
arguments in inline-section-gc.exp") caused a regression with an older
version of dejagnu.
This patch works around that problem by further reordering the
arguments to gnatmake and also arranging to leave gnatmake in "-margs"
mode.
|
|
I noticed that gdb/testsuite/lib/gnat_debug_info_test.adb is missing a
copyright header. This adds one, using the date range from the
original commit.
|
|
New in v2:
- install address map in a single shard
- update test gdb.mi/mi-sym-info.exp to cope with the fact that
different symbols could be returned when using --max-results
When playing with the .debug_names reader, I noticed it was
significantly slower than the DWARF scanner. Using a "performance"
build of GDB (with optimization, no runtime sanitizer enabled, etc), I
measure with the following command on a rather large debug info file
(~4 GB):
$ time ./gdb -q -nx --data-directory=data-directory <binary> -iex 'maint set dwarf sync on' -batch
This measures the time it takes for GDB to build the cooked index (plus
some startup and exit overhead). I have a version of the binary without
.debug_names and a version with .debug_names added using gdb-add-index.
The results are:
- without .debug_names: 7.5 seconds
- with .debug_names: 24 seconds
This is a bit embarrassing, given that the purpose of .debug_names is to
accelerate things :). The reason is that the .debug_names processing is
not parallelized at all, while the DWARF scanner is heavily
parallelized.
The process of creating the cooked index from .debug_names is roughly in
two steps:
1. scanning of .debug_names and creation of cooked index entries (see
mapped_debug_names_reader::scan_all_names)
2. finalization of the index, name canonicalization and sorting of the
entries (see cooked_index::set_contents).
This patch grabs a low hanging fruit by creating multiple cooked index
shards instead of a single one during step one. Just doing this allows
the second step of the processing to be automatically parallelized, as
each shard is sent to a separate thread to be finalized.
With this patch, I get:
- without .debug_names: 7.5 seconds
- with .debug_names: 9.7 seconds
Not as fast as we'd like, but it's an improvement.
The process of scanning .debug_names could also be parallelized to shave
off a few seconds. My profiling shows that out of those ~10 seconds of
excecution, about 6 are inside scan_all_names. Assuming perfect
parallelization with 8 threads, it means that at best we could shave
about 5 seconds from that time, which sounds interesting. I gave it a
shot, but it's a much more intrusive change, I'm not sure if I will
finish it.
This patch caused some regressions in gdb.mi/mi-sym-info.exp with the
cc-with-debug-names board, in the test about the `--max-results` switch.
It appears at this test is relying on the specific symbols returned when
using `--max-results`. As far as I know, we don't guarantee which
specific symbols are returned, so any of the matching symbols could be
returned.
The round robin method used in this patch to assign index entries to
shards ends up somewhat randomizing which CU gets expanded first during
the symbol search, and therefore which order they appear in the
objfile's CU list, and therefore which one gets searched first.
I meditated on whether keeping compunits sorted within objfiles would
help make things more stable and predictable. It would somewhat, but it
wouldn't remove all sources of randomness. It would still possible for
a call to `expand_symtabs_matching` to stop on the first hit. Which
compunit gets expanded then would still be dependent on the specific
`quick_symbol_functions` internal details / implementation.
Commit 5b99c5718f1c ("[gdb/testsuite] Fix various issues in
gdb.mi/mi-sym-info.exp") had already started to make the test a bit more
flexible in terms of which symbols it accepts, but with this patch, I
think it's possible to get wildly varying results. I therefore modified
the test to count the number of returned symbols, but not expect any
specific symbol.
Change-Id: Ifd39deb437781f72d224ec66daf6118830042941
Approved-By: Tom Tromey <tom@tromey.com>
|
|
I noticed that attempting to select a tail-call frame using 'frame
function NAME' wouldn't work:
(gdb) bt
#0 func_that_never_returns () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/frame-selection.c:49
#1 0x0000000000401183 in func_that_tail_calls () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/frame-selection.c:59
#2 0x00000000004011a5 in main () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/frame-selection.c:70
(gdb) frame function func_that_tail_calls
No frame for function "func_that_tail_calls".
(gdb) up
#1 0x0000000000401183 in func_that_tail_calls () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/frame-selection.c:59
59 func_that_never_returns ();
(gdb) disassemble
Dump of assembler code for function func_that_tail_calls:
0x000000000040117a <+0>: push %rbp
0x000000000040117b <+1>: mov %rsp,%rbp
0x000000000040117e <+4>: call 0x40116c <func_that_never_returns>
End of assembler dump.
(gdb)
The problem is that the 'function' mechanism uses get_frame_pc() and
then compares the address returned with the bounds of the function
we're looking for.
So in this case, the bounds of func_that_tail_calls are 0x40117a to
0x401183, with 0x401183 being the first address _after_ the function.
However, because func_that_tail_calls ends in a tail call, then the
get_frame_pc() is 0x401183, the first address after the function. As
a result, GDB fails to realise that frame #1 is inside the function
we're looking for, and the lookup fails.
The fix is to use get_frame_address_in_block, which will return an
adjusted address, in this case, 0x401182, which is within the function
bounds. Now the lookup works:
(gdb) frame function func_that_tail_calls
#1 0x0000000000401183 in func_that_tail_calls () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/frame-selection.c:59
59 func_that_never_returns ();
(gdb)
I've extended the gdb.base/frame-selection.exp test to cover this
case.
|
|
In a different series I tweak how disabled_by_cond is handled in
update_breakpoint_locations for code_breakpoint objects, see:
https://inbox.sourceware.org/gdb-patches/cover.1734366277.git.aburgess@redhat.com
But when I did this I ran into a regression in the test script
gdb.base/condbreak-multi-context.cc which I think is actually an issue
with this test.
The test relies on creating a multi-location breakpoint with a
condition and having GDB disable some of the locations as the
condition is only valid in some of the locations.
Here's an example of the test creating one such breakpoint:
Reading symbols from /tmp/build/gdb/testsuite/outputs/gdb.base/condbreak-multi-context/condbreak-multi-context...
(gdb) break func if a == 10
warning: failed to validate condition at location 1, disabling:
No symbol "a" in current context.
warning: failed to validate condition at location 3, disabling:
No symbol "a" in current context.
Breakpoint 1 at 0x401142: func. (3 locations)
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
stop only if a == 10
1.1 N* 0x0000000000401142 in Base::func() at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/condbreak-multi-context.cc:23
1.2 y 0x000000000040114e in A::func() at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/condbreak-multi-context.cc:31
1.3 N* 0x000000000040115a in C::func() at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/condbreak-multi-context.cc:39
(*): Breakpoint condition is invalid at this location.
(gdb)
Notice that only location 1.2 is actually enabled, 1.1 and 1.3 are
disabled due to the condition 'a == 10' not being valid.
However, notice that this b/p is created before GDB has started the
inferior. What I noticed is that if I first start the inferior then I
get a different behaviour:
Reading symbols from /tmp/build/gdb/testsuite/outputs/gdb.base/condbreak-multi-context/condbreak-multi-context...
(gdb) start
Temporary breakpoint 1 at 0x40110e: file /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/condbreak-multi-context.cc, line 49.
Starting program: /tmp/build/gdb/testsuite/outputs/gdb.base/condbreak-multi-context/condbreak-multi-context
Temporary breakpoint 1, main () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/condbreak-multi-context.cc:49
49 aobj.func ();
(gdb) break func if a == 10
Breakpoint 2 at 0x401142: func. (3 locations)
(gdb) info breakpoints
Num Type Disp Enb Address What
2 breakpoint keep y <MULTIPLE>
stop only if a == 10
2.1 y 0x0000000000401142 in Base::func() at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/condbreak-multi-context.cc:23
2.2 y 0x000000000040114e in A::func() at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/condbreak-multi-context.cc:31
2.3 y 0x000000000040115a in C::func() at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/condbreak-multi-context.cc:39
(gdb)
Notice that now all three locations are valid.
What's actually happening is that, on my machine libm.so contains a
global symbol 'a' which for 2.1 and 2.3 is being used to satisfy the
condition.
I don't believe this is actually the intention of the test, this is
just an unfortunate consequence of name collision.
The test actually relies on the local variables 'a' and 'c', and my
libm.so contains a global version of both.
So I propose that we just update the test, I've gone for the super
inventive 'aaa' and 'ccc'. With this change, after starting the
inferior I now see the expected behaviour where only one of the three
locations is enabled.
However, while I'm fixing this I figure that it would be nice if the
test checked both cases, creating the breakpoints before starting the
inferior, and after starting the inferior.
So I've updated the test to check both cases. This has meant
converting the mostly linear test script into a set of parameterised
functions which I then call with a flag to indicate if the inferior
should be started before of after creating the breakpoints.
Approved-By: Tom Tromey <tom@tromey.com>
Tested-By: Hannes Domani <ssbssa@yahoo.de>
|
|
Having looked at the dlmopen support in GDB, it occurred to me that
the current MI =library-unloaded event doesn't incude enough
information to be useful.
Consider the gdb.mi/mi-dlmopen.exp test, this test loads libraries
into multiple linker namespaces, and then unloads these libraries.
We should probably figure out a way to include the linker namepsace ID
in GDB's output, e.g. in the =library-loaded and =library-unloaded MI
events, and in the output of 'info sharedlibrary'. But this commit is
not about doing that.
This commit includes the 'ranges' information in the =library-unloaded
event output. This is the same ranges information as is included in
the =library-loaded output. Even without the linker namespace ID,
this should allow MI consumers to figure out which library instance is
being unloaded.
Here is the 'info sharedlibrary' output for mi-dlmopen.exp at the
point where all the shared libraries are loaded:
info sharedlibrary
&"info sharedlibrary\n"
~"From To Syms Read Shared Object Library\n"
~"0x00007ffff7fca000 0x00007ffff7ff03f5 Yes /lib64/ld-linux-x86-64.so.2\n"
~"0x00007ffff7eda3d0 0x00007ffff7f4e898 Yes /lib64/libm.so.6\n"
~"0x00007ffff7d0e800 0x00007ffff7e6dccd Yes /lib64/libc.so.6\n"
~"0x00007ffff7fbd040 0x00007ffff7fbd116 Yes /tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so\n"
~"0x00007ffff7fb8040 0x00007ffff7fb80f9 Yes /tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so\n"
~"0x00007ffff7bfe3d0 0x00007ffff7c72898 Yes /lib64/libm.so.6\n"
~"0x00007ffff7a32800 0x00007ffff7b91ccd Yes /lib64/libc.so.6\n"
~"0x00007ffff7fca000 0x00007ffff7ff03f5 Yes /lib64/ld-linux-x86-64.so.2\n"
~"0x00007ffff7fb3040 0x00007ffff7fb3116 Yes /tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so\n"
~"0x00007ffff7fae040 0x00007ffff7fae0f9 Yes /tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so\n"
~"0x00007ffff7ce1040 0x00007ffff7ce1116 Yes /tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so\n"
~"0x00007ffff7cdc040 0x00007ffff7cdc0f9 Yes /tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so\n"
~"0x00007ffff79253d0 0x00007ffff7999898 Yes /lib64/libm.so.6\n"
~"0x00007ffff7759800 0x00007ffff78b8ccd Yes /lib64/libc.so.6\n"
~"0x00007ffff7fca000 0x00007ffff7ff03f5 Yes /lib64/ld-linux-x86-64.so.2\n"
~"0x00007ffff7cd7040 0x00007ffff7cd7116 Yes /tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.2.so\n"
^done
(gdb)
Notice that dlmopen-lib.1.so is loaded multiple times. Here is the
=library-unloaded event when one copy of this library is unloaded
before this patch:
=library-unloaded,id="/tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so",
target-name="/tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so",
host-name="/tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so",
thread-group="i1",
It is not possible, given this information, to know which copy of
dlmopen-lib.1.so has actually been unloaded. An MI consumer would
need to query the full shared library list and update from that
information.
After this patch the new output is:
=library-unloaded,id="/tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so",
target-name="/tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so",
host-name="/tmp/build/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so",
thread-group="i1",
ranges=[{from="0x00007ffff7fbd040",to="0x00007ffff7fbd116"}],
still-in-use="false"
The new 'ranges' field allows an MI consumer to uniquely identify
which library instance was just unmapped. A frontent could,
e.g. update a library list with no need to query the full shared
library list.
To include the 'ranges' field I updated mi_interp::on_solib_unloaded
to call a new helper function. The new helper function is split out
from the existing mi_output_solib_attribs. I was tempted to just call
mi_output_solib_attribs, but doing so would mean that the
'symbols-loaded' field was also added to the =library-unloaded event,
however, the docs for 'symbols-unloaded' on =library-loaded says:
The @var{symbols-loaded} field is emitted only for backward
compatibility and should not be relied on to convey any useful
information.
And it seemed silly to add a fields to =library-unloaded, which I
would then document as something that should be ignored. The new
helper function means I can avoid emitting the 'symbols-loaded'
field.
I have also added a 'still-in-use' field. When true this indicates
that the library was removed from the inferior's library list, but the
mapping was not removed from the inferior's address space as there is
another copy of the library that is still using the library. In the
above list, notice that ld-linux-x86-64.so.2 appears 3 times, but each
instance is mapped as 0x00007ffff7fca000. When one copy of
ld-linux-x86-64.so.2 is unloaded, here's the event:
=library-unloaded,id="/lib64/ld-linux-x86-64.so.2",
target-name="/lib64/ld-linux-x86-64.so.2",
host-name="/lib64/ld-linux-x86-64.so.2",
thread-group="i1",
ranges=[{from="0x00007ffff7fca000",to="0x00007ffff7ff03f5"}],
still-in-use="true"
The 'still-in-use' field is 'true', this indicates there are at least
one instance of this library remaining mapped at 0x00007ffff7fca000.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
|
|
Consider the gdb.base/dlmopen.exp test case. The executable in this
test uses dlmopen to load libraries into multiple linker namespaces.
When a library is loaded into a separate namespace, its dependencies
are also loaded into that namespace.
This means that an inferior can have multiple copies of some
libraries, including the dynamic linker, loaded at once.
However, glibc optimises at least the dynamic linker case. Though the
library appears to be mapped multiple times (it is in the inferior's
solib list multiple times), there is really only one copy mapped into
the inferior's address space. Here is the 'info sharedlibrary' output
on an x86-64/Linux machine once all the libraries are loaded:
(gdb) info sharedlibrary
From To Syms Read Shared Object Library
0x00007ffff7fca000 0x00007ffff7ff03f5 Yes /lib64/ld-linux-x86-64.so.2
0x00007ffff7eda3d0 0x00007ffff7f4e898 Yes /lib64/libm.so.6
0x00007ffff7d0e800 0x00007ffff7e6dccd Yes /lib64/libc.so.6
0x00007ffff7fbd040 0x00007ffff7fbd116 Yes /tmp/build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.1.so
0x00007ffff7fb8040 0x00007ffff7fb80f9 Yes /tmp/build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.so
0x00007ffff7bfe3d0 0x00007ffff7c72898 Yes /lib64/libm.so.6
0x00007ffff7a32800 0x00007ffff7b91ccd Yes /lib64/libc.so.6
0x00007ffff7fca000 0x00007ffff7ff03f5 Yes /lib64/ld-linux-x86-64.so.2
0x00007ffff7fb3040 0x00007ffff7fb3116 Yes /tmp/build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.1.so
0x00007ffff7fae040 0x00007ffff7fae0f9 Yes /tmp/build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.so
0x00007ffff7ce1040 0x00007ffff7ce1116 Yes /tmp/build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.1.so
0x00007ffff7cdc040 0x00007ffff7cdc0f9 Yes /tmp/build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.so
0x00007ffff79253d0 0x00007ffff7999898 Yes /lib64/libm.so.6
0x00007ffff7759800 0x00007ffff78b8ccd Yes /lib64/libc.so.6
0x00007ffff7fca000 0x00007ffff7ff03f5 Yes /lib64/ld-linux-x86-64.so.2
0x00007ffff7cd7040 0x00007ffff7cd7116 Yes /tmp/build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.2.so
Notice that every copy of /lib64/ld-linux-x86-64.so.2 is mapped at the
same address.
As the inferior closes the libraries that it loaded, the various
copies of the dynamic linker will also be unloaded.
Currently, when this happens GDB calls notify_solib_unloaded, which
triggers the gdb::observers::solib_unloaded observer. This observer
will call disable_breakpoints_in_unloaded_shlib (in breakpoint.c),
which disables any breakpoints in the unloaded solib.
The problem with this, is that, when the dynamic linker (or any solib)
is only really mapped once as is the case here, we only want to
disable breakpoints in the library when the last instance of the
library is unloaded.
The first idea that comes to mind is that GDB should not emit the
solib_unloaded notification if a shared library is still in use,
however, this could break MI consumers.
Currently, every time a copy of ld-linux-x86-64.so.2 is unloaded,
GDB's MI interpreter will emit a =library-unloaded event. An MI
consumer might use this to update the library list that it displays to
the user, and fewer notify_solib_unloaded calls will mean fewer MI
events, which will mean the MI consumer's library list could get out
of sync with GDB.
Instead I propose that we extend GDB's solib_unloaded event to add a
new flag. The new flag indicates if the library mapping is still in
use within the inferior. Now the MI will continue to emit the
expected =library-unloaded events, but
disable_breakpoints_in_unloaded_shlib can check the new flag, when it
is true (indicating that the library is still mapped into the
inferior), no breakpoints should be disabled.
The other user of the solib_unloaded observer, in bsd-uthread.c,
should, I think, do nothing if the mapping is still in use. This
observer is also disabling breakpoints when a library is unloaded.
Most of the changes in this commit relate to passing the new flag
around for the event. The interesting changes are mostly in solib.c,
where the flag value is determined, and in breakpoint.c and
bsd-uthread.c, where the flag value is read.
There's a new MI test, the source of which is mostly copied from the
gdb.base/dlmopen.exp test. This new test is checking we see all the
expected =library-unloaded events.
|
|
In the next commit I want to add more tests to the dlmopen.exp script.
Doing this will be easier if the dlmopen.exp script was structured so
that the current tests were contained inside separatate procs. So
this commit moves all of the current tests within dlmopen into two
procs, and then calls these.
There should be no changes to what is actually being tested in this
commit.
|
|
I (Andrew Burgess) have taken this patch from this series:
https://inbox.sourceware.org/gdb-patches/20211022071933.3478427-1-m.weghorn@posteo.de/
I started off reviewing that series, but wanted to explore some
alternative strategies for solving the problems this series addresses.
However, this patch I think is super useful, so I've taken it mostly
as it was in the original series.
I have made a few minor cleanups, and I've also added some more tests.
Any bugs should be considered mine (Andrew's), but I've left the
original author (Michael Weghorn) in place as the GDB side changes are
mostly their work.
The function execv_argv::init_for_no_shell (gdb/nat/fork-inferior.c),
is passed a single string ALLARGS containing all of the inferior
arguments, and contains some custom code for splitting this argument
string into a vector of separate arguments. This function is used
when startup-with-shell is off (which is not the default).
The algorithm in this function was just splitting on whitespace
characters, and ignoring any quoting, so for example:
(gdb) set startup-with-shell off
(gdb) set args "first arg" second_arg
would result in three arguments ("first), (arg"), and (second_arg)
being passed to the inferior (the parenthesis are not part of the
parsed arguments).
This commit replaces this custom argument splitting with a use of the
existing gdb_argv class (which uses the libiberty buildargv function).
This does a better job of supporting quoting and escaping, so for the
example given above we now pass two arguments (first arg)
and (second_arg), which is certainly what I would have expected as a
GDB user.
This commit changes the 'execv_argv' class accordingly and drops the
optimization to have all the 'char *' in 'm_argv' point to a single
string rather than allocating a separate string for each arg. This is
needed because we are now going to be stripping some escaping from the
arguments, for example:
(gdb) set startup-with-shell off
(gdb) set args "literal \$"
In this case we will pass the single argument (literal $) to the
inferior, the escaping backslash will be removed. This might seem
strange as usually the backslash would be stripped by the shell, and
now we have no shell. However, I think the consistent behaviour is a
good thing; whether we start with a shell or not the escaping will be
removed.
Using gdb_argv will mean that quote characters are also stripped. If
we consider the first example again:
(gdb) set startup-with-shell off
(gdb) set args "first arg" second_arg
This is now going to pass (first arg) and (second_arg), the quotes
have been removed. If the user did want the original behaviour then
they are going to have to now do this:
(gdb) set startup-with-shell off
(gdb) set args \"first arg\" second_arg
or they could do this:
(gdb) set startup-with-shell off
(gdb) set args '"first' 'arg"' second_arg
This commit also extends the three tests that cover inferior argument
passing to cover the case where 'startup-with-shell' is off. All of
these new tests pass for native targets, but there are still problems
when using remote targets.
The remote target problems arise because of how escaping is handled
while passing arguments to remote targets. I have a larger series
that aims to address this issue:
https://inbox.sourceware.org/gdb-patches/cover.1730731085.git.aburgess@redhat.com
This patch was originally part of that series, but getting a 14 patch
series reviewed is not easy, so I've pulled this patch out on its own
for now, and the new tests are (rather crudely) disabled for remote
targets.
My hope is to work through my 14 patch series posting all of the
patches in smaller groups, which will hopefully make reviewing
easier. As more of that series gets merged, the remote argument
handling will improve, before, eventually, no tests will need to be
disabled.
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28392
Tested-By: Guinevere Larsen <guinevere@redhat.com>
Reviewed-By: Keith Seitz <keiths@redhat.com>
|
|
Recent work in the TUI has improved GDB's use of the curses
wnoutrefresh and doupdate mechanism, which improves performance by
batching together updates and then doing a single set of writes to the
screen when doupdate is finally called.
The tui_batch_rendering type is a RAII class which, in its destructor,
calls doupdate to send the batched updates to the screen.
However, if there is no tui_batch_rendering active on the call stack
then any wnoutrefresh calls will remain batched but undisplayed until
the next time doupdate happens to be called.
This problem can be seen in PR gdb/32623. When an inferior is started
the 'Starting program' message is not immediately displayed to the
user.
The 'Starting program' message originates from run_command_1 in
infcmd.c, the message is sent to the current_uiout, which will be the
TUI ui_out. After the message is sent, ui_out::flush() is called,
here's the backtrace when that happens:
#0 tui_file::flush (this=0x36e4ab0) at ../../src/gdb/tui/tui-file.c:42
#1 0x0000000001004f4b in pager_file::flush (this=0x36d35f0) at ../../src/gdb/utils.c:1531
#2 0x0000000001004f71 in gdb_flush (stream=0x36d35f0) at ../../src/gdb/utils.c:1539
#3 0x00000000006975ab in cli_ui_out::do_flush (this=0x35a50b0) at ../../src/gdb/cli-out.c:250
#4 0x00000000009fd1f9 in ui_out::flush (this=0x35a50b0) at ../../src/gdb/ui-out.h:263
#5 0x00000000009f56ad in run_command_1 (args=0x0, from_tty=1, run_how=RUN_NORMAL) at ../../src/gdb/infcmd.c:449
#6 0x00000000009f599a in run_command (args=0x0, from_tty=1) at ../../src/gdb/infcmd.c:511
And if we check out tui_file::flush (tui-file.c) we can see that this
just calls tui_win_info::refresh_window(), which in turn, just uses
wnoutrefresh to batch any pending output.
The problem is that, in the above backtrace, there is no
tui_batch_rendering active, and so there will be no doupdate call to
flush the output to the screen.
We could add a tui_batch_rendering into tui_file::flush. And
tui_file::write. And tui_file::puts .....
... but that all seems a bit unnecessary. Instead, I propose that
tui_win_info::refresh_window() should be changed. If suppress_output
is true (i.e. a tui_batch_rendering is active) then we should continue
to call wnoutrefresh(). But if suppress_output is false, meaning that
no tui_batch_rendering is in place, then we should call wrefresh(),
which immediately writes the output to the screen.
Testing but PR gdb/32623 was a little involved. We need to 'run' the
inferior and check for the 'Starting program' message. But DejaGNUU
can only check for the message once it knows the message should have
appeared. But, as the bug is that output is not displayed, we don't
have any output hints that the inferior is started yet...
In the end, I have the inferior create a file in the test's output
directory. Now DejaGNU can send the 'run' command, and wait for the
file to appear. Once that happens, we know that the 'Starting
program' message should have appeared.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32623
Approved-By: Tom Tromey <tom@tromey.com>
|
|
On ubuntu systems with libc debug info available (libc6-dbg), I see the
following failures for the gdb.base/corefile-exec-context.exp testcase:
show args
Argument list to give program being debugged when it is started is "aaaaa bbbbb ccccc ddddd e\ e\ e\ e\ e".
(gdb) PASS: gdb.base/corefile-exec-context.exp: show args
up
#1 __pthread_kill_internal (signo=6, threadid=133859295332160) at ./nptl/pthread_kill.c:78
78 in ./nptl/pthread_kill.c
(gdb) FAIL: gdb.base/corefile-exec-context.exp: move up to main
This failures is because the pattern used to parse the output of `up`
is not expecting what is seen when debugging information is present for
those frames.
This patch adjusts the pattern to allow both possible outputs.
Tested on ubuntu-22.04 and ubuntu24.04 with libc6-dbg installed for gdb
build with --with-separate-debug-dir=/usr/lib/debug.
Change-Id: I217d4b20006d0ecdb4b7a71eeb8d01597ec5ac63
Approved-By: Tom Tromey <tom@tromey.com>
|
|
When running test-case gdb.base/list-dot-nodebug.exp with target board
cc-with-gnu-debuglink, I run into:
...
(gdb) list .^M
warning: 1 ../sysdeps/x86_64/crtn.S: No such file or directory^M
(gdb) FAIL: gdb.base/list-dot-nodebug.exp: debug=none: print before start
...
The problem is that the call to gdb_gnu_strip_debug in
gdb.base/list-dot-nodebug.exp has no effect, because the target board makes
sure that compilation delivers an executable that is already stripped, with a
.gnu_debuglink section linking to the debug info.
Fix this by using -nostdlib instead of static, which means the call to
gdb_gnu_strip_debug can be removed.
This also allows us to extend the test-case to excercise "list ." before
starting the inferior, for the debug=some scenario, which is currently
skipped:
...
# We don't test "list ." before starting with some debug info
# because GDB will choose the symtab that has debuginfo, and
# print the copyright blurb. This test isn't interested (yet?)
# in checking if this default location choice is consistent.
...
While we're at it, make the effect of "list ." on the current source location
explicit using "info source" before and after "list .".
While we're at it, make sure when running with target board
cc-with-gdb-index or cc-with-debug-names, that the failure to compile the
debug=none variant due to:
...
Error while writing index ...: No debugging symbols
...
doesn't stop the test-case from running the debug=some variant.
Tested on x86_64-linux.
Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
|
|
It is possible to run GDB's testsuite against installed binaries rather
than the one from the build tree. For example, one could do:
$ make check-gdb RUNTESTFLAGS=GDB=/usr/bin/gdb
Running the testsuite this way causes error for gdb.base/gcorebg.exp:
Running [...]/gdb/testsuite/gdb.base/gcorebg.exp ...
FAIL: gdb.base/gcorebg.exp: detached=detached: Spawned gcore finished
FAIL: gdb.base/gcorebg.exp: detached=detached: Core file generated by gcore
FAIL: gdb.base/gcorebg.exp: detached=standard: Spawned gcore finished
FAIL: gdb.base/gcorebg.exp: detached=standard: Core file generated by gcore
This is due to 2 problems.
First, when running this way, the $GDB_DATA_DIRECTORY is not set (on
purpose) as the installed GDB does not need to be specified where to
find it. See this section in gdb/testsuite/lib/gdb.exp:
if ![info exists GDB] {
[....]
} else {
# If the user specifies GDB on the command line, and doesn't
# specify GDB_DATA_DIRECTORY, then assume we're testing an
# installed GDB, and let it use its own configured data directory.
if ![info exists GDB_DATA_DIRECTORY] {
set GDB_DATA_DIRECTORY ""
}
}
The testbg.exp file always assumes a non-empty GDB_DATA_DIRECTORY. As a
consequence, when calling the gcorebg binary with an empty argument
(i.e. missing argument), the program fails:
gcorebg: [...]/gdb/testsuite/gdb.base/gcorebg.c:42: main: Assertion `argc == 5' failed.
FAIL: gdb.base/gcorebg.exp: detached=standard: Spawned gcore finished
This patch does adjust the gcorebg.c and gcorebg.exp files to allow not
specifying the data-directory.
The other issue is that the testsuite assumes that the `gcore` to test
is always the one from the build tree. However, if someone is testing
an installed binary by setting GDB, I think that person would expect to
test the `gcore` script next to the binary that was specified (unless
GCORE is specified to explicitly specified). This patch does that
adjustment as well. To that end, it needs to move the block setting
GCORE after the block setting GDB.
Change-Id: I070e039903c0b5afeac357d8fac7d710ff6697b9
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This commit causes a "process ptid" to be passed to all calls
of target_pid_to_str in linux-fork.c. A "process ptid" is one
in which only the pid component is set to a non-zero value;
both the lwp and tid components are zero.
The reason for doing this is that pids associated with checkpoints can
never be a thread due to the fact that checkpoints (which are
implemented by forking a process) can only (reasonably) work with
single-threaded processes.
Without this commit, many of the "info checkpoints" commands
in gdb.multi/checkpoint-multi.exp will incorrectly show some
of the checkpoints as threads. E.g...
Id Active Target Id Frame
* 1.0 y Thread 0x7ffff7cb5740 (LWP 581704) at 0x401199, file hello.c, line 51
1.2 n process 581716 at 0x401199, file hello.c, line 51
1.3 n process 581717 at 0x401199, file hello.c, line 51
2.1 n process 581708 at 0x401258, file goodbye.c, line 62
2.2 y Thread 0x7ffff7cb5740 (LWP 581712) at 0x401258, file goodbye.c, line 62
3.0 y Thread 0x7ffff7cb5740 (LWP 581713) at 0x40115c, file hangout.c, line 31
3.2 n process 581715 at 0x40115c, file hangout.c, line 31
(gdb
With this commit in place, the output looks like this instead:
Id Active Target Id Frame
* 1.0 y process 535276 at 0x401199, file hello.c, line 51
1.2 n process 535288 at 0x401199, file hello.c, line 51
1.3 n process 535289 at 0x401199, file hello.c, line 51
2.1 n process 535280 at 0x401258, file goodbye.c, line 62
2.2 y process 535284 at 0x401258, file goodbye.c, line 62
3.0 y process 535285 at 0x40115c, file hangout.c, line 31
3.2 n process 535287 at 0x40115c, file hangout.c, line 31
(For brevity, I've removed the directory elements in each of the paths
above.)
The testcase, gdb.multi/checkpoint-multi.exp, has been updated to
reflect the fact that only "process" should now appear in output
from "info checkpoints".
Reviewed-By: Tom Tromey <tom@tromey.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
This commit causes the output of a "checkpoint" command to be
changed from:
checkpoint N: fork returned pid DDDD
to:
Checkpoint N: fork returned pid DDDD
This change was made to bring the output of the "checkpoint" command in
line with that of other commands, e.g.:
(gdb) break main
Breakpoint 1 at ...
(gdb) catch exec
Catchpoint 2 (exec)
(gdb) add-inferior
[New inferior 2]
Added inferior 2
The tests gdb.base/checkpoint.exp, gdb.base/kill-during-detach.exp,
and gdb.multi/checkpoint-multi.exp have been updated to accept the new
(capitalized) output from the "checkpoint" command.
Reviewed-By: Tom Tromey <tom@tromey.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
The current linux checkpoint code, most of which may be found in
linux-fork.c, is quite broken when attempting to use more than
one inferior. Running GDB will show internal errors when starting
two inferiors, placing a checkpoint in one, then switching to
the other and doing one of the following commands, "restart",
"detach", "kill", or continue (to program exit). Test cases
for two of those scenarios may be found in this bug:
https://sourceware.org/bugzilla/show_bug.cgi?id=31065
I've tested for each of the scenarios and many more in the new
test case, gdb.multi/checkpoint-multi.exp.
I started off with the goal of fixing just those problems, and was
mostly successful with a much smaller patch, but doing "info
checkpoints" with more than one inferior didn't work correctly due to
some of the inferiors being in the wrong program space. That led me
to making the linux-fork code fully inferior-aware.
Prior to this commit, the list of forks was being maintained in a
global named named 'fork_list'. I turned this into a per-inferior
data structure. There was also global named 'highest_fork_num' which
is also now part of the per-inferior struct. A registry key named
'checkpoint_inferior_data_key' along with function
'get_checkpoint_inferior_data' is used to access the per-inferior
data. This new function, get_checkpoint_inferior_data, is only
called by the new functions 'fork_list', 'reset_highest_fork_num',
and increment_highest_fork_num, each of which is passed a pointer to
the inferior. Most occurrences referring to the (previously) global
'fork_list' have been replaced by 'fork_list (inf)'. In some
functions, where the 'fork_list' is referenced multiple times, a local
named 'fork_list' is declared and initialized instead, like this:
auto &fork_list = ::fork_list (inf);
The constructor for 'struct fork_info' has gained an additional
parameter. In addition to passing the pid of the new fork, we now
also pass the fork identifier, fork_num, to the constructor. This
integer is shown to the user in the "info checkpoints" command and
is provided by the user, perhaps in conjunction with the inferior
number, in commands which manipulate checkpoints, e.g. 'restart' and
'delete checkpoint'.
When checkpoints are used in only one inferior, this commit will
present information to the user and will accept checkpoint identifiers
to commands in much the same way as the code did before this commit.
Per Pedro Alves's recommendations, the "info checkpoints" command has
been changed somewhat. "info checkpoints" used to display "(main
process)" for the first process in the checkpoint list. This is no
longer done because it does not provide useful information. It also
used to display "<running>", when the process is running and no useful
frame information may be displayed. This has been changed to
"(running)" in order to be more consistent with the output of the
"info threads" command. A new column has been added to the output for
showing the active process in the output from "info checkpoints".
This column will display 'y' for the active process and 'n' for the
others. For the active inferior a '*' is also printed preceding the
checkpoint identifier. Here's what things look(ed) like before and
after for just one inferior:
Before:
(gdb) info checkpoints
* 0 Thread 0x7ffff7cd3740 (LWP 84201) (main process) at 0x40114a, file hello.c, line 28
1 process 84205 at 0x401199, file hello.c, line 51
2 process 84206 at 0x4011a3, file hello.c, line 53
After:
(gdb) info checkpoints
Id Active Target Id Frame
* 0 y process 551311 at 0x40114a, file hello.c, line 28
1 n process 551314 at 0x401199, file hello.c, line 51
2 n process 551315 at 0x4011a3, file hello.c, line 53
(The Thread versus process distinction is handled by another
patch - the "After" example assumes that patch is applied too.)
When there are multiple inferiors, the "info checkpoints" output looks
like this:
(gdb) info checkpoints
Id Active Target Id Frame
1.0 y process 535276 at 0x401199, file hello.c, line 51
1.1 n process 535283 at 0x401199, file hello.c, line 51
1.2 n process 535288 at 0x401199, file hello.c, line 51
2.1 n process 535280 at 0x401258, file goodbye.c, line 62
2.2 y process 535284 at 0x401258, file goodbye.c, line 62
* 3.0 y process 535285 at 0x40115c, file hangout.c, line 31
3.2 n process 535287 at 0x40115c, file hangout.c, line 31
A new function named 'parse_checkpoint_id' has been added. As its
name suggests, it's responsible for parsing a string representing a
checkpoint identifier. These identifiers may be either a decimal
number representing the checkpoint number in the current inferior or
two decimal numbers separated by '.', in which case the first is the
inferior number and the second is the checkpoint number in that
inferior. It is called by delete_checkpoint_command,
detach_checkpoint_command, info_checkpoints_command, and
restart_command. Calls to 'parse_checkpoint_id' replace calls to
'parse_and_eval_long', plus error checking and error reporting code
near the calls to 'parse_and_eval_long'. As such, error checking and
reporting has been consolidated into a single function and the
messages output are more uniform, though this has necessitated changes
to the existing test case gdb.base/checkpoint.exp.
The functions 'find_fork_ptid' and 'find_fork_pid' used to return a
pointer to a fork_info struct. They now return a pair consisting of
the pointer to a fork_info struct in addition to a pointer to the
inferior containing that checkpoint.
'find_fork_id' returns a pointer to a fork_info struct just as it did
before, but it's now gained a new parameter, 'inf', which is the
inferior in which to look.
info_checkpoints_command used to simply iterate over the list of
forks (checkpoints), printing each one out. It now needs to iterate
over all inferiors and, for those which have checkpoints, it needs
to iterate over the list of checkpoints in that inferior. As noted
earlier, the format of the output has been changed so that checkpoint
identifiers incorporating an inferior number may be printed.
linux_fork_context, called by restart_command, now contains code to
switch inferiors when the fork being restarted is in an inferior which
is different from the current one. The scoped_switch_fork_info class
now also contains code for switching inferiors in both the constructor
and destructor.
gdb/linux-nat.c has a few changes. All but one of them are related
to passing the inferior to one of the linux-fork functions. But
one of the tests in linux_nat_target::detach has also changed in
a non-obvious way. In attempting to determine whether to call
linux_fork_detach(), that code used to do:
if (pid == inferior_ptid.pid () && forks_exist_p ())
It's been simplified to:
if (forks_exist_p (inf))
I had added the 'pid == inferior_ptid.pid ()' condition in late 2023
while working on a detach bug. It was kind of a hack to prevent
calling linux_fork_detach() when in a different inferior. That's no
longer needed since the call to forks_exist_p does this directly -
i.e. it is now inferior-aware.
Finally, the header file 'linux-fork.h' has been updated to reflect
the fact that add_fork, linux_fork_killall, linux_fork_detach, and
forks_exist_p all now require that a pointer to an inferior be passed
to these functions. Additionally (as mentioned earlier),
find_fork_pid now returns std::pair<fork_info *, inferior *> instead
'of fork_info *'.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31065
Reviewed-By: Tom Tromey <tom@tromey.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
pre-commit currently runs flake8 only on `gdb/python/**/*.py`. There
are more files we can run it on, without running it on all the testsuite
files. Add:
- gdb/gdb-gdb.py.in
- gdb/*.py
- gdb/testsuite/*.py
Fix the new errors that popped up:
gdb/copyright.py:29:21: W605 invalid escape sequence '\*'
gdb/copyright.py:29:29: W605 invalid escape sequence '\*'
gdb/copyright.py:29:38: W605 invalid escape sequence '\*'
gdb/copyright.py:29:46: W605 invalid escape sequence '\*'
gdb/copyright.py:34:1: F401 'datetime' imported but unused
gdb/testsuite/analyze-racy-logs.py:150:9: E722 do not use bare 'except'
Change-Id: Ia864c22d4f170d4e18ce3beb06a86c49966654b2
Approved-By: Tom Tromey <tom@tromey.com>
|
|
inline-section-gc.exp ends up passing "-lm" to gnatmake as an "marg"
-- meaning gnatmake should process it itself. However, the gnat-llvm
gnatmake does not know what to do with this, so the test fails.
This patch rearranges the arguments so that the (implicit) trailing
-lm ends up being passed through to the linker.
|
|
This commit adds a new method to Python architecture objects that
returns a void type for that architecture.
This will be useful later to create types for function symbols created
using Python extension code.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
This commit adds new propery "subblocks" to gdb.Block objects. This
allows Python to traverse block tree starting with global block.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
When running test-case gdb.ada/big_packed_array.exp on s390x-linux, I run
into:
...
(gdb) print bad^M
$2 = (0 => 0 <repeats 24 times>, 1)^M
(gdb) FAIL: gdb.ada/big_packed_array.exp: scenario=minimal: print bad
...
This is with gcc 7.5.0, and this xfail should trigger:
...
if { $have_xfail && [string is integer $last] \
&& [expr ($last & 0xf) == 0] } {
# gcc/101643
setup_xfail *-*-*
}
...
but it doesn't because $last is '1'.
Fix this by using 0xf0 as mask for big endian.
Tested on s390x-linux.
|
|
When running test-case gdb.ada/convvar_comp.exp on s390x-linux, I get:
...
(gdb) run ^M
Starting program: pb16_063 ^M
^M
Breakpoint 1, pck.break_me (item=...) at pck.adb:17^M
17 function Break_Me (Item : T) return Boolean is^M
(gdb) print item.started^M
Cannot access memory at address 0x0^M
(gdb) FAIL: gdb.ada/convvar_comp.exp: print item.started
...
This happens as follows.
The parameter item is available in (DW_OP_fbreg: -168):
...
<2><912>: Abbrev Number: 18 (DW_TAG_formal_parameter)
<913> DW_AT_name : (indirect string, offset: 0x14ca): item
<919> DW_AT_type : <0x929>
<91d> DW_AT_location : 3 byte block: 91 d8 7e (DW_OP_fbreg: -168)
...
and according to the rules of -O0, it's considered to be available after the
prologue, which looks like this:
...
0000000001002998 <pck__break_me>:
1002998: b3 c1 00 2b ldgr %f2,%r11
100299c: b3 c1 00 0f ldgr %f0,%r15
10029a0: e3 f0 ff 58 ff 71 lay %r15,-168(%r15)
10029a6: b9 04 00 bf lgr %r11,%r15
10029aa: e3 20 b0 a0 00 24 stg %r2,160(%r11)
...
To detect the prologue, gdb checks the line info, which looks like this:
...
pck.adb:
File name Line number Starting address View Stmt
pck.adb 17 0x1002998 x
pck.adb 17 0x1002998 1 x
pck.adb 19 0x10029b0 x
pck.adb 20 0x10029b8 x
pck.adb - 0x10029c6
...
and gdb concludes that it's an empty prologue, so we stop at 0x1002998 and
try to print parameter item, which is not available yet.
For more details, see this comment in skip_prologue_using_sal:
...
/* For languages other than assembly, treat two consecutive line
entries at the same address as a zero-instruction prologue.
...
The same thing happens on x86_64-linux, but it causes no problem there,
because amd64_skip_prologue decides not to trust the result:
...
struct compunit_symtab *cust = find_pc_compunit_symtab (func_addr);
/* LLVM backend (Clang/Flang) always emits a line note before the
prologue and another one after. We trust clang and newer Intel
compilers to emit usable line notes. */
if (post_prologue_pc
&& (cust != NULL
&& cust->producer () != nullptr
&& (producer_is_llvm (cust->producer ())
|| producer_is_icc_ge_19 (cust->producer ()))))
return std::max (start_pc, post_prologue_pc);
...
because the producer is GCC.
Work around this by setting a breakpoint on the first statement of
pck.break_me instead.
Tested on s390x-linux.
|
|
In some cases, test-cases use c++, but don't add "c++" to the compilation
flags. This can cause problems with some compilers.
Fix this in some test-cases.
Approved-By: Tom Tromey <tom@tromey.com>
PR testsuite/30380
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30380
|
|
On openSUSE Leap 15.6 with test-case gdb.base/list-dot-nodebug.exp I run into:
...
(gdb) list .^M
warning: 1 ../sysdeps/x86_64/crtn.S: No such file or directory^M
(gdb) FAIL: $exp: debug=none: print before start
...
The intent of the debug=none case is to generate an executable with no debug
info. However, we have quite a few CUs with debug info:
...
$ readelf -wi outputs/gdb.base/list-dot-nodebug/list-dot-nodebug-none \
| egrep -c " @ "
431
...
This is because this code:
...
gdb_gnu_strip_debug $executable no-debuglink
...
uses $executable, and the variable is set here:
...
set executable ${testfile}-none
...
which sets it to "list-dot-nodebug-none" and consequently
gdb_gnu_strip_debug cannot find it.
Fix this by using "[standard_output_file $executable]" instead.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR testsuite/31721
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31721
|
|
When running test-case gdb.tui/main.exp, the last command discards the
executable file and symbol table:
...
(gdb) file
No executable file now.
Discard symbol table from `main'? (y or n) [answered Y; input not from terminal]
No symbol file now.
(gdb)
...
and we end up with this source window:
...
+-tui-layout.c----------------------------------------------------------------+
| |
| |
| |
| |
| |
| |
| [ No Source Available ] |
| |
| |
| |
| |
| |
| |
+-----------------------------------------------------------------------------+
...
The source window title shouldn't be showing tui-layout.c. It's the source
file containing function main for the executable that was just discarded.
Fix this by clearing the title in tui_source_window::erase_source_content.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
|
|
When I run:
runtest dw2-using-debug-str.exp
... if I examine the gdb.log, I see:
objcopy: unable to copy file '[...]/dw2-using-debug-str'; reason: Text file busy
This happens because the inferior is still running, and objcopy --
despite the invocation seemingly not needing this -- tries to open it
for writing.
This patch works around the objcopy oddity by having gdb exit (killing
the inferior) before the invocation.
Fixing this points out that the test does not work in the
--target_board=cc-with-gdb-index case. This patch also arranges to
issue an "untested" here.
|
|
There is a test in gdb.cp/var-tag.exp that is kfail'd. I happened
across this while working on another series and found that the PR it
referenced was closed as invalid. On that basis I think the test
should be deleted.
Reviewed-By: Keith Seitz <keiths@redhat.com>
|
|
A couple of ".tcl" files in gdb.dwarf2 escaped notice during the
"require" refactoring. This patch fixes these to use "require" rather
than if/return.
|