1 /* Low-level siginfo manipulation for amd64.
3 Copyright (C) 2002-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "amd64-linux-siginfo.h"
23 #define GDB_SI_SIZE 128
25 /* The types below define the most complete kernel siginfo types known
26 for the architecture, independent of the system/libc headers. They
27 are named from a 64-bit kernel's perspective:
30 |--------+----------------------|
31 | 64-bit | nat_siginfo_t |
32 | 32-bit | compat_siginfo_t |
33 | x32 | compat_x32_siginfo_t |
38 typedef int nat_int_t
;
39 typedef unsigned long nat_uptr_t
;
41 typedef int nat_time_t
;
42 typedef int nat_timer_t
;
44 /* For native 64-bit, clock_t in _sigchld is 64-bit. */
45 typedef long nat_clock_t
;
61 int _pad
[((128 / sizeof (int)) - 4)];
77 /* POSIX.1b signals */
95 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
116 #endif /* __ILP32__ */
118 /* These types below (compat_*) define a siginfo type that is layout
119 compatible with the siginfo type exported by the 32-bit userspace
122 typedef int compat_int_t
;
123 typedef unsigned int compat_uptr_t
;
125 typedef int compat_time_t
;
126 typedef int compat_timer_t
;
127 typedef int compat_clock_t
;
129 struct compat_timeval
131 compat_time_t tv_sec
;
135 union compat_sigval_t
137 compat_int_t sival_int
;
138 compat_uptr_t sival_ptr
;
141 struct compat_siginfo_t
149 int _pad
[((128 / sizeof (int)) - 3)];
158 /* POSIX.1b timers */
163 compat_sigval_t _sigval
;
166 /* POSIX.1b signals */
171 compat_sigval_t _sigval
;
180 compat_clock_t _utime
;
181 compat_clock_t _stime
;
184 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
205 /* For x32, clock_t in _sigchld is 64bit aligned at 4 bytes. */
206 typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t
;
208 struct __attribute__ ((__aligned__ (8))) compat_x32_siginfo_t
216 int _pad
[((128 / sizeof (int)) - 3)];
225 /* POSIX.1b timers */
230 compat_sigval_t _sigval
;
233 /* POSIX.1b signals */
238 compat_sigval_t _sigval
;
247 compat_x32_clock_t _utime
;
248 compat_x32_clock_t _stime
;
251 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
255 unsigned int _addr_lsb
;
267 /* To simplify usage of siginfo fields. */
269 #define cpt_si_pid _sifields._kill._pid
270 #define cpt_si_uid _sifields._kill._uid
271 #define cpt_si_timerid _sifields._timer._tid
272 #define cpt_si_overrun _sifields._timer._overrun
273 #define cpt_si_status _sifields._sigchld._status
274 #define cpt_si_utime _sifields._sigchld._utime
275 #define cpt_si_stime _sifields._sigchld._stime
276 #define cpt_si_ptr _sifields._rt._sigval.sival_ptr
277 #define cpt_si_addr _sifields._sigfault._addr
278 #define cpt_si_addr_lsb _sifields._sigfault._addr_lsb
279 #define cpt_si_lower _sifields._sigfault.si_addr_bnd._lower
280 #define cpt_si_upper _sifields._sigfault.si_addr_bnd._upper
281 #define cpt_si_band _sifields._sigpoll._band
282 #define cpt_si_fd _sifields._sigpoll._fd
284 /* glibc at least up to 2.3.2 doesn't have si_timerid, si_overrun.
285 In their place is si_timer1,si_timer2. */
288 #define si_timerid si_timer1
291 #define si_overrun si_timer2
295 #define SEGV_BNDERR 3
298 /* The type of the siginfo object the kernel returns in
299 PTRACE_GETSIGINFO. If gdb is built as a x32 program, we get a x32
302 typedef compat_x32_siginfo_t ptrace_siginfo_t
;
304 typedef nat_siginfo_t ptrace_siginfo_t
;
307 /* Convert the system provided siginfo into compatible siginfo. */
310 compat_siginfo_from_siginfo (compat_siginfo_t
*to
, const siginfo_t
*from
)
312 ptrace_siginfo_t from_ptrace
;
314 memcpy (&from_ptrace
, from
, sizeof (from_ptrace
));
315 memset (to
, 0, sizeof (*to
));
317 to
->si_signo
= from_ptrace
.si_signo
;
318 to
->si_errno
= from_ptrace
.si_errno
;
319 to
->si_code
= from_ptrace
.si_code
;
321 if (to
->si_code
== SI_TIMER
)
323 to
->cpt_si_timerid
= from_ptrace
.cpt_si_timerid
;
324 to
->cpt_si_overrun
= from_ptrace
.cpt_si_overrun
;
325 to
->cpt_si_ptr
= from_ptrace
.cpt_si_ptr
;
327 else if (to
->si_code
== SI_USER
)
329 to
->cpt_si_pid
= from_ptrace
.cpt_si_pid
;
330 to
->cpt_si_uid
= from_ptrace
.cpt_si_uid
;
333 /* The struct compat_x32_siginfo_t doesn't contain
334 cpt_si_lower/cpt_si_upper. */
335 else if (to
->si_code
== SEGV_BNDERR
336 && to
->si_signo
== SIGSEGV
)
338 to
->cpt_si_addr
= from_ptrace
.cpt_si_addr
;
339 to
->cpt_si_lower
= from_ptrace
.cpt_si_lower
;
340 to
->cpt_si_upper
= from_ptrace
.cpt_si_upper
;
343 else if (to
->si_code
< 0)
345 to
->cpt_si_pid
= from_ptrace
.cpt_si_pid
;
346 to
->cpt_si_uid
= from_ptrace
.cpt_si_uid
;
347 to
->cpt_si_ptr
= from_ptrace
.cpt_si_ptr
;
351 switch (to
->si_signo
)
354 to
->cpt_si_pid
= from_ptrace
.cpt_si_pid
;
355 to
->cpt_si_uid
= from_ptrace
.cpt_si_uid
;
356 to
->cpt_si_status
= from_ptrace
.cpt_si_status
;
357 to
->cpt_si_utime
= from_ptrace
.cpt_si_utime
;
358 to
->cpt_si_stime
= from_ptrace
.cpt_si_stime
;
364 to
->cpt_si_addr
= from_ptrace
.cpt_si_addr
;
367 to
->cpt_si_band
= from_ptrace
.cpt_si_band
;
368 to
->cpt_si_fd
= from_ptrace
.cpt_si_fd
;
371 to
->cpt_si_pid
= from_ptrace
.cpt_si_pid
;
372 to
->cpt_si_uid
= from_ptrace
.cpt_si_uid
;
373 to
->cpt_si_ptr
= from_ptrace
.cpt_si_ptr
;
379 /* Convert the compatible siginfo into system siginfo. */
382 siginfo_from_compat_siginfo (siginfo_t
*to
, const compat_siginfo_t
*from
)
384 ptrace_siginfo_t to_ptrace
;
386 memset (&to_ptrace
, 0, sizeof (to_ptrace
));
388 to_ptrace
.si_signo
= from
->si_signo
;
389 to_ptrace
.si_errno
= from
->si_errno
;
390 to_ptrace
.si_code
= from
->si_code
;
392 if (to_ptrace
.si_code
== SI_TIMER
)
394 to_ptrace
.cpt_si_timerid
= from
->cpt_si_timerid
;
395 to_ptrace
.cpt_si_overrun
= from
->cpt_si_overrun
;
396 to_ptrace
.cpt_si_ptr
= from
->cpt_si_ptr
;
398 else if (to_ptrace
.si_code
== SI_USER
)
400 to_ptrace
.cpt_si_pid
= from
->cpt_si_pid
;
401 to_ptrace
.cpt_si_uid
= from
->cpt_si_uid
;
403 if (to_ptrace
.si_code
< 0)
405 to_ptrace
.cpt_si_pid
= from
->cpt_si_pid
;
406 to_ptrace
.cpt_si_uid
= from
->cpt_si_uid
;
407 to_ptrace
.cpt_si_ptr
= from
->cpt_si_ptr
;
411 switch (to_ptrace
.si_signo
)
414 to_ptrace
.cpt_si_pid
= from
->cpt_si_pid
;
415 to_ptrace
.cpt_si_uid
= from
->cpt_si_uid
;
416 to_ptrace
.cpt_si_status
= from
->cpt_si_status
;
417 to_ptrace
.cpt_si_utime
= from
->cpt_si_utime
;
418 to_ptrace
.cpt_si_stime
= from
->cpt_si_stime
;
424 to_ptrace
.cpt_si_addr
= from
->cpt_si_addr
;
425 to_ptrace
.cpt_si_addr_lsb
= from
->cpt_si_addr_lsb
;
428 to_ptrace
.cpt_si_band
= from
->cpt_si_band
;
429 to_ptrace
.cpt_si_fd
= from
->cpt_si_fd
;
432 to_ptrace
.cpt_si_pid
= from
->cpt_si_pid
;
433 to_ptrace
.cpt_si_uid
= from
->cpt_si_uid
;
434 to_ptrace
.cpt_si_ptr
= from
->cpt_si_ptr
;
438 memcpy (to
, &to_ptrace
, sizeof (to_ptrace
));
441 /* Convert the system provided siginfo into compatible x32 siginfo. */
444 compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t
*to
,
445 const siginfo_t
*from
)
447 ptrace_siginfo_t from_ptrace
;
449 memcpy (&from_ptrace
, from
, sizeof (from_ptrace
));
450 memset (to
, 0, sizeof (*to
));
452 to
->si_signo
= from_ptrace
.si_signo
;
453 to
->si_errno
= from_ptrace
.si_errno
;
454 to
->si_code
= from_ptrace
.si_code
;
456 if (to
->si_code
== SI_TIMER
)
458 to
->cpt_si_timerid
= from_ptrace
.cpt_si_timerid
;
459 to
->cpt_si_overrun
= from_ptrace
.cpt_si_overrun
;
460 to
->cpt_si_ptr
= from_ptrace
.cpt_si_ptr
;
462 else if (to
->si_code
== SI_USER
)
464 to
->cpt_si_pid
= from_ptrace
.cpt_si_pid
;
465 to
->cpt_si_uid
= from_ptrace
.cpt_si_uid
;
467 else if (to
->si_code
< 0)
469 to
->cpt_si_pid
= from_ptrace
.cpt_si_pid
;
470 to
->cpt_si_uid
= from_ptrace
.cpt_si_uid
;
471 to
->cpt_si_ptr
= from_ptrace
.cpt_si_ptr
;
475 switch (to
->si_signo
)
478 to
->cpt_si_pid
= from_ptrace
.cpt_si_pid
;
479 to
->cpt_si_uid
= from_ptrace
.cpt_si_uid
;
480 to
->cpt_si_status
= from_ptrace
.cpt_si_status
;
481 memcpy (&to
->cpt_si_utime
, &from_ptrace
.cpt_si_utime
,
482 sizeof (to
->cpt_si_utime
));
483 memcpy (&to
->cpt_si_stime
, &from_ptrace
.cpt_si_stime
,
484 sizeof (to
->cpt_si_stime
));
490 to
->cpt_si_addr
= from_ptrace
.cpt_si_addr
;
493 to
->cpt_si_band
= from_ptrace
.cpt_si_band
;
494 to
->cpt_si_fd
= from_ptrace
.cpt_si_fd
;
497 to
->cpt_si_pid
= from_ptrace
.cpt_si_pid
;
498 to
->cpt_si_uid
= from_ptrace
.cpt_si_uid
;
499 to
->cpt_si_ptr
= from_ptrace
.cpt_si_ptr
;
508 /* Convert the compatible x32 siginfo into system siginfo. */
510 siginfo_from_compat_x32_siginfo (siginfo_t
*to
,
511 const compat_x32_siginfo_t
*from
)
513 ptrace_siginfo_t to_ptrace
;
515 memset (&to_ptrace
, 0, sizeof (to_ptrace
));
516 to_ptrace
.si_signo
= from
->si_signo
;
517 to_ptrace
.si_errno
= from
->si_errno
;
518 to_ptrace
.si_code
= from
->si_code
;
520 if (to_ptrace
.si_code
== SI_TIMER
)
522 to_ptrace
.cpt_si_timerid
= from
->cpt_si_timerid
;
523 to_ptrace
.cpt_si_overrun
= from
->cpt_si_overrun
;
524 to_ptrace
.cpt_si_ptr
= from
->cpt_si_ptr
;
526 else if (to_ptrace
.si_code
== SI_USER
)
528 to_ptrace
.cpt_si_pid
= from
->cpt_si_pid
;
529 to_ptrace
.cpt_si_uid
= from
->cpt_si_uid
;
531 if (to_ptrace
.si_code
< 0)
533 to_ptrace
.cpt_si_pid
= from
->cpt_si_pid
;
534 to_ptrace
.cpt_si_uid
= from
->cpt_si_uid
;
535 to_ptrace
.cpt_si_ptr
= from
->cpt_si_ptr
;
539 switch (to_ptrace
.si_signo
)
542 to_ptrace
.cpt_si_pid
= from
->cpt_si_pid
;
543 to_ptrace
.cpt_si_uid
= from
->cpt_si_uid
;
544 to_ptrace
.cpt_si_status
= from
->cpt_si_status
;
545 memcpy (&to_ptrace
.cpt_si_utime
, &from
->cpt_si_utime
,
546 sizeof (to_ptrace
.cpt_si_utime
));
547 memcpy (&to_ptrace
.cpt_si_stime
, &from
->cpt_si_stime
,
548 sizeof (to_ptrace
.cpt_si_stime
));
554 to_ptrace
.cpt_si_addr
= from
->cpt_si_addr
;
557 to_ptrace
.cpt_si_band
= from
->cpt_si_band
;
558 to_ptrace
.cpt_si_fd
= from
->cpt_si_fd
;
561 to_ptrace
.cpt_si_pid
= from
->cpt_si_pid
;
562 to_ptrace
.cpt_si_uid
= from
->cpt_si_uid
;
563 to_ptrace
.cpt_si_ptr
= from
->cpt_si_ptr
;
567 memcpy (to
, &to_ptrace
, sizeof (to_ptrace
));
570 /* Convert a ptrace siginfo object, into/from the siginfo in the
571 layout of the inferiors' architecture. Returns true if any
572 conversion was done; false otherwise. If DIRECTION is 1, then copy
573 from INF to PTRACE. If DIRECTION is 0, then copy from NATIVE to
577 amd64_linux_siginfo_fixup_common (siginfo_t
*ptrace
, gdb_byte
*inf
,
579 enum amd64_siginfo_fixup_mode mode
)
581 if (mode
== FIXUP_32
)
584 compat_siginfo_from_siginfo ((compat_siginfo_t
*) inf
, ptrace
);
586 siginfo_from_compat_siginfo (ptrace
, (compat_siginfo_t
*) inf
);
590 else if (mode
== FIXUP_X32
)
593 compat_x32_siginfo_from_siginfo ((compat_x32_siginfo_t
*) inf
,
596 siginfo_from_compat_x32_siginfo (ptrace
,
597 (compat_x32_siginfo_t
*) inf
);
604 /* Sanity check for the siginfo structure sizes. */
606 static_assert (sizeof (siginfo_t
) == GDB_SI_SIZE
);
608 static_assert (sizeof (nat_siginfo_t
) == GDB_SI_SIZE
);
610 static_assert (sizeof (compat_x32_siginfo_t
) == GDB_SI_SIZE
);
611 static_assert (sizeof (compat_siginfo_t
) == GDB_SI_SIZE
);
612 static_assert (sizeof (ptrace_siginfo_t
) == GDB_SI_SIZE
);