123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- /* GNU/Linux S/390 specific low level interface, for the in-process
- agent library for GDB.
- Copyright (C) 2016-2022 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-s390-tdesc.h"
- #include <elf.h>
- #ifdef HAVE_GETAUXVAL
- #include <sys/auxv.h>
- #endif
- #define FT_FPR(x) (0x000 + (x) * 0x10)
- #define FT_VR(x) (0x000 + (x) * 0x10)
- #define FT_VR_L(x) (0x008 + (x) * 0x10)
- #define FT_GPR(x) (0x200 + (x) * 8)
- #define FT_GPR_U(x) (0x200 + (x) * 8)
- #define FT_GPR_L(x) (0x204 + (x) * 8)
- #define FT_GPR(x) (0x200 + (x) * 8)
- #define FT_ACR(x) (0x280 + (x) * 4)
- #define FT_PSWM 0x2c0
- #define FT_PSWM_U 0x2c0
- #define FT_PSWA 0x2c8
- #define FT_PSWA_L 0x2cc
- #define FT_FPC 0x2d0
- /* Mappings between registers collected by the jump pad and GDB's register
- array layout used by regcache.
- See linux-s390-low.c (s390_install_fast_tracepoint_jump_pad) for more
- details. */
- #ifndef __s390x__
- /* Used for s390-linux32, s390-linux32v1, s390-linux32v2. */
- static const int s390_linux32_ft_collect_regmap[] = {
- /* 32-bit PSWA and PSWM. */
- FT_PSWM_U, FT_PSWA_L,
- /* 32-bit GPRs (mapped to lower halves of 64-bit slots). */
- FT_GPR_L (0), FT_GPR_L (1), FT_GPR_L (2), FT_GPR_L (3),
- FT_GPR_L (4), FT_GPR_L (5), FT_GPR_L (6), FT_GPR_L (7),
- FT_GPR_L (8), FT_GPR_L (9), FT_GPR_L (10), FT_GPR_L (11),
- FT_GPR_L (12), FT_GPR_L (13), FT_GPR_L (14), FT_GPR_L (15),
- /* ACRs */
- FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
- FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
- FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
- FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
- /* FPRs (mapped to upper halves of 128-bit VR slots). */
- FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
- FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
- FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
- FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
- /* orig_r2, last_break, system_call */
- -1, -1, -1,
- };
- /* Used for s390-linux64, s390-linux64v1, s390-linux64v2, s390-vx-linux64. */
- static const int s390_linux64_ft_collect_regmap[] = {
- /* 32-bit PSWA and PSWM. */
- FT_PSWM_U, FT_PSWA_L,
- /* 32-bit halves of 64-bit GPRs. */
- FT_GPR_U (0), FT_GPR_L (0),
- FT_GPR_U (1), FT_GPR_L (1),
- FT_GPR_U (2), FT_GPR_L (2),
- FT_GPR_U (3), FT_GPR_L (3),
- FT_GPR_U (4), FT_GPR_L (4),
- FT_GPR_U (5), FT_GPR_L (5),
- FT_GPR_U (6), FT_GPR_L (6),
- FT_GPR_U (7), FT_GPR_L (7),
- FT_GPR_U (8), FT_GPR_L (8),
- FT_GPR_U (9), FT_GPR_L (9),
- FT_GPR_U (10), FT_GPR_L (10),
- FT_GPR_U (11), FT_GPR_L (11),
- FT_GPR_U (12), FT_GPR_L (12),
- FT_GPR_U (13), FT_GPR_L (13),
- FT_GPR_U (14), FT_GPR_L (14),
- FT_GPR_U (15), FT_GPR_L (15),
- /* ACRs */
- FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
- FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
- FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
- FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
- /* FPRs (mapped to upper halves of 128-bit VR slots). */
- FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
- FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
- FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
- FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
- /* orig_r2, last_break, system_call */
- -1, -1, -1,
- /* Lower halves of 128-bit VRs. */
- FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
- FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
- FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
- FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
- /* And the next 16 VRs. */
- FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
- FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
- FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
- FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
- };
- /* Used for s390-te-linux64, s390-tevx-linux64, and s390-gs-linux64. */
- static const int s390_te_linux64_ft_collect_regmap[] = {
- /* 32-bit PSWA and PSWM. */
- FT_PSWM_U, FT_PSWA_L,
- /* 32-bit halves of 64-bit GPRs. */
- FT_GPR_U (0), FT_GPR_L (0),
- FT_GPR_U (1), FT_GPR_L (1),
- FT_GPR_U (2), FT_GPR_L (2),
- FT_GPR_U (3), FT_GPR_L (3),
- FT_GPR_U (4), FT_GPR_L (4),
- FT_GPR_U (5), FT_GPR_L (5),
- FT_GPR_U (6), FT_GPR_L (6),
- FT_GPR_U (7), FT_GPR_L (7),
- FT_GPR_U (8), FT_GPR_L (8),
- FT_GPR_U (9), FT_GPR_L (9),
- FT_GPR_U (10), FT_GPR_L (10),
- FT_GPR_U (11), FT_GPR_L (11),
- FT_GPR_U (12), FT_GPR_L (12),
- FT_GPR_U (13), FT_GPR_L (13),
- FT_GPR_U (14), FT_GPR_L (14),
- FT_GPR_U (15), FT_GPR_L (15),
- /* ACRs */
- FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
- FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
- FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
- FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
- /* FPRs (mapped to upper halves of 128-bit VR slots). */
- FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
- FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
- FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
- FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
- /* orig_r2, last_break, system_call */
- -1, -1, -1,
- /* TDB */
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- /* Lower halves of 128-bit VRs. */
- FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
- FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
- FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
- FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
- /* And the next 16 VRs. */
- FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
- FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
- FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
- FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
- };
- #else /* __s390x__ */
- /* Used for s390x-linux64, s390x-linux64v1, s390x-linux64v2, s390x-vx-linux64. */
- static const int s390x_ft_collect_regmap[] = {
- /* 64-bit PSWA and PSWM. */
- FT_PSWM, FT_PSWA,
- /* 64-bit GPRs. */
- FT_GPR (0), FT_GPR (1), FT_GPR (2), FT_GPR (3),
- FT_GPR (4), FT_GPR (5), FT_GPR (6), FT_GPR (7),
- FT_GPR (8), FT_GPR (9), FT_GPR (10), FT_GPR (11),
- FT_GPR (12), FT_GPR (13), FT_GPR (14), FT_GPR (15),
- /* ACRs */
- FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
- FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
- FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
- FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
- /* FPRs (mapped to upper halves of 128-bit VR slots). */
- FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
- FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
- FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
- FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
- /* orig_r2, last_break, system_call */
- -1, -1, -1,
- /* Lower halves of 128-bit VRs. */
- FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
- FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
- FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
- FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
- /* And the next 16 VRs. */
- FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
- FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
- FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
- FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
- };
- /* Used for s390x-te-linux64, s390x-tevx-linux64, and
- s390x-gs-linux64. */
- static const int s390x_te_ft_collect_regmap[] = {
- /* 64-bit PSWA and PSWM. */
- FT_PSWM, FT_PSWA,
- /* 64-bit GPRs. */
- FT_GPR (0), FT_GPR (1), FT_GPR (2), FT_GPR (3),
- FT_GPR (4), FT_GPR (5), FT_GPR (6), FT_GPR (7),
- FT_GPR (8), FT_GPR (9), FT_GPR (10), FT_GPR (11),
- FT_GPR (12), FT_GPR (13), FT_GPR (14), FT_GPR (15),
- /* ACRs */
- FT_ACR (0), FT_ACR (1), FT_ACR (2), FT_ACR (3),
- FT_ACR (4), FT_ACR (5), FT_ACR (6), FT_ACR (7),
- FT_ACR (8), FT_ACR (9), FT_ACR (10), FT_ACR (11),
- FT_ACR (12), FT_ACR (13), FT_ACR (14), FT_ACR (15),
- /* FPRs (mapped to upper halves of 128-bit VR slots). */
- FT_FPR (0), FT_FPR (1), FT_FPR (2), FT_FPR (3),
- FT_FPR (4), FT_FPR (5), FT_FPR (6), FT_FPR (7),
- FT_FPR (8), FT_FPR (9), FT_FPR (10), FT_FPR (11),
- FT_FPR (12), FT_FPR (13), FT_FPR (14), FT_FPR (15),
- /* orig_r2, last_break, system_call */
- -1, -1, -1,
- /* TDB */
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- -1, -1, -1, -1,
- /* Lower halves of 128-bit VRs. */
- FT_VR_L (0), FT_VR_L (1), FT_VR_L (2), FT_VR_L (3),
- FT_VR_L (4), FT_VR_L (5), FT_VR_L (6), FT_VR_L (7),
- FT_VR_L (8), FT_VR_L (9), FT_VR_L (10), FT_VR_L (11),
- FT_VR_L (12), FT_VR_L (13), FT_VR_L (14), FT_VR_L (15),
- /* And the next 16 VRs. */
- FT_VR (16), FT_VR (17), FT_VR (18), FT_VR (19),
- FT_VR (20), FT_VR (21), FT_VR (22), FT_VR (23),
- FT_VR (24), FT_VR (25), FT_VR (26), FT_VR (27),
- FT_VR (28), FT_VR (29), FT_VR (30), FT_VR (31),
- };
- #endif
- /* Initialized by get_ipa_tdesc according to the tdesc in use. */
- static const int *s390_regmap;
- static int s390_regnum;
- /* Fill in REGCACHE with registers saved by the jump pad in BUF. */
- void
- supply_fast_tracepoint_registers (struct regcache *regcache,
- const unsigned char *buf)
- {
- int i;
- for (i = 0; i < s390_regnum; i++)
- if (s390_regmap[i] != -1)
- supply_register (regcache, i, ((char *) buf) + s390_regmap[i]);
- }
- ULONGEST
- get_raw_reg (const unsigned char *raw_regs, int regnum)
- {
- int offset;
- if (regnum >= s390_regnum)
- return 0;
- offset = s390_regmap[regnum];
- if (offset == -1)
- return 0;
- /* The regnums are variable, better to figure out size by FT offset. */
- /* 64-bit ones. */
- if (offset < FT_VR(16)
- #ifdef __s390x__
- || (offset >= FT_GPR(0) && offset < FT_ACR(0))
- || offset == FT_PSWM
- || offset == FT_PSWA
- #endif
- )
- return *(uint64_t *) (raw_regs + offset);
- if (offset >= FT_ACR(0 && offset < FT_PSWM)
- || offset == FT_FPC
- #ifndef __s390x__
- || (offset >= FT_GPR(0) && offset < FT_ACR(0))
- || offset == FT_PSWM_U
- || offset == FT_PSWA_L
- #endif
- )
- return *(uint32_t *) (raw_regs + offset);
- /* This leaves 128-bit VX. No way to return them. */
- return 0;
- }
- /* Return target_desc to use for IPA, given the tdesc index passed by
- gdbserver. For s390, it also sets s390_regmap and s390_regnum. */
- const struct target_desc *
- get_ipa_tdesc (int idx)
- {
- #define SET_REGMAP(regmap, skip_last) \
- do { \
- s390_regmap = regmap; \
- s390_regnum = (sizeof regmap / sizeof regmap[0]) - skip_last; \
- } while(0)
- switch (idx)
- {
- #ifdef __s390x__
- case S390_TDESC_64:
- /* Subtract number of VX regs. */
- SET_REGMAP(s390x_ft_collect_regmap, 32);
- return tdesc_s390x_linux64;
- case S390_TDESC_64V1:
- SET_REGMAP(s390x_ft_collect_regmap, 32);
- return tdesc_s390x_linux64v1;
- case S390_TDESC_64V2:
- SET_REGMAP(s390x_ft_collect_regmap, 32);
- return tdesc_s390x_linux64v2;
- case S390_TDESC_TE:
- SET_REGMAP(s390x_te_ft_collect_regmap, 32);
- return tdesc_s390x_te_linux64;
- case S390_TDESC_VX:
- SET_REGMAP(s390x_ft_collect_regmap, 0);
- return tdesc_s390x_vx_linux64;
- case S390_TDESC_TEVX:
- SET_REGMAP(s390x_te_ft_collect_regmap, 0);
- return tdesc_s390x_tevx_linux64;
- case S390_TDESC_GS:
- SET_REGMAP(s390x_te_ft_collect_regmap, 0);
- return tdesc_s390x_gs_linux64;
- #else
- case S390_TDESC_32:
- SET_REGMAP(s390_linux32_ft_collect_regmap, 0);
- return tdesc_s390_linux32;
- case S390_TDESC_32V1:
- SET_REGMAP(s390_linux32_ft_collect_regmap, 0);
- return tdesc_s390_linux32v1;
- case S390_TDESC_32V2:
- SET_REGMAP(s390_linux32_ft_collect_regmap, 0);
- return tdesc_s390_linux32v2;
- case S390_TDESC_64:
- SET_REGMAP(s390_linux64_ft_collect_regmap, 32);
- return tdesc_s390_linux64;
- case S390_TDESC_64V1:
- SET_REGMAP(s390_linux64_ft_collect_regmap, 32);
- return tdesc_s390_linux64v1;
- case S390_TDESC_64V2:
- SET_REGMAP(s390_linux64_ft_collect_regmap, 32);
- return tdesc_s390_linux64v2;
- case S390_TDESC_TE:
- SET_REGMAP(s390_te_linux64_ft_collect_regmap, 32);
- return tdesc_s390_te_linux64;
- case S390_TDESC_VX:
- SET_REGMAP(s390_linux64_ft_collect_regmap, 0);
- return tdesc_s390_vx_linux64;
- case S390_TDESC_TEVX:
- SET_REGMAP(s390_te_linux64_ft_collect_regmap, 0);
- return tdesc_s390_tevx_linux64;
- case S390_TDESC_GS:
- SET_REGMAP(s390_te_linux64_ft_collect_regmap, 0);
- return tdesc_s390_gs_linux64;
- #endif
- default:
- internal_error (__FILE__, __LINE__,
- "unknown ipa tdesc index: %d", idx);
- #ifdef __s390x__
- return tdesc_s390x_linux64;
- #else
- return tdesc_s390_linux32;
- #endif
- }
- }
- /* Allocate buffer for the jump pads. On 31-bit, JG reaches everywhere,
- so just allocate normally. On 64-bit, we have +/-4GiB of reach, and
- the executable is usually mapped at 0x80000000 - aim for somewhere
- below it. */
- void *
- alloc_jump_pad_buffer (size_t size)
- {
- #ifdef __s390x__
- uintptr_t addr;
- uintptr_t exec_base = getauxval (AT_PHDR);
- int pagesize;
- void *res;
- if (exec_base == 0)
- exec_base = 0x80000000;
- pagesize = sysconf (_SC_PAGE_SIZE);
- if (pagesize == -1)
- perror_with_name ("sysconf");
- addr = exec_base - 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)
- {
- /* 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, -1, 0);
- if (res == MAP_FAILED)
- return NULL;
- return res;
- #endif
- }
- void
- initialize_low_tracepoint (void)
- {
- #ifdef __s390x__
- init_registers_s390x_linux64 ();
- init_registers_s390x_linux64v1 ();
- init_registers_s390x_linux64v2 ();
- init_registers_s390x_te_linux64 ();
- init_registers_s390x_vx_linux64 ();
- init_registers_s390x_tevx_linux64 ();
- init_registers_s390x_gs_linux64 ();
- #else
- init_registers_s390_linux32 ();
- init_registers_s390_linux32v1 ();
- init_registers_s390_linux32v2 ();
- init_registers_s390_linux64 ();
- init_registers_s390_linux64v1 ();
- init_registers_s390_linux64v2 ();
- init_registers_s390_te_linux64 ();
- init_registers_s390_vx_linux64 ();
- init_registers_s390_tevx_linux64 ();
- init_registers_s390_gs_linux64 ();
- #endif
- }
|