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