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. */ | |
136 | #if !defined (CANNOT_FETCH_REGISTER) | |
137 | #define CANNOT_FETCH_REGISTER(regno) 0 | |
138 | #endif | |
139 | ||
140 | /* Fetch one register. */ | |
141 | ||
142 | static void | |
fba45db2 | 143 | fetch_register (int regno) |
f60300e7 MK |
144 | { |
145 | /* This isn't really an address. But ptrace thinks of it as one. */ | |
146 | CORE_ADDR regaddr; | |
147 | char mess[128]; /* For messages */ | |
148 | register int i; | |
149 | unsigned int offset; /* Offset of registers within the u area. */ | |
150 | char buf[MAX_REGISTER_RAW_SIZE]; | |
151 | int tid; | |
152 | ||
153 | if (CANNOT_FETCH_REGISTER (regno)) | |
154 | { | |
155 | memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */ | |
156 | supply_register (regno, buf); | |
157 | return; | |
158 | } | |
159 | ||
160 | /* Overload thread id onto process id */ | |
161 | if ((tid = TIDGET (inferior_pid)) == 0) | |
162 | tid = inferior_pid; /* no thread id, just use process id */ | |
163 | ||
164 | offset = U_REGS_OFFSET; | |
165 | ||
166 | regaddr = register_addr (regno, offset); | |
167 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) | |
168 | { | |
169 | errno = 0; | |
170 | *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid, | |
171 | (PTRACE_ARG3_TYPE) regaddr, 0); | |
172 | regaddr += sizeof (PTRACE_XFER_TYPE); | |
173 | if (errno != 0) | |
174 | { | |
175 | sprintf (mess, "reading register %s (#%d)", | |
176 | REGISTER_NAME (regno), regno); | |
177 | perror_with_name (mess); | |
178 | } | |
179 | } | |
180 | supply_register (regno, buf); | |
181 | } | |
182 | ||
183 | /* Fetch register values from the inferior. | |
184 | If REGNO is negative, do this for all registers. | |
185 | Otherwise, REGNO specifies which register (so we can save time). */ | |
186 | ||
187 | void | |
fba45db2 | 188 | old_fetch_inferior_registers (int regno) |
f60300e7 MK |
189 | { |
190 | if (regno >= 0) | |
191 | { | |
192 | fetch_register (regno); | |
193 | } | |
194 | else | |
195 | { | |
196 | for (regno = 0; regno < ARCH_NUM_REGS; regno++) | |
197 | { | |
198 | fetch_register (regno); | |
199 | } | |
200 | } | |
201 | } | |
202 | ||
203 | /* Registers we shouldn't try to store. */ | |
204 | #if !defined (CANNOT_STORE_REGISTER) | |
205 | #define CANNOT_STORE_REGISTER(regno) 0 | |
206 | #endif | |
207 | ||
208 | /* Store one register. */ | |
209 | ||
210 | static void | |
fba45db2 | 211 | store_register (int regno) |
f60300e7 MK |
212 | { |
213 | /* This isn't really an address. But ptrace thinks of it as one. */ | |
214 | CORE_ADDR regaddr; | |
215 | char mess[128]; /* For messages */ | |
216 | register int i; | |
217 | unsigned int offset; /* Offset of registers within the u area. */ | |
218 | int tid; | |
219 | ||
220 | if (CANNOT_STORE_REGISTER (regno)) | |
221 | { | |
222 | return; | |
223 | } | |
224 | ||
225 | /* Overload thread id onto process id */ | |
226 | if ((tid = TIDGET (inferior_pid)) == 0) | |
227 | tid = inferior_pid; /* no thread id, just use process id */ | |
228 | ||
229 | offset = U_REGS_OFFSET; | |
230 | ||
231 | regaddr = register_addr (regno, offset); | |
232 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) | |
233 | { | |
234 | errno = 0; | |
235 | ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr, | |
236 | *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]); | |
237 | regaddr += sizeof (PTRACE_XFER_TYPE); | |
238 | if (errno != 0) | |
239 | { | |
240 | sprintf (mess, "writing register %s (#%d)", | |
241 | REGISTER_NAME (regno), regno); | |
242 | perror_with_name (mess); | |
243 | } | |
244 | } | |
245 | } | |
246 | ||
247 | /* Store our register values back into the inferior. | |
248 | If REGNO is negative, do this for all registers. | |
249 | Otherwise, REGNO specifies which register (so we can save time). */ | |
250 | ||
251 | void | |
fba45db2 | 252 | old_store_inferior_registers (int regno) |
f60300e7 MK |
253 | { |
254 | if (regno >= 0) | |
255 | { | |
256 | store_register (regno); | |
257 | } | |
258 | else | |
259 | { | |
260 | for (regno = 0; regno < ARCH_NUM_REGS; regno++) | |
261 | { | |
262 | store_register (regno); | |
263 | } | |
264 | } | |
265 | } | |
5c44784c | 266 | \f |
6ce2ac0b | 267 | |
04cd15b6 MK |
268 | /* Transfering the general-purpose registers between GDB, inferiors |
269 | and core files. */ | |
270 | ||
271 | /* Fill GDB's register array with the genereal-purpose register values | |
272 | in *GREGSETP. */ | |
5c44784c | 273 | |
d4f3574e | 274 | void |
04cd15b6 | 275 | supply_gregset (elf_gregset_t *gregsetp) |
d4f3574e | 276 | { |
04cd15b6 | 277 | elf_greg_t *regp = (elf_greg_t *) gregsetp; |
6ce2ac0b | 278 | int i; |
d4f3574e | 279 | |
6ce2ac0b MK |
280 | for (i = 0; i < NUM_GREGS; i++) |
281 | supply_register (i, (char *) (regp + regmap[i])); | |
917317f4 JM |
282 | } |
283 | ||
04cd15b6 MK |
284 | /* Fill register REGNO (if it is a general-purpose register) in |
285 | *GREGSETPS with the value in GDB's register array. If REGNO is -1, | |
286 | do this for all registers. */ | |
6ce2ac0b | 287 | |
917317f4 | 288 | void |
04cd15b6 | 289 | fill_gregset (elf_gregset_t *gregsetp, int regno) |
917317f4 | 290 | { |
6ce2ac0b MK |
291 | elf_greg_t *regp = (elf_greg_t *) gregsetp; |
292 | int i; | |
04cd15b6 | 293 | |
6ce2ac0b MK |
294 | for (i = 0; i < NUM_GREGS; i++) |
295 | if ((regno == -1 || regno == i)) | |
296 | *(regp + regmap[i]) = *(elf_greg_t *) ®isters[REGISTER_BYTE (i)]; | |
d4f3574e SS |
297 | } |
298 | ||
f60300e7 MK |
299 | #ifdef HAVE_PTRACE_GETREGS |
300 | ||
04cd15b6 MK |
301 | /* Fetch all general-purpose registers from process/thread TID and |
302 | store their values in GDB's register array. */ | |
d4f3574e | 303 | |
5c44784c | 304 | static void |
ed9a39eb | 305 | fetch_regs (int tid) |
5c44784c | 306 | { |
04cd15b6 | 307 | elf_gregset_t regs; |
5c44784c | 308 | |
6ce2ac0b | 309 | if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) |
5c44784c | 310 | { |
f60300e7 MK |
311 | if (errno == EIO) |
312 | { | |
313 | /* The kernel we're running on doesn't support the GETREGS | |
314 | request. Reset `have_ptrace_getregs'. */ | |
315 | have_ptrace_getregs = 0; | |
316 | return; | |
317 | } | |
318 | ||
6ce2ac0b | 319 | perror_with_name ("Couldn't get registers"); |
5c44784c JM |
320 | } |
321 | ||
04cd15b6 | 322 | supply_gregset (®s); |
5c44784c JM |
323 | } |
324 | ||
04cd15b6 MK |
325 | /* Store all valid general-purpose registers in GDB's register array |
326 | into the process/thread specified by TID. */ | |
5c44784c | 327 | |
5c44784c | 328 | static void |
6ce2ac0b | 329 | store_regs (int tid, int regno) |
5c44784c | 330 | { |
04cd15b6 | 331 | elf_gregset_t regs; |
5c44784c | 332 | |
6ce2ac0b MK |
333 | if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) |
334 | perror_with_name ("Couldn't get registers"); | |
5c44784c | 335 | |
6ce2ac0b MK |
336 | fill_gregset (®s, regno); |
337 | ||
338 | if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) | |
339 | perror_with_name ("Couldn't write registers"); | |
5c44784c JM |
340 | } |
341 | ||
f60300e7 MK |
342 | #else |
343 | ||
344 | static void fetch_regs (int tid) {} | |
6ce2ac0b | 345 | static void store_regs (int tid, int regno) {} |
f60300e7 MK |
346 | |
347 | #endif | |
5c44784c | 348 | \f |
5c44784c | 349 | |
6ce2ac0b | 350 | /* Transfering floating-point registers between GDB, inferiors and cores. */ |
d4f3574e | 351 | |
04cd15b6 | 352 | /* Fill GDB's register array with the floating-point register values in |
917317f4 | 353 | *FPREGSETP. */ |
04cd15b6 | 354 | |
d4f3574e | 355 | void |
04cd15b6 | 356 | supply_fpregset (elf_fpregset_t *fpregsetp) |
d4f3574e | 357 | { |
6ce2ac0b | 358 | i387_supply_fsave ((char *) fpregsetp); |
756ed206 | 359 | dummy_sse_values (); |
917317f4 | 360 | } |
d4f3574e | 361 | |
04cd15b6 MK |
362 | /* Fill register REGNO (if it is a floating-point register) in |
363 | *FPREGSETP with the value in GDB's register array. If REGNO is -1, | |
364 | do this for all registers. */ | |
917317f4 JM |
365 | |
366 | void | |
04cd15b6 | 367 | fill_fpregset (elf_fpregset_t *fpregsetp, int regno) |
917317f4 | 368 | { |
6ce2ac0b | 369 | i387_fill_fsave ((char *) fpregsetp, regno); |
d4f3574e SS |
370 | } |
371 | ||
f60300e7 MK |
372 | #ifdef HAVE_PTRACE_GETREGS |
373 | ||
04cd15b6 MK |
374 | /* Fetch all floating-point registers from process/thread TID and store |
375 | thier values in GDB's register array. */ | |
917317f4 | 376 | |
d4f3574e | 377 | static void |
ed9a39eb | 378 | fetch_fpregs (int tid) |
d4f3574e | 379 | { |
04cd15b6 | 380 | elf_fpregset_t fpregs; |
d4f3574e | 381 | |
6ce2ac0b MK |
382 | if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) |
383 | perror_with_name ("Couldn't get floating point status"); | |
d4f3574e | 384 | |
04cd15b6 | 385 | supply_fpregset (&fpregs); |
d4f3574e SS |
386 | } |
387 | ||
04cd15b6 MK |
388 | /* Store all valid floating-point registers in GDB's register array |
389 | into the process/thread specified by TID. */ | |
d4f3574e | 390 | |
d4f3574e | 391 | static void |
6ce2ac0b | 392 | store_fpregs (int tid, int regno) |
d4f3574e | 393 | { |
04cd15b6 | 394 | elf_fpregset_t fpregs; |
d4f3574e | 395 | |
6ce2ac0b MK |
396 | if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) |
397 | perror_with_name ("Couldn't get floating point status"); | |
d4f3574e | 398 | |
6ce2ac0b | 399 | fill_fpregset (&fpregs, regno); |
d4f3574e | 400 | |
6ce2ac0b MK |
401 | if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0) |
402 | perror_with_name ("Couldn't write floating point status"); | |
d4f3574e SS |
403 | } |
404 | ||
f60300e7 MK |
405 | #else |
406 | ||
407 | static void fetch_fpregs (int tid) {} | |
6ce2ac0b | 408 | static void store_fpregs (int tid, int regno) {} |
f60300e7 MK |
409 | |
410 | #endif | |
5c44784c | 411 | \f |
d4f3574e | 412 | |
6ce2ac0b | 413 | /* Transfering floating-point and SSE registers to and from GDB. */ |
11cf8741 | 414 | |
6ce2ac0b | 415 | #ifdef HAVE_PTRACE_GETFPXREGS |
04cd15b6 MK |
416 | |
417 | /* Fill GDB's register array with the floating-point and SSE register | |
6ce2ac0b | 418 | values in *FPXREGSETP. */ |
04cd15b6 | 419 | |
d4f3574e | 420 | static void |
6ce2ac0b | 421 | supply_fpxregset (elf_fpxregset_t *fpxregsetp) |
d4f3574e | 422 | { |
6ce2ac0b | 423 | i387_supply_fxsave ((char *) fpxregsetp); |
d4f3574e SS |
424 | } |
425 | ||
6ce2ac0b MK |
426 | /* Fill register REGNO (if it is a floating-point or SSE register) in |
427 | *FPXREGSETP with the value in GDB's register array. If REGNO is | |
428 | -1, do this for all registers. */ | |
d4f3574e | 429 | |
d4f3574e | 430 | static void |
6ce2ac0b | 431 | fill_fpxregset (elf_fpxregset_t *fpxregsetp, int regno) |
d4f3574e | 432 | { |
6ce2ac0b | 433 | i387_fill_fxsave ((char *) fpxregsetp, regno); |
5c44784c JM |
434 | } |
435 | ||
6ce2ac0b | 436 | /* Fetch all registers covered by the PTRACE_GETFPXREGS request from |
04cd15b6 MK |
437 | process/thread TID and store their values in GDB's register array. |
438 | Return non-zero if successful, zero otherwise. */ | |
5c44784c | 439 | |
5c44784c | 440 | static int |
6ce2ac0b | 441 | fetch_fpxregs (int tid) |
5c44784c | 442 | { |
6ce2ac0b | 443 | elf_fpxregset_t fpxregs; |
5c44784c | 444 | |
6ce2ac0b | 445 | if (! have_ptrace_getfpxregs) |
5c44784c JM |
446 | return 0; |
447 | ||
6ce2ac0b | 448 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, (int) &fpxregs) < 0) |
d4f3574e | 449 | { |
5c44784c JM |
450 | if (errno == EIO) |
451 | { | |
6ce2ac0b | 452 | have_ptrace_getfpxregs = 0; |
5c44784c JM |
453 | return 0; |
454 | } | |
455 | ||
6ce2ac0b | 456 | perror_with_name ("Couldn't read floating-point and SSE registers"); |
d4f3574e SS |
457 | } |
458 | ||
6ce2ac0b | 459 | supply_fpxregset (&fpxregs); |
5c44784c JM |
460 | return 1; |
461 | } | |
d4f3574e | 462 | |
04cd15b6 | 463 | /* Store all valid registers in GDB's register array covered by the |
6ce2ac0b | 464 | PTRACE_SETFPXREGS request into the process/thread specified by TID. |
04cd15b6 | 465 | Return non-zero if successful, zero otherwise. */ |
5c44784c | 466 | |
5c44784c | 467 | static int |
6ce2ac0b | 468 | store_fpxregs (int tid, int regno) |
5c44784c | 469 | { |
6ce2ac0b | 470 | elf_fpxregset_t fpxregs; |
5c44784c | 471 | |
6ce2ac0b | 472 | if (! have_ptrace_getfpxregs) |
5c44784c | 473 | return 0; |
6ce2ac0b MK |
474 | |
475 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, &fpxregs) == -1) | |
476 | perror_with_name ("Couldn't read floating-point and SSE registers"); | |
5c44784c | 477 | |
6ce2ac0b | 478 | fill_fpxregset (&fpxregs, regno); |
5c44784c | 479 | |
6ce2ac0b MK |
480 | if (ptrace (PTRACE_SETFPXREGS, tid, 0, &fpxregs) == -1) |
481 | perror_with_name ("Couldn't write floating-point and SSE registers"); | |
5c44784c JM |
482 | |
483 | return 1; | |
484 | } | |
485 | ||
04cd15b6 | 486 | /* Fill the XMM registers in the register array with dummy values. For |
5c44784c JM |
487 | cases where we don't have access to the XMM registers. I think |
488 | this is cleaner than printing a warning. For a cleaner solution, | |
489 | we should gdbarchify the i386 family. */ | |
04cd15b6 | 490 | |
5c44784c | 491 | static void |
04cd15b6 | 492 | dummy_sse_values (void) |
5c44784c JM |
493 | { |
494 | /* C doesn't have a syntax for NaN's, so write it out as an array of | |
495 | longs. */ | |
496 | static long dummy[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; | |
497 | static long mxcsr = 0x1f80; | |
498 | int reg; | |
499 | ||
500 | for (reg = 0; reg < 8; reg++) | |
501 | supply_register (XMM0_REGNUM + reg, (char *) dummy); | |
502 | supply_register (MXCSR_REGNUM, (char *) &mxcsr); | |
d4f3574e SS |
503 | } |
504 | ||
5c44784c JM |
505 | #else |
506 | ||
f0373401 MK |
507 | static int fetch_fpxregs (int tid) { return 0; } |
508 | static int store_fpxregs (int tid, int regno) { return 0; } | |
04cd15b6 | 509 | static void dummy_sse_values (void) {} |
5c44784c | 510 | |
6ce2ac0b | 511 | #endif /* HAVE_PTRACE_GETFPXREGS */ |
5c44784c | 512 | \f |
6ce2ac0b | 513 | |
5c44784c | 514 | /* Transferring arbitrary registers between GDB and inferior. */ |
d4f3574e | 515 | |
04cd15b6 MK |
516 | /* Fetch register REGNO from the child process. If REGNO is -1, do |
517 | this for all registers (including the floating point and SSE | |
518 | registers). */ | |
d4f3574e SS |
519 | |
520 | void | |
917317f4 | 521 | fetch_inferior_registers (int regno) |
d4f3574e | 522 | { |
ed9a39eb JM |
523 | int tid; |
524 | ||
f60300e7 MK |
525 | /* Use the old method of peeking around in `struct user' if the |
526 | GETREGS request isn't available. */ | |
527 | if (! have_ptrace_getregs) | |
528 | { | |
529 | old_fetch_inferior_registers (regno); | |
530 | return; | |
531 | } | |
532 | ||
04cd15b6 | 533 | /* Linux LWP ID's are process ID's. */ |
ed9a39eb | 534 | if ((tid = TIDGET (inferior_pid)) == 0) |
04cd15b6 | 535 | tid = inferior_pid; /* Not a threaded program. */ |
ed9a39eb | 536 | |
6ce2ac0b | 537 | /* Use the PTRACE_GETFPXREGS request whenever possible, since it |
04cd15b6 | 538 | transfers more registers in one system call, and we'll cache the |
6ce2ac0b | 539 | results. But remember that fetch_fpxregs can fail, and return |
04cd15b6 | 540 | zero. */ |
5c44784c JM |
541 | if (regno == -1) |
542 | { | |
ed9a39eb | 543 | fetch_regs (tid); |
f60300e7 MK |
544 | |
545 | /* The call above might reset `have_ptrace_getregs'. */ | |
546 | if (! have_ptrace_getregs) | |
547 | { | |
548 | old_fetch_inferior_registers (-1); | |
549 | return; | |
550 | } | |
551 | ||
6ce2ac0b | 552 | if (fetch_fpxregs (tid)) |
5c44784c | 553 | return; |
ed9a39eb | 554 | fetch_fpregs (tid); |
5c44784c JM |
555 | return; |
556 | } | |
d4f3574e | 557 | |
5c44784c JM |
558 | if (GETREGS_SUPPLIES (regno)) |
559 | { | |
ed9a39eb | 560 | fetch_regs (tid); |
5c44784c JM |
561 | return; |
562 | } | |
563 | ||
6ce2ac0b | 564 | if (GETFPXREGS_SUPPLIES (regno)) |
5c44784c | 565 | { |
6ce2ac0b | 566 | if (fetch_fpxregs (tid)) |
5c44784c JM |
567 | return; |
568 | ||
569 | /* Either our processor or our kernel doesn't support the SSE | |
570 | registers, so read the FP registers in the traditional way, | |
571 | and fill the SSE registers with dummy values. It would be | |
572 | more graceful to handle differences in the register set using | |
573 | gdbarch. Until then, this will at least make things work | |
574 | plausibly. */ | |
ed9a39eb | 575 | fetch_fpregs (tid); |
5c44784c JM |
576 | return; |
577 | } | |
578 | ||
6ce2ac0b | 579 | internal_error ("Got request for bad register number %d.", regno); |
d4f3574e SS |
580 | } |
581 | ||
04cd15b6 MK |
582 | /* Store register REGNO back into the child process. If REGNO is -1, |
583 | do this for all registers (including the floating point and SSE | |
584 | registers). */ | |
d4f3574e | 585 | void |
04cd15b6 | 586 | store_inferior_registers (int regno) |
d4f3574e | 587 | { |
ed9a39eb JM |
588 | int tid; |
589 | ||
f60300e7 MK |
590 | /* Use the old method of poking around in `struct user' if the |
591 | SETREGS request isn't available. */ | |
592 | if (! have_ptrace_getregs) | |
593 | { | |
594 | old_store_inferior_registers (regno); | |
595 | return; | |
596 | } | |
597 | ||
04cd15b6 | 598 | /* Linux LWP ID's are process ID's. */ |
ed9a39eb | 599 | if ((tid = TIDGET (inferior_pid)) == 0) |
04cd15b6 | 600 | tid = inferior_pid; /* Not a threaded program. */ |
ed9a39eb | 601 | |
6ce2ac0b | 602 | /* Use the PTRACE_SETFPXREGS requests whenever possible, since it |
04cd15b6 | 603 | transfers more registers in one system call. But remember that |
6ce2ac0b | 604 | store_fpxregs can fail, and return zero. */ |
5c44784c JM |
605 | if (regno == -1) |
606 | { | |
6ce2ac0b MK |
607 | store_regs (tid, regno); |
608 | if (store_fpxregs (tid, regno)) | |
5c44784c | 609 | return; |
6ce2ac0b | 610 | store_fpregs (tid, regno); |
5c44784c JM |
611 | return; |
612 | } | |
d4f3574e | 613 | |
5c44784c JM |
614 | if (GETREGS_SUPPLIES (regno)) |
615 | { | |
6ce2ac0b | 616 | store_regs (tid, regno); |
5c44784c JM |
617 | return; |
618 | } | |
619 | ||
6ce2ac0b | 620 | if (GETFPXREGS_SUPPLIES (regno)) |
5c44784c | 621 | { |
6ce2ac0b | 622 | if (store_fpxregs (tid, regno)) |
5c44784c JM |
623 | return; |
624 | ||
625 | /* Either our processor or our kernel doesn't support the SSE | |
04cd15b6 MK |
626 | registers, so just write the FP registers in the traditional |
627 | way. */ | |
6ce2ac0b | 628 | store_fpregs (tid, regno); |
5c44784c JM |
629 | return; |
630 | } | |
631 | ||
04cd15b6 | 632 | internal_error ("Got request to store bad register number %d.", regno); |
d4f3574e | 633 | } |
de57eccd | 634 | \f |
6ce2ac0b | 635 | |
de57eccd JM |
636 | /* Interpreting register set info found in core files. */ |
637 | ||
638 | /* Provide registers to GDB from a core file. | |
639 | ||
640 | (We can't use the generic version of this function in | |
641 | core-regset.c, because Linux has *three* different kinds of | |
642 | register set notes. core-regset.c would have to call | |
6ce2ac0b | 643 | supply_fpxregset, which most platforms don't have.) |
de57eccd JM |
644 | |
645 | CORE_REG_SECT points to an array of bytes, which are the contents | |
646 | of a `note' from a core file which BFD thinks might contain | |
647 | register contents. CORE_REG_SIZE is its size. | |
648 | ||
649 | WHICH says which register set corelow suspects this is: | |
04cd15b6 MK |
650 | 0 --- the general-purpose register set, in elf_gregset_t format |
651 | 2 --- the floating-point register set, in elf_fpregset_t format | |
6ce2ac0b | 652 | 3 --- the extended floating-point register set, in elf_fpxregset_t format |
04cd15b6 MK |
653 | |
654 | REG_ADDR isn't used on Linux. */ | |
de57eccd | 655 | |
de57eccd | 656 | static void |
04cd15b6 MK |
657 | fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, |
658 | int which, CORE_ADDR reg_addr) | |
de57eccd | 659 | { |
04cd15b6 MK |
660 | elf_gregset_t gregset; |
661 | elf_fpregset_t fpregset; | |
de57eccd JM |
662 | |
663 | switch (which) | |
664 | { | |
665 | case 0: | |
666 | if (core_reg_size != sizeof (gregset)) | |
04cd15b6 | 667 | warning ("Wrong size gregset in core file."); |
de57eccd JM |
668 | else |
669 | { | |
670 | memcpy (&gregset, core_reg_sect, sizeof (gregset)); | |
671 | supply_gregset (&gregset); | |
672 | } | |
673 | break; | |
674 | ||
675 | case 2: | |
676 | if (core_reg_size != sizeof (fpregset)) | |
04cd15b6 | 677 | warning ("Wrong size fpregset in core file."); |
de57eccd JM |
678 | else |
679 | { | |
680 | memcpy (&fpregset, core_reg_sect, sizeof (fpregset)); | |
681 | supply_fpregset (&fpregset); | |
682 | } | |
683 | break; | |
684 | ||
6ce2ac0b | 685 | #ifdef HAVE_PTRACE_GETFPXREGS |
de57eccd | 686 | { |
6ce2ac0b | 687 | elf_fpxregset_t fpxregset; |
04cd15b6 | 688 | |
de57eccd | 689 | case 3: |
6ce2ac0b MK |
690 | if (core_reg_size != sizeof (fpxregset)) |
691 | warning ("Wrong size fpxregset in core file."); | |
de57eccd JM |
692 | else |
693 | { | |
6ce2ac0b MK |
694 | memcpy (&fpxregset, core_reg_sect, sizeof (fpxregset)); |
695 | supply_fpxregset (&fpxregset); | |
de57eccd JM |
696 | } |
697 | break; | |
698 | } | |
699 | #endif | |
700 | ||
701 | default: | |
702 | /* We've covered all the kinds of registers we know about here, | |
703 | so this must be something we wouldn't know what to do with | |
704 | anyway. Just ignore it. */ | |
705 | break; | |
706 | } | |
707 | } | |
a6abb2c0 | 708 | \f |
6ce2ac0b | 709 | |
a6abb2c0 MK |
710 | /* The instruction for a Linux system call is: |
711 | int $0x80 | |
712 | or 0xcd 0x80. */ | |
713 | ||
714 | static const unsigned char linux_syscall[] = { 0xcd, 0x80 }; | |
715 | ||
716 | #define LINUX_SYSCALL_LEN (sizeof linux_syscall) | |
717 | ||
718 | /* The system call number is stored in the %eax register. */ | |
719 | #define LINUX_SYSCALL_REGNUM 0 /* %eax */ | |
720 | ||
721 | /* We are specifically interested in the sigreturn and rt_sigreturn | |
722 | system calls. */ | |
723 | ||
724 | #ifndef SYS_sigreturn | |
725 | #define SYS_sigreturn 0x77 | |
726 | #endif | |
727 | #ifndef SYS_rt_sigreturn | |
728 | #define SYS_rt_sigreturn 0xad | |
729 | #endif | |
730 | ||
731 | /* Offset to saved processor flags, from <asm/sigcontext.h>. */ | |
732 | #define LINUX_SIGCONTEXT_EFLAGS_OFFSET (64) | |
733 | ||
734 | /* Resume execution of the inferior process. | |
735 | If STEP is nonzero, single-step it. | |
736 | If SIGNAL is nonzero, give it that signal. */ | |
737 | ||
738 | void | |
739 | child_resume (int pid, int step, enum target_signal signal) | |
740 | { | |
741 | int request = PTRACE_CONT; | |
742 | ||
743 | if (pid == -1) | |
744 | /* Resume all threads. */ | |
745 | /* I think this only gets used in the non-threaded case, where "resume | |
746 | all threads" and "resume inferior_pid" are the same. */ | |
747 | pid = inferior_pid; | |
748 | ||
749 | if (step) | |
750 | { | |
751 | CORE_ADDR pc = read_pc_pid (pid); | |
752 | unsigned char buf[LINUX_SYSCALL_LEN]; | |
753 | ||
754 | request = PTRACE_SINGLESTEP; | |
755 | ||
756 | /* Returning from a signal trampoline is done by calling a | |
757 | special system call (sigreturn or rt_sigreturn, see | |
758 | i386-linux-tdep.c for more information). This system call | |
759 | restores the registers that were saved when the signal was | |
760 | raised, including %eflags. That means that single-stepping | |
761 | won't work. Instead, we'll have to modify the signal context | |
762 | that's about to be restored, and set the trace flag there. */ | |
763 | ||
764 | /* First check if PC is at a system call. */ | |
765 | if (read_memory_nobpt (pc, (char *) buf, LINUX_SYSCALL_LEN) == 0 | |
766 | && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0) | |
767 | { | |
768 | int syscall = read_register_pid (LINUX_SYSCALL_REGNUM, pid); | |
769 | ||
770 | /* Then check the system call number. */ | |
771 | if (syscall == SYS_sigreturn || syscall == SYS_rt_sigreturn) | |
772 | { | |
773 | CORE_ADDR sp = read_register (SP_REGNUM); | |
774 | CORE_ADDR addr = sp; | |
775 | unsigned long int eflags; | |
776 | ||
777 | if (syscall == SYS_rt_sigreturn) | |
778 | addr = read_memory_integer (sp + 8, 4) + 20; | |
779 | ||
780 | /* Set the trace flag in the context that's about to be | |
781 | restored. */ | |
782 | addr += LINUX_SIGCONTEXT_EFLAGS_OFFSET; | |
783 | read_memory (addr, (char *) &eflags, 4); | |
784 | eflags |= 0x0100; | |
785 | write_memory (addr, (char *) &eflags, 4); | |
786 | } | |
787 | } | |
788 | } | |
789 | ||
790 | if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1) | |
791 | perror_with_name ("ptrace"); | |
792 | } | |
5c44784c | 793 | \f |
6ce2ac0b | 794 | |
04cd15b6 MK |
795 | /* Register that we are able to handle Linux ELF core file formats. */ |
796 | ||
797 | static struct core_fns linux_elf_core_fns = | |
798 | { | |
799 | bfd_target_elf_flavour, /* core_flavour */ | |
800 | default_check_format, /* check_format */ | |
801 | default_core_sniffer, /* core_sniffer */ | |
802 | fetch_core_registers, /* core_read_registers */ | |
803 | NULL /* next */ | |
804 | }; | |
de57eccd JM |
805 | |
806 | void | |
fba45db2 | 807 | _initialize_i386_linux_nat (void) |
de57eccd | 808 | { |
04cd15b6 | 809 | add_core_fns (&linux_elf_core_fns); |
de57eccd | 810 | } |