4 #include <elfutils/libdwfl.h>
5 #include <elfutils/libebl.h>
10 #include <sys/prctl.h>
11 #include <linux/prctl.h>
12 #include "crash-stack.h"
14 extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
15 size_t *length, int *status);
18 static int frame_callback (Dwfl_Frame *state, void *arg)
20 Regs *regs = static_cast<Regs*>(arg);
21 dwfl_frame_pc (state, ®s->pc, NULL);
22 return DWARF_CB_ABORT;
25 static int thread_callback (Dwfl_Thread *thread, void *thread_arg)
27 dwfl_thread_getframes (thread, frame_callback, thread_arg);
28 return DWARF_CB_ABORT;
32 static int module_callback (Dwfl_Module *module, void **userdata,
33 const char *name, Dwarf_Addr address,
36 /* To get something from module file do something like:
39 Elf *elf = dwfl_module_getelf (module, &bias);
41 cout << "Module : " << name << " @" << hex << address << " bias " << bias << endl;
43 Elf_Data *data = elf_getdata_rawchunk (elf, 0, 4, ELF_T_BYTE);
44 cout << " " << static_cast<char*>(data->d_buf)+1 << endl;
49 void getvalue (Elf *core, const void *from, size_t size, void *to)
54 .d_type = size == 32 ? ELF_T_WORD : ELF_T_XWORD,
55 .d_version = EV_CURRENT,
62 .d_buf = (void*)(from),
64 .d_version = out.d_version,
70 if (gelf_getclass (core) == ELFCLASS32)
71 data = elf32_xlatetom (&out, &in, elf_getident (core, NULL)[EI_DATA]);
73 data = elf64_xlatetom (&out, &in, elf_getident (core, NULL)[EI_DATA]);
75 fprintf (stderr, "failed to get value from core file\n");
78 int main(int argc, char **argv)
80 prctl (PR_SET_DUMPABLE, 0);
84 fprintf (stderr, "Usage: %s <core-file>\n", argv[0]);
88 int core_fd = open (argv[1], O_RDONLY);
95 elf_version (EV_CURRENT);
97 Elf *core = elf_begin (core_fd, ELF_C_READ_MMAP, NULL);
100 fprintf (stderr, "%s : Can't open ELF (%s)\n", argv[1], elf_errmsg(-1));
104 const Dwfl_Callbacks core_callbacks =
106 .find_elf = dwfl_build_id_find_elf,
107 .find_debuginfo = dwfl_standard_find_debuginfo,
108 .section_address = NULL,
109 .debuginfo_path = NULL
112 Dwfl *dwfl = dwfl_begin (&core_callbacks);
115 fprintf (stderr, "%s : Can't start dwfl (%s)\n", argv[1], dwfl_errmsg(-1));
119 if (dwfl_core_file_report (dwfl, core, NULL) < 0)
121 fprintf (stderr, "%s : dwfl report failed (%s)\n", argv[1], dwfl_errmsg(-1));
125 if (dwfl_core_file_attach (dwfl, core) < 0)
127 fprintf (stderr, "%s : dwfl attach failed (%s)\n", argv[1], dwfl_errmsg(-1));
131 Regs *regs = get_regs_struct();
133 To unwind with libelf do this:
135 dwfl_getthreads (dwfl, thread_callback, regs);
139 dwfl_getmodules (dwfl, module_callback, 0, 0);
142 GElf_Phdr *phdr = gelf_getphdr (core, 0, &mem);
143 if (phdr == NULL || phdr->p_type != PT_NOTE)
145 fprintf (stderr, "%s : Missing note section at the first position in core file\n", argv[1]);
149 Elf_Data *notes = elf_getdata_rawchunk (core, phdr->p_offset, phdr->p_filesz, ELF_T_NHDR);
152 fprintf (stderr, "%s : error getting notes (%s)\n", argv[1], dwfl_errmsg(-1));
156 Ebl *ebl = ebl_openbackend (core);
159 fprintf (stderr, "%s : Can't initialize ebl\n", argv[1]);
167 /* registers should be in the first note! */
168 if (gelf_getnote (notes, pos, &nhdr, &name_pos, &desc_pos) > 0)
170 if (nhdr.n_type == NT_PRSTATUS)
172 GElf_Word regs_offset;
174 const Ebl_Register_Location *reglocs;
176 const Ebl_Core_Item *items;
178 if (0 == ebl_core_note (ebl, &nhdr, "CORE", ®s_offset, &nregloc, ®locs, &nitems, &items))
180 fprintf (stderr, "%s : error parsing notes\n", argv[1]);
184 const char *regs_location = (const char *)(notes->d_buf) + pos + desc_pos + regs_offset;
187 for (i = 0; i < nregloc; i++)
189 const char *register_location = regs_location + reglocs[i].offset;
191 for (regnum = reglocs[i].regno; regnum < reglocs[i].regno + reglocs[i].count; regnum++)
195 const char *prefix = 0;
196 const char *setname = 0;
197 ssize_t ret = ebl_register_info (ebl, regnum, regname, sizeof(regname), &prefix, &setname, &bits, &type);
200 fprintf (stderr, "%s : can't get register info\n", argv[1]);
203 void *place_for_reg_value = get_place_for_register_value (regname, regnum);
205 if (place_for_reg_value != NULL)
206 getvalue (core, register_location, bits, place_for_reg_value);
208 register_location += bits / 8 + reglocs[i].pad;
214 /* for (int i = 0; i < 20; i++)
216 char name[100] = {0};
217 int bits = 0, type = 0;
218 const char *setname = 0;
219 const char *prefix = 0;
220 ssize_t ret = ebl_register_info (ebl, i, name, sizeof(name), &prefix, &setname, &bits, &type);
221 printf ("ebl_register_info %d ret: %d, name: %s, prefix: %s, setname: %s, bits: %d, type: %d\n",
222 i, ret, name, prefix, setname, bits, type);
225 /* printf ("PC: 0x%llx\n", (unsigned long long)regs.pc);
226 printf ("SP: 0x%llx\n", (unsigned long long)regs.sp);*/
230 create_crash_stack (regs, dwfl, core, &callstack);
232 char *dem_buffer = NULL;
235 printf ("Call stack:\n");
236 for (it = 0; it != callstack.elems; ++it)
238 if (sizeof (callstack.tab[0]) > 4)
239 printf ("0x%016llx: ", (int64_t)callstack.tab[it]);
241 printf ("0x%08x: ", (int32_t)callstack.tab[it]);
242 Dwfl_Module *module = dwfl_addrmodule (dwfl, callstack.tab[it]);
245 char *demangled_symbol = 0;
246 const char *symbol = dwfl_module_addrname (module, callstack.tab[it]);
247 if (symbol != 0 && symbol[0] == '_' && symbol[1] == 'Z')
251 demangled_symbol = __cxa_demangle (symbol, dem_buffer, NULL, &status);
253 symbol = demangled_symbol;
256 printf ("%s()", symbol);
258 if (demangled_symbol != 0)
259 free (demangled_symbol);
261 printf (" from %s\n", dwfl_module_info (module, NULL, NULL, NULL, NULL, NULL, NULL, NULL));
265 printf ("unknown function\n");
269 dwfl_report_end (dwfl, NULL, NULL);