Merge gdb and gdbserver implementations for siginfo
[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 /* These types below (compat_*) define a siginfo type that is layout
25 compatible with the siginfo type exported by the 32-bit userspace
26 support. */
27
28 typedef int compat_int_t;
29 typedef unsigned int compat_uptr_t;
30
31 typedef int compat_time_t;
32 typedef int compat_timer_t;
33 typedef int compat_clock_t;
34
35 struct compat_timeval
36 {
37 compat_time_t tv_sec;
38 int tv_usec;
39 };
40
41 typedef union compat_sigval
42 {
43 compat_int_t sival_int;
44 compat_uptr_t sival_ptr;
45 } compat_sigval_t;
46
47 typedef struct compat_siginfo
48 {
49 int si_signo;
50 int si_errno;
51 int si_code;
52
53 union
54 {
55 int _pad[((128 / sizeof (int)) - 3)];
56
57 /* kill() */
58 struct
59 {
60 unsigned int _pid;
61 unsigned int _uid;
62 } _kill;
63
64 /* POSIX.1b timers */
65 struct
66 {
67 compat_timer_t _tid;
68 int _overrun;
69 compat_sigval_t _sigval;
70 } _timer;
71
72 /* POSIX.1b signals */
73 struct
74 {
75 unsigned int _pid;
76 unsigned int _uid;
77 compat_sigval_t _sigval;
78 } _rt;
79
80 /* SIGCHLD */
81 struct
82 {
83 unsigned int _pid;
84 unsigned int _uid;
85 int _status;
86 compat_clock_t _utime;
87 compat_clock_t _stime;
88 } _sigchld;
89
90 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
91 struct
92 {
93 unsigned int _addr;
94 } _sigfault;
95
96 /* SIGPOLL */
97 struct
98 {
99 int _band;
100 int _fd;
101 } _sigpoll;
102 } _sifields;
103 } compat_siginfo_t;
104
105 /* For x32, clock_t in _sigchld is 64bit aligned at 4 bytes. */
106 typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t;
107
108 typedef struct compat_x32_siginfo
109 {
110 int si_signo;
111 int si_errno;
112 int si_code;
113
114 union
115 {
116 int _pad[((128 / sizeof (int)) - 3)];
117
118 /* kill() */
119 struct
120 {
121 unsigned int _pid;
122 unsigned int _uid;
123 } _kill;
124
125 /* POSIX.1b timers */
126 struct
127 {
128 compat_timer_t _tid;
129 int _overrun;
130 compat_sigval_t _sigval;
131 } _timer;
132
133 /* POSIX.1b signals */
134 struct
135 {
136 unsigned int _pid;
137 unsigned int _uid;
138 compat_sigval_t _sigval;
139 } _rt;
140
141 /* SIGCHLD */
142 struct
143 {
144 unsigned int _pid;
145 unsigned int _uid;
146 int _status;
147 compat_x32_clock_t _utime;
148 compat_x32_clock_t _stime;
149 } _sigchld;
150
151 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
152 struct
153 {
154 unsigned int _addr;
155 } _sigfault;
156
157 /* SIGPOLL */
158 struct
159 {
160 int _band;
161 int _fd;
162 } _sigpoll;
163 } _sifields;
164 } compat_x32_siginfo_t __attribute__ ((__aligned__ (8)));
165
166 /* To simplify usage of siginfo fields. */
167
168 #define cpt_si_pid _sifields._kill._pid
169 #define cpt_si_uid _sifields._kill._uid
170 #define cpt_si_timerid _sifields._timer._tid
171 #define cpt_si_overrun _sifields._timer._overrun
172 #define cpt_si_status _sifields._sigchld._status
173 #define cpt_si_utime _sifields._sigchld._utime
174 #define cpt_si_stime _sifields._sigchld._stime
175 #define cpt_si_ptr _sifields._rt._sigval.sival_ptr
176 #define cpt_si_addr _sifields._sigfault._addr
177 #define cpt_si_band _sifields._sigpoll._band
178 #define cpt_si_fd _sifields._sigpoll._fd
179
180 /* glibc at least up to 2.3.2 doesn't have si_timerid, si_overrun.
181 In their place is si_timer1,si_timer2. */
182
183 #ifndef si_timerid
184 #define si_timerid si_timer1
185 #endif
186 #ifndef si_overrun
187 #define si_overrun si_timer2
188 #endif
189
190 /* Convert the system provided siginfo into compatible siginfo. */
191
192 static void
193 compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
194 {
195 memset (to, 0, sizeof (*to));
196
197 to->si_signo = from->si_signo;
198 to->si_errno = from->si_errno;
199 to->si_code = from->si_code;
200
201 if (to->si_code == SI_TIMER)
202 {
203 to->cpt_si_timerid = from->si_timerid;
204 to->cpt_si_overrun = from->si_overrun;
205 to->cpt_si_ptr = (intptr_t) from->si_ptr;
206 }
207 else if (to->si_code == SI_USER)
208 {
209 to->cpt_si_pid = from->si_pid;
210 to->cpt_si_uid = from->si_uid;
211 }
212 else if (to->si_code < 0)
213 {
214 to->cpt_si_pid = from->si_pid;
215 to->cpt_si_uid = from->si_uid;
216 to->cpt_si_ptr = (intptr_t) from->si_ptr;
217 }
218 else
219 {
220 switch (to->si_signo)
221 {
222 case SIGCHLD:
223 to->cpt_si_pid = from->si_pid;
224 to->cpt_si_uid = from->si_uid;
225 to->cpt_si_status = from->si_status;
226 to->cpt_si_utime = from->si_utime;
227 to->cpt_si_stime = from->si_stime;
228 break;
229 case SIGILL:
230 case SIGFPE:
231 case SIGSEGV:
232 case SIGBUS:
233 to->cpt_si_addr = (intptr_t) from->si_addr;
234 break;
235 case SIGPOLL:
236 to->cpt_si_band = from->si_band;
237 to->cpt_si_fd = from->si_fd;
238 break;
239 default:
240 to->cpt_si_pid = from->si_pid;
241 to->cpt_si_uid = from->si_uid;
242 to->cpt_si_ptr = (intptr_t) from->si_ptr;
243 break;
244 }
245 }
246 }
247
248 /* Convert the compatible siginfo into system siginfo. */
249
250 static void
251 siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
252 {
253 memset (to, 0, sizeof (*to));
254
255 to->si_signo = from->si_signo;
256 to->si_errno = from->si_errno;
257 to->si_code = from->si_code;
258
259 if (to->si_code == SI_TIMER)
260 {
261 to->si_timerid = from->cpt_si_timerid;
262 to->si_overrun = from->cpt_si_overrun;
263 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
264 }
265 else if (to->si_code == SI_USER)
266 {
267 to->si_pid = from->cpt_si_pid;
268 to->si_uid = from->cpt_si_uid;
269 }
270 if (to->si_code < 0)
271 {
272 to->si_pid = from->cpt_si_pid;
273 to->si_uid = from->cpt_si_uid;
274 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
275 }
276 else
277 {
278 switch (to->si_signo)
279 {
280 case SIGCHLD:
281 to->si_pid = from->cpt_si_pid;
282 to->si_uid = from->cpt_si_uid;
283 to->si_status = from->cpt_si_status;
284 to->si_utime = from->cpt_si_utime;
285 to->si_stime = from->cpt_si_stime;
286 break;
287 case SIGILL:
288 case SIGFPE:
289 case SIGSEGV:
290 case SIGBUS:
291 to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
292 break;
293 case SIGPOLL:
294 to->si_band = from->cpt_si_band;
295 to->si_fd = from->cpt_si_fd;
296 break;
297 default:
298 to->si_pid = from->cpt_si_pid;
299 to->si_uid = from->cpt_si_uid;
300 to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
301 break;
302 }
303 }
304 }
305
306 /* Convert the system provided siginfo into compatible x32 siginfo. */
307
308 static void
309 compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t *to,
310 siginfo_t *from)
311 {
312 memset (to, 0, sizeof (*to));
313
314 to->si_signo = from->si_signo;
315 to->si_errno = from->si_errno;
316 to->si_code = from->si_code;
317
318 if (to->si_code == SI_TIMER)
319 {
320 to->cpt_si_timerid = from->si_timerid;
321 to->cpt_si_overrun = from->si_overrun;
322 to->cpt_si_ptr = (intptr_t) from->si_ptr;
323 }
324 else if (to->si_code == SI_USER)
325 {
326 to->cpt_si_pid = from->si_pid;
327 to->cpt_si_uid = from->si_uid;
328 }
329 else if (to->si_code < 0)
330 {
331 to->cpt_si_pid = from->si_pid;
332 to->cpt_si_uid = from->si_uid;
333 to->cpt_si_ptr = (intptr_t) from->si_ptr;
334 }
335 else
336 {
337 switch (to->si_signo)
338 {
339 case SIGCHLD:
340 to->cpt_si_pid = from->si_pid;
341 to->cpt_si_uid = from->si_uid;
342 to->cpt_si_status = from->si_status;
343 memcpy (&to->cpt_si_utime, &from->si_utime,
344 sizeof (to->cpt_si_utime));
345 memcpy (&to->cpt_si_stime, &from->si_stime,
346 sizeof (to->cpt_si_stime));
347 break;
348 case SIGILL:
349 case SIGFPE:
350 case SIGSEGV:
351 case SIGBUS:
352 to->cpt_si_addr = (intptr_t) from->si_addr;
353 break;
354 case SIGPOLL:
355 to->cpt_si_band = from->si_band;
356 to->cpt_si_fd = from->si_fd;
357 break;
358 default:
359 to->cpt_si_pid = from->si_pid;
360 to->cpt_si_uid = from->si_uid;
361 to->cpt_si_ptr = (intptr_t) from->si_ptr;
362 break;
363 }
364 }
365 }
366
367 /* Convert the compatible x32 siginfo into system siginfo. */
368 static void
369 siginfo_from_compat_x32_siginfo (siginfo_t *to,
370 compat_x32_siginfo_t *from)
371 {
372 memset (to, 0, sizeof (*to));
373
374 to->si_signo = from->si_signo;
375 to->si_errno = from->si_errno;
376 to->si_code = from->si_code;
377
378 if (to->si_code == SI_TIMER)
379 {
380 to->si_timerid = from->cpt_si_timerid;
381 to->si_overrun = from->cpt_si_overrun;
382 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
383 }
384 else if (to->si_code == SI_USER)
385 {
386 to->si_pid = from->cpt_si_pid;
387 to->si_uid = from->cpt_si_uid;
388 }
389 if (to->si_code < 0)
390 {
391 to->si_pid = from->cpt_si_pid;
392 to->si_uid = from->cpt_si_uid;
393 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
394 }
395 else
396 {
397 switch (to->si_signo)
398 {
399 case SIGCHLD:
400 to->si_pid = from->cpt_si_pid;
401 to->si_uid = from->cpt_si_uid;
402 to->si_status = from->cpt_si_status;
403 memcpy (&to->si_utime, &from->cpt_si_utime,
404 sizeof (to->si_utime));
405 memcpy (&to->si_stime, &from->cpt_si_stime,
406 sizeof (to->si_stime));
407 break;
408 case SIGILL:
409 case SIGFPE:
410 case SIGSEGV:
411 case SIGBUS:
412 to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
413 break;
414 case SIGPOLL:
415 to->si_band = from->cpt_si_band;
416 to->si_fd = from->cpt_si_fd;
417 break;
418 default:
419 to->si_pid = from->cpt_si_pid;
420 to->si_uid = from->cpt_si_uid;
421 to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
422 break;
423 }
424 }
425 }
426
427 /* Convert a native/host siginfo object, into/from the siginfo in the
428 layout of the inferiors' architecture. Returns true if any
429 conversion was done; false otherwise. If DIRECTION is 1, then copy
430 from INF to NATIVE. If DIRECTION is 0, then copy from NATIVE to INF. */
431
432 int
433 amd64_linux_siginfo_fixup_common (siginfo_t *native, gdb_byte *inf,
434 int direction,
435 enum amd64_siginfo_fixup_mode mode)
436 {
437 if (mode == FIXUP_32)
438 {
439 gdb_assert (sizeof (siginfo_t) == sizeof (compat_siginfo_t));
440
441 if (direction == 0)
442 compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
443 else
444 siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
445
446 return 1;
447 }
448 else if (mode == FIXUP_X32)
449 {
450 gdb_assert (sizeof (siginfo_t) == sizeof (compat_x32_siginfo_t));
451
452 if (direction == 0)
453 compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
454 native);
455 else
456 siginfo_from_compat_x32_siginfo (native,
457 (struct compat_x32_siginfo *) inf);
458
459 return 1;
460 }
461 return 0;
462 }
This page took 0.056811 seconds and 4 git commands to generate.