Commit | Line | Data |
---|---|---|
6ce2ac0b MK |
1 | /* Native-dependent code for Linux/x86. |
2 | Copyright 1999, 2000 Free Software Foundation, Inc. | |
d4f3574e | 3 | |
04cd15b6 | 4 | This file is part of GDB. |
d4f3574e | 5 | |
04cd15b6 MK |
6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
d4f3574e | 10 | |
04cd15b6 MK |
11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
d4f3574e | 15 | |
04cd15b6 MK |
16 | You should have received a copy of the GNU General Public License |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
d4f3574e SS |
20 | |
21 | #include "defs.h" | |
22 | #include "inferior.h" | |
23 | #include "gdbcore.h" | |
24 | ||
d4f3574e SS |
25 | #include <sys/ptrace.h> |
26 | #include <sys/user.h> | |
27 | #include <sys/procfs.h> | |
28 | ||
29 | #ifdef HAVE_SYS_REG_H | |
30 | #include <sys/reg.h> | |
31 | #endif | |
32 | ||
6ce2ac0b | 33 | /* Prototypes for supply_gregset etc. */ |
c60c0f5f MS |
34 | #include "gregset.h" |
35 | ||
6ce2ac0b MK |
36 | /* Prototypes for i387_supply_fsave etc. */ |
37 | #include "i387-nat.h" | |
38 | ||
756ed206 MK |
39 | /* Prototypes for local functions. */ |
40 | static void dummy_sse_values (void); | |
41 | ||
04cd15b6 MK |
42 | /* On Linux, threads are implemented as pseudo-processes, in which |
43 | case we may be tracing more than one process at a time. In that | |
44 | case, inferior_pid will contain the main process ID and the | |
45 | individual thread (process) ID mashed together. These macros are | |
46 | used to separate them out. These definitions should be overridden | |
47 | if thread support is included. */ | |
ed9a39eb JM |
48 | |
49 | #if !defined (PIDGET) /* Default definition for PIDGET/TIDGET. */ | |
50 | #define PIDGET(PID) PID | |
51 | #define TIDGET(PID) 0 | |
52 | #endif | |
6ce2ac0b | 53 | \f |
d4f3574e | 54 | |
04cd15b6 MK |
55 | /* The register sets used in Linux ELF core-dumps are identical to the |
56 | register sets in `struct user' that is used for a.out core-dumps, | |
57 | and is also used by `ptrace'. The corresponding types are | |
58 | `elf_gregset_t' for the general-purpose registers (with | |
59 | `elf_greg_t' the type of a single GP register) and `elf_fpregset_t' | |
60 | for the floating-point registers. | |
61 | ||
62 | Those types used to be available under the names `gregset_t' and | |
63 | `fpregset_t' too, and this file used those names in the past. But | |
64 | those names are now used for the register sets used in the | |
65 | `mcontext_t' type, and have a different size and layout. */ | |
66 | ||
67 | /* Mapping between the general-purpose registers in `struct user' | |
68 | format and GDB's register array layout. */ | |
d4f3574e SS |
69 | static int regmap[] = |
70 | { | |
71 | EAX, ECX, EDX, EBX, | |
72 | UESP, EBP, ESI, EDI, | |
73 | EIP, EFL, CS, SS, | |
04cd15b6 | 74 | DS, ES, FS, GS |
d4f3574e SS |
75 | }; |
76 | ||
5c44784c JM |
77 | /* Which ptrace request retrieves which registers? |
78 | These apply to the corresponding SET requests as well. */ | |
79 | #define GETREGS_SUPPLIES(regno) \ | |
80 | (0 <= (regno) && (regno) <= 15) | |
81 | #define GETFPREGS_SUPPLIES(regno) \ | |
82 | (FP0_REGNUM <= (regno) && (regno) <= LAST_FPU_CTRL_REGNUM) | |
6ce2ac0b | 83 | #define GETFPXREGS_SUPPLIES(regno) \ |
5c44784c JM |
84 | (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM) |
85 | ||
f60300e7 MK |
86 | /* Does the current host support the GETREGS request? */ |
87 | int have_ptrace_getregs = | |
88 | #ifdef HAVE_PTRACE_GETREGS | |
89 | 1 | |
90 | #else | |
91 | 0 | |
92 | #endif | |
93 | ; | |
94 | ||
6ce2ac0b | 95 | /* Does the current host support the GETFPXREGS request? The header |
5c44784c JM |
96 | file may or may not define it, and even if it is defined, the |
97 | kernel will return EIO if it's running on a pre-SSE processor. | |
98 | ||
99 | My instinct is to attach this to some architecture- or | |
100 | target-specific data structure, but really, a particular GDB | |
101 | process can only run on top of one kernel at a time. So it's okay | |
102 | for this to be a simple variable. */ | |
6ce2ac0b MK |
103 | int have_ptrace_getfpxregs = |
104 | #ifdef HAVE_PTRACE_GETFPXREGS | |
5c44784c JM |
105 | 1 |
106 | #else | |
107 | 0 | |
108 | #endif | |
109 | ; | |
f60300e7 | 110 | \f |
6ce2ac0b | 111 | |
97780f5f JB |
112 | /* Fetching registers directly from the U area, one at a time. */ |
113 | ||
f60300e7 MK |
114 | /* FIXME: kettenis/2000-03-05: This duplicates code from `inptrace.c'. |
115 | The problem is that we define FETCH_INFERIOR_REGISTERS since we | |
116 | want to use our own versions of {fetch,store}_inferior_registers | |
117 | that use the GETREGS request. This means that the code in | |
118 | `infptrace.c' is #ifdef'd out. But we need to fall back on that | |
119 | code when GDB is running on top of a kernel that doesn't support | |
120 | the GETREGS request. I want to avoid changing `infptrace.c' right | |
121 | now. */ | |
122 | ||
318b21ef MK |
123 | #ifndef PT_READ_U |
124 | #define PT_READ_U PTRACE_PEEKUSR | |
125 | #endif | |
126 | #ifndef PT_WRITE_U | |
127 | #define PT_WRITE_U PTRACE_POKEUSR | |
128 | #endif | |
129 | ||
f60300e7 MK |
130 | /* Default the type of the ptrace transfer to int. */ |
131 | #ifndef PTRACE_XFER_TYPE | |
132 | #define PTRACE_XFER_TYPE int | |
133 | #endif | |
134 | ||
135 | /* Registers we shouldn't try to fetch. */ | |
d5d65353 | 136 | #define OLD_CANNOT_FETCH_REGISTER(regno) ((regno) >= NUM_GREGS) |
f60300e7 MK |
137 | |
138 | /* Fetch one register. */ | |
139 | ||
140 | static void | |
fba45db2 | 141 | fetch_register (int regno) |
f60300e7 MK |
142 | { |
143 | /* This isn't really an address. But ptrace thinks of it as one. */ | |
144 | CORE_ADDR regaddr; | |
145 | char mess[128]; /* For messages */ | |
146 | register int i; | |
147 | unsigned int offset; /* Offset of registers within the u area. */ | |
148 | char buf[MAX_REGISTER_RAW_SIZE]; | |
149 | int tid; | |
150 | ||
d5d65353 | 151 | if (OLD_CANNOT_FETCH_REGISTER (regno)) |
f60300e7 MK |
152 | { |
153 | memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */ | |
154 | supply_register (regno, buf); | |
155 | return; | |
156 | } | |
157 | ||
158 | /* Overload thread id onto process id */ | |
159 | if ((tid = TIDGET (inferior_pid)) == 0) | |
160 | tid = inferior_pid; /* no thread id, just use process id */ | |
161 | ||
162 | offset = U_REGS_OFFSET; | |
163 | ||
164 | regaddr = register_addr (regno, offset); | |
165 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) | |
166 | { | |
167 | errno = 0; | |
168 | *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid, | |
169 | (PTRACE_ARG3_TYPE) regaddr, 0); | |
170 | regaddr += sizeof (PTRACE_XFER_TYPE); | |
171 | if (errno != 0) | |
172 | { | |
173 | sprintf (mess, "reading register %s (#%d)", | |
174 | REGISTER_NAME (regno), regno); | |
175 | perror_with_name (mess); | |
176 | } | |
177 | } | |
178 | supply_register (regno, buf); | |
179 | } | |
180 | ||
181 | /* Fetch register values from the inferior. | |
182 | If REGNO is negative, do this for all registers. | |
183 | Otherwise, REGNO specifies which register (so we can save time). */ | |
184 | ||
185 | void | |
fba45db2 | 186 | old_fetch_inferior_registers (int regno) |
f60300e7 MK |
187 | { |
188 | if (regno >= 0) | |
189 | { | |
190 | fetch_register (regno); | |
191 | } | |
192 | else | |
193 | { | |
194 | for (regno = 0; regno < ARCH_NUM_REGS; regno++) | |
195 | { | |
196 | fetch_register (regno); | |
197 | } | |
198 | } | |
199 | } | |
200 | ||
201 | /* Registers we shouldn't try to store. */ | |
d5d65353 | 202 | #define OLD_CANNOT_STORE_REGISTER(regno) ((regno) >= NUM_GREGS) |
f60300e7 MK |
203 | |
204 | /* Store one register. */ | |
205 | ||
206 | static void | |
fba45db2 | 207 | store_register (int regno) |
f60300e7 MK |
208 | { |
209 | /* This isn't really an address. But ptrace thinks of it as one. */ | |
210 | CORE_ADDR regaddr; | |
211 | char mess[128]; /* For messages */ | |
212 | register int i; | |
213 | unsigned int offset; /* Offset of registers within the u area. */ | |
214 | int tid; | |
215 | ||
d5d65353 | 216 | if (OLD_CANNOT_STORE_REGISTER (regno)) |
f60300e7 MK |
217 | { |
218 | return; | |
219 | } | |
220 | ||
221 | /* Overload thread id onto process id */ | |
222 | if ((tid = TIDGET (inferior_pid)) == 0) | |
223 | tid = inferior_pid; /* no thread id, just use process id */ | |
224 | ||
225 | offset = U_REGS_OFFSET; | |
226 | ||
227 | regaddr = register_addr (regno, offset); | |
228 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) | |
229 | { | |
230 | errno = 0; | |
231 | ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr, | |
232 | *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]); | |
233 | regaddr += sizeof (PTRACE_XFER_TYPE); | |
234 | if (errno != 0) | |
235 | { | |
236 | sprintf (mess, "writing register %s (#%d)", | |
237 | REGISTER_NAME (regno), regno); | |
238 | perror_with_name (mess); | |
239 | } | |
240 | } | |
241 | } | |
242 | ||
243 | /* Store our register values back into the inferior. | |
244 | If REGNO is negative, do this for all registers. | |
245 | Otherwise, REGNO specifies which register (so we can save time). */ | |
246 | ||
247 | void | |
fba45db2 | 248 | old_store_inferior_registers (int regno) |
f60300e7 MK |
249 | { |
250 | if (regno >= 0) | |
251 | { | |
252 | store_register (regno); | |
253 | } | |
254 | else | |
255 | { | |
256 | for (regno = 0; regno < ARCH_NUM_REGS; regno++) | |
257 | { | |
258 | store_register (regno); | |
259 | } | |
260 | } | |
261 | } | |
5c44784c | 262 | \f |
6ce2ac0b | 263 | |
04cd15b6 MK |
264 | /* Transfering the general-purpose registers between GDB, inferiors |
265 | and core files. */ | |
266 | ||
267 | /* Fill GDB's register array with the genereal-purpose register values | |
268 | in *GREGSETP. */ | |
5c44784c | 269 | |
d4f3574e | 270 | void |
04cd15b6 | 271 | supply_gregset (elf_gregset_t *gregsetp) |
d4f3574e | 272 | { |
04cd15b6 | 273 | elf_greg_t *regp = (elf_greg_t *) gregsetp; |
6ce2ac0b | 274 | int i; |
d4f3574e | 275 | |
6ce2ac0b MK |
276 | for (i = 0; i < NUM_GREGS; i++) |
277 | supply_register (i, (char *) (regp + regmap[i])); | |
917317f4 JM |
278 | } |
279 | ||
04cd15b6 MK |
280 | /* Fill register REGNO (if it is a general-purpose register) in |
281 | *GREGSETPS with the value in GDB's register array. If REGNO is -1, | |
282 | do this for all registers. */ | |
6ce2ac0b | 283 | |
917317f4 | 284 | void |
04cd15b6 | 285 | fill_gregset (elf_gregset_t *gregsetp, int regno) |
917317f4 | 286 | { |
6ce2ac0b MK |
287 | elf_greg_t *regp = (elf_greg_t *) gregsetp; |
288 | int i; | |
04cd15b6 | 289 | |
6ce2ac0b MK |
290 | for (i = 0; i < NUM_GREGS; i++) |
291 | if ((regno == -1 || regno == i)) | |
292 | *(regp + regmap[i]) = *(elf_greg_t *) ®isters[REGISTER_BYTE (i)]; | |
d4f3574e SS |
293 | } |
294 | ||
f60300e7 MK |
295 | #ifdef HAVE_PTRACE_GETREGS |
296 | ||
04cd15b6 MK |
297 | /* Fetch all general-purpose registers from process/thread TID and |
298 | store their values in GDB's register array. */ | |
d4f3574e | 299 | |
5c44784c | 300 | static void |
ed9a39eb | 301 | fetch_regs (int tid) |
5c44784c | 302 | { |
04cd15b6 | 303 | elf_gregset_t regs; |
5c44784c | 304 | |
6ce2ac0b | 305 | if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) |
5c44784c | 306 | { |
f60300e7 MK |
307 | if (errno == EIO) |
308 | { | |
309 | /* The kernel we're running on doesn't support the GETREGS | |
310 | request. Reset `have_ptrace_getregs'. */ | |
311 | have_ptrace_getregs = 0; | |
312 | return; | |
313 | } | |
314 | ||
6ce2ac0b | 315 | perror_with_name ("Couldn't get registers"); |
5c44784c JM |
316 | } |
317 | ||
04cd15b6 | 318 | supply_gregset (®s); |
5c44784c JM |
319 | } |
320 | ||
04cd15b6 MK |
321 | /* Store all valid general-purpose registers in GDB's register array |
322 | into the process/thread specified by TID. */ | |
5c44784c | 323 | |
5c44784c | 324 | static void |
6ce2ac0b | 325 | store_regs (int tid, int regno) |
5c44784c | 326 | { |
04cd15b6 | 327 | elf_gregset_t regs; |
5c44784c | 328 | |
6ce2ac0b MK |
329 | if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) |
330 | perror_with_name ("Couldn't get registers"); | |
5c44784c | 331 | |
6ce2ac0b MK |
332 | fill_gregset (®s, regno); |
333 | ||
334 | if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) | |
335 | perror_with_name ("Couldn't write registers"); | |
5c44784c JM |
336 | } |
337 | ||
f60300e7 MK |
338 | #else |
339 | ||
340 | static void fetch_regs (int tid) {} | |
6ce2ac0b | 341 | static void store_regs (int tid, int regno) {} |
f60300e7 MK |
342 | |
343 | #endif | |
5c44784c | 344 | \f |
5c44784c | 345 | |
6ce2ac0b | 346 | /* Transfering floating-point registers between GDB, inferiors and cores. */ |
d4f3574e | 347 | |
04cd15b6 | 348 | /* Fill GDB's register array with the floating-point register values in |
917317f4 | 349 | *FPREGSETP. */ |
04cd15b6 | 350 | |
d4f3574e | 351 | void |
04cd15b6 | 352 | supply_fpregset (elf_fpregset_t *fpregsetp) |
d4f3574e | 353 | { |
6ce2ac0b | 354 | i387_supply_fsave ((char *) fpregsetp); |
756ed206 | 355 | dummy_sse_values (); |
917317f4 | 356 | } |
d4f3574e | 357 | |
04cd15b6 MK |
358 | /* Fill register REGNO (if it is a floating-point register) in |
359 | *FPREGSETP with the value in GDB's register array. If REGNO is -1, | |
360 | do this for all registers. */ | |
917317f4 JM |
361 | |
362 | void | |
04cd15b6 | 363 | fill_fpregset (elf_fpregset_t *fpregsetp, int regno) |
917317f4 | 364 | { |
6ce2ac0b | 365 | i387_fill_fsave ((char *) fpregsetp, regno); |
d4f3574e SS |
366 | } |
367 | ||
f60300e7 MK |
368 | #ifdef HAVE_PTRACE_GETREGS |
369 | ||
04cd15b6 MK |
370 | /* Fetch all floating-point registers from process/thread TID and store |
371 | thier values in GDB's register array. */ | |
917317f4 | 372 | |
d4f3574e | 373 | static void |
ed9a39eb | 374 | fetch_fpregs (int tid) |
d4f3574e | 375 | { |
04cd15b6 | 376 | elf_fpregset_t fpregs; |
d4f3574e | 377 | |
6ce2ac0b MK |
378 | if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) |
379 | perror_with_name ("Couldn't get floating point status"); | |
d4f3574e | 380 | |
04cd15b6 | 381 | supply_fpregset (&fpregs); |
d4f3574e SS |
382 | } |
383 | ||
04cd15b6 MK |
384 | /* Store all valid floating-point registers in GDB's register array |
385 | into the process/thread specified by TID. */ | |
d4f3574e | 386 | |
d4f3574e | 387 | static void |
6ce2ac0b | 388 | store_fpregs (int tid, int regno) |
d4f3574e | 389 | { |
04cd15b6 | 390 | elf_fpregset_t fpregs; |
d4f3574e | 391 | |
6ce2ac0b MK |
392 | if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) |
393 | perror_with_name ("Couldn't get floating point status"); | |
d4f3574e | 394 | |
6ce2ac0b | 395 | fill_fpregset (&fpregs, regno); |
d4f3574e | 396 | |
6ce2ac0b MK |
397 | if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0) |
398 | perror_with_name ("Couldn't write floating point status"); | |
d4f3574e SS |
399 | } |
400 | ||
f60300e7 MK |
401 | #else |
402 | ||
403 | static void fetch_fpregs (int tid) {} | |
6ce2ac0b | 404 | static void store_fpregs (int tid, int regno) {} |
f60300e7 MK |
405 | |
406 | #endif | |
5c44784c | 407 | \f |
d4f3574e | 408 | |
6ce2ac0b | 409 | /* Transfering floating-point and SSE registers to and from GDB. */ |
11cf8741 | 410 | |
6ce2ac0b | 411 | #ifdef HAVE_PTRACE_GETFPXREGS |
04cd15b6 MK |
412 | |
413 | /* Fill GDB's register array with the floating-point and SSE register | |
6ce2ac0b | 414 | values in *FPXREGSETP. */ |
04cd15b6 | 415 | |
d4f3574e | 416 | static void |
6ce2ac0b | 417 | supply_fpxregset (elf_fpxregset_t *fpxregsetp) |
d4f3574e | 418 | { |
6ce2ac0b | 419 | i387_supply_fxsave ((char *) fpxregsetp); |
d4f3574e SS |
420 | } |
421 | ||
6ce2ac0b MK |
422 | /* Fill register REGNO (if it is a floating-point or SSE register) in |
423 | *FPXREGSETP with the value in GDB's register array. If REGNO is | |
424 | -1, do this for all registers. */ | |
d4f3574e | 425 | |
d4f3574e | 426 | static void |
6ce2ac0b | 427 | fill_fpxregset (elf_fpxregset_t *fpxregsetp, int regno) |
d4f3574e | 428 | { |
6ce2ac0b | 429 | i387_fill_fxsave ((char *) fpxregsetp, regno); |
5c44784c JM |
430 | } |
431 | ||
6ce2ac0b | 432 | /* Fetch all registers covered by the PTRACE_GETFPXREGS request from |
04cd15b6 MK |
433 | process/thread TID and store their values in GDB's register array. |
434 | Return non-zero if successful, zero otherwise. */ | |
5c44784c | 435 | |
5c44784c | 436 | static int |
6ce2ac0b | 437 | fetch_fpxregs (int tid) |
5c44784c | 438 | { |
6ce2ac0b | 439 | elf_fpxregset_t fpxregs; |
5c44784c | 440 | |
6ce2ac0b | 441 | if (! have_ptrace_getfpxregs) |
5c44784c JM |
442 | return 0; |
443 | ||
6ce2ac0b | 444 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, (int) &fpxregs) < 0) |
d4f3574e | 445 | { |
5c44784c JM |
446 | if (errno == EIO) |
447 | { | |
6ce2ac0b | 448 | have_ptrace_getfpxregs = 0; |
5c44784c JM |
449 | return 0; |
450 | } | |
451 | ||
6ce2ac0b | 452 | perror_with_name ("Couldn't read floating-point and SSE registers"); |
d4f3574e SS |
453 | } |
454 | ||
6ce2ac0b | 455 | supply_fpxregset (&fpxregs); |
5c44784c JM |
456 | return 1; |
457 | } | |
d4f3574e | 458 | |
04cd15b6 | 459 | /* Store all valid registers in GDB's register array covered by the |
6ce2ac0b | 460 | PTRACE_SETFPXREGS request into the process/thread specified by TID. |
04cd15b6 | 461 | Return non-zero if successful, zero otherwise. */ |
5c44784c | 462 | |
5c44784c | 463 | static int |
6ce2ac0b | 464 | store_fpxregs (int tid, int regno) |
5c44784c | 465 | { |
6ce2ac0b | 466 | elf_fpxregset_t fpxregs; |
5c44784c | 467 | |
6ce2ac0b | 468 | if (! have_ptrace_getfpxregs) |
5c44784c | 469 | return 0; |
6ce2ac0b MK |
470 | |
471 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, &fpxregs) == -1) | |
472 | perror_with_name ("Couldn't read floating-point and SSE registers"); | |
5c44784c | 473 | |
6ce2ac0b | 474 | fill_fpxregset (&fpxregs, regno); |
5c44784c | 475 | |
6ce2ac0b MK |
476 | if (ptrace (PTRACE_SETFPXREGS, tid, 0, &fpxregs) == -1) |
477 | perror_with_name ("Couldn't write floating-point and SSE registers"); | |
5c44784c JM |
478 | |
479 | return 1; | |
480 | } | |
481 | ||
04cd15b6 | 482 | /* Fill the XMM registers in the register array with dummy values. For |
5c44784c JM |
483 | cases where we don't have access to the XMM registers. I think |
484 | this is cleaner than printing a warning. For a cleaner solution, | |
485 | we should gdbarchify the i386 family. */ | |
04cd15b6 | 486 | |
5c44784c | 487 | static void |
04cd15b6 | 488 | dummy_sse_values (void) |
5c44784c JM |
489 | { |
490 | /* C doesn't have a syntax for NaN's, so write it out as an array of | |
491 | longs. */ | |
492 | static long dummy[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; | |
493 | static long mxcsr = 0x1f80; | |
494 | int reg; | |
495 | ||
496 | for (reg = 0; reg < 8; reg++) | |
497 | supply_register (XMM0_REGNUM + reg, (char *) dummy); | |
498 | supply_register (MXCSR_REGNUM, (char *) &mxcsr); | |
d4f3574e SS |
499 | } |
500 | ||
5c44784c JM |
501 | #else |
502 | ||
f0373401 MK |
503 | static int fetch_fpxregs (int tid) { return 0; } |
504 | static int store_fpxregs (int tid, int regno) { return 0; } | |
04cd15b6 | 505 | static void dummy_sse_values (void) {} |
5c44784c | 506 | |
6ce2ac0b | 507 | #endif /* HAVE_PTRACE_GETFPXREGS */ |
5c44784c | 508 | \f |
6ce2ac0b | 509 | |
5c44784c | 510 | /* Transferring arbitrary registers between GDB and inferior. */ |
d4f3574e | 511 | |
d5d65353 PS |
512 | /* Check if register REGNO in the child process is accessible. |
513 | If we are accessing registers directly via the U area, only the | |
514 | general-purpose registers are available. | |
515 | All registers should be accessible if we have GETREGS support. */ | |
516 | ||
517 | int | |
518 | cannot_fetch_register (int regno) | |
519 | { | |
520 | if (! have_ptrace_getregs) | |
521 | return OLD_CANNOT_FETCH_REGISTER (regno); | |
522 | return 0; | |
523 | } | |
524 | int | |
525 | cannot_store_register (int regno) | |
526 | { | |
527 | if (! have_ptrace_getregs) | |
528 | return OLD_CANNOT_STORE_REGISTER (regno); | |
529 | return 0; | |
530 | } | |
531 | ||
04cd15b6 MK |
532 | /* Fetch register REGNO from the child process. If REGNO is -1, do |
533 | this for all registers (including the floating point and SSE | |
534 | registers). */ | |
d4f3574e SS |
535 | |
536 | void | |
917317f4 | 537 | fetch_inferior_registers (int regno) |
d4f3574e | 538 | { |
ed9a39eb JM |
539 | int tid; |
540 | ||
f60300e7 MK |
541 | /* Use the old method of peeking around in `struct user' if the |
542 | GETREGS request isn't available. */ | |
543 | if (! have_ptrace_getregs) | |
544 | { | |
545 | old_fetch_inferior_registers (regno); | |
546 | return; | |
547 | } | |
548 | ||
04cd15b6 | 549 | /* Linux LWP ID's are process ID's. */ |
ed9a39eb | 550 | if ((tid = TIDGET (inferior_pid)) == 0) |
04cd15b6 | 551 | tid = inferior_pid; /* Not a threaded program. */ |
ed9a39eb | 552 | |
6ce2ac0b | 553 | /* Use the PTRACE_GETFPXREGS request whenever possible, since it |
04cd15b6 | 554 | transfers more registers in one system call, and we'll cache the |
6ce2ac0b | 555 | results. But remember that fetch_fpxregs can fail, and return |
04cd15b6 | 556 | zero. */ |
5c44784c JM |
557 | if (regno == -1) |
558 | { | |
ed9a39eb | 559 | fetch_regs (tid); |
f60300e7 MK |
560 | |
561 | /* The call above might reset `have_ptrace_getregs'. */ | |
562 | if (! have_ptrace_getregs) | |
563 | { | |
564 | old_fetch_inferior_registers (-1); | |
565 | return; | |
566 | } | |
567 | ||
6ce2ac0b | 568 | if (fetch_fpxregs (tid)) |
5c44784c | 569 | return; |
ed9a39eb | 570 | fetch_fpregs (tid); |
5c44784c JM |
571 | return; |
572 | } | |
d4f3574e | 573 | |
5c44784c JM |
574 | if (GETREGS_SUPPLIES (regno)) |
575 | { | |
ed9a39eb | 576 | fetch_regs (tid); |
5c44784c JM |
577 | return; |
578 | } | |
579 | ||
6ce2ac0b | 580 | if (GETFPXREGS_SUPPLIES (regno)) |
5c44784c | 581 | { |
6ce2ac0b | 582 | if (fetch_fpxregs (tid)) |
5c44784c JM |
583 | return; |
584 | ||
585 | /* Either our processor or our kernel doesn't support the SSE | |
586 | registers, so read the FP registers in the traditional way, | |
587 | and fill the SSE registers with dummy values. It would be | |
588 | more graceful to handle differences in the register set using | |
589 | gdbarch. Until then, this will at least make things work | |
590 | plausibly. */ | |
ed9a39eb | 591 | fetch_fpregs (tid); |
5c44784c JM |
592 | return; |
593 | } | |
594 | ||
6ce2ac0b | 595 | internal_error ("Got request for bad register number %d.", regno); |
d4f3574e SS |
596 | } |
597 | ||
04cd15b6 MK |
598 | /* Store register REGNO back into the child process. If REGNO is -1, |
599 | do this for all registers (including the floating point and SSE | |
600 | registers). */ | |
d4f3574e | 601 | void |
04cd15b6 | 602 | store_inferior_registers (int regno) |
d4f3574e | 603 | { |
ed9a39eb JM |
604 | int tid; |
605 | ||
f60300e7 MK |
606 | /* Use the old method of poking around in `struct user' if the |
607 | SETREGS request isn't available. */ | |
608 | if (! have_ptrace_getregs) | |
609 | { | |
610 | old_store_inferior_registers (regno); | |
611 | return; | |
612 | } | |
613 | ||
04cd15b6 | 614 | /* Linux LWP ID's are process ID's. */ |
ed9a39eb | 615 | if ((tid = TIDGET (inferior_pid)) == 0) |
04cd15b6 | 616 | tid = inferior_pid; /* Not a threaded program. */ |
ed9a39eb | 617 | |
6ce2ac0b | 618 | /* Use the PTRACE_SETFPXREGS requests whenever possible, since it |
04cd15b6 | 619 | transfers more registers in one system call. But remember that |
6ce2ac0b | 620 | store_fpxregs can fail, and return zero. */ |
5c44784c JM |
621 | if (regno == -1) |
622 | { | |
6ce2ac0b MK |
623 | store_regs (tid, regno); |
624 | if (store_fpxregs (tid, regno)) | |
5c44784c | 625 | return; |
6ce2ac0b | 626 | store_fpregs (tid, regno); |
5c44784c JM |
627 | return; |
628 | } | |
d4f3574e | 629 | |
5c44784c JM |
630 | if (GETREGS_SUPPLIES (regno)) |
631 | { | |
6ce2ac0b | 632 | store_regs (tid, regno); |
5c44784c JM |
633 | return; |
634 | } | |
635 | ||
6ce2ac0b | 636 | if (GETFPXREGS_SUPPLIES (regno)) |
5c44784c | 637 | { |
6ce2ac0b | 638 | if (store_fpxregs (tid, regno)) |
5c44784c JM |
639 | return; |
640 | ||
641 | /* Either our processor or our kernel doesn't support the SSE | |
04cd15b6 MK |
642 | registers, so just write the FP registers in the traditional |
643 | way. */ | |
6ce2ac0b | 644 | store_fpregs (tid, regno); |
5c44784c JM |
645 | return; |
646 | } | |
647 | ||
04cd15b6 | 648 | internal_error ("Got request to store bad register number %d.", regno); |
d4f3574e | 649 | } |
de57eccd | 650 | \f |
6ce2ac0b | 651 | |
de57eccd JM |
652 | /* Interpreting register set info found in core files. */ |
653 | ||
654 | /* Provide registers to GDB from a core file. | |
655 | ||
656 | (We can't use the generic version of this function in | |
657 | core-regset.c, because Linux has *three* different kinds of | |
658 | register set notes. core-regset.c would have to call | |
6ce2ac0b | 659 | supply_fpxregset, which most platforms don't have.) |
de57eccd JM |
660 | |
661 | CORE_REG_SECT points to an array of bytes, which are the contents | |
662 | of a `note' from a core file which BFD thinks might contain | |
663 | register contents. CORE_REG_SIZE is its size. | |
664 | ||
665 | WHICH says which register set corelow suspects this is: | |
04cd15b6 MK |
666 | 0 --- the general-purpose register set, in elf_gregset_t format |
667 | 2 --- the floating-point register set, in elf_fpregset_t format | |
6ce2ac0b | 668 | 3 --- the extended floating-point register set, in elf_fpxregset_t format |
04cd15b6 MK |
669 | |
670 | REG_ADDR isn't used on Linux. */ | |
de57eccd | 671 | |
de57eccd | 672 | static void |
04cd15b6 MK |
673 | fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, |
674 | int which, CORE_ADDR reg_addr) | |
de57eccd | 675 | { |
04cd15b6 MK |
676 | elf_gregset_t gregset; |
677 | elf_fpregset_t fpregset; | |
de57eccd JM |
678 | |
679 | switch (which) | |
680 | { | |
681 | case 0: | |
682 | if (core_reg_size != sizeof (gregset)) | |
04cd15b6 | 683 | warning ("Wrong size gregset in core file."); |
de57eccd JM |
684 | else |
685 | { | |
686 | memcpy (&gregset, core_reg_sect, sizeof (gregset)); | |
687 | supply_gregset (&gregset); | |
688 | } | |
689 | break; | |
690 | ||
691 | case 2: | |
692 | if (core_reg_size != sizeof (fpregset)) | |
04cd15b6 | 693 | warning ("Wrong size fpregset in core file."); |
de57eccd JM |
694 | else |
695 | { | |
696 | memcpy (&fpregset, core_reg_sect, sizeof (fpregset)); | |
697 | supply_fpregset (&fpregset); | |
698 | } | |
699 | break; | |
700 | ||
6ce2ac0b | 701 | #ifdef HAVE_PTRACE_GETFPXREGS |
de57eccd | 702 | { |
6ce2ac0b | 703 | elf_fpxregset_t fpxregset; |
04cd15b6 | 704 | |
de57eccd | 705 | case 3: |
6ce2ac0b MK |
706 | if (core_reg_size != sizeof (fpxregset)) |
707 | warning ("Wrong size fpxregset in core file."); | |
de57eccd JM |
708 | else |
709 | { | |
6ce2ac0b MK |
710 | memcpy (&fpxregset, core_reg_sect, sizeof (fpxregset)); |
711 | supply_fpxregset (&fpxregset); | |
de57eccd JM |
712 | } |
713 | break; | |
714 | } | |
715 | #endif | |
716 | ||
717 | default: | |
718 | /* We've covered all the kinds of registers we know about here, | |
719 | so this must be something we wouldn't know what to do with | |
720 | anyway. Just ignore it. */ | |
721 | break; | |
722 | } | |
723 | } | |
a6abb2c0 | 724 | \f |
6ce2ac0b | 725 | |
a6abb2c0 MK |
726 | /* The instruction for a Linux system call is: |
727 | int $0x80 | |
728 | or 0xcd 0x80. */ | |
729 | ||
730 | static const unsigned char linux_syscall[] = { 0xcd, 0x80 }; | |
731 | ||
732 | #define LINUX_SYSCALL_LEN (sizeof linux_syscall) | |
733 | ||
734 | /* The system call number is stored in the %eax register. */ | |
735 | #define LINUX_SYSCALL_REGNUM 0 /* %eax */ | |
736 | ||
737 | /* We are specifically interested in the sigreturn and rt_sigreturn | |
738 | system calls. */ | |
739 | ||
740 | #ifndef SYS_sigreturn | |
741 | #define SYS_sigreturn 0x77 | |
742 | #endif | |
743 | #ifndef SYS_rt_sigreturn | |
744 | #define SYS_rt_sigreturn 0xad | |
745 | #endif | |
746 | ||
747 | /* Offset to saved processor flags, from <asm/sigcontext.h>. */ | |
748 | #define LINUX_SIGCONTEXT_EFLAGS_OFFSET (64) | |
749 | ||
750 | /* Resume execution of the inferior process. | |
751 | If STEP is nonzero, single-step it. | |
752 | If SIGNAL is nonzero, give it that signal. */ | |
753 | ||
754 | void | |
755 | child_resume (int pid, int step, enum target_signal signal) | |
756 | { | |
757 | int request = PTRACE_CONT; | |
758 | ||
759 | if (pid == -1) | |
760 | /* Resume all threads. */ | |
761 | /* I think this only gets used in the non-threaded case, where "resume | |
762 | all threads" and "resume inferior_pid" are the same. */ | |
763 | pid = inferior_pid; | |
764 | ||
765 | if (step) | |
766 | { | |
767 | CORE_ADDR pc = read_pc_pid (pid); | |
768 | unsigned char buf[LINUX_SYSCALL_LEN]; | |
769 | ||
770 | request = PTRACE_SINGLESTEP; | |
771 | ||
772 | /* Returning from a signal trampoline is done by calling a | |
773 | special system call (sigreturn or rt_sigreturn, see | |
774 | i386-linux-tdep.c for more information). This system call | |
775 | restores the registers that were saved when the signal was | |
776 | raised, including %eflags. That means that single-stepping | |
777 | won't work. Instead, we'll have to modify the signal context | |
778 | that's about to be restored, and set the trace flag there. */ | |
779 | ||
780 | /* First check if PC is at a system call. */ | |
781 | if (read_memory_nobpt (pc, (char *) buf, LINUX_SYSCALL_LEN) == 0 | |
782 | && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0) | |
783 | { | |
784 | int syscall = read_register_pid (LINUX_SYSCALL_REGNUM, pid); | |
785 | ||
786 | /* Then check the system call number. */ | |
787 | if (syscall == SYS_sigreturn || syscall == SYS_rt_sigreturn) | |
788 | { | |
789 | CORE_ADDR sp = read_register (SP_REGNUM); | |
790 | CORE_ADDR addr = sp; | |
791 | unsigned long int eflags; | |
792 | ||
793 | if (syscall == SYS_rt_sigreturn) | |
794 | addr = read_memory_integer (sp + 8, 4) + 20; | |
795 | ||
796 | /* Set the trace flag in the context that's about to be | |
797 | restored. */ | |
798 | addr += LINUX_SIGCONTEXT_EFLAGS_OFFSET; | |
799 | read_memory (addr, (char *) &eflags, 4); | |
800 | eflags |= 0x0100; | |
801 | write_memory (addr, (char *) &eflags, 4); | |
802 | } | |
803 | } | |
804 | } | |
805 | ||
806 | if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1) | |
807 | perror_with_name ("ptrace"); | |
808 | } | |
5c44784c | 809 | \f |
6ce2ac0b | 810 | |
04cd15b6 MK |
811 | /* Register that we are able to handle Linux ELF core file formats. */ |
812 | ||
813 | static struct core_fns linux_elf_core_fns = | |
814 | { | |
815 | bfd_target_elf_flavour, /* core_flavour */ | |
816 | default_check_format, /* check_format */ | |
817 | default_core_sniffer, /* core_sniffer */ | |
818 | fetch_core_registers, /* core_read_registers */ | |
819 | NULL /* next */ | |
820 | }; | |
de57eccd JM |
821 | |
822 | void | |
fba45db2 | 823 | _initialize_i386_linux_nat (void) |
de57eccd | 824 | { |
04cd15b6 | 825 | add_core_fns (&linux_elf_core_fns); |
de57eccd | 826 | } |