]> granicus.if.org Git - strace/blob - printsiginfo.c
Fix time syscall decoding for some personalities
[strace] / printsiginfo.c
1 #include "defs.h"
2
3 #include <signal.h>
4 #include <linux/audit.h>
5
6 #include "printsiginfo.h"
7
8 #include "xlat/audit_arch.h"
9 #include "xlat/sigbus_codes.h"
10 #include "xlat/sigchld_codes.h"
11 #include "xlat/sigfpe_codes.h"
12 #include "xlat/sigill_codes.h"
13 #include "xlat/siginfo_codes.h"
14 #include "xlat/sigpoll_codes.h"
15 #include "xlat/sigprof_codes.h"
16 #include "xlat/sigsegv_codes.h"
17 #include "xlat/sigsys_codes.h"
18 #include "xlat/sigtrap_codes.h"
19
20 #ifdef SIGEMT
21 # include "xlat/sigemt_codes.h"
22 #endif
23
24 #ifndef SI_FROMUSER
25 # define SI_FROMUSER(sip)       ((sip)->si_code <= 0)
26 #endif
27
28 static void
29 printsigsource(const siginfo_t *sip)
30 {
31         tprintf(", si_pid=%lu, si_uid=%lu",
32                 (unsigned long) sip->si_pid,
33                 (unsigned long) sip->si_uid);
34 }
35
36 static void
37 printsigval(const siginfo_t *sip, bool verbose)
38 {
39         if (!verbose)
40                 tprints(", ...");
41         else
42                 tprintf(", si_value={int=%u, ptr=%#lx}",
43                         sip->si_int,
44                         (unsigned long) sip->si_ptr);
45 }
46
47 static void
48 print_si_code(int si_signo, int si_code)
49 {
50         const char *code = xlookup(siginfo_codes, si_code);
51
52         if (!code) {
53                 switch (si_signo) {
54                 case SIGTRAP:
55                         code = xlookup(sigtrap_codes, si_code);
56                         break;
57                 case SIGCHLD:
58                         code = xlookup(sigchld_codes, si_code);
59                         break;
60                 case SIGPOLL:
61                         code = xlookup(sigpoll_codes, si_code);
62                         break;
63                 case SIGPROF:
64                         code = xlookup(sigprof_codes, si_code);
65                         break;
66                 case SIGILL:
67                         code = xlookup(sigill_codes, si_code);
68                         break;
69 #ifdef SIGEMT
70                 case SIGEMT:
71                         code = xlookup(sigemt_codes, si_code);
72                         break;
73 #endif
74                 case SIGFPE:
75                         code = xlookup(sigfpe_codes, si_code);
76                         break;
77                 case SIGSEGV:
78                         code = xlookup(sigsegv_codes, si_code);
79                         break;
80                 case SIGBUS:
81                         code = xlookup(sigbus_codes, si_code);
82                         break;
83                 case SIGSYS:
84                         code = xlookup(sigsys_codes, si_code);
85                         break;
86                 }
87         }
88
89         if (code)
90                 tprints(code);
91         else
92                 tprintf("%#x", si_code);
93 }
94
95 static void
96 print_si_info(const siginfo_t *sip, bool verbose)
97 {
98         if (sip->si_errno) {
99                 tprints(", si_errno=");
100                 if ((unsigned) sip->si_errno < nerrnos
101                     && errnoent[sip->si_errno])
102                         tprints(errnoent[sip->si_errno]);
103                 else
104                         tprintf("%d", sip->si_errno);
105         }
106
107         if (SI_FROMUSER(sip)) {
108                 switch (sip->si_code) {
109                 case SI_USER:
110                         printsigsource(sip);
111                         break;
112                 case SI_TKILL:
113                         printsigsource(sip);
114                         break;
115 #if defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN
116                 case SI_TIMER:
117                         tprintf(", si_timerid=%#x, si_overrun=%d",
118                                 sip->si_timerid, sip->si_overrun);
119                         printsigval(sip, verbose);
120                         break;
121 #endif
122                 default:
123                         printsigsource(sip);
124                         if (sip->si_ptr)
125                                 printsigval(sip, verbose);
126                         break;
127                 }
128         } else {
129                 switch (sip->si_signo) {
130                 case SIGCHLD:
131                         printsigsource(sip);
132                         tprints(", si_status=");
133                         if (sip->si_code == CLD_EXITED)
134                                 tprintf("%d", sip->si_status);
135                         else
136                                 printsignal(sip->si_status);
137                         if (!verbose)
138                                 tprints(", ...");
139                         else
140                                 tprintf(", si_utime=%llu, si_stime=%llu",
141                                         (unsigned long long) sip->si_utime,
142                                         (unsigned long long) sip->si_stime);
143                         break;
144                 case SIGILL: case SIGFPE:
145                 case SIGSEGV: case SIGBUS:
146                         tprintf(", si_addr=%#lx",
147                                 (unsigned long) sip->si_addr);
148                         break;
149                 case SIGPOLL:
150                         switch (sip->si_code) {
151                         case POLL_IN: case POLL_OUT: case POLL_MSG:
152                                 tprintf(", si_band=%ld",
153                                         (long) sip->si_band);
154                                 break;
155                         }
156                         break;
157 #ifdef HAVE_SIGINFO_T_SI_SYSCALL
158                 case SIGSYS:
159                         tprintf(", si_call_addr=%#lx, si_syscall=__NR_%s, si_arch=",
160                                 (unsigned long) sip->si_call_addr,
161                                 syscall_name(sip->si_syscall));
162                         printxval(audit_arch, sip->si_arch, "AUDIT_ARCH_???");
163                         break;
164 #endif
165                 default:
166                         if (sip->si_pid || sip->si_uid)
167                                 printsigsource(sip);
168                         if (sip->si_ptr)
169                                 printsigval(sip, verbose);
170                 }
171         }
172 }
173
174 void
175 printsiginfo(const siginfo_t *sip, bool verbose)
176 {
177         if (sip->si_signo == 0) {
178                 tprints("{}");
179                 return;
180         }
181         tprints("{si_signo=");
182         printsignal(sip->si_signo);
183
184         tprints(", si_code=");
185         print_si_code(sip->si_signo, sip->si_code);
186
187 #ifdef SI_NOINFO
188         if (sip->si_code != SI_NOINFO)
189 #endif
190                 print_si_info(sip, verbose);
191
192         tprints("}");
193 }
194
195 void
196 printsiginfo_at(struct tcb *tcp, long addr)
197 {
198         siginfo_t si;
199
200         if (!umove_or_printaddr(tcp, addr, &si))
201                 printsiginfo(&si, verbose(tcp));
202 }