3 * Copyright (c) 2012-2016 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
30 #include <linux/unistd.h>
32 #include <sys/prctl.h>
34 #include <sys/sysinfo.h>
35 #include <sys/socket.h>
40 #include <libunwind.h>
41 #include "sys-assert.h"
44 #define CMDLINE_PATH "/proc/self/cmdline"
45 #define EXE_PATH "/proc/self/exe"
46 #define MAPS_PATH "/proc/self/maps"
47 #define MEMINFO_PATH "/proc/meminfo"
48 #define VERINFO_PATH "/etc/info.ini"
49 #define STATUS_PATH "/proc/self/status"
50 #define TASK_PATH "/proc/self/task"
52 #define CRASH_INFO_PATH "/tmp/crash_stack"
53 #define CRASH_SOCKET "/tmp/crash_socket"
54 #define CRASH_SOCKET_PATH_LEN 17
56 #define CRASH_CALLSTACKINFO_TITLE "Callstack Information"
57 #define CRASH_CALLSTACKINFO_TITLE_E "End of Call Stack"
58 #define CRASH_MAPSINFO_TITLE "Maps Information"
59 #define CRASH_MAPSINFO_TITLE_E "End of Maps Information"
60 #define CRASH_MEMINFO_TITLE "Memory Information"
61 #define CRASH_THREADINFO_TITLE "Threads Information"
63 #define STR_ANONY "[anony]"
64 #define STR_ANNOY_LEN 8
75 #define TIME_MAX_LEN 64
77 #define BUF_SIZE (BUFSIZ)
78 #define CALLSTACK_SIZE 100
79 #define FUNC_NAME_MAX_LEN 128
80 #define PATH_LEN (FILE_LEN + NAME_MAX)
82 #define KB(bytes) ((bytes)/1024)
84 /* permission for open file */
85 #define DIR_PERMS (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
86 /* permission for open file */
87 #define FILE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
89 int sig_to_handle[] = {
90 SIGILL, SIGTRAP, SIGABRT, SIGBUS,
91 SIGFPE, SIGSEGV, SIGSTKFLT, SIGXCPU, SIGXFSZ, SIGSYS };
93 #define NUM_SIG_TO_HANDLE \
94 ((int)(sizeof(sig_to_handle)/sizeof(sig_to_handle[0])))
96 struct sigaction g_oldact[NUM_SIG_TO_HANDLE];
98 extern void dump_registers(int fd, void *context);
99 extern int dump_callstack(void **callstack_addrs, int size, void *context, int retry);
101 /* get function symbol from elf */
102 static int trace_symbols(void *const *array, int size, struct addr_node *start, int fd)
105 Elf32_Ehdr elf_h = {{0, }, 0, };
106 Elf32_Shdr *s_headers;
107 Elf32_Sym *symtab_entry;
108 int i, cnt, file, ret;
110 unsigned long addr, start_addr, offset_addr;
111 unsigned int strtab_index = 0;
112 unsigned int symtab_index = 0;
114 int found_symtab = 0;
116 for (cnt = 0; cnt < size; cnt++) {
118 /* FIXME : for walking on stack trace */
119 if (dladdr(array[cnt], &info_funcs) == 0) {
120 fprintf(stderr, "[sys-assert]dladdr returnes error!\n");
121 /* print just address */
124 cnt, array[cnt], dlerror());
127 start_addr = (unsigned long)get_start_addr(array[cnt], start);
128 addr = (unsigned long)array[cnt];
129 /* because of launchpad,
130 * return value of dladdr when find executable is wrong.
131 * so fix dli_fname here */
132 if (info_funcs.dli_fbase &&
133 info_funcs.dli_fname &&
134 info_funcs.dli_fbase == (void *)BASE_LAUNCHPAD_ADDR &&
135 (strncmp("/opt/apps/", info_funcs.dli_fname,
136 strlen("/opt/apps/")) == 0)) {
137 info_funcs.dli_fname = get_fpath(array[cnt], start);
140 offset_addr = addr - start_addr;
143 /* find symbol from elf file */
144 if (info_funcs.dli_sname == NULL) {
146 /* Both dli_sname and dli_fname is NULL, sys-assert cannot trace any information.
147 Thus, sys-assert skips to translate such address entry.
148 However, if a developer wants raw information, we need to fix the code to print raw data */
149 if (info_funcs.dli_fname == NULL)
152 file = open(info_funcs.dli_fname, O_RDONLY);
154 fname = strchr(info_funcs.dli_fname, '/');
157 file = open(fname, O_RDONLY);
160 "%2d: (%p) [%s] + %p\n",
162 info_funcs.dli_fname, offset_addr);
166 ret = read(file, &elf_h, sizeof(Elf32_Ehdr));
167 if (ret < sizeof(Elf32_Ehdr) ||
168 elf_h.e_shnum <= 0 ||
169 SHN_LORESERVE < elf_h.e_shnum) {
170 fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
171 cnt, array[cnt], info_funcs.dli_fname, offset_addr);
175 if (elf_h.e_type == ET_EXEC) {
176 info_funcs.dli_fbase = 0;
180 (Elf32_Shdr *) mmap(0, elf_h.e_shnum * sizeof(Elf32_Shdr),
181 PROT_READ | PROT_WRITE,
182 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
183 if (s_headers == NULL) {
184 fprintf(stderr, "[sys-assert]malloc failed\n");
185 fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
186 cnt, array[cnt], info_funcs.dli_fname, offset_addr);
190 ret = lseek(file, elf_h.e_shoff, SEEK_SET);
191 if (ret < 0 || elf_h.e_shentsize > sizeof(Elf32_Shdr) ||
192 elf_h.e_shentsize <= 0) {
194 munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
197 for (i = 0; i < elf_h.e_shnum; i++) {
198 ret = read(file, &s_headers[i], elf_h.e_shentsize);
199 if (ret < elf_h.e_shentsize) {
200 fprintf(stderr, "[sys-assert]read error\n");
201 munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
206 for (i = 0; i < elf_h.e_shnum; i++) {
207 if (s_headers[i].sh_type == SHT_SYMTAB) {
209 if (s_headers[i].sh_entsize != 0 &&
210 s_headers[i].sh_size != 0) {
212 s_headers[i].sh_size / s_headers[i].sh_entsize;
220 "[sys-assert] can't find symtab\n");
221 munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
225 if (symtab_index < elf_h.e_shnum)
226 strtab_index = s_headers[symtab_index].sh_link;
227 if (!strtab_index || elf_h.e_shnum <= strtab_index) {
228 fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
229 cnt, array[cnt], info_funcs.dli_fname, offset_addr);
230 munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
235 (Elf32_Sym *)mmap(0, sizeof(Elf32_Sym) * num_st,
236 PROT_READ | PROT_WRITE,
237 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
238 if (symtab_entry == NULL) {
239 fprintf(stderr, "[sys-assert]malloc failed\n");
240 munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
244 ret = lseek(file, s_headers[symtab_index].sh_offset, SEEK_SET);
246 fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
247 cnt, array[cnt], info_funcs.dli_fname, offset_addr);
248 munmap(symtab_entry, sizeof(Elf32_Sym) * num_st);
249 munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
253 for (i = 0; i < num_st; i++) {
254 ret = read(file, &symtab_entry[i], sizeof(Elf32_Sym));
255 if (ret < sizeof(Elf32_Sym)) {
257 "[sys-assert]symtab_entry[%d], num_st=%d, readnum = %d\n",
261 if (((info_funcs.dli_fbase +
262 symtab_entry[i].st_value)
265 (info_funcs.dli_fbase +
266 symtab_entry[i].st_value +
267 symtab_entry[i].st_size))) {
268 if (symtab_entry[i].st_shndx != STN_UNDEF) {
270 s_headers[strtab_index].sh_offset +
271 symtab_entry[i].st_name,
275 info_funcs.dli_sname =
276 (void *)mmap(0, FUNC_NAME_MAX_LEN,
277 PROT_READ | PROT_WRITE,
278 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
279 ret = read(file, (void *)info_funcs.dli_sname,
283 info_funcs.dli_saddr =
284 info_funcs.dli_fbase +
285 symtab_entry[i].st_value;
290 munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
291 munmap(symtab_entry, sizeof(Elf32_Sym) * num_st);
295 /* print symbol name and address. */
296 if (info_funcs.dli_sname != NULL) {
297 if (array[cnt] >= info_funcs.dli_saddr)
298 fprintf_fd(fd, "%2d: %s + 0x%x (%p) [%s] + %p\n",
299 cnt, info_funcs.dli_sname,
300 (array[cnt] - info_funcs.dli_saddr),
301 array[cnt], info_funcs.dli_fname, offset_addr);
303 fprintf_fd(fd, "%2d: %s - 0x%x (%p) [%s] + %p\n",
304 cnt, info_funcs.dli_sname,
305 (info_funcs.dli_saddr - array[cnt]),
306 array[cnt], info_funcs.dli_fname, offset_addr);
308 fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
309 cnt, array[cnt], info_funcs.dli_fname, offset_addr);
314 /* get address list from maps */
315 static struct addr_node *get_addr_list_from_maps(int fd)
317 int fpath_len, result;
322 char addr[ADDR_LEN * 2];
323 char linebuf[BUF_SIZE];
324 struct addr_node *head = NULL;
325 struct addr_node *tail = NULL;
326 struct addr_node *t_node = NULL;
328 /* parsing the maps to get executable code address */
329 while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) {
330 memset(path, 0, PATH_LEN);
331 result = sscanf(linebuf, "%s %s %*s %*s %*s %s ", addr, perm, path);
334 perm[PERM_LEN - 1] = 0;
337 if ((perm[2] == 'x' && path[0] == '/') ||
338 (perm[1] == 'w' && path[0] != '/')) {
340 if (strncmp(perm, "r-xp", strlen("r-xp")) == 0) {
342 /* add addr node to list */
344 saddr = (long *)strtoul(addr, NULL, HEXA);
345 /* ffff0000-ffff1000 */
346 eaddr = (long *)strtoul(&addr[ADDR_LEN + 1], NULL, HEXA);
347 /* make node and attach to the list */
348 t_node = (struct addr_node *)mmap(0, sizeof(struct addr_node),
349 PROT_READ | PROT_WRITE,
350 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
351 if (t_node == NULL) {
352 fprintf(stderr, "error : mmap\n");
355 memcpy(t_node->perm, perm, PERM_LEN);
356 t_node->startaddr = saddr;
357 t_node->endaddr = eaddr;
358 t_node->fpath = NULL;
359 fpath_len = strlen(path);
361 t_node->fpath = (char *)mmap(0, fpath_len + 1,
362 PROT_READ | PROT_WRITE,
363 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
364 memset(t_node->fpath, 0, fpath_len + 1);
365 memcpy(t_node->fpath, path, fpath_len);
367 t_node->fpath = (char *)mmap(0, STR_ANNOY_LEN,
368 PROT_READ | PROT_WRITE,
369 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
370 memset(t_node->fpath, 0, STR_ANNOY_LEN);
371 memcpy(t_node->fpath, STR_ANONY, STR_ANNOY_LEN);
386 static void print_node_to_file(struct addr_node *start, int fd)
388 struct addr_node *t_node;
391 fprintf_fd(fd, "\n%s\n", CRASH_MAPSINFO_TITLE);
393 if (!strncmp(STR_ANONY, t_node->fpath, STR_ANNOY_LEN)) {
394 t_node = t_node->next;
397 "%16lx %16lx %s %s\n",
398 (unsigned long)t_node->startaddr,
399 (unsigned long)t_node->endaddr,
400 t_node->perm, t_node->fpath);
401 t_node = t_node->next;
404 fprintf_fd(fd, "%s\n", CRASH_MAPSINFO_TITLE_E);
407 static void free_all_nodes(struct addr_node *start)
409 struct addr_node *t_node, *n_node;
415 n_node = t_node->next;
417 if (t_node->fpath != NULL) {
418 fpath_len = strlen(t_node->fpath);
419 munmap(t_node->fpath, fpath_len + 1);
421 munmap(t_node, sizeof(struct addr_node));
425 n_node = n_node->next;
429 static void print_signal_info(int signum, const siginfo_t *info, int fd)
431 fprintf_fd(fd, "Signal: %d\n", signum);
434 fprintf_fd(fd, " (SIGILL)\n");
437 fprintf_fd(fd, " (SIGTRAP)\n");
440 fprintf_fd(fd, " (SIGABRT)\n");
443 fprintf_fd(fd, " (SIGBUS)\n");
446 fprintf_fd(fd, " (SIGFPE)\n");
449 fprintf_fd(fd, " (SIGSEGV)\n");
452 fprintf_fd(fd, " (SIGTERM)\n");
455 fprintf_fd(fd, " (SIGSTKFLT)\n");
458 fprintf_fd(fd, " (SIGXCPU)\n");
461 fprintf_fd(fd, " (SIGXFSZ)\n");
464 fprintf_fd(fd, " (SIGSYS)\n");
467 fprintf_fd(fd, "\n");
469 /* print signal si_code info */
470 fprintf_fd(fd, " si_code: %d\n", info->si_code);
471 if (info->si_code <= 0 || info->si_code >= 0x80) {
472 switch (info->si_code) {
476 " signal sent by tkill (sent by pid %d, uid %d)\n",
477 info->si_pid, info->si_uid);
483 " signal sent by kill (sent by pid %d, uid %d)\n",
484 info->si_pid, info->si_uid);
489 fprintf_fd(fd, " signal sent by the kernel\n");
493 } else if (signum == SIGILL) {
494 switch (info->si_code) {
496 fprintf_fd(fd, " illegal opcode\n");
499 fprintf_fd(fd, " illegal operand\n");
502 fprintf_fd(fd, " illegal addressing mode\n");
505 fprintf_fd(fd, " illegal trap\n");
508 fprintf_fd(fd, " privileged opcode\n");
511 fprintf_fd(fd, " privileged register\n");
514 fprintf_fd(fd, " coprocessor error\n");
517 fprintf_fd(fd, " internal stack error\n");
520 fprintf_fd(fd, " illegal si_code = %d\n", info->si_code);
523 fprintf_fd(fd, " si_addr: %p\n", info->si_addr);
524 } else if (signum == SIGFPE) {
525 switch (info->si_code) {
527 fprintf_fd(fd, " integer divide by zero\n");
530 fprintf_fd(fd, " integer overflow\n");
533 fprintf_fd(fd, " floating-point divide by zero\n");
536 fprintf_fd(fd, " floating-point overflow\n");
539 fprintf_fd(fd, " floating-point underflow\n");
542 fprintf_fd(fd, " floating-point inexact result\n");
545 fprintf_fd(fd, " invalid floating-point operation\n");
548 fprintf_fd(fd, " subscript out of range\n");
551 fprintf_fd(fd, " illegal si_code: %d\n", info->si_code);
554 } else if (signum == SIGSEGV) {
555 switch (info->si_code) {
557 fprintf_fd(fd, " address not mapped to object\n");
561 " invalid permissions for mapped object\n");
564 fprintf_fd(fd, " illegal si_code: %d\n", info->si_code);
567 fprintf_fd(fd, " si_addr = %p\n", info->si_addr);
568 } else if (signum == SIGBUS) {
569 switch (info->si_code) {
571 fprintf_fd(fd, " invalid address alignment\n");
574 fprintf_fd(fd, " nonexistent physical address\n");
577 fprintf_fd(fd, " object-specific hardware error\n");
580 fprintf_fd(fd, " illegal si_code: %d\n", info->si_code);
583 fprintf_fd(fd, " si_addr: %p\n", info->si_addr);
587 void sighandler(int signum, siginfo_t *info, void *context)
592 /* file descriptor */
594 int fd_cs; /* for cs file */
599 struct dirent *dentry=NULL;
600 char timestr[TIME_MAX_LEN];
601 char processname[NAME_MAX] = {0,};
602 char exepath[PATH_LEN] = {0,};
603 char filepath[PATH_LEN];
604 char crashid[TIME_MAX_LEN] = {0,};
608 char infoname[INFO_LEN];
609 char value[VALUE_LEN];
610 char linebuf[BUF_SIZE];
611 char *p_exepath = NULL;
612 void *callstack_addrs[CALLSTACK_SIZE];
613 int cnt_callstack = 0;
614 /* for backtrace_symbols() */
615 struct addr_node *head = NULL;
616 /* for preventing recursion */
617 static int retry_count = 0;
618 struct sysinfo si = {0,};
620 if (retry_count > 1) {
621 fprintf(stderr, "[sys-assert] recurcive called\n");
625 cur_time = time(NULL);
628 tid = (long int)syscall(__NR_gettid);
630 if ((fd = open(MAPS_PATH, O_RDONLY)) < 0) {
631 fprintf(stderr, "[sys-assert]can't open %s\n", MAPS_PATH);
633 /* parsing the maps to get code segment address*/
634 head = get_addr_list_from_maps(fd);
638 fprintf(stderr, "retry backtrace in sighandler");
639 cnt_callstack = dump_callstack(callstack_addrs, CALLSTACK_SIZE, context, retry_count);
642 if ((readnum = open_read(CMDLINE_PATH, exepath, sizeof(exepath) - 1)) <= 0) {
643 fprintf(stderr, "[sys-assert]can't read %s\n", CMDLINE_PATH);
644 readnum = snprintf(exepath, sizeof(exepath), "unknown_process");
646 exepath[readnum] = '\0';
647 /* get processname */
648 if ((p_exepath = remove_path(exepath)) == NULL)
650 snprintf(processname, NAME_MAX, "%s", p_exepath);
651 /* added temporary skip when crash-worker is asserted */
652 if (!strcmp(processname, "crash-worker") ||
653 !strcmp(processname, "crash-popup"))
655 /* make crash info file name */
656 snprintf(timestr, sizeof(timestr), "%.10ld", cur_time);
657 snprintf(crashid, sizeof(crashid), "%s_%d", processname, pid);
658 if (snprintf(filepath, PATH_LEN,
659 "%s/%s.info", CRASH_INFO_PATH, crashid) == 0) {
661 "[sys-assert]can't make crash info file name : %s\n",
665 /* check crash info dump directory, make directory if absent */
666 if (access(CRASH_INFO_PATH, F_OK) == -1) {
667 fprintf(stderr, "[sys-assert] No directory (%s)", CRASH_INFO_PATH);
668 /*TODO: making directory */
671 /* logging crash information to stderr */
672 fprintf(stderr, "crashed [%s] processname=%s, pid=%d, tid=%d, signal=%d",
673 timestr, processname, pid, tid, signum);
674 /* complete filepath_cs */
675 if (!strlen(filepath))
678 if ((fd_cs = creat(filepath, FILE_PERMS)) < 0) {
680 "[sys-assert]can't create %s. errno = %d\n",
685 /* print exepath info */
686 fprintf_fd(fd_cs, "Executable File Path: %s\n", exepath);
688 /* print signal info */
689 print_signal_info(signum, info, fd_cs);
691 /* print register info */
692 dump_registers(fd_cs, context);
695 fprintf_fd(fd_cs, "\n%s\n", CRASH_MEMINFO_TITLE);
697 fprintf_fd(fd_cs, "MemTotal: %8ld KB\n", KB(si.totalram));
698 fprintf_fd(fd_cs, "MemFree: %8ld KB\n", KB(si.freeram));
699 fprintf_fd(fd_cs, "Buffers: %8ld KB\n", KB(si.bufferram));
701 fprintf(stderr, "[sys-assert]can't get sysinfo\n");
703 if ((fd = open(MEMINFO_PATH, O_RDONLY)) < 0) {
704 fprintf(stderr, "[sys-assert]can't open %s\n", MEMINFO_PATH);
706 while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) {
707 sscanf(linebuf, "%s %s %*s", infoname, value);
708 if (strcmp("Cached:", infoname) == 0) {
709 fprintf_fd(fd_cs, "%s %8s KB\n", infoname, value);
717 if ((fd = open(STATUS_PATH, O_RDONLY)) < 0) {
718 fprintf(stderr, "[sys-assert]can't open %s\n", STATUS_PATH);
720 while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) {
721 sscanf(linebuf, "%s %s %*s", infoname, value);
722 if (strcmp("VmPeak:", infoname) == 0) {
723 fprintf_fd(fd_cs, "%s %8s KB\n", infoname,
725 } else if (strcmp("VmSize:", infoname) == 0) {
726 fprintf_fd(fd_cs, "%s %8s KB\n", infoname,
728 } else if (strcmp("VmLck:", infoname) == 0) {
729 fprintf_fd(fd_cs, "%s %8s KB\n", infoname,
731 } else if (strcmp("VmPin:", infoname) == 0) {
732 fprintf_fd(fd_cs, "%s %8s KB\n", infoname,
734 } else if (strcmp("VmHWM:", infoname) == 0) {
735 fprintf_fd(fd_cs, "%s %8s KB\n",
737 } else if (strcmp("VmRSS:", infoname) == 0) {
738 fprintf_fd(fd_cs, "%s %8s KB\n",
740 } else if (strcmp("VmData:", infoname) == 0) {
741 fprintf_fd(fd_cs, "%s %8s KB\n",
743 } else if (strcmp("VmStk:", infoname) == 0) {
744 fprintf_fd(fd_cs, "%s %8s KB\n",
746 } else if (strcmp("VmExe:", infoname) == 0) {
747 fprintf_fd(fd_cs, "%s %8s KB\n",
749 } else if (strcmp("VmLib:", infoname) == 0) {
750 fprintf_fd(fd_cs, "%s %8s KB\n",
752 } else if (strcmp("VmPTE:", infoname) == 0) {
753 fprintf_fd(fd_cs, "%s %8s KB\n",
755 } else if (strcmp("VmSwap:", infoname) == 0) {
756 fprintf_fd(fd_cs, "%s %8s KB\n",
758 } else if (strcmp("Threads:", infoname) == 0) {
759 threadnum = atoi(value);
765 /* print thread info */
767 fprintf_fd(fd_cs, "\n%s\n", CRASH_THREADINFO_TITLE);
769 "Threads: %d\nPID = %d TID = %d\n",
770 threadnum, pid, tid);
772 dir = opendir(TASK_PATH);
774 fprintf(stderr, "[sys-assert]can't open %s\n", TASK_PATH);
776 while (readdir_r(dir, &entry, &dentry) == 0 && dentry) {
777 if (strcmp(dentry->d_name, ".") == 0
778 || strcmp(dentry->d_name, "..") == 0)
780 fprintf_fd(fd_cs, "%s ", dentry->d_name);
783 fprintf_fd(fd_cs, "\n");
787 /* print maps information */
788 print_node_to_file(head, fd_cs);
789 /* print callstack */
790 fprintf_fd(fd_cs, "\n%s (PID:%d)\n", CRASH_CALLSTACKINFO_TITLE, pid);
791 fprintf_fd(fd_cs, "Call Stack Count: %d\n", cnt_callstack);
792 if (trace_symbols(&callstack_addrs[CALLSTACK_BASE],
793 cnt_callstack, head, fd_cs) < 0)
794 fprintf(stderr, "[sys-assert] trace_symbols failed\n");
795 fprintf_fd(fd_cs, "%s\n", CRASH_CALLSTACKINFO_TITLE_E);
796 free_all_nodes(head);
801 if (close(fd_cs) == -1)
802 fprintf(stderr, "[sys-assert] fd_cs close error!!\n");
804 if (prctl(PR_GET_DUMPABLE) == 0)
805 prctl(PR_SET_DUMPABLE, 1);
807 for (idx = 0; idx < NUM_SIG_TO_HANDLE; idx++) {
808 if (sig_to_handle[idx] == signum) {
809 sigaction(signum, &g_oldact[idx], NULL);
816 __attribute__ ((constructor))
821 for (idx = 0; idx < NUM_SIG_TO_HANDLE; idx++) {
822 struct sigaction act;
823 act.sa_sigaction = (void *)sighandler;
824 sigemptyset(&act.sa_mask);
825 act.sa_flags = SA_SIGINFO;
826 act.sa_flags |= SA_RESETHAND;
827 if (sigaction(sig_to_handle[idx], &act, &g_oldact[idx]) < 0) {
828 perror("[sys-assert]could not set signal handler ");