crash-stack: reformat callstack output
[platform/core/system/crash-worker.git] / src / crash-stack / crash-stack.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * Authors: Adrian Szyndela <adrian.s@samsung.com>
17  *          Ćukasz Stelmach <l.stelmach@samsung.com>
18  */
19 /**
20  * @file crash-stack.c
21  * @brief This file contains Main module of call stack unwinding program
22  *
23  * Crash-stack is a single purpose program. Its duty is to show call stack
24  * of a crashed program. Crash-stack must be called with proper arguments:
25  * either core dump file name or PID of a crashed program.
26  */
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <libelf.h>
30 #include <elfutils/libdwfl.h>
31 /*
32  * In case the program is compiled with core dumps, the license may switch to GPL2.
33  */
34 #ifdef WITH_CORE_DUMP
35 #include <elfutils/libebl.h>
36 #endif
37 #include <errno.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <sys/prctl.h>
42 #include <linux/prctl.h>
43 #include "crash-stack.h"
44 #include <string.h>
45 #include <elfutils/version.h>
46 #include <getopt.h>
47 #include <sys/ptrace.h>
48 #include <sys/uio.h>
49 #include <sys/types.h>
50 #include <sys/wait.h>
51 #include <dirent.h>
52 #include <sys/syscall.h>
53
54 static siginfo_t __siginfo;
55 static FILE *outputfile = NULL;         ///< global output stream
56 static FILE *errfile = NULL;            ///< global error stream
57
58 /**
59  * @brief definitions for getopt options: identifiers
60  */
61 enum {
62         OPT_PID,
63         OPT_TID,
64         OPT_OUTPUTFILE,
65         OPT_ERRFILE
66 };
67
68 /**
69  * @brief definitions for getopt options: full specifications
70  */
71 const struct option opts[] = {
72         { "pid", required_argument, 0, OPT_PID },
73         { "tid", required_argument, 0, OPT_TID },
74         { "output", required_argument, 0, OPT_OUTPUTFILE },
75         { "erroutput", required_argument, 0, OPT_ERRFILE },
76         { 0, 0, 0, 0 }
77 };
78
79 /*
80  * __cxa_demangle() is taken from libstdc++, however there is no header that we
81  * can take a declaration from. Importing through 'extern' allows using it.
82  */
83 /// @cond false
84 extern char *__cxa_demangle(const char *mangled_name, char *output_buffer,
85                 size_t *length, int *status);
86 ///@endcond
87
88 /**
89  * @brief A callback for dwfl_getmodules().
90  *
91  * This callback is called once for every module discovered by dwfl_getmodules().
92  *
93  * @param module the dwfl module
94  * @param userdata unused, required by dwfl_getmodules()
95  * @param name name of the module
96  * @param address address of the module
97  * @param arg 4th argument to dwfl_getmodules is passed here
98  */
99 static int __module_callback(Dwfl_Module *module, void **userdata,
100                 const char *name, Dwarf_Addr address,
101                 void *arg)
102 {
103         if (name != NULL && name[0] == '[') {
104                 /* libdwfl couldn't get the module file - we will get it later from notes */
105                 Mappings *mappings = arg;
106                 if (mappings->elems < MAX_MAPPINGS_NUM) {
107                         size_t elems = mappings->elems;
108                         mappings->tab[elems].m_start = address;
109                         mappings->tab[elems].m_end = 0;
110                         mappings->tab[elems].m_offset = 0;
111                         mappings->tab[elems].m_name = NULL;
112                         mappings->tab[elems].m_fd = -1;
113                         mappings->tab[elems].m_elf = 0;
114                         mappings->elems++;
115                 }
116         }
117         return DWARF_CB_OK;
118 }
119
120 /**
121  * @brief Reads a value of specified size from core dump file.
122  *
123  * @param core ELF handler for the core dump file
124  * @param from the source address in the ELF file
125  * @param size size of the value in bits
126  * @param to the address of allocated memory, where the value will be copied
127  */
128 static void __get_value(Elf *core, const void *from, size_t size, void *to)
129 {
130         Elf_Type type = ELF_T_BYTE;
131         switch (size) {
132         case 8: type = ELF_T_BYTE; break;
133         case 16: type = ELF_T_HALF; break;
134         case 32: type = ELF_T_WORD; break;
135         case 64: type = ELF_T_XWORD; break;
136         default:
137                  fprintf(stderr, "__get_value for strange size: %llu\n", (unsigned long long)size);
138                  break;
139         }
140         Elf_Data out = {
141                 .d_buf = to,
142                 .d_type = type,
143                 .d_version = EV_CURRENT,
144                 .d_size = size/8,
145                 .d_off = 0,
146                 .d_align = 0
147         };
148         Elf_Data in = {
149                 .d_buf = (void*)(from),
150                 .d_type = out.d_type,
151                 .d_version = out.d_version,
152                 .d_size = out.d_size,
153                 .d_off = 0,
154                 .d_align = 0
155         };
156         Elf_Data *data;
157         if (gelf_getclass(core) == ELFCLASS32)
158                 data = elf32_xlatetom(&out, &in, elf_getident(core, NULL)[EI_DATA]);
159         else
160                 data = elf64_xlatetom(&out, &in, elf_getident(core, NULL)[EI_DATA]);
161         if (data == NULL)
162                 fprintf(errfile, "failed to get value from core file\n");
163 }
164
165 /**
166  * @brief gets number of values, page size, address size, values and names from ELF notes
167  *
168  * @remarks This is very specific for organization of notes part in ELF files
169  *
170  * @param elf ELF handler - may be core file
171  * @param desc address of ELF notes descriptor
172  * @param[out] values_cnt a place for number of values
173  * @param[out] page_size a place for page size
174  * @param[out] addr_size a place for address size
175  * @param[out] values a place for address of values
176  * @param[out] filenames a place for address of filenames
177  */
178 static void __parse_note_file(Elf *elf, const char *desc, uint64_t *values_cnt, uint64_t *page_size,
179                 size_t *addr_size, const char **values, const char **filenames)
180 {
181         *addr_size = gelf_fsize(elf, ELF_T_ADDR, 1, EV_CURRENT);
182         __get_value(elf, desc, *addr_size*8, values_cnt);
183         __get_value(elf, desc + *addr_size, *addr_size*8, page_size);
184         /* First: triplets of <mapping-start> <mapping-end> <offset-in-pages>
185          *     count = values_cnt
186          * Then the names of files.
187          */
188         *values = desc + 2 * *addr_size;
189         *filenames = *values + 3 * *addr_size * *values_cnt;
190 }
191
192 /**
193  * @brief Simple accessor for mapping items in ELF files
194  *
195  * @remarks This is very specific for organization of notes part in ELF files
196  *
197  * @param elf ELF handler - may be core file
198  * @param addr_size size of addresses in this ELF
199  * @param item address of mapping item to get data from
200  * @param[out] mapping_start value of the start of the mapping
201  * @param[out] mapping_end value of the end of the mapping
202  * @param[out] offset_in_pages number of pages of offset in the file
203  */
204 static void __get_mapping_item(Elf *elf, size_t addr_size, const void *item,
205                 uint64_t *mapping_start, uint64_t *mapping_end, uint64_t *offset_in_pages)
206 {
207         __get_value(elf, item, addr_size*8, mapping_start);
208         __get_value(elf, item + addr_size, addr_size*8, mapping_end);
209         __get_value(elf, item + 2 * addr_size, addr_size*8, offset_in_pages);
210 }
211
212 /**
213  * @brief Tries to get symbol name from ELF files
214  *
215  * @remarks This function is used in case that symbol name is not available by libelf,
216  *                      e.g. when old libelf version does not take into account some modules.
217  *
218  * @param core ELF handler for the core dump file
219  * @param notes notes descriptor from core file
220  * @param address address to get symbol name for
221  * @param[out] module_name name of the module of the found symbol. Not touched when
222  *             symbol is not found
223  * @return name of the symbol or NULL if not found
224  */
225 static char *__try_symbol_from_elfs(Elf *core, Elf_Data *notes, uintptr_t address,
226                 const char **module_name)
227 {
228         GElf_Nhdr nhdr;
229         char *symbol = NULL;
230         size_t pos = 0;
231         size_t new_pos = 0;
232         size_t name_pos;
233         size_t desc_pos;
234
235         while ((new_pos = gelf_getnote(notes, pos, &nhdr, &name_pos, &desc_pos)) > 0) {
236                 if (nhdr.n_type == NT_FILE) {
237                         uint64_t values_cnt = 0, page_size = 0;
238                         const char *values;
239                         const char *filenames;
240                         size_t addr_size = 0;
241
242                         __parse_note_file(core, notes->d_buf + desc_pos, &values_cnt,
243                                                           &page_size, &addr_size, &values, &filenames);
244
245                         int ii;
246                         for (ii = 0; ii < values_cnt; ii++) {
247                                 uint64_t mapping_start = 0, mapping_end = 0, offset_in_pages = 0;
248                                 const char *item = values + 3 * addr_size * ii;
249
250                                 __get_mapping_item(core, addr_size, item, &mapping_start, &mapping_end,
251                                                                  &offset_in_pages);
252
253                                 if (mapping_start <= address && address < mapping_end) {
254                                         Elf *elf;
255                                         int fd;
256                                         fd = open(filenames, O_RDONLY);
257                                         if (-1 == fd)
258                                                 return NULL;
259
260                                         elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
261
262                                         if (NULL == elf) {
263                                                 close(fd);
264                                                 return NULL;
265                                         }
266
267                                         Elf_Scn *scn = NULL;
268                                         *module_name = filenames;
269
270                                         while ((scn = elf_nextscn(elf, scn)) != NULL) {
271                                                 GElf_Shdr shdr_mem;
272                                                 GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);
273                                                 if (shdr != NULL && (shdr->sh_type == SHT_SYMTAB || shdr->sh_type == SHT_DYNSYM)) {
274                                                         Elf_Data *sdata = elf_getdata(scn, NULL);
275                                                         unsigned int nsyms = sdata->d_size / (gelf_getclass(elf) == ELFCLASS32 ?
276                                                                         sizeof(Elf32_Sym) :
277                                                                         sizeof(Elf64_Sym));
278                                                         unsigned int cnt;
279                                                         uintptr_t address_offset = address;
280                                                         if (shdr->sh_type == SHT_DYNSYM)
281                                                                 address_offset -= mapping_start;
282                                                         for (cnt = 0; cnt < nsyms; ++cnt) {
283                                                                 GElf_Sym sym_mem;
284                                                                 Elf32_Word xndx;
285                                                                 GElf_Sym *sym = gelf_getsymshndx(sdata, NULL, cnt, &sym_mem, &xndx);
286                                                                 if (sym != NULL && sym->st_shndx != SHN_UNDEF) {
287                                                                         if (sym->st_value <= address_offset && address_offset < sym->st_value + sym->st_size) {
288                                                                                 symbol = strdup(elf_strptr(elf, shdr->sh_link, sym->st_name));
289                                                                                 break;
290                                                                         }
291                                                                 }
292                                                         }
293                                                 }
294                                         }
295
296                                         elf_end(elf);
297                                         close(fd);
298                                         return symbol;
299                                 }
300
301                                 filenames += strlen(filenames)+1;
302                         }
303                 }
304                 pos = new_pos;
305         }
306
307         return NULL;
308 }
309
310 /**
311  * @brief Opens libdwfl for using with live process
312  *
313  * @param pid pid of the process to attach to
314  * @return Dwfl handle
315  */
316 static Dwfl *__open_dwfl_with_pid(pid_t pid)
317 {
318         int status;
319         pid_t stopped_pid;
320
321         if (ptrace(PTRACE_SEIZE, pid, NULL, PTRACE_O_TRACEEXIT) != 0) {
322                 fprintf(errfile, "PTRACE_SEIZE failed on PID %d: %m\n", pid);
323                 return NULL;
324         }
325
326
327         ptrace(PTRACE_INTERRUPT, pid, 0, 0);
328
329         stopped_pid = waitpid(pid, &status, 0);
330         if (stopped_pid == -1 || stopped_pid != pid || !WIFSTOPPED(status)) {
331                 fprintf(errfile, "waitpid failed: %m, stopped_pid=%d, status=%d\n", stopped_pid, status);
332                 return NULL;
333         }
334
335         if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &__siginfo) != 0)
336                 return NULL;
337
338         static const Dwfl_Callbacks proc_callbacks = {
339                 .find_elf = dwfl_linux_proc_find_elf,
340                 .find_debuginfo = dwfl_standard_find_debuginfo,
341                 .section_address = NULL,
342                 .debuginfo_path = NULL
343         };
344
345         Dwfl *dwfl = dwfl_begin(&proc_callbacks);
346         if (dwfl == NULL) {
347                 fprintf(errfile, "process %d : Can't start dwfl (%s)\n", pid, dwfl_errmsg(-1));
348                 return NULL;
349         }
350
351         if (dwfl_linux_proc_report(dwfl, pid) < 0) {
352                 fprintf(errfile, "process %d : dwfl report failed (%s)\n", pid, dwfl_errmsg(-1));
353                 dwfl_end(dwfl);
354                 return NULL;
355         }
356
357 #if _ELFUTILS_PREREQ(0,158)
358         if (dwfl_linux_proc_attach(dwfl, pid, true) < 0) {
359                 fprintf(errfile, "process %d : dwfl attach failed (%s)\n", pid, dwfl_errmsg(-1));
360                 dwfl_end(dwfl);
361                 return NULL;
362         }
363 #endif
364         return dwfl;
365 }
366
367 /**
368  * @brief Opens libdwfl for using with core dump file
369  *
370  * @remarks This function will open core file regardless of WITH_CORE_DUMP setting.
371  *          It may help with detecting issues with using dwfl even without support
372  *          for dumps.
373  *
374  * @param core elf handler for the core dump file
375  * @param core_file_name name of the core file; needed only for diagnostics
376  * @return Dwfl handle
377  */
378 static Dwfl *__open_dwfl_with_core(Elf *core, const char *core_file_name)
379 {
380         static const Dwfl_Callbacks core_callbacks = {
381                 .find_elf = dwfl_build_id_find_elf,
382                 .find_debuginfo = dwfl_standard_find_debuginfo,
383                 .section_address = NULL,
384                 .debuginfo_path = NULL
385         };
386
387         Dwfl *dwfl = dwfl_begin(&core_callbacks);
388         if (dwfl == NULL) {
389                 fprintf(errfile, "%s : Can't start dwfl (%s)\n", core_file_name, dwfl_errmsg(-1));
390                 return NULL;
391         }
392
393 #if _ELFUTILS_PREREQ(0,158)
394         if (dwfl_core_file_report(dwfl, core, NULL) < 0)
395 #else
396                 if (dwfl_core_file_report(dwfl, core) < 0)
397 #endif
398                 {
399                         fprintf(errfile, "%s : dwfl report failed (%s)\n", core_file_name, dwfl_errmsg(-1));
400                         dwfl_end(dwfl);
401                         return NULL;
402                 }
403
404 #if _ELFUTILS_PREREQ(0,158)
405         if (dwfl_core_file_attach(dwfl, core) < 0) {
406                 fprintf(errfile, "%s : dwfl attach failed (%s)\n", core_file_name, dwfl_errmsg(-1));
407                 dwfl_end(dwfl);
408                 return NULL;
409         }
410 #endif
411         return dwfl;
412 }
413
414 /**
415  * @brief Gets registers information for live process
416  *
417  * @param pid pid of the live process
418  * @return 0 on success, -1 otherwise
419  */
420 static int __get_registers_ptrace(pid_t pid)
421 {
422         struct iovec data;
423         data.iov_base = _crash_stack_get_memory_for_ptrace_registers(&data.iov_len);
424
425         if (NULL == data.iov_base) {
426                 fprintf(errfile, "Cannot get memory for registers for ptrace (not implemented for this architecture\n");
427                 return -1;
428         }
429
430         if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &data) != 0) {
431                 fprintf(errfile, "PTRACE_GETREGSET failed on PID %d: %m\n", pid);
432                 return -1;
433         }
434
435         _crash_stack_set_ptrace_registers(data.iov_base);
436
437         return 0;
438 }
439
440 /**
441  * @brief Get information about the signal that stopped the process
442  *
443  * @param pid pid of the live process
444  * @return 0 on success, -1 otherwise
445  */
446 static int __get_signal_ptrace(pid_t pid)
447 {
448         const char* const signal_table[] = {
449                 [SIGHUP]="SIGHUP", [SIGINT]="SIGINT", [SIGQUIT]="SIGQUIT",
450                 [SIGILL]="SIGILL", [SIGTRAP]="SIGTRAP", [SIGABRT]="SIGABRT",
451                 [SIGIOT]="SIGIOT", [SIGBUS]="SIGBUS", [SIGFPE]="SIGFPE",
452                 [SIGKILL]="SIGKILL", [SIGUSR1]="SIGUSR1", [SIGSEGV]="SIGSEGV",
453                 [SIGUSR2]="SIGUSR2", [SIGPIPE]="SIGPIPE", [SIGALRM]="SIGALRM",
454                 [SIGTERM]="SIGTERM", [SIGSTKFLT]="SIGSTKFLT", [SIGCHLD]="SIGCHLD",
455                 [SIGCONT]="SIGCONT", [SIGSTOP]="SIGSTOP", [SIGTSTP]="SIGTSTP",
456                 [SIGTTIN]="SIGTTIN", [SIGTTOU]="SIGTTOU", [SIGURG]="SIGURG",
457                 [SIGXCPU]="SIGXCPU", [SIGXFSZ]="SIGXFSZ", [SIGVTALRM]="SIGVTALRM",
458                 [SIGPROF]="SIGPROF", [SIGWINCH]="SIGWINCH", [SIGIO]="SIGIO",
459                 [SIGPWR]="SIGPWR", [SIGSYS]="SIGSYS", [SIGUNUSED]="SIGUNUSED",
460         };
461
462         printf("Signal: %d\n"
463                "\t(%s)\n"
464                "\tsi_code: %d\n",
465                __siginfo.si_signo,
466                signal_table[__siginfo.si_signo],
467                __siginfo.si_code);
468         switch (__siginfo.si_code) {
469         case SI_TKILL:
470         case SI_USER:
471                 printf("\tsignal sent by %s (sent by pid %d, uid %d)",
472                        __siginfo.si_code == SI_TKILL ? "tkill" : "kill",
473                        __siginfo.si_pid, __siginfo.si_uid);
474                 break;
475         case SI_KERNEL:
476                 printf("\tsignal sent by the kernel\n");
477                 break;
478         }
479         return 0;
480 }
481
482 #ifdef WITH_CORE_DUMP
483 /**
484  * @brief Helper function for updating mappings.
485  *
486  * @remarks Old versions of libelf not always extract full information about modules.
487  *          For such cases we maintain mappings for every module. Those mappings
488  *          may be updated while reading notes from core file.
489  *
490  * @param mappings mappings database
491  * @param mapping_start address of the mapped start of the module; module is identified
492  *                      by mapping_start
493  * @param mapping_end address of the end of the module; needed to compute module boundaries
494  * @param offset offset within core file - unused
495  * @param name file name of the module
496  */
497 static void __updateMapping(Mappings *mappings, uint64_t mapping_start, uint64_t mapping_end,
498                 uint64_t offset, const char *name)
499 {
500         int i;
501         for (i = 0; i < mappings->elems; i++) {
502                 if (mappings->tab[i].m_start == mapping_start) {
503                         mappings->tab[i].m_end = mapping_end;
504                         mappings->tab[i].m_name = name;
505                         mappings->tab[i].m_offset = offset;
506                         mappings->tab[i].m_fd = open(name, O_RDONLY);
507                         mappings->tab[i].m_elf = elf_begin(mappings->tab[i].m_fd, ELF_C_READ_MMAP, NULL);
508                         return;
509                 }
510         }
511 }
512 #endif
513
514 /**
515  * @brief Gets registers from core dump
516  *
517  * @param core ELF handler for the core dump file
518  * @param core_file_name name of the core file; needed only for diagnostics
519  * @param mappings mappings database
520  * @return notes handler, NULL on error
521  */
522 static Elf_Data *__get_registers_core(Elf *core, const char *core_file_name, Mappings *mappings)
523 {
524         Elf_Data *notes = NULL;
525         /* The part below uses libebl. In case WITH_CORE_DUMP is enabled, the license
526          * may switch to GPL2.
527          */
528 #ifdef WITH_CORE_DUMP
529         GElf_Phdr mem;
530         GElf_Phdr *phdr = gelf_getphdr(core, 0, &mem);
531
532         if (phdr == NULL || phdr->p_type != PT_NOTE) {
533                 fprintf(errfile, "%s : Missing note section at the first position in core file\n",
534                                 core_file_name);
535                 return NULL;
536         }
537
538         notes = elf_getdata_rawchunk(core, phdr->p_offset, phdr->p_filesz, ELF_T_NHDR);
539         if (notes == NULL) {
540                 fprintf(errfile, "%s : error getting notes (%s)\n", core_file_name, dwfl_errmsg(-1));
541                 return NULL;
542         }
543
544         Ebl *ebl = ebl_openbackend(core);
545         if (ebl == NULL) {
546                 fprintf(errfile, "%s : Can't initialize ebl\n", core_file_name);
547                 return NULL;
548         }
549
550         GElf_Nhdr nhdr;
551         size_t name_pos;
552         size_t desc_pos;
553         size_t pos = 0;
554         size_t new_pos = 0;
555         int got_regs = 0;
556         /* registers should be in the first note! */
557         while ((new_pos = gelf_getnote(notes, pos, &nhdr, &name_pos, &desc_pos)) > 0) {
558                 if (nhdr.n_type == NT_PRSTATUS && !got_regs) {
559                         GElf_Word regs_offset;
560                         size_t nregloc;
561                         const Ebl_Register_Location *reglocs;
562                         size_t nitems;
563                         const Ebl_Core_Item *items;
564
565                         got_regs = 1;
566
567                         if (0 == ebl_core_note(ebl, &nhdr, "CORE", &regs_offset, &nregloc,
568                                                 &reglocs, &nitems, &items)) {
569                                 fprintf(errfile,
570                                                 "%s : error parsing notes (built with different build of libebl?)\n",
571                                                 core_file_name);
572                                 return NULL;
573                         }
574
575                         const char *regs_location = (const char *)(notes->d_buf) + pos + desc_pos
576                                 + regs_offset;
577                         unsigned i;
578
579                         for (i = 0; i < nregloc; i++) {
580                                 const char *register_location = regs_location + reglocs[i].offset;
581                                 int regnum;
582                                 for (regnum = reglocs[i].regno;
583                                                 regnum < reglocs[i].regno + reglocs[i].count;
584                                                 regnum++) {
585                                         char regname[5];
586                                         int bits, type;
587                                         const char *prefix = 0;
588                                         const char *setname = 0;
589
590                                         ssize_t ret = ebl_register_info(ebl, regnum, regname,
591                                                         sizeof(regname), &prefix, &setname,
592                                                         &bits, &type);
593                                         if (ret < 0) {
594                                                 fprintf(errfile, "%s : can't get register info\n", core_file_name);
595                                                 return NULL;
596                                         }
597                                         void *place_for_reg_value = _get_place_for_register_value(regname, regnum);
598
599                                         if (place_for_reg_value != NULL)
600                                                 __get_value(core, register_location, bits, place_for_reg_value);
601
602                                         register_location += bits / 8 + reglocs[i].pad;
603                                 }
604                         }
605                 } else if (nhdr.n_type == NT_FILE) {
606                         uint64_t values_cnt = 0, page_size = 0;
607                         const char *values;
608                         const char *filenames;
609                         size_t addr_size = 0;
610
611                         __parse_note_file(core, notes->d_buf + desc_pos, &values_cnt, &page_size,
612                                         &addr_size, &values, &filenames);
613
614                         int ii;
615                         /* First: triplets of <mapping-start> <mapping-end> <offset-in-pages>
616                          *     count = values_cnt
617                          * Then the names of files.
618                          */
619                         for (ii = 0; ii < values_cnt; ii++) {
620                                 uint64_t mapping_start = 0, mapping_end = 0, offset_in_pages = 0;
621                                 const char *item = values + 3 * addr_size * ii;
622
623                                 __get_mapping_item(core, addr_size, item, &mapping_start, &mapping_end,
624                                                 &offset_in_pages);
625                                 __updateMapping(mappings, mapping_start, mapping_end,
626                                                 offset_in_pages*page_size, filenames);
627                                 filenames += strlen(filenames)+1;
628                         }
629                 }
630                 pos = new_pos;
631         }
632         ebl_closebackend(ebl);
633 #else
634         fprintf(errfile, "Configured without support for core dump files\n");
635 #endif
636         return notes;
637 }
638
639 /**
640  * @brief Resolves procedure and module names using libdwfl
641  *
642  * @param proc_info gathered call stack element
643  * @param dwfl dwfl handler
644  */
645 static void __resolve_symbols_from_dwfl(ProcInfo *proc_info, Dwfl *dwfl)
646 {
647         uintptr_t address = proc_info->addr;
648         Dwfl_Module *module = dwfl_addrmodule(dwfl, address);
649         if (module) {
650
651                 const char *module_name = proc_info->module_name;
652                 if (!module_name) {
653                         const char *fname = 0;
654                         const char *module_name = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
655                         if (fname)
656                                 proc_info->module_name = strdup(fname);
657                         else if (module_name)
658                                 proc_info->module_name = strdup(module_name);
659                 }
660                 const char *symbol = proc_info->name;
661                 if (!symbol) {
662                         symbol = dwfl_module_addrname(module, proc_info->addr);
663                         if (symbol)
664                                 proc_info->name = strdup(symbol);
665                 }
666         }
667 }
668
669 /**
670  * @brief Resolves procedure and module names using elfutils
671  *
672  * @param proc_info gathered call stack element
673  * @param core ELF handler for the core dump file, NULL if live process analyzed
674  * @param notes notes handler, NULL if live process analyzed
675  */
676 static void __resolve_symbols_from_elf(ProcInfo *proc_info, Elf *core, Elf_Data *notes)
677 {
678         const char *fname = 0;
679         char *symbol_from_elf = __try_symbol_from_elfs(core, notes, proc_info->addr, &fname);
680         if (!proc_info->module_name && fname)
681                         proc_info->module_name = strdup(fname);
682
683         if (!proc_info->name && symbol_from_elf)
684                 proc_info->name = symbol_from_elf;
685 }
686
687 /**
688  * @brief Checks if symbol starts with '_Z' prefix
689  *
690  * @param symbol string to compare
691  */
692 static int is_symbol_demanglable(const char *symbol)
693 {
694         return symbol != 0 && (strlen(symbol) >= 2) &&
695                 symbol[0] == '_' && symbol[1] == 'Z';
696 }
697
698 /**
699  * @brief Replaces symbols with demangled
700  *
701  * @param proc_info gathered call stack element
702  */
703 static void __demangle_symbols(ProcInfo *proc_info)
704 {
705         int status = -1;
706         char *dem_buffer = NULL;
707         char *demangled_symbol = __cxa_demangle(proc_info->name, dem_buffer, NULL, &status);
708         if (status == 0) {
709                 free(proc_info->name);
710                 proc_info->name = demangled_symbol;
711         }
712 }
713
714 /**
715  * @brief Resolves procedure and module name
716  *
717  * @param proc_info gathered call stack element
718  * @param dwfl dwfl handler
719  * @param core ELF handler for the core dump file, NULL if live process analyzed
720  * @param notes notes handler, NULL if live process analyzed
721  */
722 static void __resolve_symbols(ProcInfo *proc_info, Dwfl *dwfl, Elf *core, Elf_Data *notes)
723 {
724         if (!proc_info->module_name || !proc_info->name)
725                 __resolve_symbols_from_dwfl(proc_info, dwfl);
726
727         if (!proc_info->module_name || !proc_info->name)
728                 __resolve_symbols_from_elf(proc_info, core, notes);
729
730         if (is_symbol_demanglable(proc_info->name))
731                 __demangle_symbols(proc_info);
732 }
733
734 /**
735  * @brief Prints call stack element to the global outputfile.
736  *
737  * @param proc_info gathered call stack element
738  */
739 static void __print_proc_info(ProcInfo *proc_info)
740 {
741         if (proc_info->name) {
742                 fprintf(outputfile, "%s ", proc_info->name);
743                 if (proc_info->offset >= 0)
744                         fprintf(outputfile, "+ 0x%x ", proc_info->offset);
745         }
746         if (sizeof(proc_info->addr) > 4)
747                 fprintf(outputfile, "(0x%016llx)", (long long)proc_info->addr);
748         else
749                 fprintf(outputfile, "(0x%08x)", (int32_t)proc_info->addr);
750
751         if (proc_info->module_name != 0)
752                 fprintf(outputfile, " [%s]", proc_info->module_name);
753
754         fprintf(outputfile, "\n");
755 }
756
757 /**
758  * @brief Prints call stack to the global outputfile.
759  *
760  * @param callstack gathered call stack database
761  * @param pid PID of the live process, 0 if core dump file analyzed
762  */
763 static void __print_callstack(Callstack *callstack, pid_t pid)
764 {
765         fprintf(outputfile, "\nCallstack Information");
766         if (pid > 1)
767                 fprintf(outputfile, " (PID:%d)", pid);
768         fprintf(outputfile, "\nCall Stack Count: %zu\n", callstack->elems);
769
770         size_t it;
771         for (it = 0; it != callstack->elems; ++it) {
772                 fprintf(outputfile, "%2zu: ", it);
773                 __print_proc_info(&callstack->proc[it]);
774         }
775         fprintf(outputfile, "End of Call Stack\n");
776 }
777
778 void callstack_constructor(Callstack *callstack)
779 {
780         size_t it;
781         callstack->elems = 0;
782         for (it = 0; it < (int)sizeof(callstack->proc)/sizeof(callstack->proc[0]); ++it) {
783                 callstack->proc[it].offset = -1;
784                 callstack->proc[it].name = 0;
785                 callstack->proc[it].module_name = 0;
786         }
787 }
788
789 void callstack_destructor(Callstack *callstack)
790 {
791         size_t it;
792         for (it = 0; it < callstack->elems; ++it) {
793                 free(callstack->proc[it].name);
794                 free(callstack->proc[it].module_name);
795         }
796         fprintf(outputfile, "End of Call Stack\n");
797 }
798
799 /**
800  * @brief Print thread information
801  *
802  * @param outputfile File handle for printing report.
803  * @param pid PID of the inspected process
804  * @param tid TID of the inspected thread
805  */
806 static void __crash_stack_print_threads(FILE* outputfile, pid_t pid, pid_t tid)
807 {
808         int threadnum=1;
809         DIR *dir;
810         struct dirent entry;
811         struct dirent *dentry=NULL;
812         char task_path[PATH_MAX];
813         struct stat sb;
814
815
816         snprintf(task_path, PATH_MAX, "/proc/%d/task", pid);
817         if (stat(task_path, &sb) == -1) {
818                 return;
819         }
820
821         threadnum = sb.st_nlink - 2;
822
823         if (threadnum > 1) {
824                 fprintf(outputfile, "\nThreads Information\n");
825                 fprintf(outputfile,
826                         "Threads: %d\nPID = %d TID = %d\n",
827                         threadnum, pid, tid);
828                 /* print thread */
829                 dir = opendir(task_path);
830                 if (!dir) {
831                         fprintf(stderr, "[crash-stack] cannot open %s\n", task_path);
832                 } else {
833                         while (readdir_r(dir, &entry, &dentry) == 0 && dentry) {
834                                 if (strcmp(dentry->d_name, ".") == 0 ||
835                                     strcmp(dentry->d_name, "..") == 0)
836                                         continue;
837                                 fprintf(outputfile, "%s ", dentry->d_name);
838                         }
839                         closedir(dir);
840                         fprintf(outputfile, "\n");
841                 }
842         }
843
844 }
845
846 /**
847  * @brief Main function.
848  *
849  * Main module accepts two forms of launching:
850  *
851  *     crash-stack core-dump-file
852  *     crash-stack --pid pid
853  *
854  * The first form allows user to print call stack of a generated core dump file.
855  * The second form allows connecting to a live process and displaying its call stack.
856  * It might be also used for connecting to a process from system's core dump handler.
857  */
858 int main(int argc, char **argv)
859 {
860         int c;
861         pid_t pid = 0;
862         pid_t tid = 0;
863
864         const char *core_file_name;
865
866         prctl(PR_SET_DUMPABLE, 0);
867
868         while ((c = getopt_long_only(argc, argv, "", opts, NULL)) != -1) {
869                 switch (c) {
870                 case OPT_PID:
871                         pid = atoi(optarg);
872                         break;
873                 case OPT_TID:
874                         tid = atoi(optarg);
875                         break;
876                 case OPT_OUTPUTFILE:
877                         outputfile = fopen(optarg, "w");
878                         break;
879                 case OPT_ERRFILE:
880                         errfile = fopen(optarg, "w");
881                         break;
882                 }
883         }
884
885         if (NULL == errfile) errfile = stderr;
886         if (NULL == outputfile) outputfile = stdout;
887
888         core_file_name = argv[optind];
889         argc -= optind;
890
891         elf_version(EV_CURRENT);
892
893         /* First, prepare dwfl and modules */
894         Elf *core = NULL;
895         int core_fd = -1;
896         Dwfl *dwfl = NULL;
897
898         if (pid > 1)
899                 dwfl = __open_dwfl_with_pid(pid);
900         else {
901                 if (argc != 1) {
902                         fprintf(errfile,
903                                         "Usage: %s [--output file] [--erroutput file] [--pid <pid> | <core-file>]\n",
904                                         argv[0]);
905                         return 1;
906                 }
907
908                 core_fd = open(core_file_name, O_RDONLY);
909                 if (core_fd < 0) {
910                         perror(core_file_name);
911                         return 2;
912                 }
913
914                 core = elf_begin(core_fd, ELF_C_READ_MMAP, NULL);
915                 if (core == NULL) {
916                         fprintf(errfile, "%s : Can't open ELF (%s)\n", core_file_name, elf_errmsg(-1));
917                         return 3;
918                 }
919
920                 dwfl = __open_dwfl_with_core(core, core_file_name);
921         }
922
923         if (NULL == dwfl)
924                 return 1111;
925
926         Mappings mappings;
927         mappings.elems = 0;
928
929         dwfl_getmodules(dwfl, __module_callback, &mappings, 0);
930         Elf_Data *notes = 0;
931
932         /* Now, get registers */
933         if (pid > 1) {
934                 if (-1 == __get_signal_ptrace(pid))
935                         return 4444;
936                 if (-1 == __get_registers_ptrace(pid))
937                         return 3333;
938         } else {
939                 notes = __get_registers_core(core, core_file_name, &mappings);
940                 if (NULL == notes)
941                         return 2222;
942         }
943
944         /* Unwind call stack */
945         Callstack callstack;
946         callstack_constructor(&callstack);
947
948         _create_crash_stack(dwfl, core, pid, &mappings, &callstack);
949         size_t it;
950         for (it = 0; it != callstack.elems; ++it)
951                 __resolve_symbols(&callstack.proc[it], dwfl, core, notes);
952
953         /* Print registers */
954         _crash_stack_print_regs(outputfile);
955
956         /* Threads */
957         __crash_stack_print_threads(outputfile, pid, tid);
958
959         /* Print the results */
960         __print_callstack(&callstack, pid);
961
962         /* Clean up */
963         callstack_destructor(&callstack);
964         dwfl_report_end(dwfl, NULL, NULL);
965         dwfl_end(dwfl);
966         if (NULL != core) elf_end(core);
967         if (-1 != core_fd) close(core_fd);
968
969         return 0;
970 }