Commit | Line | Data |
---|---|---|
d4f3574e SS |
1 | /* Native-dependent code for Linux running on i386's, for GDB. |
2 | ||
3 | This file is part of GDB. | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
18 | ||
19 | #include "defs.h" | |
20 | #include "inferior.h" | |
21 | #include "gdbcore.h" | |
22 | ||
23 | /* For i386_linux_skip_solib_resolver */ | |
24 | #include "symtab.h" | |
25 | #include "frame.h" | |
26 | #include "symfile.h" | |
27 | #include "objfiles.h" | |
28 | ||
29 | #include <sys/ptrace.h> | |
30 | #include <sys/user.h> | |
31 | #include <sys/procfs.h> | |
32 | ||
33 | #ifdef HAVE_SYS_REG_H | |
34 | #include <sys/reg.h> | |
35 | #endif | |
36 | ||
37 | /* This is a duplicate of the table in i386-xdep.c. */ | |
38 | ||
39 | static int regmap[] = | |
40 | { | |
41 | EAX, ECX, EDX, EBX, | |
42 | UESP, EBP, ESI, EDI, | |
43 | EIP, EFL, CS, SS, | |
44 | DS, ES, FS, GS, | |
45 | }; | |
46 | ||
47 | ||
5c44784c JM |
48 | /* Which ptrace request retrieves which registers? |
49 | These apply to the corresponding SET requests as well. */ | |
50 | #define GETREGS_SUPPLIES(regno) \ | |
51 | (0 <= (regno) && (regno) <= 15) | |
52 | #define GETFPREGS_SUPPLIES(regno) \ | |
53 | (FP0_REGNUM <= (regno) && (regno) <= LAST_FPU_CTRL_REGNUM) | |
54 | #define GETXFPREGS_SUPPLIES(regno) \ | |
55 | (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM) | |
56 | ||
57 | /* Does the current host support the GETXFPREGS request? The header | |
58 | file may or may not define it, and even if it is defined, the | |
59 | kernel will return EIO if it's running on a pre-SSE processor. | |
60 | ||
c2d11a7d JM |
61 | PTRACE_GETXFPREGS is a Cygnus invention, since we wrote our own |
62 | Linux kernel patch for SSE support. That patch may or may not | |
63 | actually make it into the official distribution. If you find that | |
64 | years have gone by since this stuff was added, and Linux isn't | |
65 | using PTRACE_GETXFPREGS, that means that our patch didn't make it, | |
66 | and you can delete this, and the related code. | |
67 | ||
5c44784c JM |
68 | My instinct is to attach this to some architecture- or |
69 | target-specific data structure, but really, a particular GDB | |
70 | process can only run on top of one kernel at a time. So it's okay | |
71 | for this to be a simple variable. */ | |
72 | int have_ptrace_getxfpregs = | |
73 | #ifdef HAVE_PTRACE_GETXFPREGS | |
74 | 1 | |
75 | #else | |
76 | 0 | |
77 | #endif | |
78 | ; | |
79 | ||
80 | ||
81 | \f | |
82 | /* Transfering the general registers between GDB, inferiors and core files. */ | |
83 | ||
917317f4 JM |
84 | /* Given a pointer to a general register set in struct user format |
85 | (gregset_t *), unpack the register contents and supply them as | |
86 | gdb's idea of the current register values. */ | |
d4f3574e SS |
87 | void |
88 | supply_gregset (gregsetp) | |
89 | gregset_t *gregsetp; | |
90 | { | |
91 | register int regi; | |
92 | register greg_t *regp = (greg_t *) gregsetp; | |
93 | ||
917317f4 | 94 | for (regi = 0; regi < NUM_GREGS; regi++) |
d4f3574e SS |
95 | { |
96 | supply_register (regi, (char *) (regp + regmap[regi])); | |
97 | } | |
98 | } | |
99 | ||
5c44784c | 100 | |
917317f4 JM |
101 | /* Fill in a gregset_t object with selected data from a gdb-format |
102 | register file. | |
103 | - GREGSETP points to the gregset_t object to be filled. | |
104 | - GDB_REGS points to the GDB-style register file providing the data. | |
105 | - VALID is an array indicating which registers in GDB_REGS are | |
106 | valid; the parts of *GREGSETP that would hold registers marked | |
107 | invalid in GDB_REGS are left unchanged. If VALID is zero, all | |
108 | registers are assumed to be valid. */ | |
d4f3574e | 109 | void |
917317f4 JM |
110 | convert_to_gregset (gregset_t *gregsetp, |
111 | char *gdb_regs, | |
112 | signed char *valid) | |
d4f3574e SS |
113 | { |
114 | int regi; | |
115 | register greg_t *regp = (greg_t *) gregsetp; | |
116 | ||
917317f4 JM |
117 | for (regi = 0; regi < NUM_GREGS; regi++) |
118 | if (! valid || valid[regi]) | |
119 | *(regp + regmap[regi]) = * (int *) ®isters[REGISTER_BYTE (regi)]; | |
120 | } | |
121 | ||
5c44784c JM |
122 | |
123 | /* Store GDB's value for REGNO in *GREGSETP. If REGNO is -1, do all | |
124 | of them. */ | |
917317f4 JM |
125 | void |
126 | fill_gregset (gregset_t *gregsetp, | |
127 | int regno) | |
128 | { | |
129 | if (regno == -1) | |
130 | convert_to_gregset (gregsetp, registers, 0); | |
c2d11a7d | 131 | else if (regno >= 0 && regno < NUM_GREGS) |
d4f3574e | 132 | { |
917317f4 JM |
133 | signed char valid[NUM_GREGS]; |
134 | memset (valid, 0, sizeof (valid)); | |
135 | valid[regno] = 1; | |
136 | convert_to_gregset (gregsetp, valid, valid); | |
d4f3574e SS |
137 | } |
138 | } | |
139 | ||
140 | ||
5c44784c JM |
141 | /* Read the general registers from the process, and store them |
142 | in registers[]. */ | |
143 | static void | |
144 | fetch_regs () | |
145 | { | |
146 | int ret, regno; | |
147 | gregset_t buf; | |
148 | ||
149 | ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int) &buf); | |
150 | if (ret < 0) | |
151 | { | |
152 | warning ("Couldn't get registers"); | |
153 | return; | |
154 | } | |
155 | ||
156 | supply_gregset (&buf); | |
157 | } | |
158 | ||
159 | ||
160 | /* Set the inferior's general registers to the values in registers[] | |
161 | --- but only those registers marked as valid. */ | |
162 | static void | |
163 | store_regs () | |
164 | { | |
165 | int ret, regno; | |
166 | gregset_t buf; | |
167 | ||
168 | ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int) &buf); | |
169 | if (ret < 0) | |
170 | { | |
171 | warning ("Couldn't get registers"); | |
172 | return; | |
173 | } | |
174 | ||
175 | convert_to_gregset (&buf, registers, register_valid); | |
176 | ||
177 | ret = ptrace (PTRACE_SETREGS, inferior_pid, 0, (int)buf); | |
178 | if (ret < 0) | |
179 | { | |
180 | warning ("Couldn't write registers"); | |
181 | return; | |
182 | } | |
183 | } | |
184 | ||
185 | ||
186 | \f | |
187 | /* Transfering floating-point registers between GDB, inferiors and cores. */ | |
188 | ||
189 | /* What is the address of st(N) within the fpregset_t structure F? */ | |
190 | #define FPREGSET_T_FPREG_ADDR(f, n) \ | |
917317f4 | 191 | ((char *) &(f)->st_space + (n) * 10) |
d4f3574e | 192 | |
917317f4 JM |
193 | /* Fill GDB's register file with the floating-point register values in |
194 | *FPREGSETP. */ | |
d4f3574e | 195 | void |
917317f4 | 196 | supply_fpregset (fpregset_t *fpregsetp) |
d4f3574e | 197 | { |
917317f4 JM |
198 | int i; |
199 | ||
200 | /* Supply the floating-point registers. */ | |
201 | for (i = 0; i < 8; i++) | |
5c44784c | 202 | supply_register (FP0_REGNUM + i, FPREGSET_T_FPREG_ADDR (fpregsetp, i)); |
917317f4 JM |
203 | |
204 | supply_register (FCTRL_REGNUM, (char *) &fpregsetp->cwd); | |
205 | supply_register (FSTAT_REGNUM, (char *) &fpregsetp->swd); | |
206 | supply_register (FTAG_REGNUM, (char *) &fpregsetp->twd); | |
207 | supply_register (FCOFF_REGNUM, (char *) &fpregsetp->fip); | |
208 | supply_register (FDS_REGNUM, (char *) &fpregsetp->fos); | |
209 | supply_register (FDOFF_REGNUM, (char *) &fpregsetp->foo); | |
210 | ||
211 | /* Extract the code segment and opcode from the "fcs" member. */ | |
212 | { | |
213 | long l; | |
214 | ||
215 | l = fpregsetp->fcs & 0xffff; | |
216 | supply_register (FCS_REGNUM, (char *) &l); | |
217 | ||
218 | l = (fpregsetp->fcs >> 16) & ((1 << 11) - 1); | |
219 | supply_register (FOP_REGNUM, (char *) &l); | |
220 | } | |
d4f3574e SS |
221 | } |
222 | ||
d4f3574e | 223 | |
917317f4 JM |
224 | /* Fill in an fpregset_t structure with selected data from a |
225 | gdb-format register file. | |
226 | - FPREGSETP points to the structure to be filled. | |
227 | - GDB_REGS points to the GDB-style register file providing the data. | |
228 | - VALID is an array indicating which registers in GDB_REGS are | |
229 | valid; the parts of *FPREGSETP that would hold registers marked | |
230 | invalid in GDB_REGS are left unchanged. If VALID is zero, all | |
231 | registers are assumed to be valid. */ | |
d4f3574e | 232 | void |
917317f4 JM |
233 | convert_to_fpregset (fpregset_t *fpregsetp, |
234 | char *gdb_regs, | |
235 | signed char *valid) | |
d4f3574e | 236 | { |
917317f4 JM |
237 | int i; |
238 | ||
239 | /* Fill in the floating-point registers. */ | |
240 | for (i = 0; i < 8; i++) | |
241 | if (!valid || valid[i]) | |
5c44784c | 242 | memcpy (FPREGSET_T_FPREG_ADDR (fpregsetp, i), |
917317f4 JM |
243 | ®isters[REGISTER_BYTE (FP0_REGNUM + i)], |
244 | REGISTER_RAW_SIZE(FP0_REGNUM + i)); | |
245 | ||
246 | #define fill(MEMBER, REGNO) \ | |
247 | if (! valid || valid[(REGNO)]) \ | |
248 | memcpy (&fpregsetp->MEMBER, ®isters[REGISTER_BYTE (REGNO)], \ | |
249 | sizeof (fpregsetp->MEMBER)) | |
250 | ||
251 | fill (cwd, FCTRL_REGNUM); | |
252 | fill (swd, FSTAT_REGNUM); | |
253 | fill (twd, FTAG_REGNUM); | |
254 | fill (fip, FCOFF_REGNUM); | |
255 | fill (foo, FDOFF_REGNUM); | |
256 | fill (fos, FDS_REGNUM); | |
257 | ||
258 | #undef fill | |
259 | ||
260 | if (! valid || valid[FCS_REGNUM]) | |
261 | fpregsetp->fcs | |
262 | = ((fpregsetp->fcs & ~0xffff) | |
263 | | (* (int *) ®isters[REGISTER_BYTE (FCS_REGNUM)] & 0xffff)); | |
264 | ||
265 | if (! valid || valid[FOP_REGNUM]) | |
266 | fpregsetp->fcs | |
267 | = ((fpregsetp->fcs & 0xffff) | |
268 | | ((*(int *) ®isters[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1)) | |
269 | << 16)); | |
270 | } | |
d4f3574e | 271 | |
917317f4 JM |
272 | |
273 | /* Given a pointer to a floating point register set in (fpregset_t *) | |
274 | format, update all of the registers from gdb's idea of the current | |
275 | floating point register set. */ | |
276 | ||
277 | void | |
278 | fill_fpregset (fpregset_t *fpregsetp, | |
279 | int regno) | |
280 | { | |
281 | convert_to_fpregset (fpregsetp, registers, 0); | |
d4f3574e SS |
282 | } |
283 | ||
917317f4 JM |
284 | |
285 | /* Get the whole floating point state of the process and store the | |
286 | floating point stack into registers[]. */ | |
d4f3574e | 287 | static void |
917317f4 | 288 | fetch_fpregs () |
d4f3574e SS |
289 | { |
290 | int ret, regno; | |
917317f4 | 291 | fpregset_t buf; |
d4f3574e | 292 | |
917317f4 JM |
293 | ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int) &buf); |
294 | if (ret < 0) | |
d4f3574e SS |
295 | { |
296 | warning ("Couldn't get floating point status"); | |
297 | return; | |
298 | } | |
299 | ||
917317f4 JM |
300 | /* ptrace fills an fpregset_t, so we can use the same function we do |
301 | for core files. */ | |
302 | supply_fpregset (&buf); | |
d4f3574e SS |
303 | } |
304 | ||
305 | ||
917317f4 JM |
306 | /* Set the inferior's floating-point registers to the values in |
307 | registers[] --- but only those registers marked valid. */ | |
d4f3574e | 308 | static void |
917317f4 | 309 | store_fpregs () |
d4f3574e | 310 | { |
917317f4 JM |
311 | int ret; |
312 | fpregset_t buf; | |
d4f3574e | 313 | |
917317f4 JM |
314 | ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int) &buf); |
315 | if (ret < 0) | |
d4f3574e SS |
316 | { |
317 | warning ("Couldn't get floating point status"); | |
318 | return; | |
319 | } | |
320 | ||
917317f4 | 321 | convert_to_fpregset (&buf, registers, register_valid); |
d4f3574e | 322 | |
917317f4 JM |
323 | ret = ptrace (PTRACE_SETFPREGS, inferior_pid, 0, (int) &buf); |
324 | if (ret < 0) | |
d4f3574e SS |
325 | { |
326 | warning ("Couldn't write floating point status"); | |
327 | return; | |
328 | } | |
d4f3574e SS |
329 | } |
330 | ||
5c44784c JM |
331 | \f |
332 | /* Transfering floating-point and SSE registers to and from GDB. */ | |
d4f3574e | 333 | |
5c44784c | 334 | |
11cf8741 JM |
335 | /* PTRACE_GETXFPREGS is a Cygnus invention, since we wrote our own |
336 | Linux kernel patch for SSE support. That patch may or may not | |
337 | actually make it into the official distribution. If you find that | |
338 | years have gone by since this code was added, and Linux isn't using | |
339 | PTRACE_GETXFPREGS, that means that our patch didn't make it, and | |
340 | you can delete this code. */ | |
341 | ||
5c44784c | 342 | #ifdef HAVE_PTRACE_GETXFPREGS |
d4f3574e | 343 | static void |
5c44784c | 344 | supply_xfpregset (struct user_xfpregs_struct *xfpregs) |
d4f3574e | 345 | { |
5c44784c | 346 | int reg; |
d4f3574e | 347 | |
5c44784c JM |
348 | /* Supply the floating-point registers. */ |
349 | for (reg = 0; reg < 8; reg++) | |
350 | supply_register (FP0_REGNUM + reg, (char *) &xfpregs->st_space[reg]); | |
351 | ||
352 | { | |
353 | supply_register (FCTRL_REGNUM, (char *) &xfpregs->cwd); | |
354 | supply_register (FSTAT_REGNUM, (char *) &xfpregs->swd); | |
355 | supply_register (FTAG_REGNUM, (char *) &xfpregs->twd); | |
356 | supply_register (FCOFF_REGNUM, (char *) &xfpregs->fip); | |
357 | supply_register (FDS_REGNUM, (char *) &xfpregs->fos); | |
358 | supply_register (FDOFF_REGNUM, (char *) &xfpregs->foo); | |
359 | ||
360 | /* Extract the code segment and opcode from the "fcs" member. */ | |
d4f3574e | 361 | { |
5c44784c JM |
362 | long l; |
363 | ||
364 | l = xfpregs->fcs & 0xffff; | |
365 | supply_register (FCS_REGNUM, (char *) &l); | |
366 | ||
367 | l = (xfpregs->fcs >> 16) & ((1 << 11) - 1); | |
368 | supply_register (FOP_REGNUM, (char *) &l); | |
d4f3574e | 369 | } |
5c44784c | 370 | } |
d4f3574e | 371 | |
5c44784c JM |
372 | /* Supply the SSE registers. */ |
373 | for (reg = 0; reg < 8; reg++) | |
374 | supply_register (XMM0_REGNUM + reg, (char *) &xfpregs->xmm_space[reg]); | |
375 | supply_register (MXCSR_REGNUM, (char *) &xfpregs->mxcsr); | |
d4f3574e SS |
376 | } |
377 | ||
378 | ||
d4f3574e | 379 | static void |
5c44784c JM |
380 | convert_to_xfpregset (struct user_xfpregs_struct *xfpregs, |
381 | char *gdb_regs, | |
382 | signed char *valid) | |
d4f3574e | 383 | { |
5c44784c | 384 | int reg; |
d4f3574e | 385 | |
5c44784c JM |
386 | /* Fill in the floating-point registers. */ |
387 | for (reg = 0; reg < 8; reg++) | |
388 | if (!valid || valid[reg]) | |
389 | memcpy (&xfpregs->st_space[reg], | |
390 | ®isters[REGISTER_BYTE (FP0_REGNUM + reg)], | |
391 | REGISTER_RAW_SIZE(FP0_REGNUM + reg)); | |
392 | ||
393 | #define fill(MEMBER, REGNO) \ | |
394 | if (! valid || valid[(REGNO)]) \ | |
395 | memcpy (&xfpregs->MEMBER, ®isters[REGISTER_BYTE (REGNO)], \ | |
396 | sizeof (xfpregs->MEMBER)) | |
397 | ||
398 | fill (cwd, FCTRL_REGNUM); | |
399 | fill (swd, FSTAT_REGNUM); | |
400 | fill (twd, FTAG_REGNUM); | |
401 | fill (fip, FCOFF_REGNUM); | |
402 | fill (foo, FDOFF_REGNUM); | |
403 | fill (fos, FDS_REGNUM); | |
404 | ||
405 | #undef fill | |
406 | ||
407 | if (! valid || valid[FCS_REGNUM]) | |
408 | xfpregs->fcs | |
409 | = ((xfpregs->fcs & ~0xffff) | |
410 | | (* (int *) ®isters[REGISTER_BYTE (FCS_REGNUM)] & 0xffff)); | |
411 | ||
412 | if (! valid || valid[FOP_REGNUM]) | |
413 | xfpregs->fcs | |
414 | = ((xfpregs->fcs & 0xffff) | |
415 | | ((*(int *) ®isters[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1)) | |
416 | << 16)); | |
417 | ||
418 | /* Fill in the XMM registers. */ | |
419 | for (reg = 0; reg < 8; reg++) | |
420 | if (! valid || valid[reg]) | |
421 | memcpy (&xfpregs->xmm_space[reg], | |
422 | ®isters[REGISTER_BYTE (XMM0_REGNUM + reg)], | |
423 | REGISTER_RAW_SIZE (XMM0_REGNUM + reg)); | |
424 | } | |
425 | ||
426 | ||
427 | /* Make a PTRACE_GETXFPREGS request, and supply all the register | |
428 | values that yields to GDB. */ | |
429 | static int | |
430 | fetch_xfpregs () | |
431 | { | |
432 | int ret; | |
433 | struct user_xfpregs_struct xfpregs; | |
434 | ||
435 | if (! have_ptrace_getxfpregs) | |
436 | return 0; | |
437 | ||
438 | ret = ptrace (PTRACE_GETXFPREGS, inferior_pid, 0, &xfpregs); | |
439 | if (ret == -1) | |
d4f3574e | 440 | { |
5c44784c JM |
441 | if (errno == EIO) |
442 | { | |
443 | have_ptrace_getxfpregs = 0; | |
444 | return 0; | |
445 | } | |
446 | ||
447 | warning ("couldn't read floating-point and SSE registers."); | |
448 | return 0; | |
d4f3574e SS |
449 | } |
450 | ||
5c44784c JM |
451 | supply_xfpregset (&xfpregs); |
452 | return 1; | |
453 | } | |
d4f3574e | 454 | |
5c44784c JM |
455 | |
456 | /* Send all the valid register values in GDB's register file covered | |
457 | by the PTRACE_SETXFPREGS request to the inferior. */ | |
458 | static int | |
459 | store_xfpregs () | |
460 | { | |
461 | int ret; | |
462 | struct user_xfpregs_struct xfpregs; | |
463 | ||
464 | if (! have_ptrace_getxfpregs) | |
465 | return 0; | |
466 | ||
467 | ret = ptrace (PTRACE_GETXFPREGS, inferior_pid, 0, &xfpregs); | |
468 | if (ret == -1) | |
d4f3574e | 469 | { |
5c44784c JM |
470 | if (errno == EIO) |
471 | { | |
472 | have_ptrace_getxfpregs = 0; | |
473 | return 0; | |
474 | } | |
475 | ||
476 | warning ("couldn't read floating-point and SSE registers."); | |
477 | return 0; | |
478 | } | |
479 | ||
480 | convert_to_xfpregset (&xfpregs, registers, register_valid); | |
481 | ||
482 | if (ptrace (PTRACE_SETXFPREGS, inferior_pid, 0, &xfpregs) < 0) | |
483 | { | |
484 | warning ("Couldn't write floating-point and SSE registers."); | |
485 | return 0; | |
d4f3574e | 486 | } |
5c44784c JM |
487 | |
488 | return 1; | |
489 | } | |
490 | ||
491 | ||
492 | /* Fill the XMM registers in the register file with dummy values. For | |
493 | cases where we don't have access to the XMM registers. I think | |
494 | this is cleaner than printing a warning. For a cleaner solution, | |
495 | we should gdbarchify the i386 family. */ | |
496 | static void | |
497 | dummy_sse_values () | |
498 | { | |
499 | /* C doesn't have a syntax for NaN's, so write it out as an array of | |
500 | longs. */ | |
501 | static long dummy[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; | |
502 | static long mxcsr = 0x1f80; | |
503 | int reg; | |
504 | ||
505 | for (reg = 0; reg < 8; reg++) | |
506 | supply_register (XMM0_REGNUM + reg, (char *) dummy); | |
507 | supply_register (MXCSR_REGNUM, (char *) &mxcsr); | |
d4f3574e SS |
508 | } |
509 | ||
5c44784c JM |
510 | #else |
511 | ||
512 | /* Stub versions of the above routines, for systems that don't have | |
513 | PTRACE_GETXFPREGS. */ | |
514 | static int store_xfpregs () { return 0; } | |
515 | static int fetch_xfpregs () { return 0; } | |
516 | static void dummy_sse_values () {} | |
517 | ||
518 | #endif | |
519 | ||
520 | \f | |
521 | /* Transferring arbitrary registers between GDB and inferior. */ | |
d4f3574e SS |
522 | |
523 | /* Fetch registers from the child process. | |
524 | Fetch all if regno == -1, otherwise fetch all ordinary | |
525 | registers or all floating point registers depending | |
526 | upon the value of regno. */ | |
527 | ||
528 | void | |
917317f4 | 529 | fetch_inferior_registers (int regno) |
d4f3574e | 530 | { |
5c44784c JM |
531 | /* Use the xfpregs requests whenever possible, since they transfer |
532 | more registers in one system call, and we'll cache the results. | |
533 | But remember that fetch_xfpregs can fail, and return zero. */ | |
534 | if (regno == -1) | |
535 | { | |
536 | fetch_regs (); | |
537 | if (fetch_xfpregs ()) | |
538 | return; | |
539 | fetch_fpregs (); | |
540 | return; | |
541 | } | |
d4f3574e | 542 | |
5c44784c JM |
543 | if (GETREGS_SUPPLIES (regno)) |
544 | { | |
545 | fetch_regs (); | |
546 | return; | |
547 | } | |
548 | ||
549 | if (GETXFPREGS_SUPPLIES (regno)) | |
550 | { | |
551 | if (fetch_xfpregs ()) | |
552 | return; | |
553 | ||
554 | /* Either our processor or our kernel doesn't support the SSE | |
555 | registers, so read the FP registers in the traditional way, | |
556 | and fill the SSE registers with dummy values. It would be | |
557 | more graceful to handle differences in the register set using | |
558 | gdbarch. Until then, this will at least make things work | |
559 | plausibly. */ | |
560 | fetch_fpregs (); | |
561 | dummy_sse_values (); | |
562 | return; | |
563 | } | |
564 | ||
565 | internal_error ("i386-linux-nat.c (fetch_inferior_registers): " | |
566 | "got request for bad register number %d", regno); | |
d4f3574e SS |
567 | } |
568 | ||
569 | ||
570 | /* Store our register values back into the inferior. | |
571 | If REGNO is -1, do this for all registers. | |
572 | Otherwise, REGNO specifies which register, which | |
573 | then determines whether we store all ordinary | |
574 | registers or all of the floating point registers. */ | |
575 | ||
576 | void | |
577 | store_inferior_registers (regno) | |
578 | int regno; | |
579 | { | |
5c44784c JM |
580 | /* Use the xfpregs requests whenever possible, since they transfer |
581 | more registers in one system call. But remember that | |
582 | fetch_xfpregs can fail, and return zero. */ | |
583 | if (regno == -1) | |
584 | { | |
585 | store_regs (); | |
586 | if (store_xfpregs ()) | |
587 | return; | |
588 | store_fpregs (); | |
589 | return; | |
590 | } | |
d4f3574e | 591 | |
5c44784c JM |
592 | if (GETREGS_SUPPLIES (regno)) |
593 | { | |
594 | store_regs (); | |
595 | return; | |
596 | } | |
597 | ||
598 | if (GETXFPREGS_SUPPLIES (regno)) | |
599 | { | |
600 | if (store_xfpregs ()) | |
601 | return; | |
602 | ||
603 | /* Either our processor or our kernel doesn't support the SSE | |
604 | registers, so just write the FP registers in the traditional way. */ | |
605 | store_fpregs (); | |
606 | return; | |
607 | } | |
608 | ||
609 | internal_error ("i386-linux-nat.c (store_inferior_registers): " | |
610 | "got request to store bad register number %d", regno); | |
d4f3574e SS |
611 | } |
612 | ||
613 | ||
5c44784c JM |
614 | \f |
615 | /* Calling functions in shared libraries. */ | |
616 | ||
d4f3574e SS |
617 | /* Find the minimal symbol named NAME, and return both the minsym |
618 | struct and its objfile. This probably ought to be in minsym.c, but | |
619 | everything there is trying to deal with things like C++ and | |
620 | SOFUN_ADDRESS_MAYBE_TURQUOISE, ... Since this is so simple, it may | |
621 | be considered too special-purpose for general consumption. */ | |
622 | ||
623 | static struct minimal_symbol * | |
624 | find_minsym_and_objfile (char *name, struct objfile **objfile_p) | |
625 | { | |
626 | struct objfile *objfile; | |
627 | ||
628 | ALL_OBJFILES (objfile) | |
629 | { | |
630 | struct minimal_symbol *msym; | |
631 | ||
632 | ALL_OBJFILE_MSYMBOLS (objfile, msym) | |
633 | { | |
634 | if (SYMBOL_NAME (msym) | |
635 | && STREQ (SYMBOL_NAME (msym), name)) | |
636 | { | |
637 | *objfile_p = objfile; | |
638 | return msym; | |
639 | } | |
640 | } | |
641 | } | |
642 | ||
643 | return 0; | |
644 | } | |
645 | ||
646 | ||
647 | static CORE_ADDR | |
648 | skip_hurd_resolver (CORE_ADDR pc) | |
649 | { | |
650 | /* The HURD dynamic linker is part of the GNU C library, so many | |
651 | GNU/Linux distributions use it. (All ELF versions, as far as I | |
652 | know.) An unresolved PLT entry points to "_dl_runtime_resolve", | |
653 | which calls "fixup" to patch the PLT, and then passes control to | |
654 | the function. | |
655 | ||
656 | We look for the symbol `_dl_runtime_resolve', and find `fixup' in | |
657 | the same objfile. If we are at the entry point of `fixup', then | |
658 | we set a breakpoint at the return address (at the top of the | |
659 | stack), and continue. | |
660 | ||
661 | It's kind of gross to do all these checks every time we're | |
662 | called, since they don't change once the executable has gotten | |
663 | started. But this is only a temporary hack --- upcoming versions | |
664 | of Linux will provide a portable, efficient interface for | |
665 | debugging programs that use shared libraries. */ | |
666 | ||
667 | struct objfile *objfile; | |
668 | struct minimal_symbol *resolver | |
669 | = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile); | |
670 | ||
671 | if (resolver) | |
672 | { | |
673 | struct minimal_symbol *fixup | |
674 | = lookup_minimal_symbol ("fixup", 0, objfile); | |
675 | ||
676 | if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc) | |
677 | return (SAVED_PC_AFTER_CALL (get_current_frame ())); | |
678 | } | |
679 | ||
680 | return 0; | |
681 | } | |
682 | ||
683 | ||
684 | /* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c. | |
685 | This function: | |
686 | 1) decides whether a PLT has sent us into the linker to resolve | |
687 | a function reference, and | |
688 | 2) if so, tells us where to set a temporary breakpoint that will | |
689 | trigger when the dynamic linker is done. */ | |
690 | ||
691 | CORE_ADDR | |
692 | i386_linux_skip_solib_resolver (CORE_ADDR pc) | |
693 | { | |
694 | CORE_ADDR result; | |
695 | ||
696 | /* Plug in functions for other kinds of resolvers here. */ | |
697 | result = skip_hurd_resolver (pc); | |
698 | if (result) | |
699 | return result; | |
700 | ||
701 | return 0; | |
702 | } |