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