72b30422b419993b5e7d25d3cd58e51638ec2f04
[deliverable/binutils-gdb.git] / gdb / nat / amd64-linux-siginfo.c
1 /* Low-level siginfo manipulation for amd64.
2
3 Copyright (C) 2002-2016 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 <signal.h>
21 #include "common-defs.h"
22 #include "amd64-linux-siginfo.h"
23
24 /* The nat_* types below define the most complete kernel siginfo type
25 known for the architecture, independent of the system/libc headers. */
26
27 typedef int nat_int_t;
28 typedef void* nat_uptr_t;
29
30 typedef int nat_time_t;
31 typedef int nat_timer_t;
32
33 /* For native 64-bit, clock_t in _sigchld is 64bit aligned at 4 bytes. */
34 typedef long __attribute__ ((__aligned__ (4))) nat_clock_t;
35
36 struct nat_timeval
37 {
38 nat_time_t tv_sec;
39 int tv_usec;
40 };
41
42 typedef union nat_sigval
43 {
44 nat_int_t sival_int;
45 nat_uptr_t sival_ptr;
46 } nat_sigval_t;
47
48 typedef struct nat_siginfo
49 {
50 int si_signo;
51 int si_errno;
52 int si_code;
53
54 union
55 {
56 int _pad[((128 / sizeof (int)) - 4)];
57 /* kill() */
58 struct
59 {
60 unsigned int _pid;
61 unsigned int _uid;
62 } _kill;
63
64 /* POSIX.1b timers */
65 struct
66 {
67 nat_timer_t _tid;
68 int _overrun;
69 nat_sigval_t _sigval;
70 } _timer;
71
72 /* POSIX.1b signals */
73 struct
74 {
75 unsigned int _pid;
76 unsigned int _uid;
77 nat_sigval_t _sigval;
78 } _rt;
79
80 /* SIGCHLD */
81 struct
82 {
83 unsigned int _pid;
84 unsigned int _uid;
85 int _status;
86 nat_clock_t _utime;
87 nat_clock_t _stime;
88 } _sigchld;
89
90 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
91 struct
92 {
93 nat_uptr_t _addr;
94 short int _addr_lsb;
95 struct
96 {
97 nat_uptr_t _lower;
98 nat_uptr_t _upper;
99 } si_addr_bnd;
100 } _sigfault;
101
102 /* SIGPOLL */
103 struct
104 {
105 int _band;
106 int _fd;
107 } _sigpoll;
108 } _sifields;
109 } nat_siginfo_t __attribute__ ((__aligned__ (8)));
110
111 /* Sanity check for the siginfo structure size. */
112
113 gdb_static_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t));
114
115 /* These types below (compat_*) define a siginfo type that is layout
116 compatible with the siginfo type exported by the 32-bit userspace
117 support. */
118
119 typedef int compat_int_t;
120 typedef unsigned int compat_uptr_t;
121
122 typedef int compat_time_t;
123 typedef int compat_timer_t;
124 typedef int compat_clock_t;
125
126 struct compat_timeval
127 {
128 compat_time_t tv_sec;
129 int tv_usec;
130 };
131
132 typedef union compat_sigval
133 {
134 compat_int_t sival_int;
135 compat_uptr_t sival_ptr;
136 } compat_sigval_t;
137
138 typedef struct compat_siginfo
139 {
140 int si_signo;
141 int si_errno;
142 int si_code;
143
144 union
145 {
146 int _pad[((128 / sizeof (int)) - 3)];
147
148 /* kill() */
149 struct
150 {
151 unsigned int _pid;
152 unsigned int _uid;
153 } _kill;
154
155 /* POSIX.1b timers */
156 struct
157 {
158 compat_timer_t _tid;
159 int _overrun;
160 compat_sigval_t _sigval;
161 } _timer;
162
163 /* POSIX.1b signals */
164 struct
165 {
166 unsigned int _pid;
167 unsigned int _uid;
168 compat_sigval_t _sigval;
169 } _rt;
170
171 /* SIGCHLD */
172 struct
173 {
174 unsigned int _pid;
175 unsigned int _uid;
176 int _status;
177 compat_clock_t _utime;
178 compat_clock_t _stime;
179 } _sigchld;
180
181 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
182 struct
183 {
184 unsigned int _addr;
185 short int _addr_lsb;
186 struct
187 {
188 unsigned int _lower;
189 unsigned int _upper;
190 } si_addr_bnd;
191 } _sigfault;
192
193 /* SIGPOLL */
194 struct
195 {
196 int _band;
197 int _fd;
198 } _sigpoll;
199 } _sifields;
200 } compat_siginfo_t;
201
202 /* For x32, clock_t in _sigchld is 64bit aligned at 4 bytes. */
203 typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t;
204
205 typedef struct compat_x32_siginfo
206 {
207 int si_signo;
208 int si_errno;
209 int si_code;
210
211 union
212 {
213 int _pad[((128 / sizeof (int)) - 3)];
214
215 /* kill() */
216 struct
217 {
218 unsigned int _pid;
219 unsigned int _uid;
220 } _kill;
221
222 /* POSIX.1b timers */
223 struct
224 {
225 compat_timer_t _tid;
226 int _overrun;
227 compat_sigval_t _sigval;
228 } _timer;
229
230 /* POSIX.1b signals */
231 struct
232 {
233 unsigned int _pid;
234 unsigned int _uid;
235 compat_sigval_t _sigval;
236 } _rt;
237
238 /* SIGCHLD */
239 struct
240 {
241 unsigned int _pid;
242 unsigned int _uid;
243 int _status;
244 compat_x32_clock_t _utime;
245 compat_x32_clock_t _stime;
246 } _sigchld;
247
248 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
249 struct
250 {
251 unsigned int _addr;
252 unsigned int _addr_lsb;
253 } _sigfault;
254
255 /* SIGPOLL */
256 struct
257 {
258 int _band;
259 int _fd;
260 } _sigpoll;
261 } _sifields;
262 } compat_x32_siginfo_t __attribute__ ((__aligned__ (8)));
263
264 /* To simplify usage of siginfo fields. */
265
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
278
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. */
281
282 #ifndef si_timerid
283 #define si_timerid si_timer1
284 #endif
285 #ifndef si_overrun
286 #define si_overrun si_timer2
287 #endif
288
289 /* Convert the system provided siginfo into compatible siginfo. */
290
291 static void
292 compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
293 {
294 nat_siginfo_t from_nat;
295
296 memcpy (&from_nat, from, sizeof (from_nat));
297 memset (to, 0, sizeof (*to));
298
299 to->si_signo = from_nat.si_signo;
300 to->si_errno = from_nat.si_errno;
301 to->si_code = from_nat.si_code;
302
303 if (to->si_code == SI_TIMER)
304 {
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;
308 }
309 else if (to->si_code == SI_USER)
310 {
311 to->cpt_si_pid = from_nat.cpt_si_pid;
312 to->cpt_si_uid = from_nat.cpt_si_uid;
313 }
314 else if (to->si_code < 0)
315 {
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;
319 }
320 else
321 {
322 switch (to->si_signo)
323 {
324 case SIGCHLD:
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;
330 break;
331 case SIGILL:
332 case SIGFPE:
333 case SIGSEGV:
334 case SIGBUS:
335 to->cpt_si_addr = (intptr_t) from_nat.cpt_si_addr;
336 break;
337 case SIGPOLL:
338 to->cpt_si_band = from_nat.cpt_si_band;
339 to->cpt_si_fd = from_nat.cpt_si_fd;
340 break;
341 default:
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;
345 break;
346 }
347 }
348 }
349
350 /* Convert the compatible siginfo into system siginfo. */
351
352 static void
353 siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
354 {
355 nat_siginfo_t to_nat;
356
357 memset (&to_nat, 0, sizeof (to_nat));
358
359 to_nat.si_signo = from->si_signo;
360 to_nat.si_errno = from->si_errno;
361 to_nat.si_code = from->si_code;
362
363 if (to_nat.si_code == SI_TIMER)
364 {
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;
368 }
369 else if (to_nat.si_code == SI_USER)
370 {
371 to_nat.cpt_si_pid = from->cpt_si_pid;
372 to_nat.cpt_si_uid = from->cpt_si_uid;
373 }
374 if (to_nat.si_code < 0)
375 {
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;
379 }
380 else
381 {
382 switch (to_nat.si_signo)
383 {
384 case SIGCHLD:
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;
390 break;
391 case SIGILL:
392 case SIGFPE:
393 case SIGSEGV:
394 case SIGBUS:
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;
397 break;
398 case SIGPOLL:
399 to_nat.cpt_si_band = from->cpt_si_band;
400 to_nat.cpt_si_fd = from->cpt_si_fd;
401 break;
402 default:
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;
406 break;
407 }
408 }
409 memcpy (to, &to_nat, sizeof (to_nat));
410 }
411
412 /* Convert the system provided siginfo into compatible x32 siginfo. */
413
414 static void
415 compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t *to,
416 siginfo_t *from)
417 {
418 nat_siginfo_t from_nat;
419
420 memcpy (&from_nat, from, sizeof (from_nat));
421 memset (to, 0, sizeof (*to));
422
423 to->si_signo = from_nat.si_signo;
424 to->si_errno = from_nat.si_errno;
425 to->si_code = from_nat.si_code;
426
427 if (to->si_code == SI_TIMER)
428 {
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;
432 }
433 else if (to->si_code == SI_USER)
434 {
435 to->cpt_si_pid = from_nat.cpt_si_pid;
436 to->cpt_si_uid = from_nat.cpt_si_uid;
437 }
438 else if (to->si_code < 0)
439 {
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;
443 }
444 else
445 {
446 switch (to->si_signo)
447 {
448 case SIGCHLD:
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));
456 break;
457 case SIGILL:
458 case SIGFPE:
459 case SIGSEGV:
460 case SIGBUS:
461 to->cpt_si_addr = (intptr_t) from_nat.cpt_si_addr;
462 break;
463 case SIGPOLL:
464 to->cpt_si_band = from_nat.cpt_si_band;
465 to->cpt_si_fd = from_nat.cpt_si_fd;
466 break;
467 default:
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;
471 break;
472 }
473 }
474 }
475
476
477
478
479 /* Convert the compatible x32 siginfo into system siginfo. */
480 static void
481 siginfo_from_compat_x32_siginfo (siginfo_t *to,
482 compat_x32_siginfo_t *from)
483 {
484 nat_siginfo_t to_nat;
485
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;
490
491 if (to_nat.si_code == SI_TIMER)
492 {
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;
496 }
497 else if (to_nat.si_code == SI_USER)
498 {
499 to_nat.cpt_si_pid = from->cpt_si_pid;
500 to_nat.cpt_si_uid = from->cpt_si_uid;
501 }
502 if (to_nat.si_code < 0)
503 {
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;
507 }
508 else
509 {
510 switch (to_nat.si_signo)
511 {
512 case SIGCHLD:
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));
520 break;
521 case SIGILL:
522 case SIGFPE:
523 case SIGSEGV:
524 case SIGBUS:
525 to_nat.cpt_si_addr = (void *) (intptr_t) from->cpt_si_addr;
526 break;
527 case SIGPOLL:
528 to_nat.cpt_si_band = from->cpt_si_band;
529 to_nat.cpt_si_fd = from->cpt_si_fd;
530 break;
531 default:
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;
535 break;
536 }
537 }
538 memcpy (to, &to_nat, sizeof (to_nat));
539 }
540
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. */
545
546 int
547 amd64_linux_siginfo_fixup_common (siginfo_t *native, gdb_byte *inf,
548 int direction,
549 enum amd64_siginfo_fixup_mode mode)
550 {
551 if (mode == FIXUP_32)
552 {
553 gdb_assert (sizeof (siginfo_t) == sizeof (compat_siginfo_t));
554
555 if (direction == 0)
556 compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
557 else
558 siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
559
560 return 1;
561 }
562 else if (mode == FIXUP_X32)
563 {
564 gdb_assert (sizeof (siginfo_t) == sizeof (compat_x32_siginfo_t));
565
566 if (direction == 0)
567 compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
568 native);
569 else
570 siginfo_from_compat_x32_siginfo (native,
571 (struct compat_x32_siginfo *) inf);
572
573 return 1;
574 }
575 return 0;
576 }
This page took 0.041994 seconds and 4 git commands to generate.