Home | History | Annotate | Line # | Download | only in gdbserver
      1 /* GNU/Linux/x86-64 specific low level interface, for the in-process
      2    agent library for GDB.
      3 
      4    Copyright (C) 2010-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 "linux-x86-tdesc.h"
     24 #include "gdbsupport/x86-xstate.h"
     25 
     26 /* fast tracepoints collect registers.  */
     27 
     28 #define FT_CR_RIP 0
     29 #define FT_CR_EFLAGS 1
     30 #define FT_CR_R8 2
     31 #define FT_CR_R9 3
     32 #define FT_CR_R10 4
     33 #define FT_CR_R11 5
     34 #define FT_CR_R12 6
     35 #define FT_CR_R13 7
     36 #define FT_CR_R14 8
     37 #define FT_CR_R15 9
     38 #define FT_CR_RAX 10
     39 #define FT_CR_RBX 11
     40 #define FT_CR_RCX 12
     41 #define FT_CR_RDX 13
     42 #define FT_CR_RSI 14
     43 #define FT_CR_RDI 15
     44 #define FT_CR_RBP 16
     45 #define FT_CR_RSP 17
     46 
     47 static const int x86_64_ft_collect_regmap[] = {
     48   FT_CR_RAX * 8, FT_CR_RBX * 8, FT_CR_RCX * 8, FT_CR_RDX * 8,
     49   FT_CR_RSI * 8, FT_CR_RDI * 8, FT_CR_RBP * 8, FT_CR_RSP * 8,
     50   FT_CR_R8 * 8,  FT_CR_R9 * 8,  FT_CR_R10 * 8, FT_CR_R11 * 8,
     51   FT_CR_R12 * 8, FT_CR_R13 * 8, FT_CR_R14 * 8, FT_CR_R15 * 8,
     52   FT_CR_RIP * 8, FT_CR_EFLAGS * 8
     53 };
     54 
     55 #define X86_64_NUM_FT_COLLECT_GREGS \
     56   (sizeof (x86_64_ft_collect_regmap) / sizeof(x86_64_ft_collect_regmap[0]))
     57 
     58 void
     59 supply_fast_tracepoint_registers (struct regcache *regcache,
     60 				  const unsigned char *buf)
     61 {
     62   int i;
     63 
     64   for (i = 0; i < X86_64_NUM_FT_COLLECT_GREGS; i++)
     65     supply_register (regcache, i,
     66 		     ((char *) buf) + x86_64_ft_collect_regmap[i]);
     67 }
     68 
     69 ULONGEST
     70 get_raw_reg (const unsigned char *raw_regs, int regnum)
     71 {
     72   if (regnum >= X86_64_NUM_FT_COLLECT_GREGS)
     73     return 0;
     74 
     75   return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
     76 }
     77 
     78 #ifdef HAVE_UST
     79 
     80 #include <ust/processor.h>
     81 
     82 /* "struct registers" is the UST object type holding the registers at
     83    the time of the static tracepoint marker call.  This doesn't
     84    contain RIP, but we know what it must have been (the marker
     85    address).  */
     86 
     87 #define ST_REGENTRY(REG)			\
     88   {						\
     89     offsetof (struct registers, REG),		\
     90     sizeof (((struct registers *) NULL)->REG)	\
     91   }
     92 
     93 static struct
     94 {
     95   int offset;
     96   int size;
     97 } x86_64_st_collect_regmap[] =
     98   {
     99     ST_REGENTRY(rax),
    100     ST_REGENTRY(rbx),
    101     ST_REGENTRY(rcx),
    102     ST_REGENTRY(rdx),
    103     ST_REGENTRY(rsi),
    104     ST_REGENTRY(rdi),
    105     ST_REGENTRY(rbp),
    106     ST_REGENTRY(rsp),
    107     ST_REGENTRY(r8),
    108     ST_REGENTRY(r9),
    109     ST_REGENTRY(r10),
    110     ST_REGENTRY(r11),
    111     ST_REGENTRY(r12),
    112     ST_REGENTRY(r13),
    113     ST_REGENTRY(r14),
    114     ST_REGENTRY(r15),
    115     { -1, 0 },
    116     ST_REGENTRY(rflags),
    117     ST_REGENTRY(cs),
    118     ST_REGENTRY(ss),
    119   };
    120 
    121 #define X86_64_NUM_ST_COLLECT_GREGS \
    122   (sizeof (x86_64_st_collect_regmap) / sizeof (x86_64_st_collect_regmap[0]))
    123 
    124 /* GDB's RIP register number.  */
    125 #define AMD64_RIP_REGNUM 16
    126 
    127 void
    128 supply_static_tracepoint_registers (struct regcache *regcache,
    129 				    const unsigned char *buf,
    130 				    CORE_ADDR pc)
    131 {
    132   int i;
    133   unsigned long newpc = pc;
    134 
    135   supply_register (regcache, AMD64_RIP_REGNUM, &newpc);
    136 
    137   for (i = 0; i < X86_64_NUM_ST_COLLECT_GREGS; i++)
    138     if (x86_64_st_collect_regmap[i].offset != -1)
    139       {
    140 	switch (x86_64_st_collect_regmap[i].size)
    141 	  {
    142 	  case 8:
    143 	    supply_register (regcache, i,
    144 			     ((char *) buf)
    145 			     + x86_64_st_collect_regmap[i].offset);
    146 	    break;
    147 	  case 2:
    148 	    {
    149 	      unsigned long reg
    150 		= * (short *) (((char *) buf)
    151 			       + x86_64_st_collect_regmap[i].offset);
    152 	      reg &= 0xffff;
    153 	      supply_register (regcache, i, &reg);
    154 	    }
    155 	    break;
    156 	  default:
    157 	    internal_error ("unhandled register size: %d",
    158 			    x86_64_st_collect_regmap[i].size);
    159 	    break;
    160 	  }
    161       }
    162 }
    163 
    164 #endif /* HAVE_UST */
    165 
    166 #if !defined __ILP32__
    167 /* Map the tdesc index to xcr0 mask.  */
    168 static uint64_t idx2mask[X86_TDESC_LAST] = {
    169   X86_XSTATE_X87_MASK,
    170   X86_XSTATE_SSE_MASK,
    171   X86_XSTATE_AVX_MASK,
    172   X86_XSTATE_MPX_MASK,
    173   X86_XSTATE_AVX_MPX_MASK,
    174   X86_XSTATE_AVX_AVX512_MASK,
    175   X86_XSTATE_AVX_MPX_AVX512_PKU_MASK,
    176 };
    177 #endif
    178 
    179 /* Return target_desc to use for IPA, given the tdesc index passed by
    180    gdbserver.  */
    181 
    182 const struct target_desc *
    183 get_ipa_tdesc (int idx)
    184 {
    185   if (idx >= X86_TDESC_LAST)
    186     {
    187       internal_error ("unknown ipa tdesc index: %d", idx);
    188     }
    189 
    190 #if defined __ILP32__
    191   switch (idx)
    192     {
    193     case X86_TDESC_SSE:
    194       return amd64_linux_read_description (X86_XSTATE_SSE_MASK, true);
    195     case X86_TDESC_AVX:
    196       return amd64_linux_read_description (X86_XSTATE_AVX_MASK, true);
    197     case X86_TDESC_AVX_AVX512:
    198       return amd64_linux_read_description (X86_XSTATE_AVX_AVX512_MASK, true);
    199     default:
    200       break;
    201     }
    202 #else
    203   return amd64_linux_read_description (idx2mask[idx], false);
    204 #endif
    205 
    206   internal_error ("unknown ipa tdesc index: %d", idx);
    207 }
    208 
    209 /* Allocate buffer for the jump pads.  The branch instruction has a
    210    reach of +/- 31-bit, and the executable is loaded at low addresses.
    211 
    212    64-bit: Use MAP_32BIT to allocate in the first 2GB.  Shared
    213    libraries, being allocated at the top, are unfortunately out of
    214    luck.
    215 
    216    x32: Since MAP_32BIT is 64-bit only, do the placement manually.
    217    Try allocating at '0x80000000 - SIZE' initially, decreasing until
    218    we hit a free area.  This ensures the executable is fully covered,
    219    and is as close as possible to the shared libraries, which are
    220    usually mapped at the top of the first 4GB of the address space.
    221 */
    222 
    223 void *
    224 alloc_jump_pad_buffer (size_t size)
    225 {
    226 #if __ILP32__
    227   uintptr_t addr;
    228   int pagesize;
    229 
    230   pagesize = sysconf (_SC_PAGE_SIZE);
    231   if (pagesize == -1)
    232     perror_with_name ("sysconf");
    233 
    234   addr = 0x80000000 - size;
    235 
    236   /* size should already be page-aligned, but this can't hurt.  */
    237   addr &= ~(pagesize - 1);
    238 
    239   /* Search for a free area.  If we hit 0, we're out of luck.  */
    240   for (; addr; addr -= pagesize)
    241     {
    242       void *res;
    243 
    244       /* No MAP_FIXED - we don't want to zap someone's mapping.  */
    245       res = mmap ((void *) addr, size,
    246 		  PROT_READ | PROT_WRITE | PROT_EXEC,
    247 		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    248 
    249       /* If we got what we wanted, return.  */
    250       if ((uintptr_t) res == addr)
    251 	return res;
    252 
    253       /* If we got a mapping, but at a wrong address, undo it.  */
    254       if (res != MAP_FAILED)
    255 	munmap (res, size);
    256     }
    257 
    258   return NULL;
    259 #else
    260   void *res = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
    261 		    MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
    262 
    263   if (res == MAP_FAILED)
    264     return NULL;
    265 
    266   return res;
    267 #endif
    268 }
    269 
    270 void
    271 initialize_low_tracepoint (void)
    272 {
    273 #if defined __ILP32__
    274   amd64_linux_read_description (X86_XSTATE_SSE_MASK, true);
    275   amd64_linux_read_description (X86_XSTATE_AVX_MASK, true);
    276   amd64_linux_read_description (X86_XSTATE_AVX_AVX512_MASK, true);
    277 #else
    278   for (auto i = 0; i < X86_TDESC_LAST; i++)
    279     amd64_linux_read_description (idx2mask[i], false);
    280 #endif
    281 }
    282