1 /* Low-level siginfo manipulation for amd64.
3 Copyright (C) 2002-2016 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 "common-defs.h"
22 #include "amd64-linux-siginfo.h"
24 /* The nat_* types below define the most complete kernel siginfo type
25 known for the architecture, independent of the system/libc headers. */
27 typedef int nat_int_t
;
28 typedef void* nat_uptr_t
;
30 typedef int nat_time_t
;
31 typedef int nat_timer_t
;
33 /* For native 64-bit, clock_t in _sigchld is 64bit aligned at 4 bytes. */
34 typedef long __attribute__ ((__aligned__ (4))) nat_clock_t
;
42 typedef union nat_sigval
48 typedef struct nat_siginfo
56 int _pad
[((128 / sizeof (int)) - 4)];
72 /* POSIX.1b signals */
90 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
109 } nat_siginfo_t
__attribute__ ((__aligned__ (8)));
111 /* Sanity check for the siginfo structure size. */
113 gdb_static_assert (sizeof (nat_siginfo_t
) == sizeof (siginfo_t
));
115 /* These types below (compat_*) define a siginfo type that is layout
116 compatible with the siginfo type exported by the 32-bit userspace
119 typedef int compat_int_t
;
120 typedef unsigned int compat_uptr_t
;
122 typedef int compat_time_t
;
123 typedef int compat_timer_t
;
124 typedef int compat_clock_t
;
126 struct compat_timeval
128 compat_time_t tv_sec
;
132 typedef union compat_sigval
134 compat_int_t sival_int
;
135 compat_uptr_t sival_ptr
;
138 typedef struct compat_siginfo
146 int _pad
[((128 / sizeof (int)) - 3)];
155 /* POSIX.1b timers */
160 compat_sigval_t _sigval
;
163 /* POSIX.1b signals */
168 compat_sigval_t _sigval
;
177 compat_clock_t _utime
;
178 compat_clock_t _stime
;
181 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
202 /* For x32, clock_t in _sigchld is 64bit aligned at 4 bytes. */
203 typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t
;
205 typedef struct compat_x32_siginfo
213 int _pad
[((128 / sizeof (int)) - 3)];
222 /* POSIX.1b timers */
227 compat_sigval_t _sigval
;
230 /* POSIX.1b signals */
235 compat_sigval_t _sigval
;
244 compat_x32_clock_t _utime
;
245 compat_x32_clock_t _stime
;
248 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
252 unsigned int _addr_lsb
;
262 } compat_x32_siginfo_t
__attribute__ ((__aligned__ (8)));
264 /* To simplify usage of siginfo fields. */
266 #define cpt_si_pid _sifields._kill._pid
267 #define cpt_si_uid _sifields._kill._uid
268 #define cpt_si_timerid _sifields._timer._tid
269 #define cpt_si_overrun _sifields._timer._overrun
270 #define cpt_si_status _sifields._sigchld._status
271 #define cpt_si_utime _sifields._sigchld._utime
272 #define cpt_si_stime _sifields._sigchld._stime
273 #define cpt_si_ptr _sifields._rt._sigval.sival_ptr
274 #define cpt_si_addr _sifields._sigfault._addr
275 #define cpt_si_addr_lsb _sifields._sigfault._addr_lsb
276 #define cpt_si_band _sifields._sigpoll._band
277 #define cpt_si_fd _sifields._sigpoll._fd
279 /* glibc at least up to 2.3.2 doesn't have si_timerid, si_overrun.
280 In their place is si_timer1,si_timer2. */
283 #define si_timerid si_timer1
286 #define si_overrun si_timer2
289 /* Convert the system provided siginfo into compatible siginfo. */
292 compat_siginfo_from_siginfo (compat_siginfo_t
*to
, siginfo_t
*from
)
294 nat_siginfo_t from_nat
;
296 memcpy (&from_nat
, from
, sizeof (from_nat
));
297 memset (to
, 0, sizeof (*to
));
299 to
->si_signo
= from_nat
.si_signo
;
300 to
->si_errno
= from_nat
.si_errno
;
301 to
->si_code
= from_nat
.si_code
;
303 if (to
->si_code
== SI_TIMER
)
305 to
->cpt_si_timerid
= from_nat
.cpt_si_timerid
;
306 to
->cpt_si_overrun
= from_nat
.cpt_si_overrun
;
307 to
->cpt_si_ptr
= (intptr_t) from_nat
.cpt_si_ptr
;
309 else if (to
->si_code
== SI_USER
)
311 to
->cpt_si_pid
= from_nat
.cpt_si_pid
;
312 to
->cpt_si_uid
= from_nat
.cpt_si_uid
;
314 else if (to
->si_code
< 0)
316 to
->cpt_si_pid
= from_nat
.cpt_si_pid
;
317 to
->cpt_si_uid
= from_nat
.cpt_si_uid
;
318 to
->cpt_si_ptr
= (intptr_t) from_nat
.cpt_si_ptr
;
322 switch (to
->si_signo
)
325 to
->cpt_si_pid
= from_nat
.cpt_si_pid
;
326 to
->cpt_si_uid
= from_nat
.cpt_si_uid
;
327 to
->cpt_si_status
= from_nat
.cpt_si_status
;
328 to
->cpt_si_utime
= from_nat
.cpt_si_utime
;
329 to
->cpt_si_stime
= from_nat
.cpt_si_stime
;
335 to
->cpt_si_addr
= (intptr_t) from_nat
.cpt_si_addr
;
338 to
->cpt_si_band
= from_nat
.cpt_si_band
;
339 to
->cpt_si_fd
= from_nat
.cpt_si_fd
;
342 to
->cpt_si_pid
= from_nat
.cpt_si_pid
;
343 to
->cpt_si_uid
= from_nat
.cpt_si_uid
;
344 to
->cpt_si_ptr
= (intptr_t) from_nat
.cpt_si_ptr
;
350 /* Convert the compatible siginfo into system siginfo. */
353 siginfo_from_compat_siginfo (siginfo_t
*to
, compat_siginfo_t
*from
)
355 nat_siginfo_t to_nat
;
357 memset (&to_nat
, 0, sizeof (to_nat
));
359 to_nat
.si_signo
= from
->si_signo
;
360 to_nat
.si_errno
= from
->si_errno
;
361 to_nat
.si_code
= from
->si_code
;
363 if (to_nat
.si_code
== SI_TIMER
)
365 to_nat
.cpt_si_timerid
= from
->cpt_si_timerid
;
366 to_nat
.cpt_si_overrun
= from
->cpt_si_overrun
;
367 to_nat
.cpt_si_ptr
= (void *) (intptr_t) from
->cpt_si_ptr
;
369 else if (to_nat
.si_code
== SI_USER
)
371 to_nat
.cpt_si_pid
= from
->cpt_si_pid
;
372 to_nat
.cpt_si_uid
= from
->cpt_si_uid
;
374 if (to_nat
.si_code
< 0)
376 to_nat
.cpt_si_pid
= from
->cpt_si_pid
;
377 to_nat
.cpt_si_uid
= from
->cpt_si_uid
;
378 to_nat
.cpt_si_ptr
= (void *) (intptr_t) from
->cpt_si_ptr
;
382 switch (to_nat
.si_signo
)
385 to_nat
.cpt_si_pid
= from
->cpt_si_pid
;
386 to_nat
.cpt_si_uid
= from
->cpt_si_uid
;
387 to_nat
.cpt_si_status
= from
->cpt_si_status
;
388 to_nat
.cpt_si_utime
= from
->cpt_si_utime
;
389 to_nat
.cpt_si_stime
= from
->cpt_si_stime
;
395 to_nat
.cpt_si_addr
= (void *) (intptr_t) from
->cpt_si_addr
;
396 to_nat
.cpt_si_addr_lsb
= (short) from
->cpt_si_addr_lsb
;
399 to_nat
.cpt_si_band
= from
->cpt_si_band
;
400 to_nat
.cpt_si_fd
= from
->cpt_si_fd
;
403 to_nat
.cpt_si_pid
= from
->cpt_si_pid
;
404 to_nat
.cpt_si_uid
= from
->cpt_si_uid
;
405 to_nat
.cpt_si_ptr
= (void* ) (intptr_t) from
->cpt_si_ptr
;
409 memcpy (to
, &to_nat
, sizeof (to_nat
));
412 /* Convert the system provided siginfo into compatible x32 siginfo. */
415 compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t
*to
,
418 nat_siginfo_t from_nat
;
420 memcpy (&from_nat
, from
, sizeof (from_nat
));
421 memset (to
, 0, sizeof (*to
));
423 to
->si_signo
= from_nat
.si_signo
;
424 to
->si_errno
= from_nat
.si_errno
;
425 to
->si_code
= from_nat
.si_code
;
427 if (to
->si_code
== SI_TIMER
)
429 to
->cpt_si_timerid
= from_nat
.cpt_si_timerid
;
430 to
->cpt_si_overrun
= from_nat
.cpt_si_overrun
;
431 to
->cpt_si_ptr
= (intptr_t) from_nat
.cpt_si_ptr
;
433 else if (to
->si_code
== SI_USER
)
435 to
->cpt_si_pid
= from_nat
.cpt_si_pid
;
436 to
->cpt_si_uid
= from_nat
.cpt_si_uid
;
438 else if (to
->si_code
< 0)
440 to
->cpt_si_pid
= from_nat
.cpt_si_pid
;
441 to
->cpt_si_uid
= from_nat
.cpt_si_uid
;
442 to
->cpt_si_ptr
= (intptr_t) from_nat
.cpt_si_ptr
;
446 switch (to
->si_signo
)
449 to
->cpt_si_pid
= from_nat
.cpt_si_pid
;
450 to
->cpt_si_uid
= from_nat
.cpt_si_uid
;
451 to
->cpt_si_status
= from_nat
.cpt_si_status
;
452 memcpy (&to
->cpt_si_utime
, &from_nat
.cpt_si_utime
,
453 sizeof (to
->cpt_si_utime
));
454 memcpy (&to
->cpt_si_stime
, &from_nat
.cpt_si_stime
,
455 sizeof (to
->cpt_si_stime
));
461 to
->cpt_si_addr
= (intptr_t) from_nat
.cpt_si_addr
;
464 to
->cpt_si_band
= from_nat
.cpt_si_band
;
465 to
->cpt_si_fd
= from_nat
.cpt_si_fd
;
468 to
->cpt_si_pid
= from_nat
.cpt_si_pid
;
469 to
->cpt_si_uid
= from_nat
.cpt_si_uid
;
470 to
->cpt_si_ptr
= (intptr_t) from_nat
.cpt_si_ptr
;
479 /* Convert the compatible x32 siginfo into system siginfo. */
481 siginfo_from_compat_x32_siginfo (siginfo_t
*to
,
482 compat_x32_siginfo_t
*from
)
484 nat_siginfo_t to_nat
;
486 memset (&to_nat
, 0, sizeof (to_nat
));
487 to_nat
.si_signo
= from
->si_signo
;
488 to_nat
.si_errno
= from
->si_errno
;
489 to_nat
.si_code
= from
->si_code
;
491 if (to_nat
.si_code
== SI_TIMER
)
493 to_nat
.cpt_si_timerid
= from
->cpt_si_timerid
;
494 to_nat
.cpt_si_overrun
= from
->cpt_si_overrun
;
495 to_nat
.cpt_si_ptr
= (void *) (intptr_t) from
->cpt_si_ptr
;
497 else if (to_nat
.si_code
== SI_USER
)
499 to_nat
.cpt_si_pid
= from
->cpt_si_pid
;
500 to_nat
.cpt_si_uid
= from
->cpt_si_uid
;
502 if (to_nat
.si_code
< 0)
504 to_nat
.cpt_si_pid
= from
->cpt_si_pid
;
505 to_nat
.cpt_si_uid
= from
->cpt_si_uid
;
506 to_nat
.cpt_si_ptr
= (void *) (intptr_t) from
->cpt_si_ptr
;
510 switch (to_nat
.si_signo
)
513 to_nat
.cpt_si_pid
= from
->cpt_si_pid
;
514 to_nat
.cpt_si_uid
= from
->cpt_si_uid
;
515 to_nat
.cpt_si_status
= from
->cpt_si_status
;
516 memcpy (&to_nat
.cpt_si_utime
, &from
->cpt_si_utime
,
517 sizeof (to_nat
.cpt_si_utime
));
518 memcpy (&to_nat
.cpt_si_stime
, &from
->cpt_si_stime
,
519 sizeof (to_nat
.cpt_si_stime
));
525 to_nat
.cpt_si_addr
= (void *) (intptr_t) from
->cpt_si_addr
;
528 to_nat
.cpt_si_band
= from
->cpt_si_band
;
529 to_nat
.cpt_si_fd
= from
->cpt_si_fd
;
532 to_nat
.cpt_si_pid
= from
->cpt_si_pid
;
533 to_nat
.cpt_si_uid
= from
->cpt_si_uid
;
534 to_nat
.cpt_si_ptr
= (void* ) (intptr_t) from
->cpt_si_ptr
;
538 memcpy (to
, &to_nat
, sizeof (to_nat
));
541 /* Convert a native/host siginfo object, into/from the siginfo in the
542 layout of the inferiors' architecture. Returns true if any
543 conversion was done; false otherwise. If DIRECTION is 1, then copy
544 from INF to NATIVE. If DIRECTION is 0, then copy from NATIVE to INF. */
547 amd64_linux_siginfo_fixup_common (siginfo_t
*native
, gdb_byte
*inf
,
549 enum amd64_siginfo_fixup_mode mode
)
551 if (mode
== FIXUP_32
)
553 gdb_assert (sizeof (siginfo_t
) == sizeof (compat_siginfo_t
));
556 compat_siginfo_from_siginfo ((struct compat_siginfo
*) inf
, native
);
558 siginfo_from_compat_siginfo (native
, (struct compat_siginfo
*) inf
);
562 else if (mode
== FIXUP_X32
)
564 gdb_assert (sizeof (siginfo_t
) == sizeof (compat_x32_siginfo_t
));
567 compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo
*) inf
,
570 siginfo_from_compat_x32_siginfo (native
,
571 (struct compat_x32_siginfo
*) inf
);