binutils-gdb modified for the FreeChainXenon project
Find a file
Andrew Burgess cc59d02b90 gdbserver: update target description creation for x86/linux
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 a880623024
  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>
2024-06-14 09:08:45 +01:00
bfd Automatic date update in version.in 2024-06-14 00:00:26 +00:00
binutils support_dt_relr aarch64 2024-06-11 20:29:25 +09:30
config autoconf: delete obsolete unused m4 file 2024-06-10 08:25:56 +09:30
contrib contrib: sync dg-extract-results.sh with GCC 2024-03-12 15:49:25 +00:00
cpu PR21739, Inconsistent diagnostics 2024-02-29 21:07:04 +10:30
elfcpp x86-64: Add R_X86_64_CODE_6_GOTTPOFF 2024-02-08 03:45:43 -08:00
etc Update year range in copyright notice of binutils files 2024-01-04 22:58:12 +10:30
gas aarch64: add Branch Record Buffer extension instructions 2024-06-12 14:58:35 +01:00
gdb gdb/gdbserver: share some code relating to target description creation 2024-06-14 09:08:45 +01:00
gdbserver gdbserver: update target description creation for x86/linux 2024-06-14 09:08:45 +01:00
gdbsupport gdb/gdbserver: share I386_LINUX_XSAVE_XCR0_OFFSET definition 2024-06-14 09:08:44 +01:00
gnulib autoupdate: replace obsolete macros AC_CONFIG_HEADER 2024-06-10 08:25:55 +09:30
gold autoupdate: regen after replacing obsolete macros 2024-06-10 08:25:56 +09:30
gprof autoupdate: regen after replacing obsolete macros 2024-06-10 08:25:56 +09:30
gprofng autoupdate: add square brackets around arguments of AC_INIT 2024-06-10 08:25:56 +09:30
include Add --rosegment option to BFD linker to stop the '-z separate-code' from generating two read-only segments. 2024-06-13 15:10:15 +01:00
ld Adjust linker tests that are sensitive to --rosegment 2024-06-13 17:00:29 +01:00
libbacktrace autoupdate: regen after replacing obsolete macros 2024-06-10 08:25:56 +09:30
libctf PR 31882 libctf: test suite incorrect format specifiers 2024-06-12 13:16:27 +09:30
libdecnumber regen config 2023-08-12 10:27:57 +09:30
libiberty autoupdate: regen after replacing obsolete macros 2024-06-10 08:25:56 +09:30
libsframe autoupdate: add square brackets around arguments of AC_INIT 2024-06-10 08:25:56 +09:30
opcodes aarch64: add Branch Record Buffer extension instructions 2024-06-12 14:58:35 +01:00
readline autoupdate: add square brackets around arguments of AC_INIT 2024-06-10 08:25:56 +09:30
sim regen sim/frv files for copyright update 2024-06-10 08:25:56 +09:30
texinfo
zlib autoupdate: regen after replacing obsolete macros 2024-06-10 08:25:56 +09:30
.cvsignore
.editorconfig
.gitattributes binutils-gdb/git: highlight whitespace errors in source files 2022-07-25 14:35:41 +01:00
.gitignore .gitignore: ignore .vscode 2024-05-30 12:09:35 +01:00
.pre-commit-config.yaml gdb: bump black version to 24.4.2 2024-05-16 11:34:40 -04:00
ar-lib
ChangeLog .pre-commit-config.yaml: bump black hook to 24.3.0 2024-03-20 14:44:16 -04:00
compile
config-ml.in MSP430: Add -fno-exceptions multilib 2023-08-12 10:24:26 +09:30
config.guess Synchronize config.sub and config.guess with their upstream master versions. 2024-01-04 12:00:34 +00:00
config.rpath
config.sub Synchronize config.sub and config.guess with their upstream master versions. 2024-01-04 12:00:34 +00:00
configure autoupdate: regen after replacing obsolete macros 2024-06-10 08:25:56 +09:30
configure.ac autoupdate: replace old version of AC_INIT by the new one 2024-06-10 08:25:55 +09:30
COPYING
COPYING.LIB
COPYING.LIBGLOSS
COPYING.NEWLIB
COPYING3
COPYING3.LIB
depcomp
djunpack.bat
install-sh
libtool.m4 FDPIC: Handle arm*-*-uclinuxfdpiceabi in configure scripts 2023-08-12 10:25:06 +09:30
ltgcc.m4
ltmain.sh Do not use HAVE_DOS_BASED_FILE_SYSTEM for Cygwin. 2023-08-12 10:25:06 +09:30
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
MAINTAINERS Fix compiling bfd/vms-lib.c for a 32-bit host. 2024-03-18 10:26:16 +00:00
Makefile.def Revert "Pass GUILE down to subdirectories" 2024-03-22 11:07:28 -06:00
Makefile.in Revert "Pass GUILE down to subdirectories" 2024-03-22 11:07:28 -06:00
Makefile.tpl Revert "Pass GUILE down to subdirectories" 2024-03-22 11:07:28 -06:00
makefile.vms
missing
mkdep
mkinstalldirs
move-if-change
multilib.am
README
README-maintainer-mode Note that at least dejagnu version 1.5.3 is required in order to be ale to run the testsuites. 2022-10-04 10:54:19 +01:00
SECURITY.txt Add a SECURITY.txt file describing the GNU Binutils' project's stance on security related bugs. 2023-04-20 16:52:11 +01:00
setup.com
src-release.sh src-release.sh: don't take untracked files into account in the uncommitted changes check 2024-06-10 12:40:06 +01:00
symlink-tree
test-driver
ylwrap

		   README for GNU development tools

This directory contains various GNU compilers, assemblers, linkers, 
debuggers, etc., plus their support routines, definitions, and documentation.

If you are receiving this as part of a GDB release, see the file gdb/README.
If with a binutils release, see binutils/README;  if with a libg++ release,
see libg++/README, etc.  That'll give you info about this
package -- supported targets, how to use it, how to report bugs, etc.

It is now possible to automatically configure and build a variety of
tools with one command.  To build all of the tools contained herein,
run the ``configure'' script here, e.g.:

	./configure 
	make

To install them (by default in /usr/local/bin, /usr/local/lib, etc),
then do:
	make install

(If the configure script can't determine your type of computer, give it
the name as an argument, for instance ``./configure sun4''.  You can
use the script ``config.sub'' to test whether a name is recognized; if
it is, config.sub translates it to a triplet specifying CPU, vendor,
and OS.)

If you have more than one compiler on your system, it is often best to
explicitly set CC in the environment before running configure, and to
also set CC when running make.  For example (assuming sh/bash/ksh):

	CC=gcc ./configure
	make

A similar example using csh:

	setenv CC gcc
	./configure
	make

Much of the code and documentation enclosed is copyright by
the Free Software Foundation, Inc.  See the file COPYING or
COPYING.LIB in the various directories, for a description of the
GNU General Public License terms under which you can copy the files.

REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info
on where and how to report problems.