diff options
author | Tom Tromey <tom@tromey.com> | 2019-12-15 07:37:06 -0700 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2020-02-07 08:42:25 -0700 |
commit | 919adfe8409211c726c1d05b47ca59890ee648f1 (patch) | |
tree | d2ef4abf9e5590b43a59f3f8747b0d5bab94ab6f /gdbserver/linux-amd64-ipa.c | |
parent | e8319fde715960466aca2461c74cec8907abd391 (diff) | |
download | gdb-919adfe8409211c726c1d05b47ca59890ee648f1.zip gdb-919adfe8409211c726c1d05b47ca59890ee648f1.tar.gz gdb-919adfe8409211c726c1d05b47ca59890ee648f1.tar.bz2 |
Move gdbserver to top level
This patch moves gdbserver to the top level.
This patch is as close to a pure move as possible -- gdbserver still
builds its own variant of gnulib and gdbsupport. Changing this will
be done in a separate patch.
[v2] Note that, per Simon's review comment, this patch changes the
tree so that gdbserver is not built for or1k or score. This makes
sense, because there is apparently not actually a gdbserver port here.
[v3] This version of the patch also splits out some configury into a
new file, gdbserver/configure.host, so that the top-level configure
script can simply rely on it in order to decide whether gdbserver
should be built.
[v4] This version adds documentation and removes some unnecessary
top-level dependencies.
[v5] Update docs to mention "make all-gdbserver" and change how
top-level configure decides whether to build gdbserver, switching to a
single, shared script.
Tested by the buildbot.
ChangeLog
2020-02-07 Tom Tromey <tom@tromey.com>
Pedro Alves <palves@redhat.com>
* src-release.sh (GDB_SUPPORT_DIRS): Add gdbserver.
* gdbserver: New directory, moved from gdb/gdbserver.
* configure.ac (host_tools): Add gdbserver.
Only build gdbserver on certain systems.
* Makefile.in, configure: Rebuild.
* Makefile.def (host_modules, dependencies): Add gdbserver.
* MAINTAINERS: Add gdbserver.
gdb/ChangeLog
2020-02-07 Tom Tromey <tom@tromey.com>
* README: Update gdbserver documentation.
* gdbserver: Move to top level.
* configure.tgt (build_gdbserver): Remove.
* configure.ac: Remove --enable-gdbserver.
* configure: Rebuild.
* Makefile.in (distclean): Don't mention gdbserver.
Change-Id: I826b7565b54604711dc7a11edea0499cd51ff39e
Diffstat (limited to 'gdbserver/linux-amd64-ipa.c')
-rw-r--r-- | gdbserver/linux-amd64-ipa.c | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/gdbserver/linux-amd64-ipa.c b/gdbserver/linux-amd64-ipa.c new file mode 100644 index 0000000..53d98f2 --- /dev/null +++ b/gdbserver/linux-amd64-ipa.c @@ -0,0 +1,289 @@ +/* GNU/Linux/x86-64 specific low level interface, for the in-process + agent library for GDB. + + Copyright (C) 2010-2020 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "server.h" +#include <sys/mman.h> +#include "tracepoint.h" +#include "linux-x86-tdesc.h" +#include "gdbsupport/x86-xstate.h" + +/* Defined in auto-generated file amd64-linux.c. */ +void init_registers_amd64_linux (void); +extern const struct target_desc *tdesc_amd64_linux; + +/* fast tracepoints collect registers. */ + +#define FT_CR_RIP 0 +#define FT_CR_EFLAGS 1 +#define FT_CR_R8 2 +#define FT_CR_R9 3 +#define FT_CR_R10 4 +#define FT_CR_R11 5 +#define FT_CR_R12 6 +#define FT_CR_R13 7 +#define FT_CR_R14 8 +#define FT_CR_R15 9 +#define FT_CR_RAX 10 +#define FT_CR_RBX 11 +#define FT_CR_RCX 12 +#define FT_CR_RDX 13 +#define FT_CR_RSI 14 +#define FT_CR_RDI 15 +#define FT_CR_RBP 16 +#define FT_CR_RSP 17 + +static const int x86_64_ft_collect_regmap[] = { + FT_CR_RAX * 8, FT_CR_RBX * 8, FT_CR_RCX * 8, FT_CR_RDX * 8, + FT_CR_RSI * 8, FT_CR_RDI * 8, FT_CR_RBP * 8, FT_CR_RSP * 8, + FT_CR_R8 * 8, FT_CR_R9 * 8, FT_CR_R10 * 8, FT_CR_R11 * 8, + FT_CR_R12 * 8, FT_CR_R13 * 8, FT_CR_R14 * 8, FT_CR_R15 * 8, + FT_CR_RIP * 8, FT_CR_EFLAGS * 8 +}; + +#define X86_64_NUM_FT_COLLECT_GREGS \ + (sizeof (x86_64_ft_collect_regmap) / sizeof(x86_64_ft_collect_regmap[0])) + +void +supply_fast_tracepoint_registers (struct regcache *regcache, + const unsigned char *buf) +{ + int i; + + for (i = 0; i < X86_64_NUM_FT_COLLECT_GREGS; i++) + supply_register (regcache, i, + ((char *) buf) + x86_64_ft_collect_regmap[i]); +} + +ULONGEST +get_raw_reg (const unsigned char *raw_regs, int regnum) +{ + if (regnum >= X86_64_NUM_FT_COLLECT_GREGS) + return 0; + + return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]); +} + +#ifdef HAVE_UST + +#include <ust/processor.h> + +/* "struct registers" is the UST object type holding the registers at + the time of the static tracepoint marker call. This doesn't + contain RIP, but we know what it must have been (the marker + address). */ + +#define ST_REGENTRY(REG) \ + { \ + offsetof (struct registers, REG), \ + sizeof (((struct registers *) NULL)->REG) \ + } + +static struct +{ + int offset; + int size; +} x86_64_st_collect_regmap[] = + { + ST_REGENTRY(rax), + ST_REGENTRY(rbx), + ST_REGENTRY(rcx), + ST_REGENTRY(rdx), + ST_REGENTRY(rsi), + ST_REGENTRY(rdi), + ST_REGENTRY(rbp), + ST_REGENTRY(rsp), + ST_REGENTRY(r8), + ST_REGENTRY(r9), + ST_REGENTRY(r10), + ST_REGENTRY(r11), + ST_REGENTRY(r12), + ST_REGENTRY(r13), + ST_REGENTRY(r14), + ST_REGENTRY(r15), + { -1, 0 }, + ST_REGENTRY(rflags), + ST_REGENTRY(cs), + ST_REGENTRY(ss), + }; + +#define X86_64_NUM_ST_COLLECT_GREGS \ + (sizeof (x86_64_st_collect_regmap) / sizeof (x86_64_st_collect_regmap[0])) + +/* GDB's RIP register number. */ +#define AMD64_RIP_REGNUM 16 + +void +supply_static_tracepoint_registers (struct regcache *regcache, + const unsigned char *buf, + CORE_ADDR pc) +{ + int i; + unsigned long newpc = pc; + + supply_register (regcache, AMD64_RIP_REGNUM, &newpc); + + for (i = 0; i < X86_64_NUM_ST_COLLECT_GREGS; i++) + if (x86_64_st_collect_regmap[i].offset != -1) + { + switch (x86_64_st_collect_regmap[i].size) + { + case 8: + supply_register (regcache, i, + ((char *) buf) + + x86_64_st_collect_regmap[i].offset); + break; + case 2: + { + unsigned long reg + = * (short *) (((char *) buf) + + x86_64_st_collect_regmap[i].offset); + reg &= 0xffff; + supply_register (regcache, i, ®); + } + break; + default: + internal_error (__FILE__, __LINE__, + "unhandled register size: %d", + x86_64_st_collect_regmap[i].size); + break; + } + } +} + +#endif /* HAVE_UST */ + +#if !defined __ILP32__ +/* Map the tdesc index to xcr0 mask. */ +static uint64_t idx2mask[X86_TDESC_LAST] = { + X86_XSTATE_X87_MASK, + X86_XSTATE_SSE_MASK, + X86_XSTATE_AVX_MASK, + X86_XSTATE_MPX_MASK, + X86_XSTATE_AVX_MPX_MASK, + X86_XSTATE_AVX_AVX512_MASK, + X86_XSTATE_AVX_MPX_AVX512_PKU_MASK, +}; +#endif + +/* Return target_desc to use for IPA, given the tdesc index passed by + gdbserver. */ + +const struct target_desc * +get_ipa_tdesc (int idx) +{ + if (idx >= X86_TDESC_LAST) + { + internal_error (__FILE__, __LINE__, + "unknown ipa tdesc index: %d", idx); + } + +#if defined __ILP32__ + switch (idx) + { + case X86_TDESC_SSE: + return amd64_linux_read_description (X86_XSTATE_SSE_MASK, true); + case X86_TDESC_AVX: + return amd64_linux_read_description (X86_XSTATE_AVX_MASK, true); + case X86_TDESC_AVX_AVX512: + return amd64_linux_read_description (X86_XSTATE_AVX_AVX512_MASK, true); + default: + break; + } +#else + return amd64_linux_read_description (idx2mask[idx], false); +#endif + + internal_error (__FILE__, __LINE__, + "unknown ipa tdesc index: %d", idx); +} + +/* Allocate buffer for the jump pads. The branch instruction has a + reach of +/- 31-bit, and the executable is loaded at low addresses. + + 64-bit: Use MAP_32BIT to allocate in the first 2GB. Shared + libraries, being allocated at the top, are unfortunately out of + luck. + + x32: Since MAP_32BIT is 64-bit only, do the placement manually. + Try allocating at '0x80000000 - SIZE' initially, decreasing until + we hit a free area. This ensures the executable is fully covered, + and is as close as possible to the shared libraries, which are + usually mapped at the top of the first 4GB of the address space. +*/ + +void * +alloc_jump_pad_buffer (size_t size) +{ +#if __ILP32__ + uintptr_t addr; + int pagesize; + + pagesize = sysconf (_SC_PAGE_SIZE); + if (pagesize == -1) + perror_with_name ("sysconf"); + + addr = 0x80000000 - size; + + /* size should already be page-aligned, but this can't hurt. */ + addr &= ~(pagesize - 1); + + /* Search for a free area. If we hit 0, we're out of luck. */ + for (; addr; addr -= pagesize) + { + void *res; + + /* No MAP_FIXED - we don't want to zap someone's mapping. */ + res = mmap ((void *) addr, size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + /* If we got what we wanted, return. */ + if ((uintptr_t) res == addr) + return res; + + /* If we got a mapping, but at a wrong address, undo it. */ + if (res != MAP_FAILED) + munmap (res, size); + } + + return NULL; +#else + void *res = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); + + if (res == MAP_FAILED) + return NULL; + + return res; +#endif +} + +void +initialize_low_tracepoint (void) +{ +#if defined __ILP32__ + amd64_linux_read_description (X86_XSTATE_SSE_MASK, true); + amd64_linux_read_description (X86_XSTATE_AVX_MASK, true); + amd64_linux_read_description (X86_XSTATE_AVX_AVX512_MASK, true); +#else + for (auto i = 0; i < X86_TDESC_LAST; i++) + amd64_linux_read_description (idx2mask[i], false); +#endif +} |