GDBserver
linux-i386-ipa.c
Go to the documentation of this file.
1 /* GNU/Linux/x86 specific low level interface, for the in-process
2  agent library for GDB.
3 
4  Copyright (C) 2010-2018 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 "server.h"
22 #include <sys/mman.h>
23 #include "tracepoint.h"
24 #include "linux-x86-tdesc.h"
25 #include "common/x86-xstate.h"
26 
27 /* GDB register numbers. */
28 
30 {
31  I386_EAX_REGNUM, /* %eax */
32  I386_ECX_REGNUM, /* %ecx */
33  I386_EDX_REGNUM, /* %edx */
34  I386_EBX_REGNUM, /* %ebx */
35  I386_ESP_REGNUM, /* %esp */
36  I386_EBP_REGNUM, /* %ebp */
37  I386_ESI_REGNUM, /* %esi */
38  I386_EDI_REGNUM, /* %edi */
39  I386_EIP_REGNUM, /* %eip */
40  I386_EFLAGS_REGNUM, /* %eflags */
41  I386_CS_REGNUM, /* %cs */
42  I386_SS_REGNUM, /* %ss */
43  I386_DS_REGNUM, /* %ds */
44  I386_ES_REGNUM, /* %es */
45  I386_FS_REGNUM, /* %fs */
46  I386_GS_REGNUM, /* %gs */
47  I386_ST0_REGNUM /* %st(0) */
48 };
49 
50 #define i386_num_regs 16
51 
52 #define FT_CR_EAX 15
53 #define FT_CR_ECX 14
54 #define FT_CR_EDX 13
55 #define FT_CR_EBX 12
56 #define FT_CR_UESP 11
57 #define FT_CR_EBP 10
58 #define FT_CR_ESI 9
59 #define FT_CR_EDI 8
60 #define FT_CR_EIP 7
61 #define FT_CR_EFL 6
62 #define FT_CR_DS 5
63 #define FT_CR_ES 4
64 #define FT_CR_FS 3
65 #define FT_CR_GS 2
66 #define FT_CR_SS 1
67 #define FT_CR_CS 0
68 
69 /* Mapping between the general-purpose registers in jump tracepoint
70  format and GDB's register array layout. */
71 
72 static const int i386_ft_collect_regmap[] =
73 {
74  FT_CR_EAX * 4, FT_CR_ECX * 4, FT_CR_EDX * 4, FT_CR_EBX * 4,
75  FT_CR_UESP * 4, FT_CR_EBP * 4, FT_CR_ESI * 4, FT_CR_EDI * 4,
76  FT_CR_EIP * 4, FT_CR_EFL * 4, FT_CR_CS * 4, FT_CR_SS * 4,
77  FT_CR_DS * 4, FT_CR_ES * 4, FT_CR_FS * 4, FT_CR_GS * 4
78 };
79 
80 void
82  const unsigned char *buf)
83 {
84  int i;
85 
86  for (i = 0; i < i386_num_regs; i++)
87  {
88  int regval;
89 
90  if (i >= I386_CS_REGNUM && i <= I386_GS_REGNUM)
91  regval = *(short *) (((char *) buf) + i386_ft_collect_regmap[i]);
92  else
93  regval = *(int *) (((char *) buf) + i386_ft_collect_regmap[i]);
94 
95  supply_register (regcache, i, &regval);
96  }
97 }
98 
100 get_raw_reg (const unsigned char *raw_regs, int regnum)
101 {
102  /* This should maybe be allowed to return an error code, or perhaps
103  better, have the emit_reg detect this, and emit a constant zero,
104  or something. */
105 
106  if (regnum > i386_num_regs)
107  return 0;
108  else if (regnum >= I386_CS_REGNUM && regnum <= I386_GS_REGNUM)
109  return *(short *) (raw_regs + i386_ft_collect_regmap[regnum]);
110  else
111  return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
112 }
113 
114 #ifdef HAVE_UST
115 
116 #include <ust/processor.h>
117 
118 /* "struct registers" is the UST object type holding the registers at
119  the time of the static tracepoint marker call. This doesn't
120  contain EIP, but we know what it must have been (the marker
121  address). */
122 
123 #define ST_REGENTRY(REG) \
124  { \
125  offsetof (struct registers, REG), \
126  sizeof (((struct registers *) NULL)->REG) \
127  }
128 
129 static struct
130 {
131  int offset;
132  int size;
133 } i386_st_collect_regmap[] =
134  {
135  ST_REGENTRY(eax),
136  ST_REGENTRY(ecx),
137  ST_REGENTRY(edx),
138  ST_REGENTRY(ebx),
139  ST_REGENTRY(esp),
140  ST_REGENTRY(ebp),
141  ST_REGENTRY(esi),
142  ST_REGENTRY(edi),
143  { -1, 0 }, /* eip */
144  ST_REGENTRY(eflags),
145  ST_REGENTRY(cs),
146  ST_REGENTRY(ss),
147  };
148 
149 #define i386_NUM_ST_COLLECT_GREGS \
150  (sizeof (i386_st_collect_regmap) / sizeof (i386_st_collect_regmap[0]))
151 
152 void
153 supply_static_tracepoint_registers (struct regcache *regcache,
154  const unsigned char *buf,
155  CORE_ADDR pc)
156 {
157  int i;
158  unsigned int newpc = pc;
159 
161 
162  for (i = 0; i < i386_NUM_ST_COLLECT_GREGS; i++)
163  if (i386_st_collect_regmap[i].offset != -1)
164  {
165  switch (i386_st_collect_regmap[i].size)
166  {
167  case 4:
169  ((char *) buf)
170  + i386_st_collect_regmap[i].offset);
171  break;
172  case 2:
173  {
174  unsigned long reg
175  = * (short *) (((char *) buf)
176  + i386_st_collect_regmap[i].offset);
177  reg &= 0xffff;
178  supply_register (regcache, i, &reg);
179  }
180  break;
181  default:
182  internal_error (__FILE__, __LINE__, "unhandled register size: %d",
183  i386_st_collect_regmap[i].size);
184  }
185  }
186 }
187 
188 #endif /* HAVE_UST */
189 
190 
191 /* This is only needed because reg-i386-linux-lib.o references it. We
192  may use it proper at some point. */
194 
195 /* Attempt to allocate memory for trampolines in the first 64 KiB of
196  memory to enable smaller jump patches. */
197 
198 static void
200 {
201  const CORE_ADDR buffer_end = 64 * 1024;
202  /* Ensure that the buffer will be at least 1 KiB in size, which is
203  enough space for over 200 fast tracepoints. */
204  const int min_buffer_size = 1024;
205  char buf[IPA_BUFSIZ];
206  CORE_ADDR mmap_min_addr = buffer_end + 1;
207  ULONGEST buffer_size;
208  FILE *f = fopen ("/proc/sys/vm/mmap_min_addr", "r");
209 
210  if (!f)
211  {
212  snprintf (buf, sizeof (buf), "mmap_min_addr open failed: %s",
213  strerror (errno));
214  set_trampoline_buffer_space (0, 0, buf);
215  return;
216  }
217 
218  if (fgets (buf, IPA_BUFSIZ, f))
219  sscanf (buf, "%llu", &mmap_min_addr);
220 
221  fclose (f);
222 
223  buffer_size = buffer_end - mmap_min_addr;
224 
225  if (buffer_size >= min_buffer_size)
226  {
227  if (mmap ((void *) (uintptr_t) mmap_min_addr, buffer_size,
228  PROT_READ | PROT_EXEC | PROT_WRITE,
229  MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
230  -1, 0)
231  != MAP_FAILED)
232  set_trampoline_buffer_space (mmap_min_addr, buffer_end, NULL);
233  else
234  {
235  snprintf (buf, IPA_BUFSIZ, "low-64K-buffer mmap() failed: %s",
236  strerror (errno));
237  set_trampoline_buffer_space (0, 0, buf);
238  }
239  }
240  else
241  {
242  snprintf (buf, IPA_BUFSIZ, "mmap_min_addr is %d, must be %d or less",
243  (int) mmap_min_addr, (int) buffer_end - min_buffer_size);
244  set_trampoline_buffer_space (0, 0, buf);
245  }
246 }
247 
248 /* Map the tdesc index to xcr0 mask. */
249 static uint64_t idx2mask[X86_TDESC_LAST] = {
257 };
258 
259 /* Return target_desc to use for IPA, given the tdesc index passed by
260  gdbserver. */
261 
262 const struct target_desc *
263 get_ipa_tdesc (int idx)
264 {
265  if (idx >= X86_TDESC_LAST)
266  {
267  internal_error (__FILE__, __LINE__,
268  "unknown ipa tdesc index: %d", idx);
269  }
271 }
272 
273 /* Allocate buffer for the jump pads. On i386, we can reach an arbitrary
274  address with a jump instruction, so just allocate normally. */
275 
276 void *
278 {
279  void *res = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
280  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
281 
282  if (res == MAP_FAILED)
283  return NULL;
284 
285  return res;
286 }
287 
288 void
290 {
292  for (auto i = 0; i < X86_TDESC_LAST; i++)
294 }
#define X86_XSTATE_AVX_MASK
Definition: x86-xstate.h:43
#define FT_CR_EBP
#define i386_num_regs
#define X86_XSTATE_SSE_MASK
Definition: x86-xstate.h:42
bfd_vma CORE_ADDR
Definition: common-types.h:41
const struct target_desc * i386_linux_read_description(uint64_t xcr0)
#define X86_XSTATE_MPX_MASK
Definition: x86-xstate.h:44
void supply_fast_tracepoint_registers(struct regcache *regcache, const unsigned char *buf)
void internal_error(const char *file, int line, const char *fmt,...)
Definition: errors.c:50
regnum
#define FT_CR_ECX
#define FT_CR_GS
static const int i386_ft_collect_regmap[]
#define FT_CR_EIP
const char * gdbserver_xmltarget
#define FT_CR_ESI
#define X86_XSTATE_AVX_AVX512_MASK
Definition: x86-xstate.h:46
#define FT_CR_SS
int offset
Definition: tracepoint.c:181
void * alloc_jump_pad_buffer(size_t size)
#define IPA_BUFSIZ
Definition: tracepoint.h:24
#define FT_CR_EFL
#define FT_CR_FS
#define errno
Definition: wincecompat.h:24
#define X86_XSTATE_X87_MASK
Definition: x86-xstate.h:41
#define FT_CR_CS
void initialize_low_tracepoint(void)
#define FT_CR_EBX
static uint64_t idx2mask[X86_TDESC_LAST]
#define FT_CR_EDI
const struct target_desc * get_ipa_tdesc(int idx)
#define FT_CR_DS
unsigned long long ULONGEST
Definition: common-types.h:53
ULONGEST get_raw_reg(const unsigned char *raw_regs, int regnum)
#define FT_CR_EDX
#define X86_XSTATE_AVX_MPX_MASK
Definition: x86-xstate.h:45
static void initialize_fast_tracepoint_trampoline_buffer(void)
#define FT_CR_UESP
i386_gdb_regnum
void supply_register(struct regcache *regcache, int n, const void *buf)
Definition: regcache.c:318
#define FT_CR_EAX
#define X86_XSTATE_AVX_MPX_AVX512_PKU_MASK
Definition: x86-xstate.h:47
char * strerror(int)
#define FT_CR_ES