1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "config.h"
21
22 #ifdef HAVE_SIGNAL_H
23 # if !defined(_GNU_SOURCE)
24 # define _GNU_SOURCE /* required for getting at program counter */
25 # endif
26 # include <signal.h>
27 #endif
28
29 #ifdef HAVE_SYS_UCONTEXT_H
30 # if !defined(_GNU_SOURCE)
31 # define _GNU_SOURCE /* required for getting at program counter */
32 # endif
33 # include <sys/ucontext.h>
34 #endif
35
36 #ifdef HAVE_EXECINFO_H
37 # include <execinfo.h>
38 #endif
39
40 #include "common.h"
41 #include "log.h"
42
43 #include "fatal.h"
44
get_signal_name(int sig)45 const char *get_signal_name(int sig)
46 {
47 /* either strsignal() or sys_siglist[] could be used to */
48 /* get signal name, but these methods are not portable */
49
50 /* not all POSIX signals are available on all platforms, */
51 /* so we list only signals that we react to in our handlers */
52
53 switch (sig)
54 {
55 case SIGALRM: return "SIGALRM";
56 case SIGILL: return "SIGILL";
57 case SIGFPE: return "SIGFPE";
58 case SIGSEGV: return "SIGSEGV";
59 case SIGBUS: return "SIGBUS";
60 case SIGQUIT: return "SIGQUIT";
61 case SIGHUP: return "SIGHUP";
62 case SIGINT: return "SIGINT";
63 case SIGTERM: return "SIGTERM";
64 case SIGPIPE: return "SIGPIPE";
65 case SIGUSR1: return "SIGUSR1";
66 case SIGUSR2: return "SIGUSR2";
67 default: return "unknown";
68 }
69 }
70
71 #if defined(HAVE_SYS_UCONTEXT_H) && (defined(REG_EIP) || defined(REG_RIP))
72
get_register_name(int reg)73 static const char *get_register_name(int reg)
74 {
75 switch (reg)
76 {
77
78 /* i386 */
79
80 #ifdef REG_GS
81 case REG_GS: return "gs";
82 #endif
83 #ifdef REG_FS
84 case REG_FS: return "fs";
85 #endif
86 #ifdef REG_ES
87 case REG_ES: return "es";
88 #endif
89 #ifdef REG_DS
90 case REG_DS: return "ds";
91 #endif
92 #ifdef REG_EDI
93 case REG_EDI: return "edi";
94 #endif
95 #ifdef REG_ESI
96 case REG_ESI: return "esi";
97 #endif
98 #ifdef REG_EBP
99 case REG_EBP: return "ebp";
100 #endif
101 #ifdef REG_ESP
102 case REG_ESP: return "esp";
103 #endif
104 #ifdef REG_EBX
105 case REG_EBX: return "ebx";
106 #endif
107 #ifdef REG_EDX
108 case REG_EDX: return "edx";
109 #endif
110 #ifdef REG_ECX
111 case REG_ECX: return "ecx";
112 #endif
113 #ifdef REG_EAX
114 case REG_EAX: return "eax";
115 #endif
116 #ifdef REG_EIP
117 case REG_EIP: return "eip";
118 #endif
119 #ifdef REG_CS
120 case REG_CS: return "cs";
121 #endif
122 #ifdef REG_UESP
123 case REG_UESP: return "uesp";
124 #endif
125 #ifdef REG_SS
126 case REG_SS: return "ss";
127 #endif
128
129 /* x86_64 */
130
131 #ifdef REG_R8
132 case REG_R8: return "r8";
133 #endif
134 #ifdef REG_R9
135 case REG_R9: return "r9";
136 #endif
137 #ifdef REG_R10
138 case REG_R10: return "r10";
139 #endif
140 #ifdef REG_R11
141 case REG_R11: return "r11";
142 #endif
143 #ifdef REG_R12
144 case REG_R12: return "r12";
145 #endif
146 #ifdef REG_R13
147 case REG_R13: return "r13";
148 #endif
149 #ifdef REG_R14
150 case REG_R14: return "r14";
151 #endif
152 #ifdef REG_R15
153 case REG_R15: return "r15";
154 #endif
155 #ifdef REG_RDI
156 case REG_RDI: return "rdi";
157 #endif
158 #ifdef REG_RSI
159 case REG_RSI: return "rsi";
160 #endif
161 #ifdef REG_RBP
162 case REG_RBP: return "rbp";
163 #endif
164 #ifdef REG_RBX
165 case REG_RBX: return "rbx";
166 #endif
167 #ifdef REG_RDX
168 case REG_RDX: return "rdx";
169 #endif
170 #ifdef REG_RAX
171 case REG_RAX: return "rax";
172 #endif
173 #ifdef REG_RCX
174 case REG_RCX: return "rcx";
175 #endif
176 #ifdef REG_RSP
177 case REG_RSP: return "rsp";
178 #endif
179 #ifdef REG_RIP
180 case REG_RIP: return "rip";
181 #endif
182 #ifdef REG_CSGSFS
183 case REG_CSGSFS: return "csgsfs";
184 #endif
185 #ifdef REG_OLDMASK
186 case REG_OLDMASK: return "oldmask";
187 #endif
188 #ifdef REG_CR2
189 case REG_CR2: return "cr2";
190 #endif
191
192 /* i386 and x86_64 */
193
194 #ifdef REG_EFL
195 case REG_EFL: return "efl";
196 #endif
197 #ifdef REG_ERR
198 case REG_ERR: return "err";
199 #endif
200 #ifdef REG_TRAPNO
201 case REG_TRAPNO: return "trapno";
202 #endif
203
204 /* unknown */
205
206 default: return "unknown";
207 }
208 }
209
210 #endif /* defined(HAVE_SYS_UCONTEXT_H) && (defined(REG_EIP) || defined(REG_RIP)) */
211
zbx_backtrace(void)212 void zbx_backtrace(void)
213 {
214 # define ZBX_BACKTRACE_SIZE 60
215 #ifdef HAVE_EXECINFO_H
216 char **bcktrc_syms;
217 void *bcktrc[ZBX_BACKTRACE_SIZE];
218 int bcktrc_sz, i;
219
220 zabbix_log(LOG_LEVEL_CRIT, "=== Backtrace: ===");
221
222 bcktrc_sz = backtrace(bcktrc, ZBX_BACKTRACE_SIZE);
223 bcktrc_syms = backtrace_symbols(bcktrc, bcktrc_sz);
224
225 if (NULL == bcktrc_syms)
226 {
227 zabbix_log(LOG_LEVEL_CRIT, "error in backtrace_symbols(): %s", zbx_strerror(errno));
228
229 for (i = 0; i < bcktrc_sz; i++)
230 zabbix_log(LOG_LEVEL_CRIT, "%d: %p", bcktrc_sz - i - 1, bcktrc[i]);
231 }
232 else
233 {
234 for (i = 0; i < bcktrc_sz; i++)
235 zabbix_log(LOG_LEVEL_CRIT, "%d: %s", bcktrc_sz - i - 1, bcktrc_syms[i]);
236
237 zbx_free(bcktrc_syms);
238 }
239 #else
240 zabbix_log(LOG_LEVEL_CRIT, "backtrace is not available for this platform");
241 #endif /* HAVE_EXECINFO_H */
242 }
243
zbx_log_fatal_info(void * context,unsigned int flags)244 void zbx_log_fatal_info(void *context, unsigned int flags)
245 {
246 #ifdef HAVE_SYS_UCONTEXT_H
247
248 #if defined(REG_EIP) || defined(REG_RIP)
249 ucontext_t *uctx = (ucontext_t *)context;
250 #endif
251
252 /* look for GET_PC() macro in sigcontextinfo.h files */
253 /* of glibc if you wish to add more CPU architectures */
254
255 # if defined(REG_EIP) /* i386 */
256
257 # define ZBX_GET_REG(uctx, reg) (uctx)->uc_mcontext.gregs[reg]
258 # define ZBX_GET_PC(uctx) ZBX_GET_REG(uctx, REG_EIP)
259
260 # elif defined(REG_RIP) /* x86_64 */
261
262 # define ZBX_GET_REG(uctx, reg) (uctx)->uc_mcontext.gregs[reg]
263 # define ZBX_GET_PC(uctx) ZBX_GET_REG(uctx, REG_RIP)
264
265 # endif
266
267 #endif /* HAVE_SYS_UCONTEXT_H */
268 int i;
269 FILE *fd;
270
271 zabbix_log(LOG_LEVEL_CRIT, "====== Fatal information: ======");
272
273 if (0 != (flags & ZBX_FATAL_LOG_PC_REG_SF))
274 {
275 #ifdef HAVE_SYS_UCONTEXT_H
276
277 #ifdef ZBX_GET_PC
278 /* On 64-bit GNU/Linux ZBX_GET_PC() returns 'greg_t' defined as 'long long int' (8 bytes). */
279 /* On 32-bit GNU/Linux it is defined as 'int' (4 bytes). To print registers in a common way we print */
280 /* them as 'long int' or 'unsigned long int' which is 8 bytes on 64-bit GNU/Linux and 4 bytes on */
281 /* 32-bit system. */
282
283 zabbix_log(LOG_LEVEL_CRIT, "Program counter: %p", (void *)(ZBX_GET_PC(uctx)));
284 zabbix_log(LOG_LEVEL_CRIT, "=== Registers: ===");
285
286 for (i = 0; i < NGREG; i++)
287 {
288 zabbix_log(LOG_LEVEL_CRIT, "%-7s = %16lx = %20lu = %20ld", get_register_name(i),
289 (unsigned long int)(ZBX_GET_REG(uctx, i)),
290 (unsigned long int)(ZBX_GET_REG(uctx, i)),
291 (long int)(ZBX_GET_REG(uctx, i)));
292 }
293 #ifdef REG_EBP /* dump a bit of stack frame for i386 */
294 zabbix_log(LOG_LEVEL_CRIT, "=== Stack frame: ===");
295
296 for (i = 16; i >= 2; i--)
297 {
298 unsigned int offset = (unsigned int)i * ZBX_PTR_SIZE;
299
300 zabbix_log(LOG_LEVEL_CRIT, "+0x%02x(%%ebp) = ebp + %2d = %08x = %10u = %11d%s",
301 offset, (int)offset,
302 *(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + offset),
303 *(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + offset),
304 *(int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + offset),
305 i == 2 ? " <--- call arguments" : "");
306 }
307 zabbix_log(LOG_LEVEL_CRIT, "+0x%02x(%%ebp) = ebp + %2d = %08x%28s<--- return address",
308 ZBX_PTR_SIZE, (int)ZBX_PTR_SIZE,
309 *(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + ZBX_PTR_SIZE), "");
310 zabbix_log(LOG_LEVEL_CRIT, " (%%ebp) = ebp = %08x%28s<--- saved ebp value",
311 *(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP)), "");
312
313 for (i = 1; i <= 16; i++)
314 {
315 unsigned int offset = (unsigned int)i * ZBX_PTR_SIZE;
316
317 zabbix_log(LOG_LEVEL_CRIT, "-0x%02x(%%ebp) = ebp - %2d = %08x = %10u = %11d%s",
318 offset, (int)offset,
319 *(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - offset),
320 *(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - offset),
321 *(int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - offset),
322 i == 1 ? " <--- local variables" : "");
323 }
324 #endif /* REG_EBP */
325 #else
326 zabbix_log(LOG_LEVEL_CRIT, "program counter not available for this architecture");
327 zabbix_log(LOG_LEVEL_CRIT, "=== Registers: ===");
328 zabbix_log(LOG_LEVEL_CRIT, "register dump not available for this architecture");
329 #endif /* ZBX_GET_PC */
330 #endif /* HAVE_SYS_UCONTEXT_H */
331 }
332
333 if (0 != (flags & ZBX_FATAL_LOG_BACKTRACE))
334 zbx_backtrace();
335
336 if (0 != (flags & ZBX_FATAL_LOG_MEM_MAP))
337 {
338 zabbix_log(LOG_LEVEL_CRIT, "=== Memory map: ===");
339
340 if (NULL != (fd = fopen("/proc/self/maps", "r")))
341 {
342 char line[1024];
343
344 while (NULL != fgets(line, sizeof(line), fd))
345 {
346 if (line[0] != '\0')
347 line[strlen(line) - 1] = '\0'; /* remove trailing '\n' */
348
349 zabbix_log(LOG_LEVEL_CRIT, "%s", line);
350 }
351
352 zbx_fclose(fd);
353 }
354 else
355 zabbix_log(LOG_LEVEL_CRIT, "memory map not available for this platform");
356 }
357
358 #ifdef ZBX_GET_PC
359 zabbix_log(LOG_LEVEL_CRIT, "================================");
360 zabbix_log(LOG_LEVEL_CRIT, "Please consider attaching a disassembly listing to your bug report.");
361 zabbix_log(LOG_LEVEL_CRIT, "This listing can be produced with, e.g., objdump -DSswx %s.", progname);
362 #endif
363
364 zabbix_log(LOG_LEVEL_CRIT, "================================");
365 }
366