Commit | Line | Data |
---|---|---|
a4194092 | 1 | /* Native-dependent code for GNU/Linux i386. |
a4b6fc86 | 2 | |
0b302171 | 3 | Copyright (C) 1999-2012 Free Software Foundation, Inc. |
d4f3574e | 4 | |
04cd15b6 | 5 | This file is part of GDB. |
d4f3574e | 6 | |
04cd15b6 MK |
7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | |
a9762ec7 | 9 | the Free Software Foundation; either version 3 of the License, or |
04cd15b6 | 10 | (at your option) any later version. |
d4f3574e | 11 | |
04cd15b6 MK |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
d4f3574e | 16 | |
04cd15b6 | 17 | You should have received a copy of the GNU General Public License |
a9762ec7 | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
d4f3574e SS |
19 | |
20 | #include "defs.h" | |
9bb9e8ad | 21 | #include "i386-nat.h" |
d4f3574e SS |
22 | #include "inferior.h" |
23 | #include "gdbcore.h" | |
4e052eda | 24 | #include "regcache.h" |
c131fcee | 25 | #include "regset.h" |
10d6c8cd | 26 | #include "target.h" |
4de4c07c | 27 | #include "linux-nat.h" |
d4f3574e | 28 | |
84346e11 | 29 | #include "gdb_assert.h" |
309367d4 | 30 | #include "gdb_string.h" |
c131fcee L |
31 | #include "elf/common.h" |
32 | #include <sys/uio.h> | |
d4f3574e SS |
33 | #include <sys/ptrace.h> |
34 | #include <sys/user.h> | |
35 | #include <sys/procfs.h> | |
36 | ||
37 | #ifdef HAVE_SYS_REG_H | |
38 | #include <sys/reg.h> | |
39 | #endif | |
40 | ||
ce556f85 MK |
41 | #ifndef ORIG_EAX |
42 | #define ORIG_EAX -1 | |
43 | #endif | |
44 | ||
84346e11 MK |
45 | #ifdef HAVE_SYS_DEBUGREG_H |
46 | #include <sys/debugreg.h> | |
47 | #endif | |
48 | ||
6ce2ac0b | 49 | /* Prototypes for supply_gregset etc. */ |
c60c0f5f MS |
50 | #include "gregset.h" |
51 | ||
e750d25e | 52 | #include "i387-tdep.h" |
c3833324 | 53 | #include "i386-tdep.h" |
5179e78f AC |
54 | #include "i386-linux-tdep.h" |
55 | ||
b757528f JJ |
56 | /* Defines ps_err_e, struct ps_prochandle. */ |
57 | #include "gdb_proc_service.h" | |
c131fcee L |
58 | |
59 | #include "i386-xstate.h" | |
60 | ||
61 | #ifndef PTRACE_GETREGSET | |
62 | #define PTRACE_GETREGSET 0x4204 | |
63 | #endif | |
64 | ||
65 | #ifndef PTRACE_SETREGSET | |
66 | #define PTRACE_SETREGSET 0x4205 | |
67 | #endif | |
68 | ||
7b50312a PA |
69 | /* Per-thread arch-specific data we want to keep. */ |
70 | ||
71 | struct arch_lwp_info | |
72 | { | |
73 | /* Non-zero if our copy differs from what's recorded in the thread. */ | |
74 | int debug_registers_changed; | |
75 | }; | |
76 | ||
c131fcee L |
77 | /* Does the current host support PTRACE_GETREGSET? */ |
78 | static int have_ptrace_getregset = -1; | |
6ce2ac0b | 79 | \f |
d4f3574e | 80 | |
a4b6fc86 AC |
81 | /* The register sets used in GNU/Linux ELF core-dumps are identical to |
82 | the register sets in `struct user' that is used for a.out | |
83 | core-dumps, and is also used by `ptrace'. The corresponding types | |
84 | are `elf_gregset_t' for the general-purpose registers (with | |
04cd15b6 MK |
85 | `elf_greg_t' the type of a single GP register) and `elf_fpregset_t' |
86 | for the floating-point registers. | |
87 | ||
88 | Those types used to be available under the names `gregset_t' and | |
89 | `fpregset_t' too, and this file used those names in the past. But | |
90 | those names are now used for the register sets used in the | |
91 | `mcontext_t' type, and have a different size and layout. */ | |
92 | ||
5c44784c JM |
93 | /* Which ptrace request retrieves which registers? |
94 | These apply to the corresponding SET requests as well. */ | |
e64a344c | 95 | |
5c44784c | 96 | #define GETREGS_SUPPLIES(regno) \ |
3fb1c838 | 97 | ((0 <= (regno) && (regno) <= 15) || (regno) == I386_LINUX_ORIG_EAX_REGNUM) |
e64a344c | 98 | |
6ce2ac0b | 99 | #define GETFPXREGS_SUPPLIES(regno) \ |
f6792ef4 | 100 | (I386_ST0_REGNUM <= (regno) && (regno) < I386_SSE_NUM_REGS) |
5c44784c | 101 | |
c131fcee L |
102 | #define GETXSTATEREGS_SUPPLIES(regno) \ |
103 | (I386_ST0_REGNUM <= (regno) && (regno) < I386_AVX_NUM_REGS) | |
104 | ||
f60300e7 MK |
105 | /* Does the current host support the GETREGS request? */ |
106 | int have_ptrace_getregs = | |
107 | #ifdef HAVE_PTRACE_GETREGS | |
108 | 1 | |
109 | #else | |
110 | 0 | |
111 | #endif | |
112 | ; | |
113 | ||
6ce2ac0b | 114 | /* Does the current host support the GETFPXREGS request? The header |
5c44784c JM |
115 | file may or may not define it, and even if it is defined, the |
116 | kernel will return EIO if it's running on a pre-SSE processor. | |
117 | ||
118 | My instinct is to attach this to some architecture- or | |
119 | target-specific data structure, but really, a particular GDB | |
120 | process can only run on top of one kernel at a time. So it's okay | |
121 | for this to be a simple variable. */ | |
6ce2ac0b MK |
122 | int have_ptrace_getfpxregs = |
123 | #ifdef HAVE_PTRACE_GETFPXREGS | |
3a13a53b | 124 | -1 |
5c44784c JM |
125 | #else |
126 | 0 | |
127 | #endif | |
128 | ; | |
f60300e7 | 129 | \f |
6ce2ac0b | 130 | |
ce556f85 | 131 | /* Accessing registers through the U area, one at a time. */ |
f60300e7 MK |
132 | |
133 | /* Fetch one register. */ | |
134 | ||
135 | static void | |
56be3814 | 136 | fetch_register (struct regcache *regcache, int regno) |
f60300e7 | 137 | { |
f60300e7 | 138 | int tid; |
ce556f85 | 139 | int val; |
f60300e7 | 140 | |
ce556f85 | 141 | gdb_assert (!have_ptrace_getregs); |
be0d2954 | 142 | if (i386_linux_gregset_reg_offset[regno] == -1) |
f60300e7 | 143 | { |
56be3814 | 144 | regcache_raw_supply (regcache, regno, NULL); |
f60300e7 MK |
145 | return; |
146 | } | |
147 | ||
ce556f85 | 148 | /* GNU/Linux LWP ID's are process ID's. */ |
e64a344c MK |
149 | tid = TIDGET (inferior_ptid); |
150 | if (tid == 0) | |
151 | tid = PIDGET (inferior_ptid); /* Not a threaded program. */ | |
f60300e7 | 152 | |
ce556f85 | 153 | errno = 0; |
be0d2954 L |
154 | val = ptrace (PTRACE_PEEKUSER, tid, |
155 | i386_linux_gregset_reg_offset[regno], 0); | |
ce556f85 | 156 | if (errno != 0) |
c9f4d572 | 157 | error (_("Couldn't read register %s (#%d): %s."), |
875f8d0e | 158 | gdbarch_register_name (get_regcache_arch (regcache), regno), |
ce556f85 | 159 | regno, safe_strerror (errno)); |
f60300e7 | 160 | |
56be3814 | 161 | regcache_raw_supply (regcache, regno, &val); |
f60300e7 MK |
162 | } |
163 | ||
1777feb0 | 164 | /* Store one register. */ |
f60300e7 MK |
165 | |
166 | static void | |
56be3814 | 167 | store_register (const struct regcache *regcache, int regno) |
f60300e7 | 168 | { |
f60300e7 | 169 | int tid; |
ce556f85 | 170 | int val; |
f60300e7 | 171 | |
ce556f85 | 172 | gdb_assert (!have_ptrace_getregs); |
be0d2954 | 173 | if (i386_linux_gregset_reg_offset[regno] == -1) |
ce556f85 | 174 | return; |
f60300e7 | 175 | |
ce556f85 | 176 | /* GNU/Linux LWP ID's are process ID's. */ |
e64a344c MK |
177 | tid = TIDGET (inferior_ptid); |
178 | if (tid == 0) | |
179 | tid = PIDGET (inferior_ptid); /* Not a threaded program. */ | |
f60300e7 | 180 | |
ce556f85 | 181 | errno = 0; |
56be3814 | 182 | regcache_raw_collect (regcache, regno, &val); |
be0d2954 L |
183 | ptrace (PTRACE_POKEUSER, tid, |
184 | i386_linux_gregset_reg_offset[regno], val); | |
ce556f85 | 185 | if (errno != 0) |
c9f4d572 | 186 | error (_("Couldn't write register %s (#%d): %s."), |
875f8d0e | 187 | gdbarch_register_name (get_regcache_arch (regcache), regno), |
ce556f85 | 188 | regno, safe_strerror (errno)); |
f60300e7 | 189 | } |
5c44784c | 190 | \f |
6ce2ac0b | 191 | |
04cd15b6 MK |
192 | /* Transfering the general-purpose registers between GDB, inferiors |
193 | and core files. */ | |
194 | ||
ad2a4d09 | 195 | /* Fill GDB's register array with the general-purpose register values |
04cd15b6 | 196 | in *GREGSETP. */ |
5c44784c | 197 | |
d4f3574e | 198 | void |
7f7fe91e | 199 | supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp) |
d4f3574e | 200 | { |
be0d2954 | 201 | const gdb_byte *regp = (const gdb_byte *) gregsetp; |
6ce2ac0b | 202 | int i; |
d4f3574e | 203 | |
98df6387 | 204 | for (i = 0; i < I386_NUM_GREGS; i++) |
be0d2954 L |
205 | regcache_raw_supply (regcache, i, |
206 | regp + i386_linux_gregset_reg_offset[i]); | |
3fb1c838 | 207 | |
875f8d0e UW |
208 | if (I386_LINUX_ORIG_EAX_REGNUM |
209 | < gdbarch_num_regs (get_regcache_arch (regcache))) | |
1777feb0 MS |
210 | regcache_raw_supply (regcache, I386_LINUX_ORIG_EAX_REGNUM, regp |
211 | + i386_linux_gregset_reg_offset[I386_LINUX_ORIG_EAX_REGNUM]); | |
917317f4 JM |
212 | } |
213 | ||
04cd15b6 MK |
214 | /* Fill register REGNO (if it is a general-purpose register) in |
215 | *GREGSETPS with the value in GDB's register array. If REGNO is -1, | |
216 | do this for all registers. */ | |
6ce2ac0b | 217 | |
917317f4 | 218 | void |
7f7fe91e UW |
219 | fill_gregset (const struct regcache *regcache, |
220 | elf_gregset_t *gregsetp, int regno) | |
917317f4 | 221 | { |
be0d2954 | 222 | gdb_byte *regp = (gdb_byte *) gregsetp; |
6ce2ac0b | 223 | int i; |
04cd15b6 | 224 | |
98df6387 | 225 | for (i = 0; i < I386_NUM_GREGS; i++) |
099a9414 | 226 | if (regno == -1 || regno == i) |
be0d2954 L |
227 | regcache_raw_collect (regcache, i, |
228 | regp + i386_linux_gregset_reg_offset[i]); | |
3fb1c838 | 229 | |
82ea117a | 230 | if ((regno == -1 || regno == I386_LINUX_ORIG_EAX_REGNUM) |
875f8d0e UW |
231 | && I386_LINUX_ORIG_EAX_REGNUM |
232 | < gdbarch_num_regs (get_regcache_arch (regcache))) | |
1777feb0 MS |
233 | regcache_raw_collect (regcache, I386_LINUX_ORIG_EAX_REGNUM, regp |
234 | + i386_linux_gregset_reg_offset[I386_LINUX_ORIG_EAX_REGNUM]); | |
d4f3574e SS |
235 | } |
236 | ||
f60300e7 MK |
237 | #ifdef HAVE_PTRACE_GETREGS |
238 | ||
04cd15b6 MK |
239 | /* Fetch all general-purpose registers from process/thread TID and |
240 | store their values in GDB's register array. */ | |
d4f3574e | 241 | |
5c44784c | 242 | static void |
56be3814 | 243 | fetch_regs (struct regcache *regcache, int tid) |
5c44784c | 244 | { |
04cd15b6 | 245 | elf_gregset_t regs; |
2e024c20 | 246 | elf_gregset_t *regs_p = ®s; |
5c44784c | 247 | |
6ce2ac0b | 248 | if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) |
5c44784c | 249 | { |
f60300e7 MK |
250 | if (errno == EIO) |
251 | { | |
252 | /* The kernel we're running on doesn't support the GETREGS | |
253 | request. Reset `have_ptrace_getregs'. */ | |
254 | have_ptrace_getregs = 0; | |
255 | return; | |
256 | } | |
257 | ||
e2e0b3e5 | 258 | perror_with_name (_("Couldn't get registers")); |
5c44784c JM |
259 | } |
260 | ||
2e024c20 | 261 | supply_gregset (regcache, (const elf_gregset_t *) regs_p); |
5c44784c JM |
262 | } |
263 | ||
04cd15b6 MK |
264 | /* Store all valid general-purpose registers in GDB's register array |
265 | into the process/thread specified by TID. */ | |
5c44784c | 266 | |
5c44784c | 267 | static void |
56be3814 | 268 | store_regs (const struct regcache *regcache, int tid, int regno) |
5c44784c | 269 | { |
04cd15b6 | 270 | elf_gregset_t regs; |
5c44784c | 271 | |
6ce2ac0b | 272 | if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) |
e2e0b3e5 | 273 | perror_with_name (_("Couldn't get registers")); |
5c44784c | 274 | |
56be3814 | 275 | fill_gregset (regcache, ®s, regno); |
6ce2ac0b MK |
276 | |
277 | if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) | |
e2e0b3e5 | 278 | perror_with_name (_("Couldn't write registers")); |
5c44784c JM |
279 | } |
280 | ||
f60300e7 MK |
281 | #else |
282 | ||
56be3814 UW |
283 | static void fetch_regs (struct regcache *regcache, int tid) {} |
284 | static void store_regs (const struct regcache *regcache, int tid, int regno) {} | |
f60300e7 MK |
285 | |
286 | #endif | |
5c44784c | 287 | \f |
5c44784c | 288 | |
6ce2ac0b | 289 | /* Transfering floating-point registers between GDB, inferiors and cores. */ |
d4f3574e | 290 | |
04cd15b6 | 291 | /* Fill GDB's register array with the floating-point register values in |
917317f4 | 292 | *FPREGSETP. */ |
04cd15b6 | 293 | |
d4f3574e | 294 | void |
7f7fe91e | 295 | supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp) |
d4f3574e | 296 | { |
7f7fe91e | 297 | i387_supply_fsave (regcache, -1, fpregsetp); |
917317f4 | 298 | } |
d4f3574e | 299 | |
04cd15b6 MK |
300 | /* Fill register REGNO (if it is a floating-point register) in |
301 | *FPREGSETP with the value in GDB's register array. If REGNO is -1, | |
302 | do this for all registers. */ | |
917317f4 JM |
303 | |
304 | void | |
7f7fe91e UW |
305 | fill_fpregset (const struct regcache *regcache, |
306 | elf_fpregset_t *fpregsetp, int regno) | |
917317f4 | 307 | { |
7f7fe91e | 308 | i387_collect_fsave (regcache, regno, fpregsetp); |
d4f3574e SS |
309 | } |
310 | ||
f60300e7 MK |
311 | #ifdef HAVE_PTRACE_GETREGS |
312 | ||
04cd15b6 MK |
313 | /* Fetch all floating-point registers from process/thread TID and store |
314 | thier values in GDB's register array. */ | |
917317f4 | 315 | |
d4f3574e | 316 | static void |
56be3814 | 317 | fetch_fpregs (struct regcache *regcache, int tid) |
d4f3574e | 318 | { |
04cd15b6 | 319 | elf_fpregset_t fpregs; |
d4f3574e | 320 | |
6ce2ac0b | 321 | if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) |
e2e0b3e5 | 322 | perror_with_name (_("Couldn't get floating point status")); |
d4f3574e | 323 | |
56be3814 | 324 | supply_fpregset (regcache, (const elf_fpregset_t *) &fpregs); |
d4f3574e SS |
325 | } |
326 | ||
04cd15b6 MK |
327 | /* Store all valid floating-point registers in GDB's register array |
328 | into the process/thread specified by TID. */ | |
d4f3574e | 329 | |
d4f3574e | 330 | static void |
56be3814 | 331 | store_fpregs (const struct regcache *regcache, int tid, int regno) |
d4f3574e | 332 | { |
04cd15b6 | 333 | elf_fpregset_t fpregs; |
d4f3574e | 334 | |
6ce2ac0b | 335 | if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) |
e2e0b3e5 | 336 | perror_with_name (_("Couldn't get floating point status")); |
d4f3574e | 337 | |
56be3814 | 338 | fill_fpregset (regcache, &fpregs, regno); |
d4f3574e | 339 | |
6ce2ac0b | 340 | if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0) |
e2e0b3e5 | 341 | perror_with_name (_("Couldn't write floating point status")); |
d4f3574e SS |
342 | } |
343 | ||
f60300e7 MK |
344 | #else |
345 | ||
1777feb0 MS |
346 | static void |
347 | fetch_fpregs (struct regcache *regcache, int tid) | |
348 | { | |
349 | } | |
350 | ||
351 | static void | |
352 | store_fpregs (const struct regcache *regcache, int tid, int regno) | |
353 | { | |
354 | } | |
f60300e7 MK |
355 | |
356 | #endif | |
5c44784c | 357 | \f |
d4f3574e | 358 | |
6ce2ac0b | 359 | /* Transfering floating-point and SSE registers to and from GDB. */ |
11cf8741 | 360 | |
c131fcee L |
361 | /* Fetch all registers covered by the PTRACE_GETREGSET request from |
362 | process/thread TID and store their values in GDB's register array. | |
363 | Return non-zero if successful, zero otherwise. */ | |
364 | ||
365 | static int | |
366 | fetch_xstateregs (struct regcache *regcache, int tid) | |
367 | { | |
368 | char xstateregs[I386_XSTATE_MAX_SIZE]; | |
369 | struct iovec iov; | |
370 | ||
371 | if (!have_ptrace_getregset) | |
372 | return 0; | |
373 | ||
374 | iov.iov_base = xstateregs; | |
375 | iov.iov_len = sizeof(xstateregs); | |
376 | if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE, | |
377 | &iov) < 0) | |
378 | perror_with_name (_("Couldn't read extended state status")); | |
379 | ||
380 | i387_supply_xsave (regcache, -1, xstateregs); | |
381 | return 1; | |
382 | } | |
383 | ||
384 | /* Store all valid registers in GDB's register array covered by the | |
385 | PTRACE_SETREGSET request into the process/thread specified by TID. | |
386 | Return non-zero if successful, zero otherwise. */ | |
387 | ||
388 | static int | |
389 | store_xstateregs (const struct regcache *regcache, int tid, int regno) | |
390 | { | |
391 | char xstateregs[I386_XSTATE_MAX_SIZE]; | |
392 | struct iovec iov; | |
393 | ||
394 | if (!have_ptrace_getregset) | |
395 | return 0; | |
396 | ||
397 | iov.iov_base = xstateregs; | |
398 | iov.iov_len = sizeof(xstateregs); | |
399 | if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE, | |
400 | &iov) < 0) | |
401 | perror_with_name (_("Couldn't read extended state status")); | |
402 | ||
403 | i387_collect_xsave (regcache, regno, xstateregs, 0); | |
404 | ||
405 | if (ptrace (PTRACE_SETREGSET, tid, (unsigned int) NT_X86_XSTATE, | |
406 | (int) &iov) < 0) | |
407 | perror_with_name (_("Couldn't write extended state status")); | |
408 | ||
409 | return 1; | |
410 | } | |
411 | ||
6ce2ac0b | 412 | #ifdef HAVE_PTRACE_GETFPXREGS |
04cd15b6 | 413 | |
6ce2ac0b | 414 | /* Fetch all registers covered by the PTRACE_GETFPXREGS request from |
04cd15b6 MK |
415 | process/thread TID and store their values in GDB's register array. |
416 | Return non-zero if successful, zero otherwise. */ | |
5c44784c | 417 | |
5c44784c | 418 | static int |
56be3814 | 419 | fetch_fpxregs (struct regcache *regcache, int tid) |
5c44784c | 420 | { |
6ce2ac0b | 421 | elf_fpxregset_t fpxregs; |
5c44784c | 422 | |
6ce2ac0b | 423 | if (! have_ptrace_getfpxregs) |
5c44784c JM |
424 | return 0; |
425 | ||
6ce2ac0b | 426 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, (int) &fpxregs) < 0) |
d4f3574e | 427 | { |
5c44784c JM |
428 | if (errno == EIO) |
429 | { | |
6ce2ac0b | 430 | have_ptrace_getfpxregs = 0; |
5c44784c JM |
431 | return 0; |
432 | } | |
433 | ||
e2e0b3e5 | 434 | perror_with_name (_("Couldn't read floating-point and SSE registers")); |
d4f3574e SS |
435 | } |
436 | ||
b7a8b4ef | 437 | i387_supply_fxsave (regcache, -1, (const elf_fpxregset_t *) &fpxregs); |
5c44784c JM |
438 | return 1; |
439 | } | |
d4f3574e | 440 | |
04cd15b6 | 441 | /* Store all valid registers in GDB's register array covered by the |
6ce2ac0b | 442 | PTRACE_SETFPXREGS request into the process/thread specified by TID. |
04cd15b6 | 443 | Return non-zero if successful, zero otherwise. */ |
5c44784c | 444 | |
5c44784c | 445 | static int |
56be3814 | 446 | store_fpxregs (const struct regcache *regcache, int tid, int regno) |
5c44784c | 447 | { |
6ce2ac0b | 448 | elf_fpxregset_t fpxregs; |
5c44784c | 449 | |
6ce2ac0b | 450 | if (! have_ptrace_getfpxregs) |
5c44784c | 451 | return 0; |
6ce2ac0b MK |
452 | |
453 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, &fpxregs) == -1) | |
2866d305 MK |
454 | { |
455 | if (errno == EIO) | |
456 | { | |
457 | have_ptrace_getfpxregs = 0; | |
458 | return 0; | |
459 | } | |
460 | ||
e2e0b3e5 | 461 | perror_with_name (_("Couldn't read floating-point and SSE registers")); |
2866d305 | 462 | } |
5c44784c | 463 | |
b7a8b4ef | 464 | i387_collect_fxsave (regcache, regno, &fpxregs); |
5c44784c | 465 | |
6ce2ac0b | 466 | if (ptrace (PTRACE_SETFPXREGS, tid, 0, &fpxregs) == -1) |
e2e0b3e5 | 467 | perror_with_name (_("Couldn't write floating-point and SSE registers")); |
5c44784c JM |
468 | |
469 | return 1; | |
470 | } | |
471 | ||
5c44784c JM |
472 | #else |
473 | ||
1777feb0 MS |
474 | static int |
475 | fetch_fpxregs (struct regcache *regcache, int tid) | |
476 | { | |
477 | return 0; | |
478 | } | |
479 | ||
480 | static int | |
481 | store_fpxregs (const struct regcache *regcache, int tid, int regno) | |
482 | { | |
483 | return 0; | |
484 | } | |
5c44784c | 485 | |
6ce2ac0b | 486 | #endif /* HAVE_PTRACE_GETFPXREGS */ |
5c44784c | 487 | \f |
6ce2ac0b | 488 | |
5c44784c | 489 | /* Transferring arbitrary registers between GDB and inferior. */ |
d4f3574e | 490 | |
04cd15b6 MK |
491 | /* Fetch register REGNO from the child process. If REGNO is -1, do |
492 | this for all registers (including the floating point and SSE | |
493 | registers). */ | |
d4f3574e | 494 | |
10d6c8cd | 495 | static void |
28439f5e PA |
496 | i386_linux_fetch_inferior_registers (struct target_ops *ops, |
497 | struct regcache *regcache, int regno) | |
d4f3574e | 498 | { |
ed9a39eb JM |
499 | int tid; |
500 | ||
f60300e7 MK |
501 | /* Use the old method of peeking around in `struct user' if the |
502 | GETREGS request isn't available. */ | |
ce556f85 | 503 | if (!have_ptrace_getregs) |
f60300e7 | 504 | { |
ce556f85 MK |
505 | int i; |
506 | ||
875f8d0e | 507 | for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++) |
ce556f85 | 508 | if (regno == -1 || regno == i) |
56be3814 | 509 | fetch_register (regcache, i); |
ce556f85 | 510 | |
f60300e7 MK |
511 | return; |
512 | } | |
513 | ||
a4b6fc86 | 514 | /* GNU/Linux LWP ID's are process ID's. */ |
e64a344c MK |
515 | tid = TIDGET (inferior_ptid); |
516 | if (tid == 0) | |
517 | tid = PIDGET (inferior_ptid); /* Not a threaded program. */ | |
ed9a39eb | 518 | |
6ce2ac0b | 519 | /* Use the PTRACE_GETFPXREGS request whenever possible, since it |
04cd15b6 | 520 | transfers more registers in one system call, and we'll cache the |
6ce2ac0b | 521 | results. But remember that fetch_fpxregs can fail, and return |
04cd15b6 | 522 | zero. */ |
5c44784c JM |
523 | if (regno == -1) |
524 | { | |
56be3814 | 525 | fetch_regs (regcache, tid); |
f60300e7 MK |
526 | |
527 | /* The call above might reset `have_ptrace_getregs'. */ | |
ce556f85 | 528 | if (!have_ptrace_getregs) |
f60300e7 | 529 | { |
84e473c8 | 530 | i386_linux_fetch_inferior_registers (ops, regcache, regno); |
f60300e7 MK |
531 | return; |
532 | } | |
533 | ||
c131fcee L |
534 | if (fetch_xstateregs (regcache, tid)) |
535 | return; | |
56be3814 | 536 | if (fetch_fpxregs (regcache, tid)) |
5c44784c | 537 | return; |
56be3814 | 538 | fetch_fpregs (regcache, tid); |
5c44784c JM |
539 | return; |
540 | } | |
d4f3574e | 541 | |
5c44784c JM |
542 | if (GETREGS_SUPPLIES (regno)) |
543 | { | |
56be3814 | 544 | fetch_regs (regcache, tid); |
5c44784c JM |
545 | return; |
546 | } | |
547 | ||
c131fcee L |
548 | if (GETXSTATEREGS_SUPPLIES (regno)) |
549 | { | |
550 | if (fetch_xstateregs (regcache, tid)) | |
551 | return; | |
552 | } | |
553 | ||
6ce2ac0b | 554 | if (GETFPXREGS_SUPPLIES (regno)) |
5c44784c | 555 | { |
56be3814 | 556 | if (fetch_fpxregs (regcache, tid)) |
5c44784c JM |
557 | return; |
558 | ||
559 | /* Either our processor or our kernel doesn't support the SSE | |
560 | registers, so read the FP registers in the traditional way, | |
561 | and fill the SSE registers with dummy values. It would be | |
562 | more graceful to handle differences in the register set using | |
563 | gdbarch. Until then, this will at least make things work | |
564 | plausibly. */ | |
56be3814 | 565 | fetch_fpregs (regcache, tid); |
5c44784c JM |
566 | return; |
567 | } | |
568 | ||
8e65ff28 | 569 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 570 | _("Got request for bad register number %d."), regno); |
d4f3574e SS |
571 | } |
572 | ||
04cd15b6 MK |
573 | /* Store register REGNO back into the child process. If REGNO is -1, |
574 | do this for all registers (including the floating point and SSE | |
575 | registers). */ | |
10d6c8cd | 576 | static void |
28439f5e PA |
577 | i386_linux_store_inferior_registers (struct target_ops *ops, |
578 | struct regcache *regcache, int regno) | |
d4f3574e | 579 | { |
ed9a39eb JM |
580 | int tid; |
581 | ||
f60300e7 MK |
582 | /* Use the old method of poking around in `struct user' if the |
583 | SETREGS request isn't available. */ | |
ce556f85 | 584 | if (!have_ptrace_getregs) |
f60300e7 | 585 | { |
ce556f85 MK |
586 | int i; |
587 | ||
875f8d0e | 588 | for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++) |
ce556f85 | 589 | if (regno == -1 || regno == i) |
56be3814 | 590 | store_register (regcache, i); |
ce556f85 | 591 | |
f60300e7 MK |
592 | return; |
593 | } | |
594 | ||
a4b6fc86 | 595 | /* GNU/Linux LWP ID's are process ID's. */ |
e64a344c MK |
596 | tid = TIDGET (inferior_ptid); |
597 | if (tid == 0) | |
598 | tid = PIDGET (inferior_ptid); /* Not a threaded program. */ | |
ed9a39eb | 599 | |
6ce2ac0b | 600 | /* Use the PTRACE_SETFPXREGS requests whenever possible, since it |
04cd15b6 | 601 | transfers more registers in one system call. But remember that |
6ce2ac0b | 602 | store_fpxregs can fail, and return zero. */ |
5c44784c JM |
603 | if (regno == -1) |
604 | { | |
56be3814 | 605 | store_regs (regcache, tid, regno); |
c131fcee L |
606 | if (store_xstateregs (regcache, tid, regno)) |
607 | return; | |
56be3814 | 608 | if (store_fpxregs (regcache, tid, regno)) |
5c44784c | 609 | return; |
56be3814 | 610 | store_fpregs (regcache, tid, regno); |
5c44784c JM |
611 | return; |
612 | } | |
d4f3574e | 613 | |
5c44784c JM |
614 | if (GETREGS_SUPPLIES (regno)) |
615 | { | |
56be3814 | 616 | store_regs (regcache, tid, regno); |
5c44784c JM |
617 | return; |
618 | } | |
619 | ||
c131fcee L |
620 | if (GETXSTATEREGS_SUPPLIES (regno)) |
621 | { | |
622 | if (store_xstateregs (regcache, tid, regno)) | |
623 | return; | |
624 | } | |
625 | ||
6ce2ac0b | 626 | if (GETFPXREGS_SUPPLIES (regno)) |
5c44784c | 627 | { |
56be3814 | 628 | if (store_fpxregs (regcache, tid, regno)) |
5c44784c JM |
629 | return; |
630 | ||
631 | /* Either our processor or our kernel doesn't support the SSE | |
04cd15b6 MK |
632 | registers, so just write the FP registers in the traditional |
633 | way. */ | |
56be3814 | 634 | store_fpregs (regcache, tid, regno); |
5c44784c JM |
635 | return; |
636 | } | |
637 | ||
8e65ff28 | 638 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 639 | _("Got request to store bad register number %d."), regno); |
d4f3574e | 640 | } |
de57eccd | 641 | \f |
6ce2ac0b | 642 | |
4ffc8466 MK |
643 | /* Support for debug registers. */ |
644 | ||
a79d3c27 JK |
645 | /* Get debug register REGNUM value from only the one LWP of PTID. */ |
646 | ||
7bf0983e | 647 | static unsigned long |
9f0bdab8 | 648 | i386_linux_dr_get (ptid_t ptid, int regnum) |
84346e11 MK |
649 | { |
650 | int tid; | |
7bf0983e | 651 | unsigned long value; |
84346e11 | 652 | |
9f0bdab8 DJ |
653 | tid = TIDGET (ptid); |
654 | if (tid == 0) | |
655 | tid = PIDGET (ptid); | |
84346e11 MK |
656 | |
657 | errno = 0; | |
ce556f85 | 658 | value = ptrace (PTRACE_PEEKUSER, tid, |
84346e11 MK |
659 | offsetof (struct user, u_debugreg[regnum]), 0); |
660 | if (errno != 0) | |
e2e0b3e5 | 661 | perror_with_name (_("Couldn't read debug register")); |
84346e11 MK |
662 | |
663 | return value; | |
664 | } | |
665 | ||
a79d3c27 JK |
666 | /* Set debug register REGNUM to VALUE in only the one LWP of PTID. */ |
667 | ||
84346e11 | 668 | static void |
9f0bdab8 | 669 | i386_linux_dr_set (ptid_t ptid, int regnum, unsigned long value) |
84346e11 MK |
670 | { |
671 | int tid; | |
672 | ||
9f0bdab8 DJ |
673 | tid = TIDGET (ptid); |
674 | if (tid == 0) | |
675 | tid = PIDGET (ptid); | |
84346e11 MK |
676 | |
677 | errno = 0; | |
ce556f85 | 678 | ptrace (PTRACE_POKEUSER, tid, |
84346e11 MK |
679 | offsetof (struct user, u_debugreg[regnum]), value); |
680 | if (errno != 0) | |
e2e0b3e5 | 681 | perror_with_name (_("Couldn't write debug register")); |
84346e11 MK |
682 | } |
683 | ||
7b50312a | 684 | /* Return the inferior's debug register REGNUM. */ |
a79d3c27 | 685 | |
7b50312a PA |
686 | static CORE_ADDR |
687 | i386_linux_dr_get_addr (int regnum) | |
84346e11 | 688 | { |
7b50312a PA |
689 | /* DR6 and DR7 are retrieved with some other way. */ |
690 | gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); | |
9f0bdab8 | 691 | |
7b50312a | 692 | return i386_linux_dr_get (inferior_ptid, regnum); |
84346e11 MK |
693 | } |
694 | ||
7b50312a | 695 | /* Return the inferior's DR7 debug control register. */ |
a79d3c27 | 696 | |
7b50312a PA |
697 | static unsigned long |
698 | i386_linux_dr_get_control (void) | |
84346e11 | 699 | { |
7b50312a PA |
700 | return i386_linux_dr_get (inferior_ptid, DR_CONTROL); |
701 | } | |
9f0bdab8 | 702 | |
7b50312a | 703 | /* Get DR_STATUS from only the one LWP of INFERIOR_PTID. */ |
84346e11 | 704 | |
7b50312a PA |
705 | static unsigned long |
706 | i386_linux_dr_get_status (void) | |
707 | { | |
708 | return i386_linux_dr_get (inferior_ptid, DR_STATUS); | |
84346e11 MK |
709 | } |
710 | ||
7b50312a PA |
711 | /* Callback for iterate_over_lwps. Update the debug registers of |
712 | LWP. */ | |
713 | ||
714 | static int | |
715 | update_debug_registers_callback (struct lwp_info *lwp, void *arg) | |
716 | { | |
6e012a6c PA |
717 | if (lwp->arch_private == NULL) |
718 | lwp->arch_private = XCNEW (struct arch_lwp_info); | |
719 | ||
7b50312a PA |
720 | /* The actual update is done later just before resuming the lwp, we |
721 | just mark that the registers need updating. */ | |
722 | lwp->arch_private->debug_registers_changed = 1; | |
723 | ||
724 | /* If the lwp isn't stopped, force it to momentarily pause, so we | |
725 | can update its debug registers. */ | |
726 | if (!lwp->stopped) | |
727 | linux_stop_lwp (lwp); | |
728 | ||
8da828f7 | 729 | /* Continue the iteration. */ |
7b50312a PA |
730 | return 0; |
731 | } | |
732 | ||
733 | /* Set DR_CONTROL to ADDR in all LWPs of the current inferior. */ | |
a79d3c27 | 734 | |
9bb9e8ad | 735 | static void |
7b50312a | 736 | i386_linux_dr_set_control (unsigned long control) |
84346e11 | 737 | { |
7b50312a PA |
738 | ptid_t pid_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid)); |
739 | ||
740 | iterate_over_lwps (pid_ptid, update_debug_registers_callback, NULL); | |
84346e11 MK |
741 | } |
742 | ||
7b50312a PA |
743 | /* Set address REGNUM (zero based) to ADDR in all LWPs of the current |
744 | inferior. */ | |
a79d3c27 | 745 | |
7b50312a PA |
746 | static void |
747 | i386_linux_dr_set_addr (int regnum, CORE_ADDR addr) | |
84346e11 | 748 | { |
7b50312a PA |
749 | ptid_t pid_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid)); |
750 | ||
751 | gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); | |
752 | ||
753 | iterate_over_lwps (pid_ptid, update_debug_registers_callback, NULL); | |
9f0bdab8 DJ |
754 | } |
755 | ||
7b50312a PA |
756 | /* Called when resuming a thread. |
757 | If the debug regs have changed, update the thread's copies. */ | |
a79d3c27 JK |
758 | |
759 | static void | |
7b50312a | 760 | i386_linux_prepare_to_resume (struct lwp_info *lwp) |
a79d3c27 | 761 | { |
7b50312a | 762 | int clear_status = 0; |
a79d3c27 | 763 | |
6e012a6c PA |
764 | /* NULL means this is the main thread still going through the shell, |
765 | or, no watchpoint has been set yet. In that case, there's | |
766 | nothing to do. */ | |
767 | if (lwp->arch_private == NULL) | |
768 | return; | |
769 | ||
7b50312a | 770 | if (lwp->arch_private->debug_registers_changed) |
a79d3c27 | 771 | { |
7b50312a PA |
772 | struct i386_debug_reg_state *state = i386_debug_reg_state (); |
773 | int i; | |
774 | ||
775 | for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++) | |
776 | if (state->dr_ref_count[i] > 0) | |
777 | { | |
778 | i386_linux_dr_set (lwp->ptid, i, state->dr_mirror[i]); | |
779 | ||
780 | /* If we're setting a watchpoint, any change the inferior | |
781 | had done itself to the debug registers needs to be | |
782 | discarded, otherwise, i386_stopped_data_address can get | |
783 | confused. */ | |
784 | clear_status = 1; | |
785 | } | |
4c38200f | 786 | |
7b50312a PA |
787 | i386_linux_dr_set (lwp->ptid, DR_CONTROL, state->dr_control_mirror); |
788 | ||
789 | lwp->arch_private->debug_registers_changed = 0; | |
a79d3c27 | 790 | } |
7b50312a PA |
791 | |
792 | if (clear_status || lwp->stopped_by_watchpoint) | |
793 | i386_linux_dr_set (lwp->ptid, DR_STATUS, 0); | |
a79d3c27 JK |
794 | } |
795 | ||
9f0bdab8 | 796 | static void |
7b50312a | 797 | i386_linux_new_thread (struct lwp_info *lp) |
9f0bdab8 | 798 | { |
7b50312a | 799 | struct arch_lwp_info *info = XCNEW (struct arch_lwp_info); |
9f0bdab8 | 800 | |
7b50312a | 801 | info->debug_registers_changed = 1; |
9f0bdab8 | 802 | |
7b50312a | 803 | lp->arch_private = info; |
84346e11 MK |
804 | } |
805 | \f | |
806 | ||
5bca7895 MK |
807 | /* Called by libthread_db. Returns a pointer to the thread local |
808 | storage (or its descriptor). */ | |
809 | ||
810 | ps_err_e | |
811 | ps_get_thread_area (const struct ps_prochandle *ph, | |
812 | lwpid_t lwpid, int idx, void **base) | |
813 | { | |
814 | /* NOTE: cagney/2003-08-26: The definition of this buffer is found | |
815 | in the kernel header <asm-i386/ldt.h>. It, after padding, is 4 x | |
816 | 4 byte integers in size: `entry_number', `base_addr', `limit', | |
817 | and a bunch of status bits. | |
818 | ||
819 | The values returned by this ptrace call should be part of the | |
820 | regcache buffer, and ps_get_thread_area should channel its | |
821 | request through the regcache. That way remote targets could | |
822 | provide the value using the remote protocol and not this direct | |
823 | call. | |
824 | ||
825 | Is this function needed? I'm guessing that the `base' is the | |
766062f6 | 826 | address of a descriptor that libthread_db uses to find the |
b2fa5097 | 827 | thread local address base that GDB needs. Perhaps that |
5bca7895 MK |
828 | descriptor is defined by the ABI. Anyway, given that |
829 | libthread_db calls this function without prompting (gdb | |
830 | requesting tls base) I guess it needs info in there anyway. */ | |
831 | unsigned int desc[4]; | |
832 | gdb_assert (sizeof (int) == 4); | |
833 | ||
834 | #ifndef PTRACE_GET_THREAD_AREA | |
835 | #define PTRACE_GET_THREAD_AREA 25 | |
836 | #endif | |
837 | ||
838 | if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, | |
839 | (void *) idx, (unsigned long) &desc) < 0) | |
840 | return PS_ERR; | |
841 | ||
842 | *(int *)base = desc[1]; | |
843 | return PS_OK; | |
844 | } | |
845 | \f | |
846 | ||
a4b6fc86 | 847 | /* The instruction for a GNU/Linux system call is: |
a6abb2c0 MK |
848 | int $0x80 |
849 | or 0xcd 0x80. */ | |
850 | ||
851 | static const unsigned char linux_syscall[] = { 0xcd, 0x80 }; | |
852 | ||
853 | #define LINUX_SYSCALL_LEN (sizeof linux_syscall) | |
854 | ||
855 | /* The system call number is stored in the %eax register. */ | |
7532965f | 856 | #define LINUX_SYSCALL_REGNUM I386_EAX_REGNUM |
a6abb2c0 MK |
857 | |
858 | /* We are specifically interested in the sigreturn and rt_sigreturn | |
859 | system calls. */ | |
860 | ||
861 | #ifndef SYS_sigreturn | |
862 | #define SYS_sigreturn 0x77 | |
863 | #endif | |
864 | #ifndef SYS_rt_sigreturn | |
865 | #define SYS_rt_sigreturn 0xad | |
866 | #endif | |
867 | ||
868 | /* Offset to saved processor flags, from <asm/sigcontext.h>. */ | |
869 | #define LINUX_SIGCONTEXT_EFLAGS_OFFSET (64) | |
870 | ||
871 | /* Resume execution of the inferior process. | |
872 | If STEP is nonzero, single-step it. | |
873 | If SIGNAL is nonzero, give it that signal. */ | |
874 | ||
10d6c8cd | 875 | static void |
28439f5e PA |
876 | i386_linux_resume (struct target_ops *ops, |
877 | ptid_t ptid, int step, enum target_signal signal) | |
a6abb2c0 | 878 | { |
39f77062 KB |
879 | int pid = PIDGET (ptid); |
880 | ||
a96d9b2e SDJ |
881 | int request; |
882 | ||
883 | if (catch_syscall_enabled () > 0) | |
884 | request = PTRACE_SYSCALL; | |
885 | else | |
886 | request = PTRACE_CONT; | |
a6abb2c0 | 887 | |
a6abb2c0 MK |
888 | if (step) |
889 | { | |
594f7785 | 890 | struct regcache *regcache = get_thread_regcache (pid_to_ptid (pid)); |
e17a4113 UW |
891 | struct gdbarch *gdbarch = get_regcache_arch (regcache); |
892 | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | |
7b86a1b8 | 893 | ULONGEST pc; |
8e70166d | 894 | gdb_byte buf[LINUX_SYSCALL_LEN]; |
a6abb2c0 MK |
895 | |
896 | request = PTRACE_SINGLESTEP; | |
897 | ||
e17a4113 UW |
898 | regcache_cooked_read_unsigned (regcache, |
899 | gdbarch_pc_regnum (gdbarch), &pc); | |
7b86a1b8 | 900 | |
a6abb2c0 MK |
901 | /* Returning from a signal trampoline is done by calling a |
902 | special system call (sigreturn or rt_sigreturn, see | |
903 | i386-linux-tdep.c for more information). This system call | |
904 | restores the registers that were saved when the signal was | |
905 | raised, including %eflags. That means that single-stepping | |
906 | won't work. Instead, we'll have to modify the signal context | |
907 | that's about to be restored, and set the trace flag there. */ | |
908 | ||
909 | /* First check if PC is at a system call. */ | |
8defab1a | 910 | if (target_read_memory (pc, buf, LINUX_SYSCALL_LEN) == 0 |
a6abb2c0 MK |
911 | && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0) |
912 | { | |
7b86a1b8 UW |
913 | ULONGEST syscall; |
914 | regcache_cooked_read_unsigned (regcache, | |
915 | LINUX_SYSCALL_REGNUM, &syscall); | |
a6abb2c0 MK |
916 | |
917 | /* Then check the system call number. */ | |
918 | if (syscall == SYS_sigreturn || syscall == SYS_rt_sigreturn) | |
919 | { | |
7b86a1b8 | 920 | ULONGEST sp, addr; |
a6abb2c0 | 921 | unsigned long int eflags; |
7bf0983e | 922 | |
7b86a1b8 | 923 | regcache_cooked_read_unsigned (regcache, I386_ESP_REGNUM, &sp); |
a6abb2c0 | 924 | if (syscall == SYS_rt_sigreturn) |
f3d6df6d YQ |
925 | addr = read_memory_unsigned_integer (sp + 8, 4, byte_order) |
926 | + 20; | |
7b86a1b8 UW |
927 | else |
928 | addr = sp; | |
a6abb2c0 MK |
929 | |
930 | /* Set the trace flag in the context that's about to be | |
931 | restored. */ | |
932 | addr += LINUX_SIGCONTEXT_EFLAGS_OFFSET; | |
8e70166d | 933 | read_memory (addr, (gdb_byte *) &eflags, 4); |
a6abb2c0 | 934 | eflags |= 0x0100; |
8e70166d | 935 | write_memory (addr, (gdb_byte *) &eflags, 4); |
a6abb2c0 MK |
936 | } |
937 | } | |
938 | } | |
939 | ||
940 | if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1) | |
e2e0b3e5 | 941 | perror_with_name (("ptrace")); |
a6abb2c0 | 942 | } |
4de4c07c | 943 | |
10d6c8cd DJ |
944 | static void (*super_post_startup_inferior) (ptid_t ptid); |
945 | ||
946 | static void | |
947 | i386_linux_child_post_startup_inferior (ptid_t ptid) | |
4de4c07c DJ |
948 | { |
949 | i386_cleanup_dregs (); | |
10d6c8cd DJ |
950 | super_post_startup_inferior (ptid); |
951 | } | |
952 | ||
90884b2b L |
953 | /* Get Linux/x86 target description from running target. */ |
954 | ||
955 | static const struct target_desc * | |
956 | i386_linux_read_description (struct target_ops *ops) | |
957 | { | |
3a13a53b | 958 | int tid; |
c131fcee L |
959 | static uint64_t xcr0; |
960 | ||
3a13a53b L |
961 | /* GNU/Linux LWP ID's are process ID's. */ |
962 | tid = TIDGET (inferior_ptid); | |
963 | if (tid == 0) | |
964 | tid = PIDGET (inferior_ptid); /* Not a threaded program. */ | |
965 | ||
966 | #ifdef HAVE_PTRACE_GETFPXREGS | |
967 | if (have_ptrace_getfpxregs == -1) | |
968 | { | |
969 | elf_fpxregset_t fpxregs; | |
970 | ||
971 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, (int) &fpxregs) < 0) | |
972 | { | |
973 | have_ptrace_getfpxregs = 0; | |
974 | have_ptrace_getregset = 0; | |
975 | return tdesc_i386_mmx_linux; | |
976 | } | |
977 | } | |
978 | #endif | |
979 | ||
c131fcee L |
980 | if (have_ptrace_getregset == -1) |
981 | { | |
c131fcee L |
982 | uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))]; |
983 | struct iovec iov; | |
984 | ||
c131fcee L |
985 | iov.iov_base = xstateregs; |
986 | iov.iov_len = sizeof (xstateregs); | |
987 | ||
988 | /* Check if PTRACE_GETREGSET works. */ | |
989 | if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE, | |
990 | &iov) < 0) | |
991 | have_ptrace_getregset = 0; | |
992 | else | |
993 | { | |
994 | have_ptrace_getregset = 1; | |
995 | ||
996 | /* Get XCR0 from XSAVE extended state. */ | |
997 | xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET | |
998 | / sizeof (long long))]; | |
999 | } | |
1000 | } | |
1001 | ||
1002 | /* Check the native XCR0 only if PTRACE_GETREGSET is available. */ | |
1003 | if (have_ptrace_getregset | |
1004 | && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK) | |
1005 | return tdesc_i386_avx_linux; | |
1006 | else | |
1007 | return tdesc_i386_linux; | |
90884b2b L |
1008 | } |
1009 | ||
10d6c8cd DJ |
1010 | void |
1011 | _initialize_i386_linux_nat (void) | |
1012 | { | |
1013 | struct target_ops *t; | |
1014 | ||
1015 | /* Fill in the generic GNU/Linux methods. */ | |
1016 | t = linux_target (); | |
1017 | ||
c03374d5 DJ |
1018 | i386_use_watchpoints (t); |
1019 | ||
9bb9e8ad PM |
1020 | i386_dr_low.set_control = i386_linux_dr_set_control; |
1021 | i386_dr_low.set_addr = i386_linux_dr_set_addr; | |
7b50312a | 1022 | i386_dr_low.get_addr = i386_linux_dr_get_addr; |
9bb9e8ad | 1023 | i386_dr_low.get_status = i386_linux_dr_get_status; |
7b50312a | 1024 | i386_dr_low.get_control = i386_linux_dr_get_control; |
9bb9e8ad PM |
1025 | i386_set_debug_register_length (4); |
1026 | ||
10d6c8cd DJ |
1027 | /* Override the default ptrace resume method. */ |
1028 | t->to_resume = i386_linux_resume; | |
1029 | ||
1030 | /* Override the GNU/Linux inferior startup hook. */ | |
1031 | super_post_startup_inferior = t->to_post_startup_inferior; | |
1032 | t->to_post_startup_inferior = i386_linux_child_post_startup_inferior; | |
1033 | ||
1034 | /* Add our register access methods. */ | |
1035 | t->to_fetch_registers = i386_linux_fetch_inferior_registers; | |
1036 | t->to_store_registers = i386_linux_store_inferior_registers; | |
1037 | ||
90884b2b L |
1038 | t->to_read_description = i386_linux_read_description; |
1039 | ||
10d6c8cd | 1040 | /* Register the target. */ |
f973ed9c | 1041 | linux_nat_add_target (t); |
9f0bdab8 | 1042 | linux_nat_set_new_thread (t, i386_linux_new_thread); |
7b50312a | 1043 | linux_nat_set_prepare_to_resume (t, i386_linux_prepare_to_resume); |
4de4c07c | 1044 | } |