]>
Commit | Line | Data |
---|---|---|
1 | /* Native-dependent code for GNU/Linux i386. | |
2 | ||
3 | Copyright (C) 1999-2025 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GDB. | |
6 | ||
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 | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
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. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "inferior.h" | |
21 | #include "gdbcore.h" | |
22 | #include "regcache.h" | |
23 | #include "elf/common.h" | |
24 | #include "nat/gdb_ptrace.h" | |
25 | #include <sys/uio.h> | |
26 | #include "gregset.h" | |
27 | #include "gdb_proc_service.h" | |
28 | ||
29 | #include "nat/i386-linux.h" | |
30 | #include "i387-tdep.h" | |
31 | #include "i386-tdep.h" | |
32 | #include "i386-linux-tdep.h" | |
33 | #include "gdbsupport/x86-xstate.h" | |
34 | ||
35 | #include "x86-linux-nat.h" | |
36 | #include "nat/linux-ptrace.h" | |
37 | #include "inf-ptrace.h" | |
38 | ||
39 | struct i386_linux_nat_target final : public x86_linux_nat_target | |
40 | { | |
41 | /* Add our register access methods. */ | |
42 | void fetch_registers (struct regcache *, int) override; | |
43 | void store_registers (struct regcache *, int) override; | |
44 | ||
45 | /* Override the default ptrace resume method. */ | |
46 | void low_resume (ptid_t ptid, int step, enum gdb_signal sig) override; | |
47 | }; | |
48 | ||
49 | static i386_linux_nat_target the_i386_linux_nat_target; | |
50 | ||
51 | /* The register sets used in GNU/Linux ELF core-dumps are identical to | |
52 | the register sets in `struct user' that is used for a.out | |
53 | core-dumps, and is also used by `ptrace'. The corresponding types | |
54 | are `elf_gregset_t' for the general-purpose registers (with | |
55 | `elf_greg_t' the type of a single GP register) and `elf_fpregset_t' | |
56 | for the floating-point registers. | |
57 | ||
58 | Those types used to be available under the names `gregset_t' and | |
59 | `fpregset_t' too, and this file used those names in the past. But | |
60 | those names are now used for the register sets used in the | |
61 | `mcontext_t' type, and have a different size and layout. */ | |
62 | ||
63 | /* Which ptrace request retrieves which registers? | |
64 | These apply to the corresponding SET requests as well. */ | |
65 | ||
66 | #define GETREGS_SUPPLIES(regno) \ | |
67 | ((0 <= (regno) && (regno) <= 15) || (regno) == I386_LINUX_ORIG_EAX_REGNUM) | |
68 | ||
69 | #define GETFPXREGS_SUPPLIES(regno) \ | |
70 | (I386_ST0_REGNUM <= (regno) && (regno) < I386_SSE_NUM_REGS) | |
71 | ||
72 | #define GETXSTATEREGS_SUPPLIES(regno) \ | |
73 | (I386_ST0_REGNUM <= (regno) && (regno) < I386_PKEYS_NUM_REGS) | |
74 | ||
75 | /* Does the current host support the GETREGS request? */ | |
76 | int have_ptrace_getregs = | |
77 | #ifdef HAVE_PTRACE_GETREGS | |
78 | 1 | |
79 | #else | |
80 | 0 | |
81 | #endif | |
82 | ; | |
83 | \f | |
84 | ||
85 | /* Accessing registers through the U area, one at a time. */ | |
86 | ||
87 | /* Fetch one register. */ | |
88 | ||
89 | static void | |
90 | fetch_register (struct regcache *regcache, int regno) | |
91 | { | |
92 | pid_t tid; | |
93 | int val; | |
94 | ||
95 | gdb_assert (!have_ptrace_getregs); | |
96 | if (i386_linux_gregset_reg_offset[regno] == -1) | |
97 | { | |
98 | regcache->raw_supply (regno, NULL); | |
99 | return; | |
100 | } | |
101 | ||
102 | tid = get_ptrace_pid (regcache->ptid ()); | |
103 | ||
104 | errno = 0; | |
105 | val = ptrace (PTRACE_PEEKUSER, tid, | |
106 | i386_linux_gregset_reg_offset[regno], 0); | |
107 | if (errno != 0) | |
108 | error (_("Couldn't read register %s (#%d): %s."), | |
109 | gdbarch_register_name (regcache->arch (), regno), | |
110 | regno, safe_strerror (errno)); | |
111 | ||
112 | regcache->raw_supply (regno, &val); | |
113 | } | |
114 | ||
115 | /* Store one register. */ | |
116 | ||
117 | static void | |
118 | store_register (const struct regcache *regcache, int regno) | |
119 | { | |
120 | pid_t tid; | |
121 | int val; | |
122 | ||
123 | gdb_assert (!have_ptrace_getregs); | |
124 | if (i386_linux_gregset_reg_offset[regno] == -1) | |
125 | return; | |
126 | ||
127 | tid = get_ptrace_pid (regcache->ptid ()); | |
128 | ||
129 | errno = 0; | |
130 | regcache->raw_collect (regno, &val); | |
131 | ptrace (PTRACE_POKEUSER, tid, | |
132 | i386_linux_gregset_reg_offset[regno], val); | |
133 | if (errno != 0) | |
134 | error (_("Couldn't write register %s (#%d): %s."), | |
135 | gdbarch_register_name (regcache->arch (), regno), | |
136 | regno, safe_strerror (errno)); | |
137 | } | |
138 | \f | |
139 | ||
140 | /* Transferring the general-purpose registers between GDB, inferiors | |
141 | and core files. */ | |
142 | ||
143 | /* Fill GDB's register array with the general-purpose register values | |
144 | in *GREGSETP. */ | |
145 | ||
146 | void | |
147 | supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp) | |
148 | { | |
149 | const gdb_byte *regp = (const gdb_byte *) gregsetp; | |
150 | int i; | |
151 | ||
152 | for (i = 0; i < I386_NUM_GREGS; i++) | |
153 | regcache->raw_supply (i, regp + i386_linux_gregset_reg_offset[i]); | |
154 | ||
155 | if (I386_LINUX_ORIG_EAX_REGNUM | |
156 | < gdbarch_num_regs (regcache->arch ())) | |
157 | regcache->raw_supply | |
158 | (I386_LINUX_ORIG_EAX_REGNUM, | |
159 | regp + i386_linux_gregset_reg_offset[I386_LINUX_ORIG_EAX_REGNUM]); | |
160 | } | |
161 | ||
162 | /* Fill register REGNO (if it is a general-purpose register) in | |
163 | *GREGSETPS with the value in GDB's register array. If REGNO is -1, | |
164 | do this for all registers. */ | |
165 | ||
166 | void | |
167 | fill_gregset (const struct regcache *regcache, | |
168 | elf_gregset_t *gregsetp, int regno) | |
169 | { | |
170 | gdb_byte *regp = (gdb_byte *) gregsetp; | |
171 | int i; | |
172 | ||
173 | for (i = 0; i < I386_NUM_GREGS; i++) | |
174 | if (regno == -1 || regno == i) | |
175 | regcache->raw_collect (i, regp + i386_linux_gregset_reg_offset[i]); | |
176 | ||
177 | if ((regno == -1 || regno == I386_LINUX_ORIG_EAX_REGNUM) | |
178 | && I386_LINUX_ORIG_EAX_REGNUM | |
179 | < gdbarch_num_regs (regcache->arch ())) | |
180 | regcache->raw_collect | |
181 | (I386_LINUX_ORIG_EAX_REGNUM, | |
182 | regp + i386_linux_gregset_reg_offset[I386_LINUX_ORIG_EAX_REGNUM]); | |
183 | } | |
184 | ||
185 | #ifdef HAVE_PTRACE_GETREGS | |
186 | ||
187 | /* Fetch all general-purpose registers from process/thread TID and | |
188 | store their values in GDB's register array. */ | |
189 | ||
190 | static void | |
191 | fetch_regs (struct regcache *regcache, int tid) | |
192 | { | |
193 | elf_gregset_t regs; | |
194 | elf_gregset_t *regs_p = ®s; | |
195 | ||
196 | if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) | |
197 | { | |
198 | if (errno == EIO) | |
199 | { | |
200 | /* The kernel we're running on doesn't support the GETREGS | |
201 | request. Reset `have_ptrace_getregs'. */ | |
202 | have_ptrace_getregs = 0; | |
203 | return; | |
204 | } | |
205 | ||
206 | perror_with_name (_("Couldn't get registers")); | |
207 | } | |
208 | ||
209 | supply_gregset (regcache, (const elf_gregset_t *) regs_p); | |
210 | } | |
211 | ||
212 | /* Store all valid general-purpose registers in GDB's register array | |
213 | into the process/thread specified by TID. */ | |
214 | ||
215 | static void | |
216 | store_regs (const struct regcache *regcache, int tid, int regno) | |
217 | { | |
218 | elf_gregset_t regs; | |
219 | ||
220 | if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) | |
221 | perror_with_name (_("Couldn't get registers")); | |
222 | ||
223 | fill_gregset (regcache, ®s, regno); | |
224 | ||
225 | if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) | |
226 | perror_with_name (_("Couldn't write registers")); | |
227 | } | |
228 | ||
229 | #else | |
230 | ||
231 | static void fetch_regs (struct regcache *regcache, int tid) {} | |
232 | static void store_regs (const struct regcache *regcache, int tid, int regno) {} | |
233 | ||
234 | #endif | |
235 | \f | |
236 | ||
237 | /* Transferring floating-point registers between GDB, inferiors and cores. */ | |
238 | ||
239 | /* Fill GDB's register array with the floating-point register values in | |
240 | *FPREGSETP. */ | |
241 | ||
242 | void | |
243 | supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp) | |
244 | { | |
245 | i387_supply_fsave (regcache, -1, fpregsetp); | |
246 | } | |
247 | ||
248 | /* Fill register REGNO (if it is a floating-point register) in | |
249 | *FPREGSETP with the value in GDB's register array. If REGNO is -1, | |
250 | do this for all registers. */ | |
251 | ||
252 | void | |
253 | fill_fpregset (const struct regcache *regcache, | |
254 | elf_fpregset_t *fpregsetp, int regno) | |
255 | { | |
256 | i387_collect_fsave (regcache, regno, fpregsetp); | |
257 | } | |
258 | ||
259 | #ifdef HAVE_PTRACE_GETREGS | |
260 | ||
261 | /* Fetch all floating-point registers from process/thread TID and store | |
262 | their values in GDB's register array. */ | |
263 | ||
264 | static void | |
265 | fetch_fpregs (struct regcache *regcache, int tid) | |
266 | { | |
267 | elf_fpregset_t fpregs; | |
268 | ||
269 | if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) | |
270 | perror_with_name (_("Couldn't get floating point status")); | |
271 | ||
272 | supply_fpregset (regcache, (const elf_fpregset_t *) &fpregs); | |
273 | } | |
274 | ||
275 | /* Store all valid floating-point registers in GDB's register array | |
276 | into the process/thread specified by TID. */ | |
277 | ||
278 | static void | |
279 | store_fpregs (const struct regcache *regcache, int tid, int regno) | |
280 | { | |
281 | elf_fpregset_t fpregs; | |
282 | ||
283 | if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) | |
284 | perror_with_name (_("Couldn't get floating point status")); | |
285 | ||
286 | fill_fpregset (regcache, &fpregs, regno); | |
287 | ||
288 | if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0) | |
289 | perror_with_name (_("Couldn't write floating point status")); | |
290 | } | |
291 | ||
292 | #else | |
293 | ||
294 | static void | |
295 | fetch_fpregs (struct regcache *regcache, int tid) | |
296 | { | |
297 | } | |
298 | ||
299 | static void | |
300 | store_fpregs (const struct regcache *regcache, int tid, int regno) | |
301 | { | |
302 | } | |
303 | ||
304 | #endif | |
305 | \f | |
306 | ||
307 | /* Transferring floating-point and SSE registers to and from GDB. */ | |
308 | ||
309 | /* Fetch all registers covered by the PTRACE_GETREGSET request from | |
310 | process/thread TID and store their values in GDB's register array. | |
311 | Return non-zero if successful, zero otherwise. */ | |
312 | ||
313 | static int | |
314 | fetch_xstateregs (struct regcache *regcache, int tid) | |
315 | { | |
316 | struct gdbarch *gdbarch = regcache->arch (); | |
317 | const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch); | |
318 | gdb::byte_vector xstateregs (tdep->xsave_layout.sizeof_xsave); | |
319 | struct iovec iov; | |
320 | ||
321 | if (have_ptrace_getregset != TRIBOOL_TRUE) | |
322 | return 0; | |
323 | ||
324 | iov.iov_base = xstateregs.data (); | |
325 | iov.iov_len = xstateregs.size (); | |
326 | if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE, | |
327 | &iov) < 0) | |
328 | perror_with_name (_("Couldn't read extended state status")); | |
329 | ||
330 | i387_supply_xsave (regcache, -1, xstateregs.data ()); | |
331 | return 1; | |
332 | } | |
333 | ||
334 | /* Store all valid registers in GDB's register array covered by the | |
335 | PTRACE_SETREGSET request into the process/thread specified by TID. | |
336 | Return non-zero if successful, zero otherwise. */ | |
337 | ||
338 | static int | |
339 | store_xstateregs (const struct regcache *regcache, int tid, int regno) | |
340 | { | |
341 | struct gdbarch *gdbarch = regcache->arch (); | |
342 | const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch); | |
343 | gdb::byte_vector xstateregs (tdep->xsave_layout.sizeof_xsave); | |
344 | struct iovec iov; | |
345 | ||
346 | if (have_ptrace_getregset != TRIBOOL_TRUE) | |
347 | return 0; | |
348 | ||
349 | iov.iov_base = xstateregs.data (); | |
350 | iov.iov_len = xstateregs.size (); | |
351 | if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE, | |
352 | &iov) < 0) | |
353 | perror_with_name (_("Couldn't read extended state status")); | |
354 | ||
355 | i387_collect_xsave (regcache, regno, xstateregs.data (), 0); | |
356 | ||
357 | if (ptrace (PTRACE_SETREGSET, tid, (unsigned int) NT_X86_XSTATE, | |
358 | (int) &iov) < 0) | |
359 | perror_with_name (_("Couldn't write extended state status")); | |
360 | ||
361 | return 1; | |
362 | } | |
363 | ||
364 | #ifdef HAVE_PTRACE_GETFPXREGS | |
365 | ||
366 | /* Fetch all registers covered by the PTRACE_GETFPXREGS request from | |
367 | process/thread TID and store their values in GDB's register array. | |
368 | Return non-zero if successful, zero otherwise. */ | |
369 | ||
370 | static int | |
371 | fetch_fpxregs (struct regcache *regcache, int tid) | |
372 | { | |
373 | elf_fpxregset_t fpxregs; | |
374 | ||
375 | if (have_ptrace_getfpxregs == TRIBOOL_FALSE) | |
376 | return 0; | |
377 | ||
378 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, (int) &fpxregs) < 0) | |
379 | { | |
380 | if (errno == EIO) | |
381 | { | |
382 | have_ptrace_getfpxregs = TRIBOOL_FALSE; | |
383 | return 0; | |
384 | } | |
385 | ||
386 | perror_with_name (_("Couldn't read floating-point and SSE registers")); | |
387 | } | |
388 | ||
389 | i387_supply_fxsave (regcache, -1, (const elf_fpxregset_t *) &fpxregs); | |
390 | return 1; | |
391 | } | |
392 | ||
393 | /* Store all valid registers in GDB's register array covered by the | |
394 | PTRACE_SETFPXREGS request into the process/thread specified by TID. | |
395 | Return non-zero if successful, zero otherwise. */ | |
396 | ||
397 | static int | |
398 | store_fpxregs (const struct regcache *regcache, int tid, int regno) | |
399 | { | |
400 | elf_fpxregset_t fpxregs; | |
401 | ||
402 | if (have_ptrace_getfpxregs == TRIBOOL_FALSE) | |
403 | return 0; | |
404 | ||
405 | if (ptrace (PTRACE_GETFPXREGS, tid, 0, &fpxregs) == -1) | |
406 | { | |
407 | if (errno == EIO) | |
408 | { | |
409 | have_ptrace_getfpxregs = TRIBOOL_FALSE; | |
410 | return 0; | |
411 | } | |
412 | ||
413 | perror_with_name (_("Couldn't read floating-point and SSE registers")); | |
414 | } | |
415 | ||
416 | i387_collect_fxsave (regcache, regno, &fpxregs); | |
417 | ||
418 | if (ptrace (PTRACE_SETFPXREGS, tid, 0, &fpxregs) == -1) | |
419 | perror_with_name (_("Couldn't write floating-point and SSE registers")); | |
420 | ||
421 | return 1; | |
422 | } | |
423 | ||
424 | #else | |
425 | ||
426 | static int | |
427 | fetch_fpxregs (struct regcache *regcache, int tid) | |
428 | { | |
429 | return 0; | |
430 | } | |
431 | ||
432 | static int | |
433 | store_fpxregs (const struct regcache *regcache, int tid, int regno) | |
434 | { | |
435 | return 0; | |
436 | } | |
437 | ||
438 | #endif /* HAVE_PTRACE_GETFPXREGS */ | |
439 | \f | |
440 | ||
441 | /* Transferring arbitrary registers between GDB and inferior. */ | |
442 | ||
443 | /* Fetch register REGNO from the child process. If REGNO is -1, do | |
444 | this for all registers (including the floating point and SSE | |
445 | registers). */ | |
446 | ||
447 | void | |
448 | i386_linux_nat_target::fetch_registers (struct regcache *regcache, int regno) | |
449 | { | |
450 | pid_t tid; | |
451 | ||
452 | /* Use the old method of peeking around in `struct user' if the | |
453 | GETREGS request isn't available. */ | |
454 | if (!have_ptrace_getregs) | |
455 | { | |
456 | int i; | |
457 | ||
458 | for (i = 0; i < gdbarch_num_regs (regcache->arch ()); i++) | |
459 | if (regno == -1 || regno == i) | |
460 | fetch_register (regcache, i); | |
461 | ||
462 | return; | |
463 | } | |
464 | ||
465 | tid = get_ptrace_pid (regcache->ptid ()); | |
466 | ||
467 | /* Use the PTRACE_GETFPXREGS request whenever possible, since it | |
468 | transfers more registers in one system call, and we'll cache the | |
469 | results. But remember that fetch_fpxregs can fail, and return | |
470 | zero. */ | |
471 | if (regno == -1) | |
472 | { | |
473 | fetch_regs (regcache, tid); | |
474 | ||
475 | /* The call above might reset `have_ptrace_getregs'. */ | |
476 | if (!have_ptrace_getregs) | |
477 | { | |
478 | fetch_registers (regcache, regno); | |
479 | return; | |
480 | } | |
481 | ||
482 | if (fetch_xstateregs (regcache, tid)) | |
483 | return; | |
484 | if (fetch_fpxregs (regcache, tid)) | |
485 | return; | |
486 | fetch_fpregs (regcache, tid); | |
487 | return; | |
488 | } | |
489 | ||
490 | if (GETREGS_SUPPLIES (regno)) | |
491 | { | |
492 | fetch_regs (regcache, tid); | |
493 | return; | |
494 | } | |
495 | ||
496 | if (GETXSTATEREGS_SUPPLIES (regno)) | |
497 | { | |
498 | if (fetch_xstateregs (regcache, tid)) | |
499 | return; | |
500 | } | |
501 | ||
502 | if (GETFPXREGS_SUPPLIES (regno)) | |
503 | { | |
504 | if (fetch_fpxregs (regcache, tid)) | |
505 | return; | |
506 | ||
507 | /* Either our processor or our kernel doesn't support the SSE | |
508 | registers, so read the FP registers in the traditional way, | |
509 | and fill the SSE registers with dummy values. It would be | |
510 | more graceful to handle differences in the register set using | |
511 | gdbarch. Until then, this will at least make things work | |
512 | plausibly. */ | |
513 | fetch_fpregs (regcache, tid); | |
514 | return; | |
515 | } | |
516 | ||
517 | internal_error (_("Got request for bad register number %d."), regno); | |
518 | } | |
519 | ||
520 | /* Store register REGNO back into the child process. If REGNO is -1, | |
521 | do this for all registers (including the floating point and SSE | |
522 | registers). */ | |
523 | void | |
524 | i386_linux_nat_target::store_registers (struct regcache *regcache, int regno) | |
525 | { | |
526 | pid_t tid; | |
527 | ||
528 | /* Use the old method of poking around in `struct user' if the | |
529 | SETREGS request isn't available. */ | |
530 | if (!have_ptrace_getregs) | |
531 | { | |
532 | int i; | |
533 | ||
534 | for (i = 0; i < gdbarch_num_regs (regcache->arch ()); i++) | |
535 | if (regno == -1 || regno == i) | |
536 | store_register (regcache, i); | |
537 | ||
538 | return; | |
539 | } | |
540 | ||
541 | tid = get_ptrace_pid (regcache->ptid ()); | |
542 | ||
543 | /* Use the PTRACE_SETFPXREGS requests whenever possible, since it | |
544 | transfers more registers in one system call. But remember that | |
545 | store_fpxregs can fail, and return zero. */ | |
546 | if (regno == -1) | |
547 | { | |
548 | store_regs (regcache, tid, regno); | |
549 | if (store_xstateregs (regcache, tid, regno)) | |
550 | return; | |
551 | if (store_fpxregs (regcache, tid, regno)) | |
552 | return; | |
553 | store_fpregs (regcache, tid, regno); | |
554 | return; | |
555 | } | |
556 | ||
557 | if (GETREGS_SUPPLIES (regno)) | |
558 | { | |
559 | store_regs (regcache, tid, regno); | |
560 | return; | |
561 | } | |
562 | ||
563 | if (GETXSTATEREGS_SUPPLIES (regno)) | |
564 | { | |
565 | if (store_xstateregs (regcache, tid, regno)) | |
566 | return; | |
567 | } | |
568 | ||
569 | if (GETFPXREGS_SUPPLIES (regno)) | |
570 | { | |
571 | if (store_fpxregs (regcache, tid, regno)) | |
572 | return; | |
573 | ||
574 | /* Either our processor or our kernel doesn't support the SSE | |
575 | registers, so just write the FP registers in the traditional | |
576 | way. */ | |
577 | store_fpregs (regcache, tid, regno); | |
578 | return; | |
579 | } | |
580 | ||
581 | internal_error (_("Got request to store bad register number %d."), regno); | |
582 | } | |
583 | \f | |
584 | ||
585 | /* Called by libthread_db. Returns a pointer to the thread local | |
586 | storage (or its descriptor). */ | |
587 | ||
588 | ps_err_e | |
589 | ps_get_thread_area (struct ps_prochandle *ph, | |
590 | lwpid_t lwpid, int idx, void **base) | |
591 | { | |
592 | unsigned int base_addr; | |
593 | ps_err_e result; | |
594 | ||
595 | result = x86_linux_get_thread_area (lwpid, (void *) idx, &base_addr); | |
596 | ||
597 | if (result == PS_OK) | |
598 | *(int *) base = base_addr; | |
599 | ||
600 | return result; | |
601 | } | |
602 | \f | |
603 | ||
604 | /* The instruction for a GNU/Linux system call is: | |
605 | int $0x80 | |
606 | or 0xcd 0x80. */ | |
607 | ||
608 | static const unsigned char linux_syscall[] = { 0xcd, 0x80 }; | |
609 | ||
610 | #define LINUX_SYSCALL_LEN (sizeof linux_syscall) | |
611 | ||
612 | /* The system call number is stored in the %eax register. */ | |
613 | #define LINUX_SYSCALL_REGNUM I386_EAX_REGNUM | |
614 | ||
615 | /* We are specifically interested in the sigreturn and rt_sigreturn | |
616 | system calls. */ | |
617 | ||
618 | #ifndef SYS_sigreturn | |
619 | #define SYS_sigreturn 0x77 | |
620 | #endif | |
621 | #ifndef SYS_rt_sigreturn | |
622 | #define SYS_rt_sigreturn 0xad | |
623 | #endif | |
624 | ||
625 | /* Offset to saved processor flags, from <asm/sigcontext.h>. */ | |
626 | #define LINUX_SIGCONTEXT_EFLAGS_OFFSET (64) | |
627 | ||
628 | /* Resume execution of the inferior process. | |
629 | If STEP is nonzero, single-step it. | |
630 | If SIGNAL is nonzero, give it that signal. */ | |
631 | ||
632 | void | |
633 | i386_linux_nat_target::low_resume (ptid_t ptid, int step, enum gdb_signal signal) | |
634 | { | |
635 | int pid = ptid.lwp (); | |
636 | int request; | |
637 | ||
638 | if (catch_syscall_enabled ()) | |
639 | request = PTRACE_SYSCALL; | |
640 | else | |
641 | request = PTRACE_CONT; | |
642 | ||
643 | if (step) | |
644 | { | |
645 | struct regcache *regcache = get_thread_regcache (this, ptid); | |
646 | struct gdbarch *gdbarch = regcache->arch (); | |
647 | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | |
648 | ULONGEST pc; | |
649 | gdb_byte buf[LINUX_SYSCALL_LEN]; | |
650 | ||
651 | request = PTRACE_SINGLESTEP; | |
652 | ||
653 | regcache_cooked_read_unsigned (regcache, | |
654 | gdbarch_pc_regnum (gdbarch), &pc); | |
655 | ||
656 | /* Returning from a signal trampoline is done by calling a | |
657 | special system call (sigreturn or rt_sigreturn, see | |
658 | i386-linux-tdep.c for more information). This system call | |
659 | restores the registers that were saved when the signal was | |
660 | raised, including %eflags. That means that single-stepping | |
661 | won't work. Instead, we'll have to modify the signal context | |
662 | that's about to be restored, and set the trace flag there. */ | |
663 | ||
664 | /* First check if PC is at a system call. */ | |
665 | if (target_read_memory (pc, buf, LINUX_SYSCALL_LEN) == 0 | |
666 | && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0) | |
667 | { | |
668 | ULONGEST syscall; | |
669 | regcache_cooked_read_unsigned (regcache, | |
670 | LINUX_SYSCALL_REGNUM, &syscall); | |
671 | ||
672 | /* Then check the system call number. */ | |
673 | if (syscall == SYS_sigreturn || syscall == SYS_rt_sigreturn) | |
674 | { | |
675 | ULONGEST sp, addr; | |
676 | unsigned long int eflags; | |
677 | ||
678 | regcache_cooked_read_unsigned (regcache, I386_ESP_REGNUM, &sp); | |
679 | if (syscall == SYS_rt_sigreturn) | |
680 | addr = read_memory_unsigned_integer (sp + 8, 4, byte_order) | |
681 | + 20; | |
682 | else | |
683 | addr = sp; | |
684 | ||
685 | /* Set the trace flag in the context that's about to be | |
686 | restored. */ | |
687 | addr += LINUX_SIGCONTEXT_EFLAGS_OFFSET; | |
688 | read_memory (addr, (gdb_byte *) &eflags, 4); | |
689 | eflags |= 0x0100; | |
690 | write_memory (addr, (gdb_byte *) &eflags, 4); | |
691 | } | |
692 | } | |
693 | } | |
694 | ||
695 | if (ptrace (request, pid, 0, gdb_signal_to_host (signal)) == -1) | |
696 | perror_with_name (("ptrace")); | |
697 | } | |
698 | ||
699 | INIT_GDB_FILE (i386_linux_nat) | |
700 | { | |
701 | linux_target = &the_i386_linux_nat_target; | |
702 | ||
703 | /* Add the target. */ | |
704 | add_inf_child_target (linux_target); | |
705 | } |