forked from Imagelibrary/binutils-gdb
0c9953e0e07173f172c0994302d062a57dae57b0
18 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1048062a3f |
gdbserver: pass osabi to GDB in more target descriptions
Problem Description ------------------- On a Windows machine I built gdbserver, configured for the target 'x86_64-w64-mingw32', then on a GNU/Linux machine I built GDB with support for all target (--enable-targets=all). On the Windows machine I start gdbserver with a small test binary: $ gdbserver 192.168.129.25:54321 C:\some\directory\executable.exe On the GNU/Linux machine I start GDB without the test binary, and connect to gdbserver. As I have not given GDB the test binary, my expectation is that GDB would connect to gdbserver and then download the file over the remote protocol, but instead I was presented with this message: (gdb) target remote 192.168.129.25:54321 Remote debugging using 192.168.129.25:54321 warning: C:\some\directory\executable.exe: No such file or directory. 0x00007ffa3e1e1741 in ?? () (gdb) What I found is that if I told GDB where to find the binary, like this: (gdb) file target:C:/some/directory/executable.exe A program is being debugged already. Are you sure you want to change the file? (y or n) y Reading C:/some/directory/executable.exe from remote target... warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead. Reading C:/some/directory/executable.exe from remote target... Reading symbols from target:C:/some/directory/executable.exe... (gdb) then GDB would download the executable. The Actual Issue ---------------- I tracked the problem down to exec_file_find (solib.c). The remote target was passing an absolute Windows filename (beginning with "C:/" in this case), but in exec_file_find GDB was failing the IS_TARGET_ABSOLUTE_PATH call, and so was treating the filename as relative. The IS_TARGET_ABSOLUTE_PATH call was failing because GDB thought that the file system kind was "unix", and as the filename didn't start with a "/" it assumed the filename was not absolute. But I'm connecting to a Windows target and 'target-file-system-kind' was set to "auto", so GDB should be figuring out that the target file-system is "dos-based". Looking in effective_target_file_system_kind (filesystem.c), we find that the logic of "auto" is delegated to the current gdbarch. However in windows-tdep.c we see: set_gdbarch_has_dos_based_file_system (gdbarch, 1); So if we are using a Windows gdbarch we should have "dos-based" filesystems. What this means is that after connecting to the remote target GDB has selected the wrong gdbarch. What's happening is that the target description sent back by the remote target only includes the x86-64 registers. There's no information about which OS we're on. As a consequence, GDB picks the first x86-64 gdbarch which can handle the provided register set, which happens to be a GNU/Linux gdbarch. And indeed, there doesn't appear to be anywhere in gdbserver that sets the osabi on the target descriptions. Some target descriptions do have their osabi set when the description is created, e.g. in: gdb/arch/amd64.c - Sets GNU/Linux osabi when appropriate. gdb/arch/i386.c - Likewise. gdb/arch/tic6x.c - Always set GNU/Linux osabi. There are also some cases in gdb/features/*.c where the tdesc is set, but these locations are only called from GDB, not from gdbserver. This means that many target descriptions are created without an osabi, gdbserver does nothing to fix this, and the description is returned to GDB without an osabi included. This leaves GDB having to guess what the target osabi is, and in some cases, GDB can get this wrong. Proposed Solution ----------------- I propose to change init_target_desc so that it requires an gdb_osabi to be passed in, this will then be used to set the target_desc osabi field. I believe that within gdbserver init_target_desc is called for every target_desc, so this should mean that every target_desc has an opportunity to set the osabi to something sane. I did consider passing the osabi into the code which creates the target_desc objects, but that would require updating far more code, as each target has its own code for creating target descriptions. The approach taken here requires minimal changes and forces every user of init_target_desc to think about what the correct osabi is. In some cases, e.g. amd64, where the osabi is already set when the target_desc is created, the init_target_desc call will override the current value, however, we should always be replacing it with the same actual value. i.e. if the target_desc is created with the osabi set to GNU/Linux, then this should only happen when gdbserver is built for GNU/Linux, in which case the init_target_desc should also be setting the osabi to GNU/Linux. The Tricky Bits --------------- Some targets, like amd64, use a features based approach for creating target_desc objects, there's a function in arch/amd64.c which creates a target_desc, adds features too it, and returns the new target_desc. This target_desc is then passed to an init_target_desc call within gdbserver. This is the easy case to handle. Then there are other targets which instead have a fixed set of xml files, each of which is converted into a .dat file, which is then used to generate a .cc file, which is compiled into gdbserver. The generated .cc file creates the target_desc object and calls init_target_desc on it. In this case though the target description that is sent to GDB isn't generated from the target_desc object, but is instead the contents of the fixed xml file. For this case the osabi which we pass to init_target_desc should match the osabi that exists in the fixed xml file. Luckily, in the previous commit I copied the osabi information from the fixed xml files into the .dat files. So in this commit I have extended regdat.sh to read the osabi from the .dat file and use it in the generated init_target_desc call. The problem with some of these .dat base targets is that their fixed xml files don't currently contain any osabi information, and the file names don't indicate that they are Linux only (despite them currently only being used from gdbserver for Linux targets), so I don't currently feel confident adding any osabi information to these files. An example would be features/rs6000/powerpc-64.xml. For now I've just ignored these cases. The init_target_desc will use GDB_OSABI_UNKNOWN which is the default. This means that for these targets nothing changes from the current behaviour. But many other targets do now pass the osabi back. Targets that do pass the osabi back are improved with this commit. Conclusion ---------- Now when I connect to the Windows remote the target description returned includes the osabi name. With this extra information GDB selects the correct gdbarch object, which means that GDB understands the target has a "dos-based" file-system. With that correct GDB understands that the filename it was given is absolute, and so fetches the file from the remote as we'd like. Reviewed-By: Kevin Buettner <kevinb@redhat.com> |
||
|
|
a9ed7a0814 |
Revert "gdbserver: pass osabi to GDB in target description"
This reverts commit
|
||
|
|
98bcde5e26 |
gdbserver: pass osabi to GDB in target description
On a Windows machine I built gdbserver, configured for the target 'x86_64-w64-mingw32', then on a GNU/Linux machine I built GDB with support for all target (--enable-targets=all). On the Windows machine I start gdbserver with a small test binary: $ gdbserver 192.168.129.25:54321 C:\some\directory\executable.exe On the GNU/Linux machine I start GDB without the test binary, and connect to gdbserver. As I have not given GDB the test binary, my expectation is that GDB would connect to gdbserver and then download the file over the remote protocol, but instead I was presented with this message: (gdb) target remote 192.168.129.25:54321 Remote debugging using 192.168.129.25:54321 warning: C:\some\directory\executable.exe: No such file or directory. 0x00007ffa3e1e1741 in ?? () (gdb) What I found is that if I told GDB where to find the binary, like this: (gdb) file target:C:/some/directory/executable.exe A program is being debugged already. Are you sure you want to change the file? (y or n) y Reading C:/some/directory/executable.exe from remote target... warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead. Reading C:/some/directory/executable.exe from remote target... Reading symbols from target:C:/some/directory/executable.exe... (gdb) then GDB would download the executable. I eventually tracked the problem down to exec_file_find (solib.c). The remote target was passing an absolute Windows filename (beginning with "C:/" in this case), but in exec_file_find GDB was failing the IS_TARGET_ABSOLUTE_PATH call, and so was treating the filename as relative. The IS_TARGET_ABSOLUTE_PATH call was failing because GDB thought that the file system kind was "unix", and as the filename didn't start with a "/" it assumed the filename was not absolute. But I'm connecting to a Windows target, my 'target-file-system-kind' was set to "auto", so should be figuring out that my file-system is "dos-based". Looking in effective_target_file_system_kind (filesystem.c), we find that the logic of "auto" is delegated to the current gdbarch. However in windows-tdep.c we see: set_gdbarch_has_dos_based_file_system (gdbarch, 1); So if we are using a Windows gdbarch we should have "dos-based" filesystems. What this means is that after connecting to the remote target GDB has selected the wrong gdbarch. What's happening is that the target description sent back by the remote target only includes the x86-64 registers. There's no information about which OS we're on. As a consequence, GDB picks the first x86-64 gdbarch which can handle the provided register set, which happens to be a GNU/Linux gdbarch. And indeed, there doesn't appear to be anywhere in gdbserver that sets the osabi on the target descriptions, though some target descriptions do have their osabi set when the description is created, e.g. in: gdb/arch/amd64.c - Sets GNU/Linux osabi when appropriate. gdb/arch/i386.c - Likewise. gdb/arch/tic6x.c - Always set GNU/Linux osabi. Most target descriptions are created without an osabi, gdbserver does nothing to fix this, and the description is returned to GDB without an osabi included. I propose that we always set the osabi name on the target descriptions returned from gdbserver. We could try to do this when the description is first created, but that would mean passing extra flags into the tdesc creation code (or just passing the osabi string in), and I don't think that's really necessary. If we consider the tdesc creation as being about figuring out which registers are on the target, then it makes sense that the osabi information is injected later. So what I've done is require the osabi name to be passed to the init_target_desc function. This is called, I believe, for all targets, in the gdbserver code. Now when I connect to the Windows remote the target description returned includes the osabi name. With this extra information GDB selects the correct gdbarch object, which means that GDB understands the target has a "dos-based" file-system. With that correct GDB understands that the filename it was given is absolute, and so fetches the file from the remote as we'd like. Approved-By: Luis Machado <luis.machado@arm.com> Approved-By: Simon Marchi <simon.marchi@efficios.com> |
||
|
|
646d754d14 |
gdb/gdbserver: share x86/linux tdesc caching
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>
|
||
|
|
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
|
||
|
|
bf616be991 |
gdb/gdbserver: share some code relating to target description creation
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>
|
||
|
|
18d2988e5d |
gdb, gdbserver, gdbsupport: remove includes of early headers
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> |
||
|
|
49a7660fb5 |
Revert "gdb/gdbserver: share some code relating to target description creation"
This reverts commit
|
||
|
|
cba2791ca6 |
Revert "gdbserver: update target description creation for x86/linux"
This reverts commit
|
||
|
|
69324a74e3 |
Revert "gdb/gdbserver: share x86/linux tdesc caching"
This reverts commit
|
||
|
|
198ff6ff81 |
gdb/gdbserver: share x86/linux tdesc caching
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> |
||
|
|
61bb321605 |
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, 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
|
||
|
|
cd9b374ffe |
gdb/gdbserver: share some code relating to target description creation
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>
|
||
|
|
1d506c26d9 |
Update copyright year range in header of all files managed by GDB
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.
|
||
|
|
213516ef31 |
Update copyright year range in header of all files managed by GDB
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. |
||
|
|
4a94e36819 |
Automatic Copyright Year update after running gdb/copyright.py
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. |
||
|
|
3666a04883 |
Update copyright year range in all GDB files
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.
|
||
|
|
feacfcacaa |
gdbserver: rename source files to .cc
For the same reasons outlined in the previous patch, this patch renames gdbserver source files to .cc. I have moved the "-x c++" switch to only those rules that require it. gdbserver/ChangeLog: * Makefile.in: Rename source files from .c to .cc. * %.c: Rename to %.cc. * configure.ac: Rename server.c to server.cc. * configure: Re-generate. |