| Age | Commit message (Collapse) | Author | Files | Lines |
|
At Red Hat we have an out of tree AArch64 watchpoint test which broke
after this commit:
commit cf16ab724a41e4cbaf723b5633d4e7b29f61372b
Date: Tue Mar 12 17:08:18 2024 +0100
[gdb/tdep] Fix gdb.base/watch-bitfields.exp on aarch64
The problem with AArch64 hardware watchpoints is that they (as I
understand it) are restricted to a minimum of 8 bytes.
The problem is that current AArch64 hardware has imprecise hardware
watchpoint events due to unaligned accesses. The address reported for
the watchpoint event will depend on the access size. As a result, it
is possible that multiple watchpoints could potentially account for a
single watchpoint event, which is the case in the RH test. GDB can
then miss-identify which watchpoint actually triggered.
Prior to the above commit the RH test was passing. However, the test
was relying on, in the case of ambiguity, GDB selecting the first
created watchpoint. That behaviour changed with the above commit.
Now GDB favours reporting non write breakpoints, and will only report
a write breakpoint if no non-write breakpoint exists in the same
region.
I originally posted a patch to try and tweak the existing logic to
restore enough of the original behaviour that the RH test would pass,
this can be found here (2 iterations):
https://inbox.sourceware.org/gdb-patches/65e746b6394f04faa027e778f733eda95d20f368.1753115072.git.aburgess@redhat.com
https://inbox.sourceware.org/gdb-patches/638cbe9b738c0c529f6370f90ba4a395711f63ae.1753971315.git.aburgess@redhat.com
Neither of these really resolved the problem, they fixed some cases,
but broke others.
Ultimately, the problem on AArch64 is that for a single watchpoint
trap, there could be multiple watchpoints that are potentially
responsible. The existing API defined by the target_ops methods
stopped_by_watchpoint() and stopped_data_address() only allow for two
possible options:
1. If stopped_by_watchpoint() is true then stopped_data_address()
can return true and a single address which identifies all
watchpoints at that single address, or
2. If stopped_by_watchpoint() is true then stopped_data_address()
can return false, in which case GDB will check all write
watchpoints to see if any have changed, if they have, then GDB
tells the user that that was the triggering watchpoint.
If we are in a situation where we have to choose between multiple
write and read watchpoints then the current API doesn't allow the
architecture specific code to tell GDB core about this case.
In this commit I propose that we change the target_ops API,
specifically, the method:
bool target_ops::stopped_data_address (CORE_ADDR *);
will change to:
std::vector<CORE_ADDR> target_ops::stopped_data_addresses ();
The architecture specific code can now return a set of watchpoint
addresses, allowing GDB to identify a set of watchpoints that might
have triggered. GDB core can then select the most likely watchpoint,
and present that to the user.
As with the old API, target_ops::stopped_data_addresses should only be
called when target_ops::stopped_by_watchpoint is true, in which case
it's return values can be interpreted like this:
a. An empty vector; this replaces the old case where false was
returned. GDB should check all the write watchpoints and select
the one that changed as the responsible watchpoint.
b. A single entry vector; all targets except AArch64 currently
return at most a single entry vector. The single address
indicates the watchpoint(s) that triggered.
c. A multi-entry vector; currently AArch64 only. These addresses
indicate the set of watchpoints that might have triggered. GDB
will check the write watchpoints to see which (if any) changed,
and if no write watchpoints changed, GDB will present the first
access watchpoint.
In the future, we might want to improve the handling of (c) so that
GDB tells the user that multiple access watchpoints might have
triggered, and then list all of them. This might clear up some
confusion. But I think that can be done in the future (I don't have
an immediate plan to work on this). I think this change is already a
good improvement.
The changes for this are pretty extensive, but here's a basic summary:
* Within gdb/ changing the API name from stopped_data_address to
stopped_data_addresses throughout. Comments are updated too where
needed.
* For targets other than AArch64, the existing code is retained with
as few changes as possible, we only allow for a single address to
be returned, the address is now wrapped in a vector. Where we
used to return false, we now return the empty vector.
* For AArch64, the return a vector logic is pushed through to
gdb/nat/aarch64-hw-point.{c,h}, and aarch64_stopped_data_address
changes to aarch64_stopped_data_addresses, and is updated to
return a vector of addresses.
* In infrun.c there's some updates to some debug output.
* In breakpoint.c the interesting changes are in
watchpoints_triggered. The existing code has three cases to
handle:
(i) target_stopped_by_watchpoint returns false. This case is
unchanged.
(ii) target_stopped_data_address returns false. This case is now
calling target_stopped_data_addresses, and checks for the
empty vector, but otherwise is unchanged.
(iii) target_stopped_data_address returns true, and a single
address. This code calls target_stopped_data_addresses, and
now handles the possibility of a vector containing multiple
entries. We need to first loop over every watchpoint
setting its triggered status to 'no', then we check every
address in the vector setting matching watchpoint's
triggered status to 'yes'. But the actual logic for if a
watchpoint matches an address or not is unchanged.
The important thing to notice here is that in case (iii), before
this patch, GDB could already set _multiple_ watchpoints to
triggered. For example, setting a read and write watchpoint on
the same address would result in multiple watchpoints being marked
as triggered. This patch just extends this so that multiple
watchpoints, at multiple addresses, can now be marked as
triggered.
* In remote.c there is an interesting change. We need to allow
gdbserver to pass the multiple addresses back to GDB. To achieve
this, I now allow multiple 'watch', 'rwatch', and 'awatch' tokens
in a 'T' stop reply packet. There's a new feature multi-wp-addr
which is passed in the qSupported packet to determine if the
remote is allowed to pass back multiple watchpoint stop reasons.
If the remote passed multiple watchpoint addresses then these are
collected and returned from the target_ops::stopped_data_addresses
call.
If a new GDB connects to an old gdbserver that doesn't understand
the multi-wp-addr feature, then gdbserver will continue to return
a single watchpoint address in the 'T' packet, which is what
happens before this patch.
* In gdbserver/ the changes are pretty similar. The API is renamed
from ::stopped_data_address to ::stopped_data_addresses, and
::low_stopped_data_address to ::low_stopped_data_addresses.
There's also code added to detect the new multi-wp-addr feature.
If this feature is not advertised from GDB then only a single
watchpoint address will be returned in the 'T' stop reply packet.
* In GDB and gdbserver, for all targets except AArch64, the existing
code to figure out a watchpoint address is retained, we just wrap
the single address into a vector.
* For AArch64, we call aarch64_stopped_data_addresses, which returns
the required vector.
For testing, I've built GDB on GNU/Linux for i386, x86-64, PPC64le,
ARM, and AArch64. That still leaves a lot of targets possibly
impacted by this change as untested. Which is a risk. I certainly
wouldn't want to push this patch until after GDB 17 branches so we
have time to find and fix any regressions that are introduced.
I've run a full regression test on AArch64 and x86-64 (both GNU/Linux)
with no regressions. As I said above, for other targets nothing
should really have changed, all non-AArch64 targets just return a
single watchpoint address from target_ops::stopped_data_addresses(),
so, as long as the target builds, it should run unchanged.
I also sent the branch through the sourceware CI, and everything
passed.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33240
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33252
Acked-By: Tom de Vries <tdevries@suse.de>
|
|
This commit extends GDB for x86/Linux to include the NT_I386_TLS note
in generated core files (i.e. created with `generate-core-file` or
`gcore` command). This note contains the 3 per-thread TLS related
GDT (global descriptor table) entries, and is present for i386
binaries, or those compiled on x86-64 with -m32.
The approach I have taken to achieve this, is to make the 3 GDT
entries available within 3 new registers. I added these registers to
the org.gnu.gdb.i386.linux target description feature, as this feature
seemed perfectly named. As the new registers are optional I don't see
any harm in extending this existing feature. I did consider adding a
new feature with `tls` in the name, but this seemed excessive given
the existing feature.
Which GDT entries are used for TLS varies between i386 and x86-64
running in 32-bit mode. As such the registers are named with suffixes
0, 1, and 2, and it is left to GDB or gdbserver, to find the correct
GDT entries (based on the precise target) and place the contents into
these registers.
With this done, adding the relevant regset is sufficient to get the
tls contents emitted as a core file note. Support for emitting the
note into the generated core file relies on some BFD changes which
were made in an earlier commit:
commit ea6ec00ff4520895735e4913cb90c933c7296f04
Date: Fri Jul 25 19:51:58 2025 +0100
bfd: support for NT_386_TLS notes
The three new registers are readable and writable. Writing to one of
the new registers will update the relevant kernel GDT entry.
Each TLS GDT is represented by a 'struct user_desc' (see 'man 2
get_thread_area' for details), the first 4 bytes of each 'user_desc'
is the 'entry_number' field, this is the index of the GDT within the
kernel, and cannot be modified. Attempts to write to this region of
the register will be ignored, but will not give an error.
I did consider not including this part of the user_desc within the
register value, but this becomes difficult when we consider remote
targets, GDB would then need to figure out what these indexes were so
that the core file note could be generated. Sure, we probably could
figure the correct index values out, but I figure, why bother, we can
just pass them through in the register and know for certain that we
have the correct values.
For testing, there's a new test that covers the basic functionality,
including read/write access to the new registers, and checking that
the NT_386_TLS note is added to the core file, and that the note
contents can be read by GDB.
I also manually tested opening a core file generated from an old
GDB (so no NT_386_TLS notes) using a GDB with this patch. This works
fine, the new tls registers are not created as the NT_GDB_TDESC
note (the target description) doesn't include the new registers.
Out of interest I also patched an old version of GDB to avoid creating
the NT_GDB_TDESC, and created a core file. This core file contained
neither the NT_386_TLS nor NT_GDB_TDESC. When opening this core file
with a patched GDB, the new registers do show up, but their contents
are given as <unavailable>, which is exactly what we'd expect, GDB
builds a target description based on the architecture, the
architecture says these registers should exist, but they are missing
from the core file, hence, <unavailable>.
I also tested using a patched GDB with an old version of gdbserver,
the new registers don't show up as the old gdbserver doesn't send them
in its target description. And a core file created using the gcore
command in such a setup leaves no NT_386_TLS notes added, which is
what we'd expect.
And I also tested a new gdbserver running with an old version of GDB.
As the new tls registers are now mentioned in the target description,
then obviously, the old GDB does see the registers, and present them
to the user, however GDB doesn't know how to use these registers to
create a NT_386_TLS, so that note isn't added to any core files.
Also, while a new GDB places the tls registers into the 'system'
group, an old GDB doesn't do this, so the registers end up in the
'general' group by default. This means they show up within 'info
registers' output. This isn't ideal, but there's not much that can be
done about this.
Overall, I feel the combinations of old and new tools has been tested,
and the behaviours are what we'd want or expect.
I'm tagging this commit with PR gdb/15591, even though this patch
isn't directly related. That bug is for improving GDB's testing of
TLS support in core files. The test in this commit does do some very
simple reading of a TLS variable, but there's only two threads, and
one TLS variable, so it's not extensive. Additionally, the test in
this commit is x86 only, so this should not be considered a full
resolution to that bug. But still, it's something.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=15591
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-By: Christina Schimpe <christina.schimpe@intel.com>
Reviewed-By: Keith Seitz <keiths@redhat.com>
|
|
I noticed my IDE (VSCode) starting to automatically trim trailing
whitespaces on save, despite the setting for it being disabled. I
realized that this is because the .editorconfig file now has
trim_trailing_whitespace = true
for many file types. If we have this EditorConfig setting forcing
editors to trim trailing whitespaces, I think it would make sense to
clean up trailing whitespaces from our files. Otherwise, people will
always get spurious whitespace changes when editing these files.
I did a mass cleanup using this command:
$ find gdb gdbserver gdbsupport -type f \( \
-name "*.c" -o \
-name "*.h" -o \
-name "*.cc" -o \
-name "*.texi" -o \
-name "*.exp" -o \
-name "*.tcl" -o \
-name "*.py" -o \
-name "*.s" -o \
-name "*.S" -o \
-name "*.asm" -o \
-name "*.awk" -o \
-name "*.ac" -o \
-name "Makefile*" -o \
-name "*.sh" -o \
-name "*.adb" -o \
-name "*.ads" -o \
-name "*.d" -o \
-name "*.go" -o \
-name "*.F90" -o \
-name "*.f90" \
\) -exec sed -ri 's/[ \t]+$//' {} +
I then did an autotools regen, because we don't actually want to change
the Makefile and Makefile.in files that are generated.
Change-Id: I6f91b83e3b8c4dc7d5d51a2ebf60706120efe691
|
|
This patch adds the user mode register PL3_SSP which is part of the
Intel(R) Control-Flow Enforcement Technology (CET) feature for support
of shadow stack.
For now, only native and remote debugging support for shadow stack
userspace on amd64 linux are covered by this patch including 64 bit and
x32 support. 32 bit support is not covered due to missing Linux kernel
support.
This patch requires fixing the test gdb.base/inline-frame-cycle-unwind
which is failing in case the shadow stack pointer is unavailable.
Such a state is possible if shadow stack is disabled for the current thread
but supported by HW.
This test uses the Python unwinder inline-frame-cycle-unwind.py which fakes
the cyclic stack cycle by reading the pending frame's registers and adding
them to the unwinder:
~~~
for reg in pending_frame.architecture().registers("general"):
val = pending_frame.read_register(reg)
unwinder.add_saved_register(reg, val)
return unwinder
~~~
However, in case the python unwinder is used we add a register (pl3_ssp) that is
unavailable. This leads to a NOT_AVAILABLE_ERROR caught in
gdb/frame-unwind.c:frame_unwind_try_unwinder and it is continued with standard
unwinders. This destroys the faked cyclic behavior and the stack is
further unwinded after frame 5.
In the working scenario an error should be triggered:
~~~
bt
0 inline_func () at /tmp/gdb.base/inline-frame-cycle-unwind.c:49^M
1 normal_func () at /tmp/gdb.base/inline-frame-cycle-unwind.c:32^M
2 0x000055555555516e in inline_func () at /tmp/gdb.base/inline-frame-cycle-unwind.c:45^M
3 normal_func () at /tmp/gdb.base/inline-frame-cycle-unwind.c:32^M
4 0x000055555555516e in inline_func () at /tmp/gdb.base/inline-frame-cycle-unwind.c:45^M
5 normal_func () at /tmp/gdb.base/inline-frame-cycle-unwind.c:32^M
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) PASS: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 5: backtrace when the unwind is broken at frame 5
~~~
To fix the Python unwinder, we simply skip the unavailable registers.
Also it makes the test gdb.dap/scopes.exp fail. The shadow stack feature is
disabled by default, so the pl3_ssp register which is added with my CET
shadow stack series will be shown as unavailable and we see a TCL error:
~~
>>> {"seq": 12, "type": "request", "command": "variables", "arguments": {"variablesReference": 2, "count": 85}}
Content-Length: 129^M
^M
{"request_seq": 12, "type": "response", "command": "variables", "success": false, "message": "value is not available", "seq": 25}FAIL: gdb.dap/scopes.exp: fetch all registers success
ERROR: tcl error sourcing /tmp/gdb/testsuite/gdb.dap/scopes.exp.
ERROR: tcl error code TCL LOOKUP DICT body
ERROR: key "body" not known in dictionary
while executing
"dict get $val body variables"
(file "/tmp/gdb/testsuite/gdb.dap/scopes.exp" line 152)
invoked from within
"source /tmp/gdb/testsuite/gdb.dap/scopes.exp"
("uplevel" body line 1)
invoked from within
"uplevel #0 source /tmp/gdb/testsuite/gdb.dap/scopes.exp"
invoked from within
"catch "uplevel #0 source $test_file_name" msg"
UNRESOLVED: gdb.dap/scopes.exp: testcase '/tmp/gdb/testsuite/gdb.dap/scopes.exp' aborted due to Tcl error
~~
I am fixing this by enabling the test for CET shadow stack, in case we
detect that the HW supports it:
~~~
# If x86 shadow stack is supported we need to configure GLIBC_TUNABLES
# such that the feature is enabled and the register pl3_ssp is
# available. Otherwise the reqeust to fetch all registers will fail
# with "message": "value is not available".
if { [allow_ssp_tests] } {
append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK"
}
~~~
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Luis Machado <luis.machado@arm.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
|
|
The XSAVE function set is organized in state components, which are a set of
registers or parts of registers. So-called XSAVE-supported features are
organized using state-component bitmaps, each bit corresponding to a
single state component.
The Intel Software Developer's Manual uses the term xstate_bv for a
state-component bitmap, which is defined as XCR0 | IA32_XSS. The control
register XCR0 only contains a state-component bitmap that specifies user state
components, while IA32_XSS contains a state-component bitmap that specifies
supervisor state components.
Until now, XCR0 is used as input for target description creation in GDB.
However, a following patch will add userspace support for the CET shadow
stack feature by Intel. The CET state is configured in IA32_XSS and consists
of 2 state components:
- State component 11 used for the 2 MSRs controlling user-mode
functionality for CET (CET_U state)
- State component 12 used for the 3 MSRs containing shadow-stack pointers
for privilege levels 0-2 (CET_S state).
Reading the CET shadow stack pointer register on linux requires a separate
ptrace call using NT_X86_SHSTK. To pass the CET shadow stack enablement
state we would like to pass the xstate_bv value instead of xcr0 for target
description creation. To prepare for that, we rename the xcr0 mask
values for target description creation to xstate_bv. However, this
patch doesn't add any functional changes in GDB.
Future states specified in IA32_XSS such as CET will create a combined
xstate_bv_mask including xcr0 register value and its corresponding bit in
the state component bitmap. This combined mask will then be used to create
the target descriptions.
Reviewed-By: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Approved-By: Luis Machado <luis.machado@arm.com>
|
|
On x86 the PTRACE_GETREGSET request is currently only used for the xstate regset.
The size of the xstate regset is initialized to 0 such that it can be reset to
the appropriate size once we know it is supported for the current target
in x86_linux_read_description.
However, this configuration would not just affect the xstate regset but any regset
with PTRACE_GETREGSET request that is added in the future. The new regset would be
misconfigured with the xstate regset size. To avoid this we add an assert for
unsupported regsets and check explicitly for the note type of the register set.
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Approved-By: Luis Machado <luis.machado@arm.com>
|
|
This updates the copyright headers to include 2025. I did this by
running gdb/copyright.py and then manually modifying a few files as
noted by the script.
Approved-By: Eli Zaretskii <eliz@gnu.org>
|
|
Boolify the 'fetch' parameter of the get_thread_regcache function.
All of the current uses pass true for this parameter. Therefore, define
its default value as true and remove the argument from the uses.
We still keep the parameter, though, to give downstream targets the
option to obtain a regcache without having to fetch the whole
contents. Our (Intel) downstream target is an example.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
|
The `get_thread_regcache` function has a `fetch` option to skip
fetching the registers from the target. It seems this option is set
to false only at uses where we just need to access the tdesc through
the regcache of the current thread, as in
struct regcache *regcache = get_thread_regcache (current_thread, 0);
... regcache->tdesc ...
Since the tdesc of a regcache is set from the process of the thread
that owns the regcache, we can simplify the code to access the tdesc
via the process, as in
... current_process ()->tdesc ...
This is intended to be a refactoring with no behavioral change.
Tested only for the linux-x86-low target.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
|
Remove the 'struct' keyword in occurrences of 'struct thread_info'.
This is a code clean-up.
Tested by rebuilding.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
|
I was thinking of changing this macro to a function, but I don't think
it adds much value over just accessing the field directly.
Change-Id: I5dc63e9db0773549c5b55a1279212e2d1213f50c
Approved-By: Tom Tromey <tom@tromey.com>
|
|
This function doesn't seem so useful. Use `thread_info::id::lwp`
directly.
Change-Id: Ib4a86eeeee6c1342bc1c092f083589ce28009be1
Reviewed-By: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
|
|
GDB deprecated the commands "show/set mpx bound" in GDB 15.1, as Intel
listed Intel(R) Memory Protection Extensions (MPX) as removed in 2019.
MPX is also deprecated in gcc (since v9.1), the linux kernel (since v5.6)
and glibc (since v2.35). Let's now remove MPX support in GDB completely.
This includes the removal of:
- MPX functionality including register support
- deprecated mpx commands
- i386 and amd64 implementation of the hooks report_signal_info and
get_siginfo_type
- tests
- and pretty printer.
We keep MPX register numbers to not break compatibility with old gdbservers.
Approved-By: Felix Willgerodt <felix.willgerodt@intel.com>
|
|
This commit builds on the previous series of commits to share the
target description caching code between GDB and gdbserver for
x86/Linux targets.
The objective of this commit is to move the four functions (2 each of)
i386_linux_read_description and amd64_linux_read_description into the
gdb/arch/ directory and combine them so we have just a single copy of
each. Then GDB, gdbserver, and the in-process-agent (IPA) will link
against these shared functions.
One curiosity with this patch is the function
x86_linux_post_init_tdesc. On the gdbserver side the two functions
amd64_linux_read_description and i386_linux_read_description have some
functionality that is not present on the GDB side, there is some
additional configuration that is performed as each target description
is created, to setup the expedited registers.
To support this I've added the function x86_linux_post_init_tdesc.
This function is called from the two *_linux_read_description
functions, but is implemented separately for GDB and gdbserver.
An alternative approach that avoids adding x86_linux_post_init_tdesc
would be to have x86_linux_tdesc_for_tid return a non-const target
description, then in x86_target::low_arch_setup we could inspect the
target description to figure out if it is 64-bit or not, and modify
the target description as needed. In the end I think that adding the
x86_linux_post_init_tdesc function is the simpler solution.
The contents of gdbserver/linux-x86-low.cc have moved to
gdb/arch/x86-linux-tdesc-features.c, and gdbserver/linux-x86-tdesc.h
has moved to gdb/arch/x86-linux-tdesc-features.h, this change leads to
some updates in the #includes in the gdbserver/ directory.
This commit also changes how target descriptions are cached.
Previously both GDB and gdbserver used static C-style arrays to act as
the tdesc cache. This was fine, except for two problems. Either the
C-style arrays would need to be placed in x86-linux-tdesc-features.c,
which would allow us to use the x86_linux_*_tdesc_count_1() functions
to size the arrays for us, or we'd need to hard code the array sizes
using separate #defines, which we'd then have to keep in sync with the
rest of the code in x86-linux-tdesc-features.c.
Given both of these problems I decided a better solution would be to
just switch to using a std::unordered_map to act as the cache. This
will resize automatically, and we can use the xcr0 value as the key.
At first inspection, using xcr0 might seem to be a problem; after all
the {i386,amd64}_create_target_description functions take more than
just the xcr0 value. However, this patch is only for x86/Linux
targets, and for x86/Linux all of the other flags passed to the tdesc
creation functions have constant values and so are irrelevant when we
consider tdesc caching.
For testing I've done the following:
- Built on x86-64 GNU/Linux for all targets, and just for the native
target,
- Build on i386 GNU/Linux for all targets, and just for the native
target,
- Build on a 64-bit, non-x86 GNU/Linux for all targets, just for the
native target, and for targets x86_64-*-linux and i386-*-linux.
Approved-By: Felix Willgerodt <felix.willgerodt@intel.com>
|
|
This commit is part of a series which aims to share more of the target
description creation between GDB and gdbserver for x86/Linux.
After some refactoring earlier in this series the shared
x86_linux_tdesc_for_tid function was added into nat/x86-linux-tdesc.c.
However, this function still relies on amd64_linux_read_description
and i386_linux_read_description which are implemented separately for
both gdbserver and GDB. Given that at their core, all these functions
do is:
1. take an xcr0 value as input,
2. mask out some feature bits,
3. look for a cached pre-generated target description and return it
if found,
4. if no cached target description is found then call either
amd64_create_target_description or
i386_create_target_description to create a new target
description, which is then added to the cache. Return the newly
created target description.
The inner functions amd64_create_target_description and
i386_create_target_description are already shared between GDB and
gdbserver (in the gdb/arch/ directory), so the only thing that
the *_read_description functions really do is add the caching layer,
and it feels like this really could be shared.
However, we have a small problem.
Despite using the same {amd64,i386}_create_target_description
functions in both GDB and gdbserver to create the target descriptions,
on the gdbserver side we cache target descriptions based on a reduced
set of xcr0 feature bits.
What this means is that, in theory, different xcr0 values can map to
the same cache entry, which could result in the wrong target
description being used.
However, I'm not sure if this can actually happen in reality. Within
gdbserver we already split the target description cache based on i386,
amd64, and x32. I suspect within a given gdbserver session we'll only
see at most one target description for each of these.
The cache conflicting problem is caused by xcr0_to_tdesc_idx, which
maps an xcr0 value to a enum x86_linux_tdesc value, and there are only
7 usable values in enum x86_linux_tdesc.
In contrast, on the GDB side there are 64, 32, and 16 cache slots for
i386, amd64, and x32 respectively.
On the GDB side it is much more important to cache things correctly as
a single GDB session might connect to multiple different remote
targets, each of which might have slightly different x86
architectures.
And so, if we want to merge the target description caching between GDB
and gdbserver, then we need to first update gdbserver so that it
caches in the same way as GDB, that is, it needs to adopt a mechanism
that allows for the same number of cache slots of each of i386, amd64,
and x32. In this way, when the caching is shared, GDB's behaviour
will not change.
Unfortunately it's a little more complex than that due to the in
process agent (IPA).
When the IPA is in use, gdbserver sends a target description index to
the IPA, and the IPA uses this to find the correct target description
to use, the IPA having first generated every possible target
description.
Interestingly, there is certainly a bug here which results from only
having 7 values in enum x86_linux_tdesc. As multiple possible target
descriptions in gdbserver map to the same enum x86_linux_tdesc value,
then, when the enum x86_linux_tdesc value is sent to the IPA there is
no way for gdbserver to know that the IPA will select the correct
target description. This bug will get fixed by this commit.
** START OF AN ASIDE **
Back in the day I suspect this approach of sending a target
description index made perfect sense. However since this commit:
commit a8806230241d201f808d856eaae4d44088117b0c
Date: Thu Dec 7 17:07:01 2017 +0000
Initialize target description early in IPA
I think that passing an index was probably a bad idea.
We used to pass the index, and then use that index to lookup which
target description to instantiate and use, the target description was
not generated until the index arrived.
However, the above commit fixed an issue where we can't call malloc()
within (certain parts of) the IPA (apparently), so instead we now
pre-compute _every_ possible target description within the IPA. The
index is only used to lookup which of the (many) pre-computed target
descriptions to use.
It would (I think) have been easier all around if the IPA just
self-inspected, figured out its own xcr0 value, and used that to
create the one target description that is required. So long as the
xcr0 to target description code is shared (at compile time) with
gdbserver, then we can be sure that the IPA will derive the same
target description as gdbserver, and we would avoid all this index
passing business, which has made this commit so very, very painful.
I did look at how a process might derive its own xcr0 value, but I
don't believe this is actually that simple, so for now I've just
doubled down on the index passing approach.
While reviewing earlier iterations of this patch there has been
discussion about the possibility of removing the IPA from GDB. That
would certainly make all of the code touched in this patch much
simpler, but I don't really want to do that as part of this series.
** END OF AN ASIDE **
Currently then for x86/linux, gdbserver sends a number between 0 and 7
to the IPA, and the IPA uses this to create a target description.
However, I am proposing that gdbserver should now create one of (up
to) 64 different target descriptions for i386, so this 0 to 7 index
isn't going to be good enough any more (amd64 and x32 have slightly
fewer possible target descriptions, but still more than 8, so the
problem is the same).
For a while I wondered if I was going to have to try and find some
backward compatible solution for this mess. But after seeing how
lightly the IPA is actually documented, I wonder if it is not the case
that there is a tight coupling between a version of gdbserver and a
version of the IPA? At least I'm hoping so, and that's what I've
assumed in this commit.
In this commit I have thrown out the old IPA target description index
numbering scheme, and switched to a completely new numbering scheme.
Instead of the index that is passed being arbitrary, the index is
instead calculated from the set of xcr0 features that are present on
the target. Within the IPA we can then reverse this logic to recreate
the xcr0 value based on the index, and from the xcr0 value we can
choose the correct target description.
With the gdbserver to IPA numbering scheme issue resolved I have then
update the gdbserver versions of amd64_linux_read_description and
i386_linux_read_description so that they cache target descriptions
using the same set of xcr0 features as GDB itself.
After this gdbserver should now always come up with the same target
description as GDB does on any x86/Linux target.
This commit does not introduce any new code sharing between GDB and
gdbserver as previous commits in this series have done. Instead this
commit is all about bringing GDB and gdbserver into alignment
functionally so that the next commit(s) can merge the GDB and
gdbserver versions of these functions.
Notes On The Implementation
---------------------------
Previously, within gdbserver, target descriptions were cached within
arrays. These arrays were sized based on enum x86_linux_tdesc and
xcr0_to_tdesc_idx returned the array (cache) index.
Now we need different array lengths for each of i386, amd64, and x32.
And the index to use within each array is calculated based on which
xcr0 bits are set and valid for a particular target type.
I really wanted to avoid having fixed array sizes, or having the set
of relevant xcr0 bits encoded in multiple places.
The solution I came up with was to create a single data structure
which would contain a list of xcr0 bits along with flags to indicate
which of the i386, amd64, and x32 targets the bit is relevant for. By
making the table constexpr, and adding some constexpr helper
functions, it is possible to calculate the sizes for the cache arrays
at compile time, as well as the bit masks needed to each target type.
During review it was pointed out[1] that possibly the failure to check
the SSE and X87 bits for amd64/x32 targets might be an error, however,
if this is the case then this is an issue that existed long before
this patch. I'd really like to keep this patch focused on reworking
the existing code and try to avoid changing how target descriptions
are actually created, mostly out of fear that I'll break something.
[1] https://inbox.sourceware.org/gdb-patches/MN2PR11MB4566070607318EE7E669A5E28E1B2@MN2PR11MB4566.namprd11.prod.outlook.com
Approved-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Felix Willgerodt <felix.willgerodt@intel.com>
|
|
This commit is part of a series to share more of the x86 target
description creation code between GDB and gdbserver.
Unlike previous commits which were mostly refactoring, this commit is
the first that makes a real change, though that change should mostly
be for gdbserver; I've largely adopted the "GDB" way of doing things
for gdbserver, and this fixes a real gdbserver bug.
On a x86-64 Linux target, running the test:
gdb.server/connect-with-no-symbol-file.exp
results in two core files being created. Both of these core files are
from the inferior process, created after gdbserver has detached.
In this test a gdbserver process is started and then, after gdbserver
has started, but before GDB attaches, we either delete the inferior
executable, or change its permissions so it can't be read. Only after
doing this do we attempt to connect with GDB.
As GDB connects to gdbserver, gdbserver attempts to figure out the
target description so that it can send the description to GDB, this
involves a call to x86_linux_read_description.
In x86_linux_read_description one of the first things we do is try to
figure out if the process is 32-bit or 64-bit. To do this we look up
the executable via the thread-id, and then attempt to read the
architecture size from the executable. This isn't going to work if
the executable has been deleted, or is no longer readable.
And so, as we can't read the executable, we default to an i386 target
and use an i386 target description.
A consequence of using an i386 target description is that addresses
are assumed to be 32-bits. Here's an example session that shows the
problems this causes. This is run on an x86-64 machine, and the test
binary (xx.x) is a standard 64-bit x86-64 binary:
shell_1$ gdbserver --once localhost :54321 /tmp/xx.x
shell_2$ gdb -q
(gdb) set sysroot
(gdb) shell chmod 000 /tmp/xx.x
(gdb) target remote :54321
Remote debugging using :54321
warning: /tmp/xx.x: Permission denied.
0xf7fd3110 in ?? ()
(gdb) show architecture
The target architecture is set to "auto" (currently "i386").
(gdb) p/x $pc
$1 = 0xf7fd3110
(gdb) info proc mappings
process 2412639
Mapped address spaces:
Start Addr End Addr Size Offset Perms objfile
0x400000 0x401000 0x1000 0x0 r--p /tmp/xx.x
0x401000 0x402000 0x1000 0x1000 r-xp /tmp/xx.x
0x402000 0x403000 0x1000 0x2000 r--p /tmp/xx.x
0x403000 0x405000 0x2000 0x2000 rw-p /tmp/xx.x
0xf7fcb000 0xf7fcf000 0x4000 0x0 r--p [vvar]
0xf7fcf000 0xf7fd1000 0x2000 0x0 r-xp [vdso]
0xf7fd1000 0xf7fd3000 0x2000 0x0 r--p /usr/lib64/ld-2.30.so
0xf7fd3000 0xf7ff3000 0x20000 0x2000 r-xp /usr/lib64/ld-2.30.so
0xf7ff3000 0xf7ffb000 0x8000 0x22000 r--p /usr/lib64/ld-2.30.so
0xf7ffc000 0xf7ffe000 0x2000 0x2a000 rw-p /usr/lib64/ld-2.30.so
0xf7ffe000 0xf7fff000 0x1000 0x0 rw-p
0xfffda000 0xfffff000 0x25000 0x0 rw-p [stack]
0xff600000 0xff601000 0x1000 0x0 r-xp [vsyscall]
(gdb) info inferiors
Num Description Connection Executable
* 1 process 2412639 1 (remote :54321)
(gdb) shell cat /proc/2412639/maps
00400000-00401000 r--p 00000000 fd:03 45907133 /tmp/xx.x
00401000-00402000 r-xp 00001000 fd:03 45907133 /tmp/xx.x
00402000-00403000 r--p 00002000 fd:03 45907133 /tmp/xx.x
00403000-00405000 rw-p 00002000 fd:03 45907133 /tmp/xx.x
7ffff7fcb000-7ffff7fcf000 r--p 00000000 00:00 0 [vvar]
7ffff7fcf000-7ffff7fd1000 r-xp 00000000 00:00 0 [vdso]
7ffff7fd1000-7ffff7fd3000 r--p 00000000 fd:00 143904 /usr/lib64/ld-2.30.so
7ffff7fd3000-7ffff7ff3000 r-xp 00002000 fd:00 143904 /usr/lib64/ld-2.30.so
7ffff7ff3000-7ffff7ffb000 r--p 00022000 fd:00 143904 /usr/lib64/ld-2.30.so
7ffff7ffc000-7ffff7ffe000 rw-p 0002a000 fd:00 143904 /usr/lib64/ld-2.30.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
7ffffffda000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
(gdb)
Notice the difference between the mappings reported via GDB and those
reported directly from the kernel via /proc/PID/maps, the addresses of
every mapping is clamped to 32-bits for GDB, while the kernel reports
real 64-bit addresses.
Notice also that the $pc value is a 32-bit value. It appears to be
within one of the mappings reported by GDB, but is outside any of the
mappings reported from the kernel.
And this is where the problem arises. When gdbserver detaches from
the inferior we pass the inferior the address from which it should
resume. Due to the 32/64 bit confusion we tell the inferior to resume
from the 32-bit $pc value, which is not within any valid mapping, and
so, as soon as the inferior resumes, it segfaults.
If we look at how GDB (not gdbserver) figures out its target
description then we see an interesting difference. GDB doesn't try to
read the executable. Instead GDB uses ptrace to query the thread's
state, and uses this to figure out the if the thread is 32 or 64 bit.
If we update gdbserver to do it the "GDB" way then the above problem
is resolved, gdbserver now sees the process as 64-bit, and when we
detach from the inferior we give it the correct 64-bit address, and
the inferior no longer segfaults.
Now, I could just update the gdbserver code, but better, I think, to
share one copy of the code between GDB and gdbserver in gdb/nat/.
That is what this commit does.
The cores of x86_linux_read_description from gdbserver and
x86_linux_nat_target::read_description from GDB are moved into a new
file gdb/nat/x86-linux-tdesc.c and combined into a single function
x86_linux_tdesc_for_tid which is called from each location.
This new function does things mostly the GDB way, some changes are
needed to allow for the sharing; we now take some pointers for where
the shared code can cache the xcr0 and xsave layout values.
Another thing to note about this commit is how the functions
i386_linux_read_description and amd64_linux_read_description are
handled. For now I've left these function as implemented separately
in GDB and gdbserver. I've moved the declarations of these functions
into gdb/arch/{i386,amd64}-linux-tdesc.h, but the implementations are
left where they are.
A later commit in this series will make these functions shared too,
but doing this is not trivial, so I've left that for a separate
commit. Merging the declarations as I've done here ensures that
everyone implements the function to the same API, and once these
functions are shared (in a later commit) we'll want a shared
declaration anyway.
Reviewed-By: Felix Willgerodt <felix.willgerodt@intel.com>
Acked-By: John Baldwin <jhb@FreeBSD.org>
|
|
The have_ptrace_getfpxregs global tracks whether GDB or gdbserver is
running on a kernel that supports the GETFPXREGS ptrace request.
Currently this global is declared twice (once in GDB and once in
gdbserver), I think it makes sense to move this global into the nat/
directory, and have a single declaration and definition.
While moving this variable I have converted it to a tribool, as that
was what it really was, if even used the same numbering as the tribool
enum (-1, 0, 1). Where have_ptrace_getfpxregs was used I have updated
in the obvious way.
However, while making this change I noticed what I think is a bug in
x86_linux_nat_target::read_description and x86_linux_read_description,
both of these functions can be called multiple times, but in both
cases we only end up calling i386_linux_read_description the first
time through in the event that PTRACE_GETFPXREGS is not supported.
This is because initially have_ptrace_getfpxregs will be
TRIBOOL_UNKNOWN, but after the ptrace call fails we set
have_ptrace_getfpxregs to TRIBOOL_FALSE. The next time we attempt to
read the target description we'll skip the ptrace call, and so skip
the call to i386_linux_read_description.
I've not tried to address this preexisting bug in this commit, this is
purely a refactor, there should be no user visible changes after this
commit. In later commits I'll merge the gdbserver and GDB code
together into the nat/ directory, and after that I'll try to address
this bug.
Reviewed-By: Felix Willgerodt <felix.willgerodt@intel.com>
|
|
This commit is part of a series that aims to share more of the x86
target description reading/generation code between GDB and gdbserver.
There are a huge number of similarities between the code in
gdbserver's x86_linux_read_description function and GDB's
x86_linux_nat_target::read_description function, and it is this
similarity that I plan, in a later commit, to share between GDB and
gdbserver.
However, one thing that is different in x86_linux_read_description is
the code inside the '!use_xml' block. This is the code that handles
the case where gdbserver is not allowed to send an XML target
description back to GDB. In this case gdbserver uses some predefined,
fixed, target descriptions.
First, it's worth noting that I suspect this code is not tested any
more. I couldn't find anything in the testsuite that tries to disable
XML target description support. And the idea of having a single
"fixed" target description really doesn't work well when we think
about all the various x86 extensions that exist. Part of me would
like to rip out the no-xml support in gdbserver (at least for x86),
and if a GDB connects that doesn't support XML target descriptions,
gdbserver can just give an error and drop the connection. GDB has
supported XML target descriptions for 16 years now, I think it would
be reasonable for our shipped gdbserver to drop support for the old
way of doing things.
Anyway.... this commit doesn't do that.
What I did notice was that, over time, the '!use_xml' block appears to
have "drifted" within the x86_linux_read_description function; it's
now not the first check we do. Instead we make some ptrace calls and
return a target description generated based on the result of these
ptrace calls. Surely it only makes sense to generate variable target
descriptions if we can send these back to GDB?
So in this commit I propose to move the '!use_xml' block earlier in
the x86_linux_read_description function.
The benefit of this is that this leaves the later half of
x86_linux_read_description much more similar to the GDB function
x86_linux_nat_target::read_description and sets us up for potentially
sharing code between GDB and gdbserver in a later commit.
Approved-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Felix Willgerodt <felix.willgerodt@intel.com>
|
|
Share the definition of I386_LINUX_XSAVE_XCR0_OFFSET between GDB and
gdbserver.
This commit moves the definition into gdbsupport/x86-xstate.h, which
allows the #define to be shared.
There should be no user visible changes after this commit.
Approved-By: Felix Willgerodt <felix.willgerodt@intel.com>
|
|
Convert the have_ptrace_getregset global within gdbserver to a
tribool. This brings the flag into alignment with the corresponding
flag in GDB.
The gdbserver have_ptrace_getregset variable is already used as a
tribool, it just doesn't have the tribool type.
In a future commit I plan to share more code between GDB and
gdbserver, and having this variable be the same type in both code
bases will make the sharing much easier.
There should be no user visible changes after this commit.
Approved-By: John Baldwin <jhb@FreeBSD.org>
Reviewed-By: Felix Willgerodt <felix.willgerodt@intel.com>
|
|
Now that defs.h, server.h and common-defs.h are included via the
`-include` option, it is no longer necessary for source files to include
them. Remove all the inclusions of these files I could find. Update
the generation scripts where relevant.
Change-Id: Ia026cff269c1b7ae7386dd3619bc9bb6a5332837
Approved-By: Pedro Alves <pedro@palves.net>
|
|
This reverts commit 5920765d7513aaae9241a1850d62d73e0477f81c.
|
|
This reverts commit 0a7bb97ad2f2fe2d18a442dad265051e34eab13e.
|
|
This reverts commit 7816b81e9b36ea0f57662bfd7446b573bf0c9e54.
|
|
This reverts commit cd9b374ffe372dcaf7e4c15548cf53a301d8dcdd.
|
|
This reverts commit 61bb321605fc74703adc994fd7a78e9d2495ca7a.
|
|
This reverts commit 198ff6ff819c240545f9fc68b39636fd376d4ba9.
|
|
This commit builds on the previous series of commits to share the
target description caching code between GDB and gdbserver for
x86/Linux targets.
The objective of this commit is to move the four functions (2 each of)
i386_linux_read_description and amd64_linux_read_description into
gdb/nat/x86-linux-tdesc.c and combine them so we have just a single
copy of each. Then both GDB and gdbserver will link against these
shared functions.
It is worth reading the description of the previous commit to see why
this merging is not as simple as it seems: on the gdbserver side we
actually have two users of these functions, gdbserver itself, and the
in process agent (IPA).
However, the previous commit streamlined the gdbserver code, and so
now it is simple to move the two functions along with all their
support functions from the gdbserver directory into the gdb/nat/
directory, and then GDB is fine to call these functions.
One small curiosity with this patch is the function
x86_linux_post_init_tdesc. On the gdbserver side the two functions
amd64_linux_read_description and i386_linux_read_description have some
functionality that is not present on the GDB side, that is some
additional configuration that is performed as each target description
is created to setup the expedited registers.
To support this I've added the function x86_linux_post_init_tdesc.
This function is called from the two *_linux_read_description
functions, but is implemented separately for GDB and gdbserver.
This does mean adding back some non-shared code when this whole series
has been about sharing code, but now the only non-shared bit is the
single line that is actually different between GDB and gdbserver, all
the rest, which is identical, is now shared.
I did need to add a new rule to the gdbserver Makefile, this is to
allow the nat/x86-linux-tdesc.c file to be compiled for the IPA.
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
|
This commit is part of a series which aims to share more of the target
description creation between GDB and gdbserver for x86/Linux.
After some refactoring, the previous commit actually started to share
some code, we added the shared x86_linux_tdesc_for_tid function into
nat/x86-linux-tdesc.c. However, this function still relies on
amd64_linux_read_description and i386_linux_read_description which are
implemented separately for both gdbserver and GDB. Given that at
their core, all these functions to is:
1. take an xcr0 value as input,
2. mask out some feature bits,
3. look for a cached pre-generated target description and return it
if found,
4. if no cached target description is found then call either
amd64_create_target_description or
i386_create_target_description to create a new target
description, which is then added to the cache. Return the newly
created target description.
The inner functions amd64_create_target_description and
i386_create_target_description are already shared between GDB and
gdbserver (in the gdb/arch/ directory), so the only thing that
the *_read_description functions really do is add the caching layer,
and it feels like this really could be shared.
However, we have a small problem.
On the GDB side we create target descriptions using a different set of
cpu features than on the gdbserver side! This means that for the
exact same target, we might get a different target description when
using native GDB vs using gdbserver. This surely feels like a
mistake, I would expect to get the same target description on each.
The table below shows the number of possible different target
descriptions that we can create on the GDB side vs on the gdbserver
side for each target type:
| GDB | gdbserver
------|-----|----------
i386 | 64 | 7
amd64 | 32 | 7
x32 | 16 | 7
So in theory, all I want to do is move the GDB version
of *_read_description into the nat/ directory and have gdbserver use
that, then both GDB and gdbserver would be able to create any of the
possible target descriptions.
Unfortunately it's a little more complex than that due to the in
process agent (IPA).
When the IPA is in use, gdbserver sends a target description index to
the IPA, and the IPA uses this to find the correct target description
to use.
** START OF AN ASIDE **
Back in the day I suspect this approach made perfect sense. However
since this commit:
commit a8806230241d201f808d856eaae4d44088117b0c
Date: Thu Dec 7 17:07:01 2017 +0000
Initialize target description early in IPA
I think passing the index is now more trouble than its worth.
We used to pass the index, and then use that index to lookup which
target description to instantiate and use. However, the above commit
fixed an issue where we can't call malloc() within (certain parts of)
the IPA (apparently), so instead we now pre-compute _every_ possible
target description within the IPA. The index is now only used to
lookup which of the (many) pre-computed target descriptions to use.
It would (I think) have been easier all around if the IPA just
self-inspected, figured out its own xcr0 value, and used that to
create the one target description that is required. So long as the
xcr0 to target description code is shared (at compile time) with
gdbserver, then we can be sure that the IPA will derive the same
target description as gdbserver, and we would avoid all this index
passing business, which has made this commit so very, very painful.
** END OF AN ASIDE **
Currently then for x86/linux, gdbserver sends a number between 0 and 7
to the IPA, and the IPA uses this to create a target description.
However, I am proposing that gdbserver should now create one of (up
to) 64 different target descriptions for i386, so this 0 to 7 index
isn't going to be good enough any more (amd64 and x32 have slightly
fewer possible target descriptions, but still more than 8, so the
problem is the same).
For a while I wondered if I was going to have to try and find some
backward compatible solution for this mess. But after seeing how
lightly the IPA is actually documented, I wonder if it is not the case
that there is a tight coupling between a version of gdbserver and a
version of the IPA? At least I'm hoping so.
In this commit I have thrown out the old IPA target description index
numbering scheme, and switched to a completely new numbering scheme.
Instead of the index that is passed being arbitrary, the index is
instead calculated from the set of cpu features that are present on
the target. Within the IPA we can then reverse this logic to recreate
the xcr0 value based on the index, and from the xcr0 value we can
create the correct target description.
With the gdbserver to IPA numbering scheme issue resolved I have then
update the gdbserver versions of amd64_linux_read_description and
i386_linux_read_description so that they create target descriptions
using the same set of cpu features as GDB itself.
After this gdbserver should now always come up with the same target
description as GDB does on any x86/Linux target.
This commit does not introduce any new code sharing between GDB and
gdbserver as previous commits in this series does. Instead this
commit is all about bringing GDB and gdbserver into alignment
functionally so that the next commit can merge the GDB and gdbserver
versions of these functions.
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
|
This commit is part of a series to share more of the x86 target
description creation code between GDB and gdbserver.
Unlike previous commits which were mostly refactoring, this commit is
the first that makes a real change, though that change should mostly
be for gdbserver; I've largely adopted the "GDB" way of doing things
for gdbserver, and this fixes a real gdbserver bug.
On a x86-64 Linux target, running the test:
gdb.server/connect-with-no-symbol-file.exp
results in two core files being created. Both of these core files are
from the inferior process, created after gdbserver has detached.
In this test a gdbserver process is started and then, after gdbserver
has started, but before GDB attaches, we either delete the inferior
executable, or change its permissions so it can't be read. Only after
doing this do we attempt to connect with GDB.
As GDB connects to gdbserver, gdbserver attempts to figure out the
target description so that it can send the description to GDB, this
involves a call to x86_linux_read_description.
In x86_linux_read_description one of the first things we do is try to
figure out if the process is 32-bit or 64-bit. To do this we look up
the executable via the thread-id, and then attempt to read the
architecture size from the executable. This isn't going to work if
the executable has been deleted, or is no longer readable.
And so, as we can't read the executable, we default to an i386 target
and use an i386 target description.
A consequence of using an i386 target description is that addresses
are assumed to be 32-bits. Here's an example session that shows the
problems this causes. This is run on an x86-64 machine, and the test
binary (xx.x) is a standard 64-bit x86-64 binary:
shell_1$ gdbserver --once localhost :54321 /tmp/xx.x
shell_2$ gdb -q
(gdb) set sysroot
(gdb) shell chmod 000 /tmp/xx.x
(gdb) target remote :54321
Remote debugging using :54321
warning: /tmp/xx.x: Permission denied.
0xf7fd3110 in ?? ()
(gdb) show architecture
The target architecture is set to "auto" (currently "i386").
(gdb) p/x $pc
$1 = 0xf7fd3110
(gdb) info proc mappings
process 2412639
Mapped address spaces:
Start Addr End Addr Size Offset Perms objfile
0x400000 0x401000 0x1000 0x0 r--p /tmp/xx.x
0x401000 0x402000 0x1000 0x1000 r-xp /tmp/xx.x
0x402000 0x403000 0x1000 0x2000 r--p /tmp/xx.x
0x403000 0x405000 0x2000 0x2000 rw-p /tmp/xx.x
0xf7fcb000 0xf7fcf000 0x4000 0x0 r--p [vvar]
0xf7fcf000 0xf7fd1000 0x2000 0x0 r-xp [vdso]
0xf7fd1000 0xf7fd3000 0x2000 0x0 r--p /usr/lib64/ld-2.30.so
0xf7fd3000 0xf7ff3000 0x20000 0x2000 r-xp /usr/lib64/ld-2.30.so
0xf7ff3000 0xf7ffb000 0x8000 0x22000 r--p /usr/lib64/ld-2.30.so
0xf7ffc000 0xf7ffe000 0x2000 0x2a000 rw-p /usr/lib64/ld-2.30.so
0xf7ffe000 0xf7fff000 0x1000 0x0 rw-p
0xfffda000 0xfffff000 0x25000 0x0 rw-p [stack]
0xff600000 0xff601000 0x1000 0x0 r-xp [vsyscall]
(gdb) info inferiors
Num Description Connection Executable
* 1 process 2412639 1 (remote :54321)
(gdb) shell cat /proc/2412639/maps
00400000-00401000 r--p 00000000 fd:03 45907133 /tmp/xx.x
00401000-00402000 r-xp 00001000 fd:03 45907133 /tmp/xx.x
00402000-00403000 r--p 00002000 fd:03 45907133 /tmp/xx.x
00403000-00405000 rw-p 00002000 fd:03 45907133 /tmp/xx.x
7ffff7fcb000-7ffff7fcf000 r--p 00000000 00:00 0 [vvar]
7ffff7fcf000-7ffff7fd1000 r-xp 00000000 00:00 0 [vdso]
7ffff7fd1000-7ffff7fd3000 r--p 00000000 fd:00 143904 /usr/lib64/ld-2.30.so
7ffff7fd3000-7ffff7ff3000 r-xp 00002000 fd:00 143904 /usr/lib64/ld-2.30.so
7ffff7ff3000-7ffff7ffb000 r--p 00022000 fd:00 143904 /usr/lib64/ld-2.30.so
7ffff7ffc000-7ffff7ffe000 rw-p 0002a000 fd:00 143904 /usr/lib64/ld-2.30.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
7ffffffda000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
(gdb)
Notice the difference between the mappings reported via GDB and those
reported directly from the kernel via /proc/PID/maps, the addresses of
every mapping is clamped to 32-bits for GDB, while the kernel reports
real 64-bit addresses.
Notice also that the $pc value is a 32-bit value. It appears to be
within one of the mappings reported by GDB, but is outside any of the
mappings reported from the kernel.
And this is where the problem arises. When gdbserver detaches from
the inferior we pass the inferior the address from which it should
resume. Due to the 32/64 bit confusion we tell the inferior to resume
from the 32-bit $pc value, which is not within any valid mapping, and
so, as soon as the inferior resumes, it segfaults.
If we look at how GDB (not gdbserver) figures out its target
description then we see an interesting difference. GDB doesn't try to
read the executable. Instead GDB uses ptrace to query the thread's
state, and uses this to figure out the if the thread is 32 or 64 bit.
If we update gdbserver to do it the "GDB" way then the above problem
is resolved, gdbserver now sees the process as 64-bit, and when we
detach from the inferior we give it the correct 64-bit address, and
the inferior no longer segfaults.
Now, I could just update the gdbserver code, but better, I think, to
share one copy of the code between GDB and gdbserver in gdb/nat/.
That is what this commit does.
The cores of x86_linux_read_description from gdbserver and
x86_linux_nat_target::read_description from GDB are moved into a new
file gdb/nat/x86-linux-tdesc.c and combined into a single function
x86_linux_tdesc_for_tid which is called from each location.
This new function does things the GDB way, the only changes are to
allow for the sharing; we now have a callback function to call the
first time that the xcr0 state is read, this allows for GDB and
gdbserver to perform their own initialisation as needed, and
additionally, the new function takes a pointer for where to cache the
xcr0 value, this isn't needed for this commit, but will be useful in a
later commit where gdbserver will want to read this cached xcr0
value.
Another thing to note about this commit is how the functions
i386_linux_read_description and amd64_linux_read_description are
handled. For now I've left these function as implemented separately
in GDB and gdbserver. I've moved the declarations of these functions
into gdb/nat/x86-linux-tdesc.h, but the implementations are left as
separate.
A later commit in this series will make these functions shared too,
but doing this is not trivial, so I've left that for a separate
commit. Merging the declarations as I've done here ensures that
everyone implements the function to the same API, and once these
functions are shared (in a later commit) we'll want a shared
declaration anyway.
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
|
Share the definition of I386_LINUX_XSAVE_XCR0_OFFSET between GDB and
gdbserver.
This commit is part of a series that aims to share more of the x86
target description creation code between GDB and gdbserver. The
I386_LINUX_XSAVE_XCR0_OFFSET #define is used as part of the target
description creation, and I noticed that this constant is defined
separately for GDB and gdbserver.
This commit moves the definition into gdb/nat/x86-linux.h, which
allows the #define to be shared.
There should be no user visible changes after this commit.
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
|
This commit is part of a series that aims to share more of the x86
target description reading/generation code between GDB and gdbserver.
There are a huge number of similarities between the code in
gdbserver's x86_linux_read_description function and GDB's
x86_linux_nat_target::read_description function, and it is this
similarity that I plan, in a later commit, to share between GDB and
gdbserver.
However, one thing that is different in x86_linux_read_description is
the code inside the '!use_xml' block. This is the code that handles
the case where gdbserver is not allowed to send an XML target
description back to GDB. In this case gdbserver uses some predefined,
fixed, target descriptions.
First, it's worth noting that I suspect this code is not tested any
more. I couldn't find anything in the testsuite that tries to disable
XML target description support. And the idea of having a single
"fixed" target description really doesn't work well when we think
about all the various x86 extensions that exist. Part of me would
like to rip out the no-xml support in gdbserver (at least for x86),
and if a GDB connects that doesn't support XML target descriptions,
gdbserver can just give an error and drop the connection. GDB has
supported XML target descriptions for 16 years now, I think it would
be reasonable for our shipped gdbserver to drop support for the old
way of doing things.
Anyway.... this commit doesn't do that.
What I did notice was that, over time, the '!use_xml' block appears to
have "drifted" within the x86_linux_read_description function; it's
now not the first check we do. Instead we make some ptrace calls and
return a target description generated based on the result of these
ptrace calls. Surely it only makes sense to generate variable target
descriptions if we can send these back to GDB?
So in this commit I propose to move the '!use_xml' block earlier in
the x86_linux_read_description function.
The benefit of this is that this leaves the later half of
x86_linux_read_description much more similar to the GDB function
x86_linux_nat_target::read_description and sets us up for potentially
sharing code between GDB and gdbserver in a later commit.
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
|
Convert the have_ptrace_getregset global within gdbserver to a
tribool. This brings the flag into alignment with the corresponding
flag in GDB.
The gdbserver have_ptrace_getregset variable is already used as a
tribool, it just doesn't have the tribool type.
In a future commit I plan to share more code between GDB and
gdbserver, and having this variable be the same type in both code
bases will make the sharing much easier.
There should be no user visible changes after this commit.
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
|
Since MPX isn't available for x32, we should clear X86_XSTATE_MPX bits
on x32.
PR server/31511
* linux-x86-low.cc (x86_linux_read_description): Clear
X86_XSTATE_MPX bits in xcr0 on x32.
Reviewed-by: Felix Willgerodt <felix.willgerodt@intel.com>
|
|
This commit is the result of the following actions:
- Running gdb/copyright.py to update all of the copyright headers to
include 2024,
- Manually updating a few files the copyright.py script told me to
update, these files had copyright headers embedded within the
file,
- Regenerating gdbsupport/Makefile.in to refresh it's copyright
date,
- Using grep to find other files that still mentioned 2023. If
these files were updated last year from 2022 to 2023 then I've
updated them this year to 2024.
I'm sure I've probably missed some dates. Feel free to fix them up as
you spot them.
|
|
Make x86_xcr0 private to i387-fp.cc and use i387_set_xsave_mask to set
the value instead. Add a static global instance of x86_xsave_layout
and initialize it in the new function as well to be used in a future
commit to parse XSAVE extended state regions.
Update the Linux port to use this function rather than setting
x86_xcr0 directly. In the case that XML is not supported, don't
bother setting x86_xcr0 to the default value but just omit the call to
i387_set_xsave_mask as i387-fp.cc defaults to the SSE case used for
non-XML.
In addition, use x86_xsave_length to determine the size of the XSAVE
register set via CPUID.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
|
This commit is the result of running the gdb/copyright.py script,
which automated the update of the copyright year range for all
source files managed by the GDB project to be updated to include
year 2023.
|
|
Commit 4855cbdc3d8f ("gdbserver/linux-x86: make is_64bit_tdesc accept
thread as a parameter") caused this when building in 32 bits / i386
mode:
CXX linux-x86-low.o
In file included from /home/smarchi/src/binutils-gdb/gdbserver/linux-x86-low.cc:24:
/home/smarchi/src/binutils-gdb/gdbserver/linux-x86-low.cc: In member function ‘virtual int x86_target::low_get_thread_area(int, CORE_ADDR*)’:
/home/smarchi/src/binutils-gdb/gdbserver/linux-x86-low.cc:357:47: error: ‘lwp’ was not declared in this scope
357 | struct thread_info *thr = get_lwp_thread (lwp);
| ^~~
/home/smarchi/src/binutils-gdb/gdbserver/linux-low.h:709:31: note: in definition of macro ‘get_lwp_thread’
709 | #define get_lwp_thread(lwp) ((lwp)->thread)
| ^~~
This is because it moved the lwp variable declaration inside the
__x86_64__ guard, making it unavailable when building in 32 bits mode.
Move the lwp variable outside of the __x86_64__ region.
Change-Id: I7fa3938c6b44b345c27a52c8b8d3ea12aba53e05
|
|
ps_get_thread_area receives as a parameter the lwpid it must work on.
It then calls is_64bit_tdesc, which uses the current_thread as the
thread to work on. However, it is not said that both are the same.
This became a problem when working in a following patch that makes
find_one_thread switch to a process but to no thread (current_thread ==
nullptr). When libthread_db needed to get the thread area,
is_64bit_tdesc would try to get the regcache of a nullptr thread.
Fix that by making is_64bit_tdesc accept the thread to work on as a
parameter. Find the right thread from the context, when possible (when
we know the lwpid to work on). Otherwise, pass "current_thread", to
retain the existing behavior.
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
Change-Id: I44394d6be92392fa28de71982fd04517ce8a3007
|
|
Add the threads_debug_printf and THREADS_SCOPED_DEBUG_ENTER_EXIT, which
use the logging infrastructure from gdbsupport/common-debug.h. Replace
all debug_print uses that are predicated by debug_threads with
threads_dethreads_debug_printf. Replace uses of the debug_enter and
debug_exit macros with THREADS_SCOPED_DEBUG_ENTER_EXIT, which serves
essentially the same purpose, but allows showing what comes between the
enter and the exit in an indented form.
Note that "threads" debug is currently used for a bit of everything in
GDBserver, not only threads related stuff. It should ideally be cleaned
up and separated logically as is done in GDB, but that's out of the
scope of this patch.
Change-Id: I2d4546464462cb4c16f7f1168c5cec5a89f2289a
|
|
This commit brings all the changes made by running gdb/copyright.py
as per GDB's Start of New Year Procedure.
For the avoidance of doubt, all changes in this commits were
performed by the script.
|
|
Replace the direct assignments to current_thread with
switch_to_thread. Use scoped_restore_current_thread when appropriate.
There is one instance remaining in linux-low.cc's wait_for_sigstop.
This will be handled in a separate patch.
Regression-tested on X86-64 Linux using the native-gdbserver and
native-extended-gdbserver board files.
|
|
I'm trying to enable clang's -Wmissing-variable-declarations warning.
This patch fixes all the obvious spots where we can simply add "static"
(at least, found when building on x86-64 Linux).
gdb/ChangeLog:
* aarch64-linux-tdep.c (aarch64_linux_record_tdep): Make static.
* aarch64-tdep.c (tdesc_aarch64_list, aarch64_prologue_unwind,
aarch64_stub_unwind, aarch64_normal_base, ): Make static.
* arm-linux-tdep.c (arm_prologue_unwind): Make static.
* arm-tdep.c (struct frame_unwind): Make static.
* auto-load.c (auto_load_safe_path_vec): Make static.
* csky-tdep.c (csky_stub_unwind): Make static.
* gdbarch.c (gdbarch_data_registry): Make static.
* gnu-v2-abi.c (gnu_v2_abi_ops): Make static.
* i386-netbsd-tdep.c (i386nbsd_mc_reg_offset): Make static.
* i386-tdep.c (i386_frame_setup_skip_insns,
i386_tramp_chain_in_reg_insns, i386_tramp_chain_on_stack_insns):
Make static.
* infrun.c (observer_mode): Make static.
* linux-nat.c (sigchld_action): Make static.
* linux-thread-db.c (thread_db_list): Make static.
* maint-test-options.c (maintenance_test_options_list):
* mep-tdep.c (mep_csr_registers): Make static.
* mi/mi-cmds.c (struct mi_cmd_stats): Remove struct type name.
(stats): Make static.
* nat/linux-osdata.c (struct osdata_type): Make static.
* ppc-netbsd-tdep.c (ppcnbsd_reg_offsets): Make static.
* progspace.c (last_program_space_num): Make static.
* python/py-param.c (struct parm_constant): Remove struct type
name.
(parm_constants): Make static.
* python/py-record-btrace.c (btpy_list_methods): Make static.
* python/py-record.c (recpy_gap_type): Make static.
* record.c (record_goto_cmdlist): Make static.
* regcache.c (regcache_descr_handle): Make static.
* registry.h (DEFINE_REGISTRY): Make definition static.
* symmisc.c (std_in, std_out, std_err): Make static.
* top.c (previous_saved_command_line): Make static.
* tracepoint.c (trace_user, trace_notes, trace_stop_notes): Make
static.
* unittests/command-def-selftests.c (nr_duplicates,
nr_invalid_prefixcmd, lists): Make static.
* unittests/observable-selftests.c (test_notification): Make
static.
* unittests/optional/assignment/1.cc (counter): Make static.
* unittests/optional/assignment/2.cc (counter): Make static.
* unittests/optional/assignment/3.cc (counter): Make static.
* unittests/optional/assignment/4.cc (counter): Make static.
* unittests/optional/assignment/5.cc (counter): Make static.
* unittests/optional/assignment/6.cc (counter): Make static.
gdbserver/ChangeLog:
* ax.cc (bytecode_address_table): Make static.
* debug.cc (debug_file): Make static.
* linux-low.cc (stopping_threads): Make static.
(step_over_bkpt): Make static.
* linux-x86-low.cc (amd64_emit_ops, i386_emit_ops): Make static.
* tracepoint.cc (stop_tracing_bkpt, flush_trace_buffer_bkpt,
alloced_trace_state_variables, trace_buffer_ctrl,
tracing_start_time, tracing_stop_time, tracing_user_name,
tracing_notes, tracing_stop_note): Make static.
Change-Id: Ic1d8034723b7802502bda23770893be2338ab020
|
|
Consider a minimal test-case test.c:
...
int main (void) { return 0; }
...
compiled with -m32:
...
$ gcc test.c -m32
...
When running the exec using gdbserver on openSUSE Factory (currently running a
linux kernel version 5.10.5):
...
$ gdbserver localhost:12345 a.out
...
to which we connect in a gdb session, we run into a segfault in the inferior:
...
$ gdb -batch -q -ex "target remote localhost:12345" -ex continue
Program received signal SIGSEGV, Segmentation fault.
0xf7dd8bd2 in init_cacheinfo () at ../sysdeps/x86/cacheinfo.c:761
...
The segfault is caused by gdbserver overwriting $gs_base with 0 using
PTRACE_SETREGS. After it is overwritten, the next use of $gs in the inferior
will trigger the segfault.
Before linux kernel version 5.9, the value used by PTRACE_SETREGS for $gs_base
was ignored, but starting version 5.9, the linux kernel has support for
intel architecture extension FSGSBASE, which allows users to modify $gs_base,
and consequently PTRACE_SETREGS can no longer ignore the $gs_base value.
The overwrite of $gs_base with 0 is done by a memset in x86_fill_gregset,
which was added in commit 9e0aa64f551 "Fix gdbserver qGetTLSAddr for
x86_64 -m32". The memset intends to zero-extend 32-bit registers that are
tracked in the regcache to 64-bit when writing them into the PTRACE_SETREGS
data argument. But in addition, it overwrites other registers that are
not tracked in the regcache, such as $gs_base.
Fix the segfault by redoing the fix from commit 9e0aa64f551 in minimal form.
Tested on x86_64-linux:
- openSUSE Leap 15.2 (using kernel version 5.3.18):
- native
- gdbserver -m32
- -m32
- openSUSE Factory (using kernel version 5.10.5):
- native
- m32
gdbserver/ChangeLog:
2021-01-20 Tom de Vries <tdevries@suse.de>
* linux-x86-low.cc (collect_register_i386): New function.
(x86_fill_gregset): Remove memset. Use collect_register_i386.
|
|
This commits the result of running gdb/copyright.py as per our Start
of New Year procedure...
gdb/ChangeLog
Update copyright year range in copyright header of all GDB files.
|
|
Many spots incorrectly use only spaces for indentation (for example,
there are a lot of spots in ada-lang.c). I've always found it awkward
when I needed to edit one of these spots: do I keep the original wrong
indentation, or do I fix it? What if the lines around it are also
wrong, do I fix them too? I probably don't want to fix them in the same
patch, to avoid adding noise to my patch.
So I propose to fix as much as possible once and for all (hopefully).
One typical counter argument for this is that it makes code archeology
more difficult, because git-blame will show this commit as the last
change for these lines. My counter counter argument is: when
git-blaming, you often need to do "blame the file at the parent commit"
anyway, to go past some other refactor that touched the line you are
interested in, but is not the change you are looking for. So you
already need a somewhat efficient way to do this.
Using some interactive tool, rather than plain git-blame, makes this
trivial. For example, I use "tig blame <file>", where going back past
the commit that changed the currently selected line is one keystroke.
It looks like Magit in Emacs does it too (though I've never used it).
Web viewers of Github and Gitlab do it too. My point is that it won't
really make archeology more difficult.
The other typical counter argument is that it will cause conflicts with
existing patches. That's true... but it's a one time cost, and those
are not conflicts that are difficult to resolve. I have also tried "git
rebase --ignore-whitespace", it seems to work well. Although that will
re-introduce the faulty indentation, so one needs to take care of fixing
the indentation in the patch after that (which is easy).
gdb/ChangeLog:
* aarch64-linux-tdep.c: Fix indentation.
* aarch64-ravenscar-thread.c: Fix indentation.
* aarch64-tdep.c: Fix indentation.
* aarch64-tdep.h: Fix indentation.
* ada-lang.c: Fix indentation.
* ada-lang.h: Fix indentation.
* ada-tasks.c: Fix indentation.
* ada-typeprint.c: Fix indentation.
* ada-valprint.c: Fix indentation.
* ada-varobj.c: Fix indentation.
* addrmap.c: Fix indentation.
* addrmap.h: Fix indentation.
* agent.c: Fix indentation.
* aix-thread.c: Fix indentation.
* alpha-bsd-nat.c: Fix indentation.
* alpha-linux-tdep.c: Fix indentation.
* alpha-mdebug-tdep.c: Fix indentation.
* alpha-nbsd-tdep.c: Fix indentation.
* alpha-obsd-tdep.c: Fix indentation.
* alpha-tdep.c: Fix indentation.
* amd64-bsd-nat.c: Fix indentation.
* amd64-darwin-tdep.c: Fix indentation.
* amd64-linux-nat.c: Fix indentation.
* amd64-linux-tdep.c: Fix indentation.
* amd64-nat.c: Fix indentation.
* amd64-obsd-tdep.c: Fix indentation.
* amd64-tdep.c: Fix indentation.
* amd64-windows-tdep.c: Fix indentation.
* annotate.c: Fix indentation.
* arc-tdep.c: Fix indentation.
* arch-utils.c: Fix indentation.
* arch/arm-get-next-pcs.c: Fix indentation.
* arch/arm.c: Fix indentation.
* arm-linux-nat.c: Fix indentation.
* arm-linux-tdep.c: Fix indentation.
* arm-nbsd-tdep.c: Fix indentation.
* arm-pikeos-tdep.c: Fix indentation.
* arm-tdep.c: Fix indentation.
* arm-tdep.h: Fix indentation.
* arm-wince-tdep.c: Fix indentation.
* auto-load.c: Fix indentation.
* auxv.c: Fix indentation.
* avr-tdep.c: Fix indentation.
* ax-gdb.c: Fix indentation.
* ax-general.c: Fix indentation.
* bfin-linux-tdep.c: Fix indentation.
* block.c: Fix indentation.
* block.h: Fix indentation.
* blockframe.c: Fix indentation.
* bpf-tdep.c: Fix indentation.
* break-catch-sig.c: Fix indentation.
* break-catch-syscall.c: Fix indentation.
* break-catch-throw.c: Fix indentation.
* breakpoint.c: Fix indentation.
* breakpoint.h: Fix indentation.
* bsd-uthread.c: Fix indentation.
* btrace.c: Fix indentation.
* build-id.c: Fix indentation.
* buildsym-legacy.h: Fix indentation.
* buildsym.c: Fix indentation.
* c-typeprint.c: Fix indentation.
* c-valprint.c: Fix indentation.
* c-varobj.c: Fix indentation.
* charset.c: Fix indentation.
* cli/cli-cmds.c: Fix indentation.
* cli/cli-decode.c: Fix indentation.
* cli/cli-decode.h: Fix indentation.
* cli/cli-script.c: Fix indentation.
* cli/cli-setshow.c: Fix indentation.
* coff-pe-read.c: Fix indentation.
* coffread.c: Fix indentation.
* compile/compile-cplus-types.c: Fix indentation.
* compile/compile-object-load.c: Fix indentation.
* compile/compile-object-run.c: Fix indentation.
* completer.c: Fix indentation.
* corefile.c: Fix indentation.
* corelow.c: Fix indentation.
* cp-abi.h: Fix indentation.
* cp-namespace.c: Fix indentation.
* cp-support.c: Fix indentation.
* cp-valprint.c: Fix indentation.
* cris-linux-tdep.c: Fix indentation.
* cris-tdep.c: Fix indentation.
* darwin-nat-info.c: Fix indentation.
* darwin-nat.c: Fix indentation.
* darwin-nat.h: Fix indentation.
* dbxread.c: Fix indentation.
* dcache.c: Fix indentation.
* disasm.c: Fix indentation.
* dtrace-probe.c: Fix indentation.
* dwarf2/abbrev.c: Fix indentation.
* dwarf2/attribute.c: Fix indentation.
* dwarf2/expr.c: Fix indentation.
* dwarf2/frame.c: Fix indentation.
* dwarf2/index-cache.c: Fix indentation.
* dwarf2/index-write.c: Fix indentation.
* dwarf2/line-header.c: Fix indentation.
* dwarf2/loc.c: Fix indentation.
* dwarf2/macro.c: Fix indentation.
* dwarf2/read.c: Fix indentation.
* dwarf2/read.h: Fix indentation.
* elfread.c: Fix indentation.
* eval.c: Fix indentation.
* event-top.c: Fix indentation.
* exec.c: Fix indentation.
* exec.h: Fix indentation.
* expprint.c: Fix indentation.
* f-lang.c: Fix indentation.
* f-typeprint.c: Fix indentation.
* f-valprint.c: Fix indentation.
* fbsd-nat.c: Fix indentation.
* fbsd-tdep.c: Fix indentation.
* findvar.c: Fix indentation.
* fork-child.c: Fix indentation.
* frame-unwind.c: Fix indentation.
* frame-unwind.h: Fix indentation.
* frame.c: Fix indentation.
* frv-linux-tdep.c: Fix indentation.
* frv-tdep.c: Fix indentation.
* frv-tdep.h: Fix indentation.
* ft32-tdep.c: Fix indentation.
* gcore.c: Fix indentation.
* gdb_bfd.c: Fix indentation.
* gdbarch.sh: Fix indentation.
* gdbarch.c: Re-generate
* gdbarch.h: Re-generate.
* gdbcore.h: Fix indentation.
* gdbthread.h: Fix indentation.
* gdbtypes.c: Fix indentation.
* gdbtypes.h: Fix indentation.
* glibc-tdep.c: Fix indentation.
* gnu-nat.c: Fix indentation.
* gnu-nat.h: Fix indentation.
* gnu-v2-abi.c: Fix indentation.
* gnu-v3-abi.c: Fix indentation.
* go32-nat.c: Fix indentation.
* guile/guile-internal.h: Fix indentation.
* guile/scm-cmd.c: Fix indentation.
* guile/scm-frame.c: Fix indentation.
* guile/scm-iterator.c: Fix indentation.
* guile/scm-math.c: Fix indentation.
* guile/scm-ports.c: Fix indentation.
* guile/scm-pretty-print.c: Fix indentation.
* guile/scm-value.c: Fix indentation.
* h8300-tdep.c: Fix indentation.
* hppa-linux-nat.c: Fix indentation.
* hppa-linux-tdep.c: Fix indentation.
* hppa-nbsd-nat.c: Fix indentation.
* hppa-nbsd-tdep.c: Fix indentation.
* hppa-obsd-nat.c: Fix indentation.
* hppa-tdep.c: Fix indentation.
* hppa-tdep.h: Fix indentation.
* i386-bsd-nat.c: Fix indentation.
* i386-darwin-nat.c: Fix indentation.
* i386-darwin-tdep.c: Fix indentation.
* i386-dicos-tdep.c: Fix indentation.
* i386-gnu-nat.c: Fix indentation.
* i386-linux-nat.c: Fix indentation.
* i386-linux-tdep.c: Fix indentation.
* i386-nto-tdep.c: Fix indentation.
* i386-obsd-tdep.c: Fix indentation.
* i386-sol2-nat.c: Fix indentation.
* i386-tdep.c: Fix indentation.
* i386-tdep.h: Fix indentation.
* i386-windows-tdep.c: Fix indentation.
* i387-tdep.c: Fix indentation.
* i387-tdep.h: Fix indentation.
* ia64-libunwind-tdep.c: Fix indentation.
* ia64-libunwind-tdep.h: Fix indentation.
* ia64-linux-nat.c: Fix indentation.
* ia64-linux-tdep.c: Fix indentation.
* ia64-tdep.c: Fix indentation.
* ia64-tdep.h: Fix indentation.
* ia64-vms-tdep.c: Fix indentation.
* infcall.c: Fix indentation.
* infcmd.c: Fix indentation.
* inferior.c: Fix indentation.
* infrun.c: Fix indentation.
* iq2000-tdep.c: Fix indentation.
* language.c: Fix indentation.
* linespec.c: Fix indentation.
* linux-fork.c: Fix indentation.
* linux-nat.c: Fix indentation.
* linux-tdep.c: Fix indentation.
* linux-thread-db.c: Fix indentation.
* lm32-tdep.c: Fix indentation.
* m2-lang.c: Fix indentation.
* m2-typeprint.c: Fix indentation.
* m2-valprint.c: Fix indentation.
* m32c-tdep.c: Fix indentation.
* m32r-linux-tdep.c: Fix indentation.
* m32r-tdep.c: Fix indentation.
* m68hc11-tdep.c: Fix indentation.
* m68k-bsd-nat.c: Fix indentation.
* m68k-linux-nat.c: Fix indentation.
* m68k-linux-tdep.c: Fix indentation.
* m68k-tdep.c: Fix indentation.
* machoread.c: Fix indentation.
* macrocmd.c: Fix indentation.
* macroexp.c: Fix indentation.
* macroscope.c: Fix indentation.
* macrotab.c: Fix indentation.
* macrotab.h: Fix indentation.
* main.c: Fix indentation.
* mdebugread.c: Fix indentation.
* mep-tdep.c: Fix indentation.
* mi/mi-cmd-catch.c: Fix indentation.
* mi/mi-cmd-disas.c: Fix indentation.
* mi/mi-cmd-env.c: Fix indentation.
* mi/mi-cmd-stack.c: Fix indentation.
* mi/mi-cmd-var.c: Fix indentation.
* mi/mi-cmds.c: Fix indentation.
* mi/mi-main.c: Fix indentation.
* mi/mi-parse.c: Fix indentation.
* microblaze-tdep.c: Fix indentation.
* minidebug.c: Fix indentation.
* minsyms.c: Fix indentation.
* mips-linux-nat.c: Fix indentation.
* mips-linux-tdep.c: Fix indentation.
* mips-nbsd-tdep.c: Fix indentation.
* mips-tdep.c: Fix indentation.
* mn10300-linux-tdep.c: Fix indentation.
* mn10300-tdep.c: Fix indentation.
* moxie-tdep.c: Fix indentation.
* msp430-tdep.c: Fix indentation.
* namespace.h: Fix indentation.
* nat/fork-inferior.c: Fix indentation.
* nat/gdb_ptrace.h: Fix indentation.
* nat/linux-namespaces.c: Fix indentation.
* nat/linux-osdata.c: Fix indentation.
* nat/netbsd-nat.c: Fix indentation.
* nat/x86-dregs.c: Fix indentation.
* nbsd-nat.c: Fix indentation.
* nbsd-tdep.c: Fix indentation.
* nios2-linux-tdep.c: Fix indentation.
* nios2-tdep.c: Fix indentation.
* nto-procfs.c: Fix indentation.
* nto-tdep.c: Fix indentation.
* objfiles.c: Fix indentation.
* objfiles.h: Fix indentation.
* opencl-lang.c: Fix indentation.
* or1k-tdep.c: Fix indentation.
* osabi.c: Fix indentation.
* osabi.h: Fix indentation.
* osdata.c: Fix indentation.
* p-lang.c: Fix indentation.
* p-typeprint.c: Fix indentation.
* p-valprint.c: Fix indentation.
* parse.c: Fix indentation.
* ppc-linux-nat.c: Fix indentation.
* ppc-linux-tdep.c: Fix indentation.
* ppc-nbsd-nat.c: Fix indentation.
* ppc-nbsd-tdep.c: Fix indentation.
* ppc-obsd-nat.c: Fix indentation.
* ppc-ravenscar-thread.c: Fix indentation.
* ppc-sysv-tdep.c: Fix indentation.
* ppc64-tdep.c: Fix indentation.
* printcmd.c: Fix indentation.
* proc-api.c: Fix indentation.
* producer.c: Fix indentation.
* producer.h: Fix indentation.
* prologue-value.c: Fix indentation.
* prologue-value.h: Fix indentation.
* psymtab.c: Fix indentation.
* python/py-arch.c: Fix indentation.
* python/py-bpevent.c: Fix indentation.
* python/py-event.c: Fix indentation.
* python/py-event.h: Fix indentation.
* python/py-finishbreakpoint.c: Fix indentation.
* python/py-frame.c: Fix indentation.
* python/py-framefilter.c: Fix indentation.
* python/py-inferior.c: Fix indentation.
* python/py-infthread.c: Fix indentation.
* python/py-objfile.c: Fix indentation.
* python/py-prettyprint.c: Fix indentation.
* python/py-registers.c: Fix indentation.
* python/py-signalevent.c: Fix indentation.
* python/py-stopevent.c: Fix indentation.
* python/py-stopevent.h: Fix indentation.
* python/py-threadevent.c: Fix indentation.
* python/py-tui.c: Fix indentation.
* python/py-unwind.c: Fix indentation.
* python/py-value.c: Fix indentation.
* python/py-xmethods.c: Fix indentation.
* python/python-internal.h: Fix indentation.
* python/python.c: Fix indentation.
* ravenscar-thread.c: Fix indentation.
* record-btrace.c: Fix indentation.
* record-full.c: Fix indentation.
* record.c: Fix indentation.
* reggroups.c: Fix indentation.
* regset.h: Fix indentation.
* remote-fileio.c: Fix indentation.
* remote.c: Fix indentation.
* reverse.c: Fix indentation.
* riscv-linux-tdep.c: Fix indentation.
* riscv-ravenscar-thread.c: Fix indentation.
* riscv-tdep.c: Fix indentation.
* rl78-tdep.c: Fix indentation.
* rs6000-aix-tdep.c: Fix indentation.
* rs6000-lynx178-tdep.c: Fix indentation.
* rs6000-nat.c: Fix indentation.
* rs6000-tdep.c: Fix indentation.
* rust-lang.c: Fix indentation.
* rx-tdep.c: Fix indentation.
* s12z-tdep.c: Fix indentation.
* s390-linux-tdep.c: Fix indentation.
* score-tdep.c: Fix indentation.
* ser-base.c: Fix indentation.
* ser-mingw.c: Fix indentation.
* ser-uds.c: Fix indentation.
* ser-unix.c: Fix indentation.
* serial.c: Fix indentation.
* sh-linux-tdep.c: Fix indentation.
* sh-nbsd-tdep.c: Fix indentation.
* sh-tdep.c: Fix indentation.
* skip.c: Fix indentation.
* sol-thread.c: Fix indentation.
* solib-aix.c: Fix indentation.
* solib-darwin.c: Fix indentation.
* solib-frv.c: Fix indentation.
* solib-svr4.c: Fix indentation.
* solib.c: Fix indentation.
* source.c: Fix indentation.
* sparc-linux-tdep.c: Fix indentation.
* sparc-nbsd-tdep.c: Fix indentation.
* sparc-obsd-tdep.c: Fix indentation.
* sparc-ravenscar-thread.c: Fix indentation.
* sparc-tdep.c: Fix indentation.
* sparc64-linux-tdep.c: Fix indentation.
* sparc64-nbsd-tdep.c: Fix indentation.
* sparc64-obsd-tdep.c: Fix indentation.
* sparc64-tdep.c: Fix indentation.
* stabsread.c: Fix indentation.
* stack.c: Fix indentation.
* stap-probe.c: Fix indentation.
* stubs/ia64vms-stub.c: Fix indentation.
* stubs/m32r-stub.c: Fix indentation.
* stubs/m68k-stub.c: Fix indentation.
* stubs/sh-stub.c: Fix indentation.
* stubs/sparc-stub.c: Fix indentation.
* symfile-mem.c: Fix indentation.
* symfile.c: Fix indentation.
* symfile.h: Fix indentation.
* symmisc.c: Fix indentation.
* symtab.c: Fix indentation.
* symtab.h: Fix indentation.
* target-float.c: Fix indentation.
* target.c: Fix indentation.
* target.h: Fix indentation.
* tic6x-tdep.c: Fix indentation.
* tilegx-linux-tdep.c: Fix indentation.
* tilegx-tdep.c: Fix indentation.
* top.c: Fix indentation.
* tracefile-tfile.c: Fix indentation.
* tracepoint.c: Fix indentation.
* tui/tui-disasm.c: Fix indentation.
* tui/tui-io.c: Fix indentation.
* tui/tui-regs.c: Fix indentation.
* tui/tui-stack.c: Fix indentation.
* tui/tui-win.c: Fix indentation.
* tui/tui-winsource.c: Fix indentation.
* tui/tui.c: Fix indentation.
* typeprint.c: Fix indentation.
* ui-out.h: Fix indentation.
* unittests/copy_bitwise-selftests.c: Fix indentation.
* unittests/memory-map-selftests.c: Fix indentation.
* utils.c: Fix indentation.
* v850-tdep.c: Fix indentation.
* valarith.c: Fix indentation.
* valops.c: Fix indentation.
* valprint.c: Fix indentation.
* valprint.h: Fix indentation.
* value.c: Fix indentation.
* value.h: Fix indentation.
* varobj.c: Fix indentation.
* vax-tdep.c: Fix indentation.
* windows-nat.c: Fix indentation.
* windows-tdep.c: Fix indentation.
* xcoffread.c: Fix indentation.
* xml-syscall.c: Fix indentation.
* xml-tdesc.c: Fix indentation.
* xstormy16-tdep.c: Fix indentation.
* xtensa-config.c: Fix indentation.
* xtensa-linux-nat.c: Fix indentation.
* xtensa-linux-tdep.c: Fix indentation.
* xtensa-tdep.c: Fix indentation.
gdbserver/ChangeLog:
* ax.cc: Fix indentation.
* dll.cc: Fix indentation.
* inferiors.h: Fix indentation.
* linux-low.cc: Fix indentation.
* linux-nios2-low.cc: Fix indentation.
* linux-ppc-ipa.cc: Fix indentation.
* linux-ppc-low.cc: Fix indentation.
* linux-x86-low.cc: Fix indentation.
* linux-xtensa-low.cc: Fix indentation.
* regcache.cc: Fix indentation.
* server.cc: Fix indentation.
* tracepoint.cc: Fix indentation.
gdbsupport/ChangeLog:
* common-exceptions.h: Fix indentation.
* event-loop.cc: Fix indentation.
* fileio.cc: Fix indentation.
* filestuff.cc: Fix indentation.
* gdb-dlfcn.cc: Fix indentation.
* gdb_string_view.h: Fix indentation.
* job-control.cc: Fix indentation.
* signals.cc: Fix indentation.
Change-Id: I4bad7ae6be0fbe14168b8ebafb98ffe14964a695
|
|
Update allocate_target_description to return a target_desc_up, a
specialisation of unique_ptr.
This commit does not attempt to make use of the unique_ptr in the
best possible way, in almost all cases we immediately release the
pointer from within the unique_ptr and then continue as before.
There are a few places where it was easy to handle the unique_ptr, and
in these cases I've done that.
Everything under gdb/features/* is auto-regenerated.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* arch/aarch32.c (aarch32_create_target_description): Release
unique_ptr returned from allocate_target_description.
* arch/aarch64.c (aarch64_create_target_description): Likewise.
* arch/amd64.c (amd64_create_target_description): Likewise.
* arch/arc.c (arc_create_target_description): Likewise.
* arch/arm.c (arm_create_target_description): Likewise.
* arch/i386.c (i386_create_target_description): Likewise.
* arch/riscv.c (riscv_create_target_description): Update return
type. Handle allocate_target_description returning a unique_ptr.
(riscv_lookup_target_description): Update to handle unique_ptr.
* arch/tic6x.c (tic6x_create_target_description): Release
unique_ptr returned from allocate_target_description.
* features/microblaze-with-stack-protect.c: Regenerate.
* features/microblaze.c: Regenerate.
* features/mips-dsp-linux.c: Regenerate.
* features/mips-linux.c: Regenerate.
* features/mips64-dsp-linux.c: Regenerate.
* features/mips64-linux.c: Regenerate.
* features/nds32.c: Regenerate.
* features/nios2.c: Regenerate.
* features/or1k.c: Regenerate.
* features/rs6000/powerpc-32.c: Regenerate.
* features/rs6000/powerpc-32l.c: Regenerate.
* features/rs6000/powerpc-403.c: Regenerate.
* features/rs6000/powerpc-403gc.c: Regenerate.
* features/rs6000/powerpc-405.c: Regenerate.
* features/rs6000/powerpc-505.c: Regenerate.
* features/rs6000/powerpc-601.c: Regenerate.
* features/rs6000/powerpc-602.c: Regenerate.
* features/rs6000/powerpc-603.c: Regenerate.
* features/rs6000/powerpc-604.c: Regenerate.
* features/rs6000/powerpc-64.c: Regenerate.
* features/rs6000/powerpc-64l.c: Regenerate.
* features/rs6000/powerpc-7400.c: Regenerate.
* features/rs6000/powerpc-750.c: Regenerate.
* features/rs6000/powerpc-860.c: Regenerate.
* features/rs6000/powerpc-altivec32.c: Regenerate.
* features/rs6000/powerpc-altivec32l.c: Regenerate.
* features/rs6000/powerpc-altivec64.c: Regenerate.
* features/rs6000/powerpc-altivec64l.c: Regenerate.
* features/rs6000/powerpc-e500.c: Regenerate.
* features/rs6000/powerpc-e500l.c: Regenerate.
* features/rs6000/powerpc-isa205-32l.c: Regenerate.
* features/rs6000/powerpc-isa205-64l.c: Regenerate.
* features/rs6000/powerpc-isa205-altivec32l.c: Regenerate.
* features/rs6000/powerpc-isa205-altivec64l.c: Regenerate.
* features/rs6000/powerpc-isa205-ppr-dscr-vsx32l.c: Regenerate.
* features/rs6000/powerpc-isa205-ppr-dscr-vsx64l.c: Regenerate.
* features/rs6000/powerpc-isa205-vsx32l.c: Regenerate.
* features/rs6000/powerpc-isa205-vsx64l.c: Regenerate.
* features/rs6000/powerpc-isa207-htm-vsx32l.c: Regenerate.
* features/rs6000/powerpc-isa207-htm-vsx64l.c: Regenerate.
* features/rs6000/powerpc-isa207-vsx32l.c: Regenerate.
* features/rs6000/powerpc-isa207-vsx64l.c: Regenerate.
* features/rs6000/powerpc-vsx32.c: Regenerate.
* features/rs6000/powerpc-vsx32l.c: Regenerate.
* features/rs6000/powerpc-vsx64.c: Regenerate.
* features/rs6000/powerpc-vsx64l.c: Regenerate.
* features/rs6000/rs6000.c: Regenerate.
* features/rx.c: Regenerate.
* features/s390-gs-linux64.c: Regenerate.
* features/s390-linux32.c: Regenerate.
* features/s390-linux32v1.c: Regenerate.
* features/s390-linux32v2.c: Regenerate.
* features/s390-linux64.c: Regenerate.
* features/s390-linux64v1.c: Regenerate.
* features/s390-linux64v2.c: Regenerate.
* features/s390-te-linux64.c: Regenerate.
* features/s390-tevx-linux64.c: Regenerate.
* features/s390-vx-linux64.c: Regenerate.
* features/s390x-gs-linux64.c: Regenerate.
* features/s390x-linux64.c: Regenerate.
* features/s390x-linux64v1.c: Regenerate.
* features/s390x-linux64v2.c: Regenerate.
* features/s390x-te-linux64.c: Regenerate.
* features/s390x-tevx-linux64.c: Regenerate.
* features/s390x-vx-linux64.c: Regenerate.
* mips-tdep.c (_initialize_mips_tdep): Release unique_ptr returned
from allocate_target_description.
* target-descriptions.c (allocate_target_description): Update
return type.
(print_c_tdesc::visit_pre): Release unique_ptr returned from
allocate_target_description.
gdbserver/ChangeLog:
* linux-low.cc (linux_process_target::handle_extended_wait):
Release the unique_ptr returned from allocate_target_description.
* linux-riscv-low.cc (riscv_target::low_arch_setup): Likewise.
* linux-x86-low.cc (tdesc_amd64_linux_no_xml): Change type.
(tdesc_i386_linux_no_xml): Change type.
(x86_linux_read_description): Borrow pointer from unique_ptr
object.
(x86_target::get_ipa_tdesc_idx): Likewise.
(initialize_low_arch): Likewise.
* tdesc.cc (allocate_target_description): Update return type.
gdbsupport/ChangeLog:
* tdesc.h (allocate_target_description): Update return type.
|
|
My understanding is that it's mildly better to use a static const
array, as opposed to a "const char *", for a global string constant,
when possible. This makes sense to me because the pointer requires a
load from an address, whereas the array is just the address.
So, I searched for these in gdb and gdbserver. This patch fixes the
ones I found.
gdb/ChangeLog
2020-09-15 Tom Tromey <tromey@adacore.com>
* unittests/memory-map-selftests.c (valid_mem_map): Now array.
* ui-style.c (ansi_regex_text): Now array.
* rust-exp.y (number_regex_text): Now array.
* linespec.c (linespec_quote_characters): Now array.
* jit.c (jit_break_name, jit_descriptor_name, reader_init_fn_sym):
Now arrays.
gdbserver/ChangeLog
2020-09-15 Tom Tromey <tromey@adacore.com>
* linux-x86-low.cc (xmltarget_i386_linux_no_xml)
(xmltarget_amd64_linux_no_xml): Now arrays.
|
|
When building gdbserver with AddressSanitizer, I get this annoying
little leak when gdbserver exits:
==307817==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 14 byte(s) in 1 object(s) allocated from:
#0 0x7f7fd4256459 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x563bef981b80 in xmalloc /home/simark/src/binutils-gdb/gdbserver/../gdb/alloc.c:60
#2 0x563befb53301 in xstrdup /home/simark/src/binutils-gdb/libiberty/xstrdup.c:34
#3 0x563bef9d742b in handle_query /home/simark/src/binutils-gdb/gdbserver/server.cc:2286
#4 0x563bef9ed0b7 in process_serial_event /home/simark/src/binutils-gdb/gdbserver/server.cc:4061
#5 0x563bef9f1d9e in handle_serial_event(int, void*) /home/simark/src/binutils-gdb/gdbserver/server.cc:4402
#6 0x563befb0ec65 in handle_file_event /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:548
#7 0x563befb0f49f in gdb_wait_for_event /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:673
#8 0x563befb0d4a1 in gdb_do_one_event() /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:215
#9 0x563bef9e721a in start_event_loop /home/simark/src/binutils-gdb/gdbserver/server.cc:3484
#10 0x563bef9eb90a in captured_main /home/simark/src/binutils-gdb/gdbserver/server.cc:3875
#11 0x563bef9ec2c7 in main /home/simark/src/binutils-gdb/gdbserver/server.cc:3961
#12 0x7f7fd3330001 in __libc_start_main (/usr/lib/libc.so.6+0x27001)
SUMMARY: AddressSanitizer: 14 byte(s) leaked in 1 allocation(s).
This is due to the handling of unknown qsupported features in
handle_query. The `qsupported` vector is built, containing all the
feature names received from GDB. As we iterate on them, when we
encounter unknown ones, we move them at the beginning of the vector, in
preparation of passing this vector of unknown features down to the
target (which may know about them).
When moving these unknown features to other slots in the vector, we
overwrite other pointers without freeing them, which therefore leak.
An easy fix would be to add a `free` when doing the move. However, I
think this is a good opportunity to sprinkle a bit of automatic memory
management in this code.
So, use a vector of std::string which owns all the entries. And use a
separate vector (that doesn't own the entries) for the unknown ones,
which is then passed to target_process_qsupported.
Given that the `c_str` method of std::string returns a `const char *`,
it follows that process_stratum_target::process_qsupported must accept a
`const char **` instead of a `char **`. And while at it, change the
pointer + size paramters to use an array_view instead.
gdbserver/ChangeLog:
* server.cc (handle_query): Use std::vector of
std::string for `qsupported` vector. Use separate
vector for unknowns.
* target.h (class process_stratum_target) <process_qsupported>:
Change parameters to array_view of const char *.
(target_process_qsupported): Remove `count` parameter.
* target.cc (process_stratum_target::process_qsupported): Change
parameters to array_view of const char *.
* linux-x86-low.cc (class x86_target) <process_qsupported>:
Likewise.
Change-Id: I97f133825faa6d7abbf83a58504eb0ba77462812
|
|
I recently stumbled on this code mentioning Linux kernel 2.6.25, and
thought it could be time for some spring cleaning (newer GDBs probably
don't need to supports 12-year old kernels). I then found that the
"legacy" case is probably broken anyway, which gives an even better
motivation for its removal.
In short, this patch removes the configure checks that check if
user_regs_struct contains the fs_base/gs_base fields and adjusts all
uses of the HAVE_STRUCT_USER_REGS_STRUCT_{FS,GS}_BASE macros. The
longer explanation/rationale follows.
Apparently, Linux kernels since 2.6.25 (that's from 2008) have been
reliably providing fs_base and gs_base as part of user_regs_struct.
Commit df5d438e33d7 in the Linux kernel [1] seems related. This means
that we can get these values by reading registers with PTRACE_GETREGS.
Previously, these values were obtained using a separate
PTRACE_ARCH_PRCTL ptrace call.
First, I'm not even sure the configure check was really right in the
first place.
The user_regs_struct used by GDB comes from
/usr/include/x86_64-linux-gnu/sys/user.h (or equivalent on other
distros) and is provided by glibc. glibc has had the fs_base/gs_base
fields in there for a very long time, at least since this commit from
2001 [2]. The Linux kernel also has its version of user_regs_struct,
which I think was exported to user-space at some point. It included the
fs_base/gs_base fields since at least this 2002 commit [3]. In any
case, my conclusion is that the fields were there long before the
aforementioned Linux kernel commit. The kernel commit didn't add these
fields, it only made sure that they have reliable values when obtained
with PTRACE_GETREGS.
So, checking for the presence of the fs_base/gs_base fields in struct
user_regs_struct doesn't sound like a good way of knowing if we can
reliably get the fs_base/gs_base values from PTRACE_GETREGS. My guess
is that if we were using that strategy on a < 2.6.25 kernel, things
would not work correctly:
- configure would find that the user_regs_struct has the fs_base/gs_base
fields (which are probided by glibc anyway)
- we would be reading the fs_base/gs_base values using PTRACE_GETREGS,
for which the kernel would provide unreliable values
Second, I have tried to see how things worked by forcing GDB to not use
fs_base/gs_base from PTRACE_GETREGS (forcing it to use the "legacy"
code, by configuring with
ac_cv_member_struct_user_regs_struct_gs_base=no ac_cv_member_struct_user_regs_struct_fs_base=no
Doing so breaks writing registers back to the inferior. For example,
calling an inferior functions gives an internal error:
(gdb) p malloc(10)
/home/smarchi/src/binutils-gdb/gdb/i387-tdep.c:1408: internal-error: invalid i387 regnum 152
The relevant last frames where this error happens are:
#8 0x0000563123d262fc in internal_error (file=0x563123e93fd8 "/home/smarchi/src/binutils-gdb/gdb/i387-tdep.c", line=1408, fmt=0x563123e94482 "invalid i387 regnum %d") at /home/smarchi/src/binutils-gdb/gdbsupport/errors.cc:55
#9 0x0000563123047d0d in i387_collect_xsave (regcache=0x5631269453f0, regnum=152, xsave=0x7ffd38402a20, gcore=0) at /home/smarchi/src/binutils-gdb/gdb/i387-tdep.c:1408
#10 0x0000563122c69e8a in amd64_collect_xsave (regcache=0x5631269453f0, regnum=152, xsave=0x7ffd38402a20, gcore=0) at /home/smarchi/src/binutils-gdb/gdb/amd64-tdep.c:3448
#11 0x0000563122c5e94c in amd64_linux_nat_target::store_registers (this=0x56312515fd10 <the_amd64_linux_nat_target>, regcache=0x5631269453f0, regnum=152) at /home/smarchi/src/binutils-gdb/gdb/amd64-linux-nat.c:335
#12 0x00005631234c8c80 in target_store_registers (regcache=0x5631269453f0, regno=152) at /home/smarchi/src/binutils-gdb/gdb/target.c:3485
#13 0x00005631232e8df7 in regcache::raw_write (this=0x5631269453f0, regnum=152, buf=0x56312759e468 "@\225\372\367\377\177") at /home/smarchi/src/binutils-gdb/gdb/regcache.c:765
#14 0x00005631232e8f0c in regcache::cooked_write (this=0x5631269453f0, regnum=152, buf=0x56312759e468 "@\225\372\367\377\177") at /home/smarchi/src/binutils-gdb/gdb/regcache.c:778
#15 0x00005631232e75ec in regcache::restore (this=0x5631269453f0, src=0x5631275eb130) at /home/smarchi/src/binutils-gdb/gdb/regcache.c:283
#16 0x0000563123083fc4 in infcall_suspend_state::restore (this=0x5631273ed930, gdbarch=0x56312718cf20, tp=0x5631270bca90, regcache=0x5631269453f0) at /home/smarchi/src/binutils-gdb/gdb/infrun.c:9103
#17 0x0000563123081eed in restore_infcall_suspend_state (inf_state=0x5631273ed930) at /home/smarchi/src/binutils-gdb/gdb/infrun.c:9151
The problem seems to be that amd64_linux_nat_target::store_registers
calls amd64_native_gregset_supplies_p to know whether gregset provides
fs_base. When !HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE,
amd64_native_gregset_supplies_p returns false. store_registers
therefore assumes that it must be an "xstate" register. This is of
course wrong, and that leads to the failed assertion when
i387_collect_xsave doesn't recognize the register.
amd64_linux_nat_target::store_registers could probably be fixed to
handle this case, but I don't think it's worth it, given that it would
only be to support very old kernels.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=df5d438e33d7fc914ba9b6e0d6b019a8966c5fcc
[2] https://sourceware.org/git/?p=glibc.git;a=commit;h=c9cf6ddeebb7bb
[3] https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git/commit/?id=88e4bc32686ebd0b1111a94f93eba2d334241f68
gdb/ChangeLog:
* configure.ac: Remove check for fs_base/gs_base in
user_regs_struct.
* configure: Re-generate.
* config.in: Re-generate.
* amd64-nat.c (amd64_native_gregset_reg_offset): Adjust.
* amd64-linux-nat.c (amd64_linux_nat_target::fetch_registers,
amd64_linux_nat_target::store_registers, ps_get_thread_area, ): Adjust.
gdbserver/ChangeLog:
* configure.ac: Remove check for fs_base/gs_base in
user_regs_struct.
* configure: Re-generate.
* config.in: Re-generate.
* linux-x86-low.cc (x86_64_regmap, x86_fill_gregset,
x86_store_gregset): Adjust.
|