Home | History | Annotate | Line # | Download | only in gdbserver
      1 /* GNU/Linux/AArch64 specific low level interface, for the in-process
      2    agent library for GDB.
      3 
      4    Copyright (C) 2015-2024 Free Software Foundation, Inc.
      5 
      6    This file is part of GDB.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20 
     21 #include <sys/mman.h>
     22 #include "tracepoint.h"
     23 #include <elf.h>
     24 #ifdef HAVE_GETAUXVAL
     25 #include <sys/auxv.h>
     26 #endif
     27 #include "linux-aarch64-tdesc.h"
     28 
     29 /* Each register saved by the jump pad is in a 16 byte cell.  */
     30 #define FT_CR_SIZE 16
     31 
     32 #define FT_CR_FPCR	0
     33 #define FT_CR_FPSR	1
     34 #define FT_CR_CPSR	2
     35 #define FT_CR_PC	3
     36 #define FT_CR_SP	4
     37 #define FT_CR_X0	5
     38 #define FT_CR_GPR(n)	(FT_CR_X0 + (n))
     39 #define FT_CR_FPR(n)	(FT_CR_GPR (31) + (n))
     40 
     41 /* Mapping between registers collected by the jump pad and GDB's register
     42    array layout used by regcache.
     43 
     44    See linux-aarch64-low.c (aarch64_install_fast_tracepoint_jump_pad) for
     45    more details.  */
     46 
     47 static const int aarch64_ft_collect_regmap[] = {
     48   FT_CR_GPR (0),
     49   FT_CR_GPR (1),
     50   FT_CR_GPR (2),
     51   FT_CR_GPR (3),
     52   FT_CR_GPR (4),
     53   FT_CR_GPR (5),
     54   FT_CR_GPR (6),
     55   FT_CR_GPR (7),
     56   FT_CR_GPR (8),
     57   FT_CR_GPR (9),
     58   FT_CR_GPR (10),
     59   FT_CR_GPR (11),
     60   FT_CR_GPR (12),
     61   FT_CR_GPR (13),
     62   FT_CR_GPR (14),
     63   FT_CR_GPR (15),
     64   FT_CR_GPR (16),
     65   FT_CR_GPR (17),
     66   FT_CR_GPR (18),
     67   FT_CR_GPR (19),
     68   FT_CR_GPR (20),
     69   FT_CR_GPR (21),
     70   FT_CR_GPR (22),
     71   FT_CR_GPR (23),
     72   FT_CR_GPR (24),
     73   FT_CR_GPR (25),
     74   FT_CR_GPR (26),
     75   FT_CR_GPR (27),
     76   FT_CR_GPR (28),
     77   /* FP */
     78   FT_CR_GPR (29),
     79   /* LR */
     80   FT_CR_GPR (30),
     81   FT_CR_SP,
     82   FT_CR_PC,
     83   FT_CR_CPSR,
     84   FT_CR_FPR (0),
     85   FT_CR_FPR (1),
     86   FT_CR_FPR (2),
     87   FT_CR_FPR (3),
     88   FT_CR_FPR (4),
     89   FT_CR_FPR (5),
     90   FT_CR_FPR (6),
     91   FT_CR_FPR (7),
     92   FT_CR_FPR (8),
     93   FT_CR_FPR (9),
     94   FT_CR_FPR (10),
     95   FT_CR_FPR (11),
     96   FT_CR_FPR (12),
     97   FT_CR_FPR (13),
     98   FT_CR_FPR (14),
     99   FT_CR_FPR (15),
    100   FT_CR_FPR (16),
    101   FT_CR_FPR (17),
    102   FT_CR_FPR (18),
    103   FT_CR_FPR (19),
    104   FT_CR_FPR (20),
    105   FT_CR_FPR (21),
    106   FT_CR_FPR (22),
    107   FT_CR_FPR (23),
    108   FT_CR_FPR (24),
    109   FT_CR_FPR (25),
    110   FT_CR_FPR (26),
    111   FT_CR_FPR (27),
    112   FT_CR_FPR (28),
    113   FT_CR_FPR (29),
    114   FT_CR_FPR (30),
    115   FT_CR_FPR (31),
    116   FT_CR_FPSR,
    117   FT_CR_FPCR
    118 };
    119 
    120 #define AARCH64_NUM_FT_COLLECT_GREGS \
    121   (sizeof (aarch64_ft_collect_regmap) / sizeof(aarch64_ft_collect_regmap[0]))
    122 
    123 /* Fill in REGCACHE with registers saved by the jump pad in BUF.  */
    124 
    125 void
    126 supply_fast_tracepoint_registers (struct regcache *regcache,
    127 				  const unsigned char *buf)
    128 {
    129   int i;
    130 
    131   for (i = 0; i < AARCH64_NUM_FT_COLLECT_GREGS; i++)
    132     supply_register (regcache, i,
    133 		     ((char *) buf)
    134 		     + (aarch64_ft_collect_regmap[i] * FT_CR_SIZE));
    135 }
    136 
    137 ULONGEST
    138 get_raw_reg (const unsigned char *raw_regs, int regnum)
    139 {
    140   if (regnum >= AARCH64_NUM_FT_COLLECT_GREGS)
    141     return 0;
    142 
    143   return *(ULONGEST *) (raw_regs
    144 			+ aarch64_ft_collect_regmap[regnum] * FT_CR_SIZE);
    145 }
    146 
    147 /* Return target_desc to use for IPA, given the tdesc index passed by
    148    gdbserver.  Index is ignored, since we have only one tdesc
    149    at the moment.  SVE, pauth, MTE and TLS not yet supported.  */
    150 
    151 const struct target_desc *
    152 get_ipa_tdesc (int idx)
    153 {
    154   return aarch64_linux_read_description ({});
    155 }
    156 
    157 /* Allocate buffer for the jump pads.  The branch instruction has a reach
    158    of +/- 128MiB, and the executable is loaded at 0x400000 (4MiB).
    159    To maximize the area of executable that can use tracepoints, try
    160    allocating at 0x400000 - size initially, decreasing until we hit
    161    a free area.  */
    162 
    163 void *
    164 alloc_jump_pad_buffer (size_t size)
    165 {
    166   uintptr_t addr;
    167   uintptr_t exec_base = getauxval (AT_PHDR);
    168   int pagesize;
    169   void *res;
    170 
    171   if (exec_base == 0)
    172     exec_base = 0x400000;
    173 
    174   pagesize = sysconf (_SC_PAGE_SIZE);
    175   if (pagesize == -1)
    176     perror_with_name ("sysconf");
    177 
    178   addr = exec_base - size;
    179 
    180   /* size should already be page-aligned, but this can't hurt.  */
    181   addr &= ~(pagesize - 1);
    182 
    183   /* Search for a free area.  If we hit 0, we're out of luck.  */
    184   for (; addr; addr -= pagesize)
    185     {
    186       /* No MAP_FIXED - we don't want to zap someone's mapping.  */
    187       res = mmap ((void *) addr, size,
    188 		  PROT_READ | PROT_WRITE | PROT_EXEC,
    189 		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    190 
    191       /* If we got what we wanted, return.  */
    192       if ((uintptr_t) res == addr)
    193 	return res;
    194 
    195       /* If we got a mapping, but at a wrong address, undo it.  */
    196       if (res != MAP_FAILED)
    197 	munmap (res, size);
    198     }
    199 
    200   return NULL;
    201 }
    202 
    203 void
    204 initialize_low_tracepoint (void)
    205 {
    206   /* SVE, pauth, MTE and TLS not yet supported.  */
    207   aarch64_linux_read_description ({});
    208 }
    209