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-2015 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 
25 /* GDB register numbers. */
26 
28 {
29  I386_EAX_REGNUM, /* %eax */
30  I386_ECX_REGNUM, /* %ecx */
31  I386_EDX_REGNUM, /* %edx */
32  I386_EBX_REGNUM, /* %ebx */
33  I386_ESP_REGNUM, /* %esp */
34  I386_EBP_REGNUM, /* %ebp */
35  I386_ESI_REGNUM, /* %esi */
36  I386_EDI_REGNUM, /* %edi */
37  I386_EIP_REGNUM, /* %eip */
38  I386_EFLAGS_REGNUM, /* %eflags */
39  I386_CS_REGNUM, /* %cs */
40  I386_SS_REGNUM, /* %ss */
41  I386_DS_REGNUM, /* %ds */
42  I386_ES_REGNUM, /* %es */
43  I386_FS_REGNUM, /* %fs */
44  I386_GS_REGNUM, /* %gs */
45  I386_ST0_REGNUM /* %st(0) */
46 };
47 
48 #define i386_num_regs 16
49 
50 /* Defined in auto-generated file i386-linux.c. */
51 void init_registers_i386_linux (void);
52 extern const struct target_desc *tdesc_i386_linux;
53 
54 #define FT_CR_EAX 15
55 #define FT_CR_ECX 14
56 #define FT_CR_EDX 13
57 #define FT_CR_EBX 12
58 #define FT_CR_UESP 11
59 #define FT_CR_EBP 10
60 #define FT_CR_ESI 9
61 #define FT_CR_EDI 8
62 #define FT_CR_EIP 7
63 #define FT_CR_EFL 6
64 #define FT_CR_DS 5
65 #define FT_CR_ES 4
66 #define FT_CR_FS 3
67 #define FT_CR_GS 2
68 #define FT_CR_SS 1
69 #define FT_CR_CS 0
70 
71 /* Mapping between the general-purpose registers in jump tracepoint
72  format and GDB's register array layout. */
73 
74 static const int i386_ft_collect_regmap[] =
75 {
76  FT_CR_EAX * 4, FT_CR_ECX * 4, FT_CR_EDX * 4, FT_CR_EBX * 4,
77  FT_CR_UESP * 4, FT_CR_EBP * 4, FT_CR_ESI * 4, FT_CR_EDI * 4,
78  FT_CR_EIP * 4, FT_CR_EFL * 4, FT_CR_CS * 4, FT_CR_SS * 4,
79  FT_CR_DS * 4, FT_CR_ES * 4, FT_CR_FS * 4, FT_CR_GS * 4
80 };
81 
82 void
83 supply_fast_tracepoint_registers (struct regcache *regcache,
84  const unsigned char *buf)
85 {
86  int i;
87 
88  for (i = 0; i < i386_num_regs; i++)
89  {
90  int regval;
91 
92  if (i >= I386_CS_REGNUM && i <= I386_GS_REGNUM)
93  regval = *(short *) (((char *) buf) + i386_ft_collect_regmap[i]);
94  else
95  regval = *(int *) (((char *) buf) + i386_ft_collect_regmap[i]);
96 
97  supply_register (regcache, i, &regval);
98  }
99 }
100 
102 gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
103 {
104  /* This should maybe be allowed to return an error code, or perhaps
105  better, have the emit_reg detect this, and emit a constant zero,
106  or something. */
107 
108  if (regnum > i386_num_regs)
109  return 0;
110  else if (regnum >= I386_CS_REGNUM && regnum <= I386_GS_REGNUM)
111  return *(short *) (raw_regs + i386_ft_collect_regmap[regnum]);
112  else
113  return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
114 }
115 
116 #ifdef HAVE_UST
117 
118 #include <ust/processor.h>
119 
120 /* "struct registers" is the UST object type holding the registers at
121  the time of the static tracepoint marker call. This doesn't
122  contain EIP, but we know what it must have been (the marker
123  address). */
124 
125 #define ST_REGENTRY(REG) \
126  { \
127  offsetof (struct registers, REG), \
128  sizeof (((struct registers *) NULL)->REG) \
129  }
130 
131 static struct
132 {
133  int offset;
134  int size;
135 } i386_st_collect_regmap[] =
136  {
137  ST_REGENTRY(eax),
138  ST_REGENTRY(ecx),
139  ST_REGENTRY(edx),
140  ST_REGENTRY(ebx),
141  ST_REGENTRY(esp),
142  ST_REGENTRY(ebp),
143  ST_REGENTRY(esi),
144  ST_REGENTRY(edi),
145  { -1, 0 }, /* eip */
146  ST_REGENTRY(eflags),
147  ST_REGENTRY(cs),
148  ST_REGENTRY(ss),
149  };
150 
151 #define i386_NUM_ST_COLLECT_GREGS \
152  (sizeof (i386_st_collect_regmap) / sizeof (i386_st_collect_regmap[0]))
153 
154 void
155 supply_static_tracepoint_registers (struct regcache *regcache,
156  const unsigned char *buf,
157  CORE_ADDR pc)
158 {
159  int i;
160  unsigned int newpc = pc;
161 
162  supply_register (regcache, I386_EIP_REGNUM, &newpc);
163 
164  for (i = 0; i < i386_NUM_ST_COLLECT_GREGS; i++)
165  if (i386_st_collect_regmap[i].offset != -1)
166  {
167  switch (i386_st_collect_regmap[i].size)
168  {
169  case 4:
170  supply_register (regcache, i,
171  ((char *) buf)
172  + i386_st_collect_regmap[i].offset);
173  break;
174  case 2:
175  {
176  unsigned long reg
177  = * (short *) (((char *) buf)
178  + i386_st_collect_regmap[i].offset);
179  reg &= 0xffff;
180  supply_register (regcache, i, &reg);
181  }
182  break;
183  default:
184  internal_error (__FILE__, __LINE__, "unhandled register size: %d",
185  i386_st_collect_regmap[i].size);
186  }
187  }
188 }
189 
190 #endif /* HAVE_UST */
191 
192 
193 /* This is only needed because reg-i386-linux-lib.o references it. We
194  may use it proper at some point. */
196 
197 /* Attempt to allocate memory for trampolines in the first 64 KiB of
198  memory to enable smaller jump patches. */
199 
200 static void
202 {
203  const CORE_ADDR buffer_end = 64 * 1024;
204  /* Ensure that the buffer will be at least 1 KiB in size, which is
205  enough space for over 200 fast tracepoints. */
206  const int min_buffer_size = 1024;
207  char buf[IPA_BUFSIZ];
208  CORE_ADDR mmap_min_addr = buffer_end + 1;
209  ULONGEST buffer_size;
210  FILE *f = fopen ("/proc/sys/vm/mmap_min_addr", "r");
211 
212  if (!f)
213  {
214  snprintf (buf, sizeof (buf), "mmap_min_addr open failed: %s",
215  strerror (errno));
216  set_trampoline_buffer_space (0, 0, buf);
217  return;
218  }
219 
220  if (fgets (buf, IPA_BUFSIZ, f))
221  sscanf (buf, "%llu", &mmap_min_addr);
222 
223  fclose (f);
224 
225  buffer_size = buffer_end - mmap_min_addr;
226 
227  if (buffer_size >= min_buffer_size)
228  {
229  if (mmap ((void *) (uintptr_t) mmap_min_addr, buffer_size,
230  PROT_READ | PROT_EXEC | PROT_WRITE,
231  MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
232  -1, 0)
233  != MAP_FAILED)
234  set_trampoline_buffer_space (mmap_min_addr, buffer_end, NULL);
235  else
236  {
237  snprintf (buf, IPA_BUFSIZ, "low-64K-buffer mmap() failed: %s",
238  strerror (errno));
239  set_trampoline_buffer_space (0, 0, buf);
240  }
241  }
242  else
243  {
244  snprintf (buf, IPA_BUFSIZ, "mmap_min_addr is %d, must be %d or less",
245  (int) mmap_min_addr, (int) buffer_end - min_buffer_size);
246  set_trampoline_buffer_space (0, 0, buf);
247  }
248 }
249 
250 void
252 {
254  ipa_tdesc = tdesc_i386_linux;
256 }
#define IP_AGENT_EXPORT_FUNC
Definition: tracepoint.h:65
#define FT_CR_EBP
#define i386_num_regs
bfd_vma CORE_ADDR
Definition: common-types.h:41
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
void init_registers_i386_linux(void)
Definition: i386-linux.c:78
static const int i386_ft_collect_regmap[]
#define FT_CR_EIP
const char * gdbserver_xmltarget
#define FT_CR_ESI
#define FT_CR_SS
int offset
Definition: tracepoint.c:179
#define IPA_BUFSIZ
Definition: tracepoint.h:24
const struct target_desc * tdesc_i386_linux
Definition: i386-linux.c:75
#define FT_CR_EFL
#define FT_CR_FS
#define errno
Definition: wincecompat.h:24
#define FT_CR_CS
void initialize_low_tracepoint(void)
#define FT_CR_EBX
#define FT_CR_EDI
#define FT_CR_DS
unsigned long long ULONGEST
Definition: common-types.h:53
IP_AGENT_EXPORT_FUNC ULONGEST gdb_agent_get_raw_reg(const unsigned char *raw_regs, int regnum)
#define FT_CR_EDX
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:330
#define FT_CR_EAX
char * strerror(int)
#define FT_CR_ES