Commit | Line | Data |
---|---|---|
d0722149 DE |
1 | /* GNU/Linux/x86-64 specific low level interface, for the remote server |
2 | for GDB. | |
3 | Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008, 2009 | |
4 | 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 <assert.h> | |
22 | #include <signal.h> | |
23 | #include "server.h" | |
24 | #include "linux-low.h" | |
25 | #include "i387-fp.h" | |
26 | ||
27 | #include "gdb_proc_service.h" | |
28 | ||
29 | /* NOTE: gdb_proc_service.h may include linux/elf.h. | |
30 | We need Elf32_Phdr. If we don't get linux/elf.h we could include | |
31 | elf.h like linux-ppc-low.c does. */ | |
32 | ||
33 | /* Defined in auto-generated file reg-i386-linux.c. */ | |
34 | void init_registers_i386_linux (void); | |
35 | /* Defined in auto-generated file reg-x86-64-linux.c. */ | |
36 | void init_registers_x86_64_linux (void); | |
37 | ||
38 | #include <sys/reg.h> | |
39 | #include <sys/procfs.h> | |
40 | #include <sys/ptrace.h> | |
41 | ||
42 | #ifndef PTRACE_GET_THREAD_AREA | |
43 | #define PTRACE_GET_THREAD_AREA 25 | |
44 | #endif | |
45 | ||
46 | /* This definition comes from prctl.h, but some kernels may not have it. */ | |
47 | #ifndef PTRACE_ARCH_PRCTL | |
48 | #define PTRACE_ARCH_PRCTL 30 | |
49 | #endif | |
50 | ||
51 | /* The following definitions come from prctl.h, but may be absent | |
52 | for certain configurations. */ | |
53 | #ifndef ARCH_GET_FS | |
54 | #define ARCH_SET_GS 0x1001 | |
55 | #define ARCH_SET_FS 0x1002 | |
56 | #define ARCH_GET_FS 0x1003 | |
57 | #define ARCH_GET_GS 0x1004 | |
58 | #endif | |
59 | ||
60 | #ifdef __x86_64__ | |
61 | ||
62 | /* Mapping between the general-purpose registers in `struct user' | |
63 | format and GDB's register array layout. | |
64 | Note that the transfer layout uses 64-bit regs. */ | |
65 | static /*const*/ int i386_regmap[] = | |
66 | { | |
67 | RAX * 8, RCX * 8, RDX * 8, RBX * 8, | |
68 | RSP * 8, RBP * 8, RSI * 8, RDI * 8, | |
69 | RIP * 8, EFLAGS * 8, CS * 8, SS * 8, | |
70 | DS * 8, ES * 8, FS * 8, GS * 8 | |
71 | }; | |
72 | ||
73 | #define I386_NUM_REGS (sizeof (i386_regmap) / sizeof (i386_regmap[0])) | |
74 | ||
75 | /* So code below doesn't have to care, i386 or amd64. */ | |
76 | #define ORIG_EAX ORIG_RAX | |
77 | ||
78 | static const int x86_64_regmap[] = | |
79 | { | |
80 | RAX * 8, RBX * 8, RCX * 8, RDX * 8, | |
81 | RSI * 8, RDI * 8, RBP * 8, RSP * 8, | |
82 | R8 * 8, R9 * 8, R10 * 8, R11 * 8, | |
83 | R12 * 8, R13 * 8, R14 * 8, R15 * 8, | |
84 | RIP * 8, EFLAGS * 8, CS * 8, SS * 8, | |
85 | DS * 8, ES * 8, FS * 8, GS * 8, | |
86 | -1, -1, -1, -1, -1, -1, -1, -1, | |
87 | -1, -1, -1, -1, -1, -1, -1, -1, | |
88 | -1, -1, -1, -1, -1, -1, -1, -1, | |
89 | -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
90 | ORIG_RAX * 8 | |
91 | }; | |
92 | ||
93 | #define X86_64_NUM_REGS (sizeof (x86_64_regmap) / sizeof (x86_64_regmap[0])) | |
94 | ||
95 | #else /* ! __x86_64__ */ | |
96 | ||
97 | /* Mapping between the general-purpose registers in `struct user' | |
98 | format and GDB's register array layout. */ | |
99 | static /*const*/ int i386_regmap[] = | |
100 | { | |
101 | EAX * 4, ECX * 4, EDX * 4, EBX * 4, | |
102 | UESP * 4, EBP * 4, ESI * 4, EDI * 4, | |
103 | EIP * 4, EFL * 4, CS * 4, SS * 4, | |
104 | DS * 4, ES * 4, FS * 4, GS * 4 | |
105 | }; | |
106 | ||
107 | #define I386_NUM_REGS (sizeof (i386_regmap) / sizeof (i386_regmap[0])) | |
108 | ||
109 | #endif | |
110 | \f | |
111 | /* Called by libthread_db. */ | |
112 | ||
113 | ps_err_e | |
114 | ps_get_thread_area (const struct ps_prochandle *ph, | |
115 | lwpid_t lwpid, int idx, void **base) | |
116 | { | |
117 | #ifdef __x86_64__ | |
118 | int use_64bit = register_size (0) == 8; | |
119 | ||
120 | if (use_64bit) | |
121 | { | |
122 | switch (idx) | |
123 | { | |
124 | case FS: | |
125 | if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0) | |
126 | return PS_OK; | |
127 | break; | |
128 | case GS: | |
129 | if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0) | |
130 | return PS_OK; | |
131 | break; | |
132 | default: | |
133 | return PS_BADADDR; | |
134 | } | |
135 | return PS_ERR; | |
136 | } | |
137 | #endif | |
138 | ||
139 | { | |
140 | unsigned int desc[4]; | |
141 | ||
142 | if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, | |
143 | (void *) (intptr_t) idx, (unsigned long) &desc) < 0) | |
144 | return PS_ERR; | |
145 | ||
146 | *(int *)base = desc[1]; | |
147 | return PS_OK; | |
148 | } | |
149 | } | |
150 | \f | |
151 | static int | |
152 | i386_cannot_store_register (int regno) | |
153 | { | |
154 | return regno >= I386_NUM_REGS; | |
155 | } | |
156 | ||
157 | static int | |
158 | i386_cannot_fetch_register (int regno) | |
159 | { | |
160 | return regno >= I386_NUM_REGS; | |
161 | } | |
162 | ||
163 | static void | |
164 | x86_fill_gregset (void *buf) | |
165 | { | |
166 | int i; | |
167 | ||
168 | #ifdef __x86_64__ | |
169 | if (register_size (0) == 8) | |
170 | { | |
171 | for (i = 0; i < X86_64_NUM_REGS; i++) | |
172 | if (x86_64_regmap[i] != -1) | |
173 | collect_register (i, ((char *) buf) + x86_64_regmap[i]); | |
174 | return; | |
175 | } | |
176 | #endif | |
177 | ||
178 | for (i = 0; i < I386_NUM_REGS; i++) | |
179 | collect_register (i, ((char *) buf) + i386_regmap[i]); | |
180 | ||
181 | collect_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4); | |
182 | } | |
183 | ||
184 | static void | |
185 | x86_store_gregset (const void *buf) | |
186 | { | |
187 | int i; | |
188 | ||
189 | #ifdef __x86_64__ | |
190 | if (register_size (0) == 8) | |
191 | { | |
192 | for (i = 0; i < X86_64_NUM_REGS; i++) | |
193 | if (x86_64_regmap[i] != -1) | |
194 | supply_register (i, ((char *) buf) + x86_64_regmap[i]); | |
195 | return; | |
196 | } | |
197 | #endif | |
198 | ||
199 | for (i = 0; i < I386_NUM_REGS; i++) | |
200 | supply_register (i, ((char *) buf) + i386_regmap[i]); | |
201 | ||
202 | supply_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4); | |
203 | } | |
204 | ||
205 | static void | |
206 | x86_fill_fpregset (void *buf) | |
207 | { | |
208 | #ifdef __x86_64__ | |
209 | i387_cache_to_fxsave (buf); | |
210 | #else | |
211 | i387_cache_to_fsave (buf); | |
212 | #endif | |
213 | } | |
214 | ||
215 | static void | |
216 | x86_store_fpregset (const void *buf) | |
217 | { | |
218 | #ifdef __x86_64__ | |
219 | i387_fxsave_to_cache (buf); | |
220 | #else | |
221 | i387_fsave_to_cache (buf); | |
222 | #endif | |
223 | } | |
224 | ||
225 | #ifndef __x86_64__ | |
226 | ||
227 | static void | |
228 | x86_fill_fpxregset (void *buf) | |
229 | { | |
230 | i387_cache_to_fxsave (buf); | |
231 | } | |
232 | ||
233 | static void | |
234 | x86_store_fpxregset (const void *buf) | |
235 | { | |
236 | i387_fxsave_to_cache (buf); | |
237 | } | |
238 | ||
239 | #endif | |
240 | ||
241 | /* ??? The non-biarch i386 case stores all the i387 regs twice. | |
242 | Once in i387_.*fsave.* and once in i387_.*fxsave.*. | |
243 | This is, presumably, to handle the case where PTRACE_[GS]ETFPXREGS | |
244 | doesn't work. IWBN to avoid the duplication in the case where it | |
245 | does work. Maybe the arch_setup routine could check whether it works | |
246 | and update target_regsets accordingly, maybe by moving target_regsets | |
247 | to linux_target_ops and set the right one there, rather than having to | |
248 | modify the target_regsets global. */ | |
249 | ||
250 | struct regset_info target_regsets[] = | |
251 | { | |
252 | #ifdef HAVE_PTRACE_GETREGS | |
253 | { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t), | |
254 | GENERAL_REGS, | |
255 | x86_fill_gregset, x86_store_gregset }, | |
256 | # ifndef __x86_64__ | |
257 | # ifdef HAVE_PTRACE_GETFPXREGS | |
258 | { PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, sizeof (elf_fpxregset_t), | |
259 | EXTENDED_REGS, | |
260 | x86_fill_fpxregset, x86_store_fpxregset }, | |
261 | # endif | |
262 | # endif | |
263 | { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t), | |
264 | FP_REGS, | |
265 | x86_fill_fpregset, x86_store_fpregset }, | |
266 | #endif /* HAVE_PTRACE_GETREGS */ | |
267 | { 0, 0, -1, -1, NULL, NULL } | |
268 | }; | |
269 | ||
270 | static CORE_ADDR | |
271 | x86_get_pc (void) | |
272 | { | |
273 | int use_64bit = register_size (0) == 8; | |
274 | ||
275 | if (use_64bit) | |
276 | { | |
277 | unsigned long pc; | |
278 | collect_register_by_name ("rip", &pc); | |
279 | return (CORE_ADDR) pc; | |
280 | } | |
281 | else | |
282 | { | |
283 | unsigned int pc; | |
284 | collect_register_by_name ("eip", &pc); | |
285 | return (CORE_ADDR) pc; | |
286 | } | |
287 | } | |
288 | ||
289 | static void | |
290 | x86_set_pc (CORE_ADDR pc) | |
291 | { | |
292 | int use_64bit = register_size (0) == 8; | |
293 | ||
294 | if (use_64bit) | |
295 | { | |
296 | unsigned long newpc = pc; | |
297 | supply_register_by_name ("rip", &newpc); | |
298 | } | |
299 | else | |
300 | { | |
301 | unsigned int newpc = pc; | |
302 | supply_register_by_name ("eip", &newpc); | |
303 | } | |
304 | } | |
305 | \f | |
306 | static const unsigned char x86_breakpoint[] = { 0xCC }; | |
307 | #define x86_breakpoint_len 1 | |
308 | ||
309 | static int | |
310 | x86_breakpoint_at (CORE_ADDR pc) | |
311 | { | |
312 | unsigned char c; | |
313 | ||
314 | read_inferior_memory (pc, &c, 1); | |
315 | if (c == 0xCC) | |
316 | return 1; | |
317 | ||
318 | return 0; | |
319 | } | |
320 | \f | |
321 | /* When GDBSERVER is built as a 64-bit application on linux, the | |
322 | PTRACE_GETSIGINFO data is always presented in 64-bit layout. Since | |
323 | debugging a 32-bit inferior with a 64-bit GDBSERVER should look the same | |
324 | as debugging it with a 32-bit GDBSERVER, we do the 32-bit <-> 64-bit | |
325 | conversion in-place ourselves. */ | |
326 | ||
327 | /* These types below (compat_*) define a siginfo type that is layout | |
328 | compatible with the siginfo type exported by the 32-bit userspace | |
329 | support. */ | |
330 | ||
331 | #ifdef __x86_64__ | |
332 | ||
333 | typedef int compat_int_t; | |
334 | typedef unsigned int compat_uptr_t; | |
335 | ||
336 | typedef int compat_time_t; | |
337 | typedef int compat_timer_t; | |
338 | typedef int compat_clock_t; | |
339 | ||
340 | struct compat_timeval | |
341 | { | |
342 | compat_time_t tv_sec; | |
343 | int tv_usec; | |
344 | }; | |
345 | ||
346 | typedef union compat_sigval | |
347 | { | |
348 | compat_int_t sival_int; | |
349 | compat_uptr_t sival_ptr; | |
350 | } compat_sigval_t; | |
351 | ||
352 | typedef struct compat_siginfo | |
353 | { | |
354 | int si_signo; | |
355 | int si_errno; | |
356 | int si_code; | |
357 | ||
358 | union | |
359 | { | |
360 | int _pad[((128 / sizeof (int)) - 3)]; | |
361 | ||
362 | /* kill() */ | |
363 | struct | |
364 | { | |
365 | unsigned int _pid; | |
366 | unsigned int _uid; | |
367 | } _kill; | |
368 | ||
369 | /* POSIX.1b timers */ | |
370 | struct | |
371 | { | |
372 | compat_timer_t _tid; | |
373 | int _overrun; | |
374 | compat_sigval_t _sigval; | |
375 | } _timer; | |
376 | ||
377 | /* POSIX.1b signals */ | |
378 | struct | |
379 | { | |
380 | unsigned int _pid; | |
381 | unsigned int _uid; | |
382 | compat_sigval_t _sigval; | |
383 | } _rt; | |
384 | ||
385 | /* SIGCHLD */ | |
386 | struct | |
387 | { | |
388 | unsigned int _pid; | |
389 | unsigned int _uid; | |
390 | int _status; | |
391 | compat_clock_t _utime; | |
392 | compat_clock_t _stime; | |
393 | } _sigchld; | |
394 | ||
395 | /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ | |
396 | struct | |
397 | { | |
398 | unsigned int _addr; | |
399 | } _sigfault; | |
400 | ||
401 | /* SIGPOLL */ | |
402 | struct | |
403 | { | |
404 | int _band; | |
405 | int _fd; | |
406 | } _sigpoll; | |
407 | } _sifields; | |
408 | } compat_siginfo_t; | |
409 | ||
410 | #define cpt_si_pid _sifields._kill._pid | |
411 | #define cpt_si_uid _sifields._kill._uid | |
412 | #define cpt_si_timerid _sifields._timer._tid | |
413 | #define cpt_si_overrun _sifields._timer._overrun | |
414 | #define cpt_si_status _sifields._sigchld._status | |
415 | #define cpt_si_utime _sifields._sigchld._utime | |
416 | #define cpt_si_stime _sifields._sigchld._stime | |
417 | #define cpt_si_ptr _sifields._rt._sigval.sival_ptr | |
418 | #define cpt_si_addr _sifields._sigfault._addr | |
419 | #define cpt_si_band _sifields._sigpoll._band | |
420 | #define cpt_si_fd _sifields._sigpoll._fd | |
421 | ||
422 | /* glibc at least up to 2.3.2 doesn't have si_timerid, si_overrun. | |
423 | In their place is si_timer1,si_timer2. */ | |
424 | #ifndef si_timerid | |
425 | #define si_timerid si_timer1 | |
426 | #endif | |
427 | #ifndef si_overrun | |
428 | #define si_overrun si_timer2 | |
429 | #endif | |
430 | ||
431 | static void | |
432 | compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from) | |
433 | { | |
434 | memset (to, 0, sizeof (*to)); | |
435 | ||
436 | to->si_signo = from->si_signo; | |
437 | to->si_errno = from->si_errno; | |
438 | to->si_code = from->si_code; | |
439 | ||
440 | if (to->si_code < 0) | |
441 | { | |
442 | to->cpt_si_ptr = (intptr_t) from->si_ptr; | |
443 | } | |
444 | else if (to->si_code == SI_USER) | |
445 | { | |
446 | to->cpt_si_pid = from->si_pid; | |
447 | to->cpt_si_uid = from->si_uid; | |
448 | } | |
449 | else if (to->si_code == SI_TIMER) | |
450 | { | |
451 | to->cpt_si_timerid = from->si_timerid; | |
452 | to->cpt_si_overrun = from->si_overrun; | |
453 | to->cpt_si_ptr = (intptr_t) from->si_ptr; | |
454 | } | |
455 | else | |
456 | { | |
457 | switch (to->si_signo) | |
458 | { | |
459 | case SIGCHLD: | |
460 | to->cpt_si_pid = from->si_pid; | |
461 | to->cpt_si_uid = from->si_uid; | |
462 | to->cpt_si_status = from->si_status; | |
463 | to->cpt_si_utime = from->si_utime; | |
464 | to->cpt_si_stime = from->si_stime; | |
465 | break; | |
466 | case SIGILL: | |
467 | case SIGFPE: | |
468 | case SIGSEGV: | |
469 | case SIGBUS: | |
470 | to->cpt_si_addr = (intptr_t) from->si_addr; | |
471 | break; | |
472 | case SIGPOLL: | |
473 | to->cpt_si_band = from->si_band; | |
474 | to->cpt_si_fd = from->si_fd; | |
475 | break; | |
476 | default: | |
477 | to->cpt_si_pid = from->si_pid; | |
478 | to->cpt_si_uid = from->si_uid; | |
479 | to->cpt_si_ptr = (intptr_t) from->si_ptr; | |
480 | break; | |
481 | } | |
482 | } | |
483 | } | |
484 | ||
485 | static void | |
486 | siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from) | |
487 | { | |
488 | memset (to, 0, sizeof (*to)); | |
489 | ||
490 | to->si_signo = from->si_signo; | |
491 | to->si_errno = from->si_errno; | |
492 | to->si_code = from->si_code; | |
493 | ||
494 | if (to->si_code < 0) | |
495 | { | |
496 | to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr; | |
497 | } | |
498 | else if (to->si_code == SI_USER) | |
499 | { | |
500 | to->si_pid = from->cpt_si_pid; | |
501 | to->si_uid = from->cpt_si_uid; | |
502 | } | |
503 | else if (to->si_code == SI_TIMER) | |
504 | { | |
505 | to->si_timerid = from->cpt_si_timerid; | |
506 | to->si_overrun = from->cpt_si_overrun; | |
507 | to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr; | |
508 | } | |
509 | else | |
510 | { | |
511 | switch (to->si_signo) | |
512 | { | |
513 | case SIGCHLD: | |
514 | to->si_pid = from->cpt_si_pid; | |
515 | to->si_uid = from->cpt_si_uid; | |
516 | to->si_status = from->cpt_si_status; | |
517 | to->si_utime = from->cpt_si_utime; | |
518 | to->si_stime = from->cpt_si_stime; | |
519 | break; | |
520 | case SIGILL: | |
521 | case SIGFPE: | |
522 | case SIGSEGV: | |
523 | case SIGBUS: | |
524 | to->si_addr = (void *) (intptr_t) from->cpt_si_addr; | |
525 | break; | |
526 | case SIGPOLL: | |
527 | to->si_band = from->cpt_si_band; | |
528 | to->si_fd = from->cpt_si_fd; | |
529 | break; | |
530 | default: | |
531 | to->si_pid = from->cpt_si_pid; | |
532 | to->si_uid = from->cpt_si_uid; | |
533 | to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr; | |
534 | break; | |
535 | } | |
536 | } | |
537 | } | |
538 | ||
539 | #endif /* __x86_64__ */ | |
540 | ||
541 | /* Convert a native/host siginfo object, into/from the siginfo in the | |
542 | layout of the inferiors' architecture. Returns true if any | |
543 | conversion was done; false otherwise. If DIRECTION is 1, then copy | |
544 | from INF to NATIVE. If DIRECTION is 0, copy from NATIVE to | |
545 | INF. */ | |
546 | ||
547 | static int | |
548 | x86_siginfo_fixup (struct siginfo *native, void *inf, int direction) | |
549 | { | |
550 | #ifdef __x86_64__ | |
551 | /* Is the inferior 32-bit? If so, then fixup the siginfo object. */ | |
552 | if (register_size (0) == 4) | |
553 | { | |
554 | assert (sizeof (struct siginfo) == sizeof (compat_siginfo_t)); | |
555 | ||
556 | if (direction == 0) | |
557 | compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native); | |
558 | else | |
559 | siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf); | |
560 | ||
561 | return 1; | |
562 | } | |
563 | #endif | |
564 | ||
565 | return 0; | |
566 | } | |
567 | \f | |
568 | /* Return non-zero if the target is 64-bit. */ | |
569 | ||
570 | static void | |
571 | x86_arch_setup (void) | |
572 | { | |
573 | #ifdef __x86_64__ | |
574 | int pid = pid_of (get_thread_lwp (current_inferior)); | |
575 | char *file = linux_child_pid_to_exec_file (pid); | |
576 | int use_64bit = elf_64_file_p (file); | |
577 | ||
578 | free (file); | |
579 | ||
580 | if (use_64bit < 0) | |
581 | { | |
582 | /* This can only happen if /proc/<pid>/exe is unreadable, | |
583 | but "that can't happen" if we've gotten this far. | |
584 | Fall through and assume this is a 32-bit program. */ | |
585 | } | |
586 | else if (use_64bit) | |
587 | { | |
588 | init_registers_x86_64_linux (); | |
589 | ||
590 | /* Amd64 doesn't have HAVE_LINUX_USRREGS. */ | |
591 | the_low_target.num_regs = -1; | |
592 | the_low_target.regmap = NULL; | |
593 | the_low_target.cannot_fetch_register = NULL; | |
594 | the_low_target.cannot_store_register = NULL; | |
595 | ||
596 | /* Amd64 has 16 xmm regs. */ | |
597 | num_xmm_registers = 16; | |
598 | ||
599 | return; | |
600 | } | |
601 | #endif | |
602 | ||
603 | /* Ok we have a 32-bit inferior. */ | |
604 | ||
605 | init_registers_i386_linux (); | |
606 | ||
607 | the_low_target.num_regs = I386_NUM_REGS; | |
608 | the_low_target.regmap = i386_regmap; | |
609 | the_low_target.cannot_fetch_register = i386_cannot_fetch_register; | |
610 | the_low_target.cannot_store_register = i386_cannot_store_register; | |
611 | ||
612 | /* I386 has 8 xmm regs. */ | |
613 | num_xmm_registers = 8; | |
614 | } | |
615 | ||
616 | /* This is initialized assuming an amd64 target. | |
617 | x86_arch_setup will correct it for i386 or amd64 targets. */ | |
618 | ||
619 | struct linux_target_ops the_low_target = | |
620 | { | |
621 | x86_arch_setup, | |
622 | -1, | |
623 | NULL, | |
624 | NULL, | |
625 | NULL, | |
626 | x86_get_pc, | |
627 | x86_set_pc, | |
628 | x86_breakpoint, | |
629 | x86_breakpoint_len, | |
630 | NULL, | |
631 | 1, | |
632 | x86_breakpoint_at, | |
633 | NULL, | |
634 | NULL, | |
635 | NULL, | |
636 | NULL, | |
637 | /* collect_ptrace_register/supply_ptrace_register are not needed in the | |
638 | native i386 case (no registers smaller than an xfer unit), and are not | |
639 | used in the biarch case (HAVE_LINUX_USRREGS is not defined). */ | |
640 | NULL, | |
641 | NULL, | |
642 | /* need to fix up i386 siginfo if host is amd64 */ | |
643 | x86_siginfo_fixup, | |
644 | }; |