Support for attaching with ptrace 94/67994/8
authorAdrian Szyndela <adrian.s@samsung.com>
Thu, 28 Apr 2016 10:00:33 +0000 (12:00 +0200)
committerAdrian Szyndela <adrian.s@samsung.com>
Wed, 11 May 2016 11:37:10 +0000 (13:37 +0200)
Additionally:
* made it compiling on aarch64 and x86;
* removed CXX from CMakeLists.txt as it is no longer used.

Change-Id: Id2bdbd19ed864def580afb583b2c044af245fd2e

CMakeLists.txt
src/crash-manager/crash-manager.sh.in
src/crash-stack/crash-stack-arm.c
src/crash-stack/crash-stack-libelf.c
src/crash-stack/crash-stack.c
src/crash-stack/crash-stack.h

index 0281ce3..f273bb0 100644 (file)
@@ -1,5 +1,5 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(crash-worker C CXX)
+PROJECT(crash-worker C)
 
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 
index 176edc4..49f1536 100644 (file)
@@ -7,6 +7,8 @@ PATH=/bin:/usr/bin
 CRASH_PATH="@CRASH_PATH@"
 CRASH_TEMP="@CRASH_TEMP@"
 
+DEBUG=1
+
 # Expected invocation from kernel:
 #
 #   argv0 PID UID GID SIGNAL TIME CMD
@@ -30,8 +32,14 @@ log_path="${pfx}/${name}.log"
 
 mkdir -p "$CRASH_PATH" "$pfx"
 
-@CRASH_PIPE_PATH@ --save-core "$core_path" --report "$@" > "$info_path"
-@CRASH_STACK_PATH@ "$core_path" >> "$info_path"
+if [ $DEBUG -eq 1 ]
+then
+  @CRASH_PIPE_PATH@ --save-core "$core_path" --report "$@" > "$info_path"
+  @CRASH_STACK_PATH@ "$core_path" >> "$info_path"
+else
+  @CRASH_PIPE_PATH@ --report "$@" > "$info_path"
+  @CRASH_STACK_PATH@ --pid "$pid" >> "$info_path"
+fi
 dump_systemstate -d -k -f "$log_path" || true
 
 tar czf "${temp_dir}/report.tar.gz" -C "$temp_dir" "$name"
index 8643473..4d21661 100644 (file)
@@ -2,10 +2,12 @@
 #include "wind/unwarm.h"
 
 #include <string.h>
+#include <sys/ptrace.h>
 
 static Elf *g_core = NULL;
 static Dwfl *g_dwfl = NULL;
 static Mappings *g_mappings = NULL;
+static pid_t g_pid = 0;
 
 struct Regs
 {
@@ -16,28 +18,24 @@ struct Regs
   Dwarf_Addr spsr;
 };
 
+typedef struct Regs Regs;
 static Regs g_regs;
 
-Regs *get_regs_struct (void)
-{
-  return &g_regs;
-}
-
 void *get_place_for_register_value (const char *regname, int regnum)
 {
-  if (strcmp (regname, "pc") == 0)
+  if (strcmp (regname, "pc") == 0 || REG_PC == regnum)
   {
     return &g_regs.pc;
   }
-  else if (strcmp (regname, "sp") == 0)
+  else if (strcmp (regname, "sp") == 0 || REG_SP == regnum)
   {
     return &g_regs.sp;
   }
-  else if (strcmp (regname, "lr") == 0)
+  else if (strcmp (regname, "lr") == 0 || REG_LR == regnum)
   {
     return &g_regs.lr;
   }
-  else if (strcmp (regname, "spsr") == 0)
+  else if (strcmp (regname, "spsr") == 0 || REG_SPSR == regnum)
   {
     return &g_regs.spsr;
   }
@@ -115,6 +113,14 @@ Boolean readT (Int32 a, void *v, size_t size)
     return TRUE;
   }
 
+  /* Still no data, but we have a process - read memory with ptrace */
+  if (NULL == data && g_pid > 1)
+  {
+     long val = ptrace (PTRACE_PEEKDATA, g_pid, a, NULL);
+     memcpy (v, &val, size);
+     return TRUE;
+  }
+
   return FALSE;
 }
 
@@ -191,7 +197,7 @@ static Int32 getProloguePC (Int32 current_pc)
     return result;
 }
 
-void create_crash_stack (Regs *regs, Dwfl *dwfl, Elf *core, Mappings *mappings, Callstack *callstack)
+void create_crash_stack (Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack)
 {
   UnwindCallbacks callbacks =
   {
@@ -210,23 +216,24 @@ void create_crash_stack (Regs *regs, Dwfl *dwfl, Elf *core, Mappings *mappings,
   g_dwfl = dwfl;
   g_core = core;
   g_mappings = mappings;
+  g_pid = pid;
 
-  callstack->tab[0] = regs->pc;
+  callstack->tab[0] = g_regs.pc;
   callstack->elems = 1;
 
-  UnwInitState (&state, &callbacks, callstack, regs->pc, regs->sp);
+  UnwInitState (&state, &callbacks, callstack, g_regs.pc, g_regs.sp);
   int i;
   for (i = 0; i < REGS_REGULAR_NUM; i++)
   {
-    state.regData[i].v = regs->regs[i];
+    state.regData[i].v = g_regs.regs[i];
     state.regData[i].o = REG_VAL_FROM_CONST;
   }
-  state.regData[REG_LR].v = regs->lr;
+  state.regData[REG_LR].v = g_regs.lr;
   state.regData[REG_LR].o = REG_VAL_FROM_STACK;
-  state.regData[REG_SPSR].v = regs->spsr;
+  state.regData[REG_SPSR].v = g_regs.spsr;
   state.regData[REG_SPSR].o = REG_VAL_FROM_CONST;
 
-  if (UnwIsAddrThumb (regs->pc, regs->spsr))
+  if (UnwIsAddrThumb (g_regs.pc, g_regs.spsr))
     UnwStartThumb (&state);
   else
     UnwStartArm (&state);
index 732c1ea..c8c8773 100644 (file)
@@ -1,6 +1,8 @@
 #include "crash-stack.h"
 #include <elfutils/libdwfl.h>
+#include <elfutils/version.h>
 
+#if _ELFUTILS_PREREQ(0,158)
 static int frame_callback (Dwfl_Frame *state, void *arg)
 {
   Callstack *callstack = (Callstack*)arg;
@@ -15,20 +17,18 @@ static int thread_callback (Dwfl_Thread *thread, void *thread_arg)
   dwfl_thread_getframes (thread, frame_callback, thread_arg);
   return DWARF_CB_ABORT;
 }
-
-Regs *get_regs_struct (void)
-{
-  return 0;
-}
+#endif
 
 void *get_place_for_register_value (const char *regname, int regnum)
 {
   return 0;
 }
 
-void create_crash_stack (Regs *regs, Dwfl *dwfl, Elf *core, Mappings *mappings, Callstack *callstack)
+void create_crash_stack (Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack)
 {
   callstack->elems = 0;
+#if _ELFUTILS_PREREQ(0,158)
   dwfl_getthreads (dwfl, thread_callback, callstack);
+#endif
 }
 
index f7e6639..76ce25d 100644 (file)
 #include "crash-stack.h"
 #include <string.h>
 #include <elfutils/version.h>
+#include <getopt.h>
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+static FILE *outputfile = NULL;
+static FILE *errfile = NULL;
+
+enum {
+    OPT_PID,
+    OPT_OUTPUTFILE,
+    OPT_ERRFILE
+};
+
+const struct option opts[] = {
+    { "pid", required_argument, 0, OPT_PID },
+    { "output", required_argument, 0, OPT_OUTPUTFILE },
+    { "erroutput", required_argument, 0, OPT_ERRFILE },
+    { 0, 0, 0, 0 }
+};
 
 extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
                             size_t *length, int *status);
@@ -36,6 +57,7 @@ static int module_callback (Dwfl_Module *module, void **userdata,
       mappings->elems++;
     }
   }
+/*  fprintf(errfile, "Got module %s @0x%llx\n", name, (long long)address);*/
   return DWARF_CB_OK;
 }
 
@@ -65,7 +87,7 @@ static void getvalue (Elf *core, const void *from, size_t size, void *to)
   else
     data = elf64_xlatetom (&out, &in, elf_getident (core, NULL)[EI_DATA]);
   if (data == NULL)
-    fprintf (stderr, "failed to get value from core file\n");
+    fprintf (errfile, "failed to get value from core file\n");
 }
 
 static void updateMapping (Mappings *mappings, uint64_t mapping_start, uint64_t mapping_end,
@@ -122,17 +144,17 @@ static char *try_symbol_from_elfs (Elf *core, Elf_Data *notes, uintptr_t address
   {
     if (nhdr.n_type == NT_FILE)
     {
-      uint64_t values_cnt, page_size;
+      uint64_t values_cnt = 0, page_size = 0;
       const char *values;
       const char *filenames;
-      size_t addr_size;
+      size_t addr_size = 0;
 
       parse_note_file(core, notes->d_buf + desc_pos, &values_cnt, &page_size, &addr_size, &values, &filenames);
 
       int ii;
       for (ii = 0; ii < values_cnt; ii++)
       {
-          uint64_t mapping_start, mapping_end, offset_in_pages;
+          uint64_t mapping_start = 0, mapping_end = 0, offset_in_pages = 0;
           const char *item = values + 3 * addr_size * ii;
 
           get_mapping_item (core, addr_size, item, &mapping_start, &mapping_end, &offset_in_pages);
@@ -198,33 +220,62 @@ static char *try_symbol_from_elfs (Elf *core, Elf_Data *notes, uintptr_t address
   return NULL;
 }
 
-int main(int argc, char **argv)
+static Dwfl *open_dwfl_with_pid (pid_t pid)
 {
-  prctl (PR_SET_DUMPABLE, 0);
+  int status;
+  pid_t stopped_pid;
 
-  if (argc != 2)
+  if (ptrace (PTRACE_SEIZE, pid, NULL, PTRACE_O_TRACEEXIT) != 0)
   {
-    fprintf (stderr, "Usage: %s <core-file>\n", argv[0]);
-    return 1;
+    fprintf(errfile, "PTRACE_SEIZE failed on PID %d: %m\n", pid);
+    return NULL;
   }
 
-  int core_fd = open (argv[1], O_RDONLY);
-  if (core_fd < 0)
+  ptrace (PTRACE_INTERRUPT, pid, 0, 0);
+
+  stopped_pid = waitpid(pid, &status, 0);
+  if (stopped_pid == -1 || stopped_pid != pid || !WIFSTOPPED(status))
   {
-    perror (argv[1]);
-    return 2;
+    fprintf(errfile, "waitpid failed: %m, stopped_pid=%d, status=%d\n", stopped_pid, status);
+    return NULL;
   }
 
-  elf_version (EV_CURRENT);
+  static const Dwfl_Callbacks proc_callbacks =
+  {
+    .find_elf = dwfl_linux_proc_find_elf,
+    .find_debuginfo = dwfl_standard_find_debuginfo,
+    .section_address = NULL,
+    .debuginfo_path = NULL
+  };
+
+  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+  if (dwfl == NULL)
+  {
+    fprintf (errfile, "process %d : Can't start dwfl (%s)\n", pid, dwfl_errmsg(-1));
+    return NULL;
+  }
+
+  if (dwfl_linux_proc_report (dwfl, pid) < 0)
+  {
+    fprintf (errfile, "process %d : dwfl report failed (%s)\n", pid, dwfl_errmsg(-1));
+    dwfl_end (dwfl);
+    return NULL;
+  }
 
-  Elf *core = elf_begin (core_fd, ELF_C_READ_MMAP, NULL);
-  if (core == NULL)
+#if _ELFUTILS_PREREQ(0,158)
+  if (dwfl_linux_proc_attach (dwfl, pid, true) < 0)
   {
-    fprintf (stderr, "%s : Can't open ELF (%s)\n", argv[1], elf_errmsg(-1));
-    return 3;
+    fprintf (errfile, "process %d : dwfl attach failed (%s)\n", pid, dwfl_errmsg(-1));
+    dwfl_end (dwfl);
+    return NULL;
   }
+#endif
+  return dwfl;
+}
 
-  const Dwfl_Callbacks core_callbacks =
+static Dwfl *open_dwfl_with_core (Elf *core, const char *core_file_name)
+{
+  static const Dwfl_Callbacks core_callbacks =
   {
     .find_elf = dwfl_build_id_find_elf,
     .find_debuginfo = dwfl_standard_find_debuginfo,
@@ -235,8 +286,8 @@ int main(int argc, char **argv)
   Dwfl *dwfl = dwfl_begin (&core_callbacks);
   if (dwfl == NULL)
   {
-    fprintf (stderr, "%s : Can't start dwfl (%s)\n", argv[1], dwfl_errmsg(-1));
-    return 4;
+    fprintf (errfile, "%s : Can't start dwfl (%s)\n", core_file_name, dwfl_errmsg(-1));
+    return NULL;
   }
 
 #if _ELFUTILS_PREREQ(0,158)
@@ -245,45 +296,73 @@ int main(int argc, char **argv)
   if (dwfl_core_file_report (dwfl, core) < 0)
 #endif
   {
-    fprintf (stderr, "%s : dwfl report failed (%s)\n", argv[1], dwfl_errmsg(-1));
-    return 5;
+    fprintf (errfile, "%s : dwfl report failed (%s)\n", core_file_name, dwfl_errmsg(-1));
+    dwfl_end (dwfl);
+    return NULL;
   }
 
 #if _ELFUTILS_PREREQ(0,158)
   if (dwfl_core_file_attach (dwfl, core) < 0)
   {
-    fprintf (stderr, "%s : dwfl attach failed (%s)\n", argv[1], dwfl_errmsg(-1));
-    return 6;
+    fprintf (errfile, "%s : dwfl attach failed (%s)\n", core_file_name, dwfl_errmsg(-1));
+    dwfl_end (dwfl);
+    return NULL;
   }
 #endif
+  return dwfl;
+}
 
-  Regs *regs = get_regs_struct();
+static int get_registers_ptrace (pid_t pid)
+{
+  struct iovec data;
+  uintptr_t regbuf[20];
 
-  Mappings mappings;
-  mappings.elems = 0;
+  data.iov_base = regbuf;
+  data.iov_len = sizeof (regbuf);
 
-  dwfl_getmodules (dwfl, module_callback, &mappings, 0);
+  if (ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS, &data) != 0)
+  {
+    fprintf(errfile, "PTRACE_GETREGSET failed on PID %d: %m\n", pid);
+    return -1;
+  }
+
+  size_t i;
+  for (i = 0;
+       i * sizeof (regbuf[0]) < data.iov_len && i < sizeof (regbuf)/sizeof (regbuf[0]);
+       i++)
+  {
+    void *reg = get_place_for_register_value ("", i);
+
+    if (NULL != reg)
+      memcpy (reg, &regbuf[i], sizeof (regbuf[i]));
+  }
+  return 0;
+}
 
+static Elf_Data *get_registers_core (Elf *core, const char *core_file_name, Mappings *mappings)
+{
   GElf_Phdr mem;
   GElf_Phdr *phdr = gelf_getphdr (core, 0, &mem);
+
   if (phdr == NULL || phdr->p_type != PT_NOTE)
   {
-    fprintf (stderr, "%s : Missing note section at the first position in core file\n", argv[1]);
-    return 8;
+    fprintf (errfile, "%s : Missing note section at the first position in core file\n",
+        core_file_name);
+    return NULL;
   }
 
   Elf_Data *notes = elf_getdata_rawchunk (core, phdr->p_offset, phdr->p_filesz, ELF_T_NHDR);
   if (notes == NULL)
   {
-    fprintf (stderr, "%s : error getting notes (%s)\n", argv[1], dwfl_errmsg(-1));
-    return 9;
+    fprintf (errfile, "%s : error getting notes (%s)\n", core_file_name, dwfl_errmsg(-1));
+    return NULL;
   }
 
   Ebl *ebl = ebl_openbackend (core);
   if (ebl == NULL)
   {
-    fprintf (stderr, "%s : Can't initialize ebl\n", argv[1]);
-    return 7;
+    fprintf (errfile, "%s : Can't initialize ebl\n", core_file_name);
+    return NULL;
   }
 
   GElf_Nhdr nhdr;
@@ -305,30 +384,39 @@ int main(int argc, char **argv)
 
       got_regs = 1;
 
-      if (0 == ebl_core_note (ebl, &nhdr, "CORE", &regs_offset, &nregloc, &reglocs, &nitems, &items))
+      if (0 == ebl_core_note (ebl, &nhdr, "CORE", &regs_offset, &nregloc,
+            &reglocs, &nitems, &items))
       {
-        fprintf (stderr, "%s : error parsing notes\n", argv[1]);
-        return 100;
+        fprintf (errfile,
+            "%s : error parsing notes (built with different build of libebl?)\n",
+            core_file_name);
+        return NULL;
       }
 
-      const char *regs_location = (const char *)(notes->d_buf) + pos + desc_pos + regs_offset;
+      const char *regs_location = (const char *)(notes->d_buf) + pos + desc_pos
+                                  + regs_offset;
       unsigned i;
 
       for (i = 0; i < nregloc; i++)
       {
         const char *register_location = regs_location + reglocs[i].offset;
         int regnum;
-        for (regnum = reglocs[i].regno; regnum < reglocs[i].regno + reglocs[i].count; regnum++)
+        for (regnum = reglocs[i].regno;
+             regnum < reglocs[i].regno + reglocs[i].count;
+             regnum++)
         {
           char regname[5];
           int bits, type;
           const char *prefix = 0;
           const char *setname = 0;
-          ssize_t ret = ebl_register_info (ebl, regnum, regname, sizeof(regname), &prefix, &setname, &bits, &type);
+
+          ssize_t ret = ebl_register_info (ebl, regnum, regname,
+                                           sizeof(regname), &prefix, &setname,
+                                           &bits, &type);
           if (ret < 0)
           {
-            fprintf (stderr, "%s : can't get register info\n", argv[1]);
-            return 11;
+            fprintf (errfile, "%s : can't get register info\n", core_file_name);
+            return NULL;
           }
           void *place_for_reg_value = get_place_for_register_value (regname, regnum);
 
@@ -341,13 +429,13 @@ int main(int argc, char **argv)
     }
     else if (nhdr.n_type == NT_FILE)
     {
-      uint64_t values_cnt, page_size;
+      uint64_t values_cnt = 0, page_size = 0;
       const char *values;
       const char *filenames;
-      size_t addr_size;
+      size_t addr_size = 0;
 
-      parse_note_file(core, notes->d_buf + desc_pos, &values_cnt, &page_size, &addr_size, &values, &filenames);
-//      printf("addr_size: %d, mappings: %llu, page size: %llu\n", addr_size, values_cnt, page_size);
+      parse_note_file(core, notes->d_buf + desc_pos, &values_cnt, &page_size,
+          &addr_size, &values, &filenames);
 
       int ii;
       /* First: triplets of <mapping-start> <mapping-end> <offset-in-pages>
@@ -356,48 +444,48 @@ int main(int argc, char **argv)
        */
       for (ii = 0; ii < values_cnt; ii++)
       {
-          uint64_t mapping_start, mapping_end, offset_in_pages;
+          uint64_t mapping_start = 0, mapping_end = 0, offset_in_pages = 0;
           const char *item = values + 3 * addr_size * ii;
 
-          get_mapping_item (core, addr_size, item, &mapping_start, &mapping_end, &offset_in_pages);
-/*          printf ("<0x%08llx-0x%08llx>@0x%08llx: %s\n", mapping_start, mapping_end, offset_in_pages,
-              filenames);
-*/
-          updateMapping (&mappings, mapping_start, mapping_end, offset_in_pages*page_size, filenames);
-          filenames += strlen(filenames)+1;
+          get_mapping_item (core, addr_size, item, &mapping_start, &mapping_end,
+                            &offset_in_pages);
+          updateMapping (mappings, mapping_start, mapping_end,
+                         offset_in_pages*page_size, filenames);
+          filenames += strlen (filenames)+1;
       }
     }
     pos = new_pos;
   }
+  ebl_closebackend (ebl);
+  return notes;
+}
 
-/*  printf ("PC: 0x%llx\n", (unsigned long long)regs.pc);
-  printf ("SP: 0x%llx\n", (unsigned long long)regs.sp);*/
-
-  Callstack callstack;
-
-  create_crash_stack (regs, dwfl, core, &mappings, &callstack);
+static void printCallstack (Callstack *callstack, Dwfl *dwfl, Elf *core, pid_t pid,
+    Elf_Data *notes)
+{
+  fprintf (outputfile, "Call stack");
+  if (pid > 1) fprintf (outputfile, " for PID %d", pid);
+  fprintf (outputfile, ":\n");
 
   char *dem_buffer = NULL;
   size_t it;
-
-  printf ("Call stack:\n");
-  for (it = 0; it != callstack.elems; ++it)
+  for (it = 0; it != callstack->elems; ++it)
   {
-    if (sizeof (callstack.tab[0]) > 4)
-      printf ("0x%016llx: ", (long long)callstack.tab[it]);
+    if (sizeof (callstack->tab[0]) > 4)
+      fprintf (outputfile, "0x%016llx: ", (long long)callstack->tab[it]);
     else
-      printf ("0x%08x: ", (int32_t)callstack.tab[it]);
-    Dwfl_Module *module = dwfl_addrmodule (dwfl, callstack.tab[it]);
+      fprintf (outputfile, "0x%08x: ", (int32_t)callstack->tab[it]);
+    Dwfl_Module *module = dwfl_addrmodule (dwfl, callstack->tab[it]);
     if (module)
     {
       char *demangled_symbol = 0;
-      const char *symbol = dwfl_module_addrname (module, callstack.tab[it]);
+      const char *symbol = dwfl_module_addrname (module, callstack->tab[it]);
       const char *fname = 0;
       const char *module_name = dwfl_module_info (module, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
       char *symbol_from_elf = 0;
       if (symbol == NULL)
       {
-        symbol = symbol_from_elf = try_symbol_from_elfs (core, notes, callstack.tab[it], &fname);
+        symbol = symbol_from_elf = try_symbol_from_elfs (core, notes, callstack->tab[it], &fname);
       }
       if (symbol != 0 && symbol[0] == '_' && symbol[1] == 'Z')
       {
@@ -408,9 +496,9 @@ int main(int argc, char **argv)
           symbol = demangled_symbol;
       }
       if (symbol != 0)
-        printf ("%s()", symbol);
+        fprintf (outputfile, "%s()", symbol);
       else
-        printf ("<unknown>");
+        fprintf (outputfile, "<unknown>");
 
       if (demangled_symbol != 0)
         free (demangled_symbol);
@@ -418,19 +506,119 @@ int main(int argc, char **argv)
       if (symbol_from_elf != 0)
         free (symbol_from_elf);
 
-      printf (" from %s\n", fname != NULL ? fname : module_name);
+      fprintf (outputfile, " from %s\n", fname != NULL ? fname : module_name);
     }
     else
     {
-      printf ("unknown function\n");
+      fprintf (outputfile, "unknown function\n");
     }
   }
+}
+
+int main(int argc, char **argv)
+{
+  int c;
+  pid_t pid = 0;
+
+  const char *core_file_name;
+
+  prctl (PR_SET_DUMPABLE, 0);
+
+  while ((c = getopt_long_only(argc, argv, "", opts, NULL)) != -1)
+  {
+    switch (c)
+    {
+      case OPT_PID:
+        pid = atoi(optarg);
+        break;
+      case OPT_OUTPUTFILE:
+        outputfile = fopen(optarg, "w");
+        break;
+      case OPT_ERRFILE:
+        errfile = fopen(optarg, "w");
+        break;
+    }
+  }
+
+  if (NULL == errfile) errfile = stderr;
+  if (NULL == outputfile) outputfile = stdout;
+
+  core_file_name = argv[optind];
+  argc -= optind;
+
+  elf_version (EV_CURRENT);
+
+  /* First, prepare dwfl and modules */
+  Elf *core = NULL;
+  int core_fd = -1;
+  Dwfl *dwfl = NULL;
+
+  if (pid > 1)
+  {
+    dwfl = open_dwfl_with_pid (pid);
+  }
+  else
+  {
+    if (argc != 1)
+    {
+      fprintf (errfile,
+               "Usage: %s [--output file] [--erroutput file] [--pid <pid> | <core-file>]\n",
+               argv[0]);
+      return 1;
+    }
+
+    core_fd = open (core_file_name, O_RDONLY);
+    if (core_fd < 0)
+    {
+      perror (core_file_name);
+      return 2;
+    }
+
+    core = elf_begin (core_fd, ELF_C_READ_MMAP, NULL);
+    if (core == NULL)
+    {
+      fprintf (errfile, "%s : Can't open ELF (%s)\n", core_file_name, elf_errmsg(-1));
+      return 3;
+    }
+
+    dwfl = open_dwfl_with_core (core, core_file_name);
+  }
+
+  if (NULL == dwfl)
+    return 1111;
+
+  Mappings mappings;
+  mappings.elems = 0;
+
+  dwfl_getmodules (dwfl, module_callback, &mappings, 0);
+  Elf_Data *notes = 0;
+
+  /* Now, get registers */
+  if (pid > 1)
+  {
+    if (-1 == get_registers_ptrace (pid))
+      return 3333;
+  }
+  else
+  {
+    notes = get_registers_core (core, core_file_name, &mappings);
+    if (NULL == notes)
+      return 2222;
+  }
+
+  /* Unwind call stack */
+  Callstack callstack;
+
+  create_crash_stack (dwfl, core, pid, &mappings, &callstack);
+
+  /* Print the results */
+  printCallstack (&callstack, dwfl, core, pid, notes);
 
+  /* Clean up */
   dwfl_report_end (dwfl, NULL, NULL);
   dwfl_end (dwfl);
-  ebl_closebackend(ebl);
-  elf_end (core);
-  close (core_fd);
+  if (NULL != core) elf_end (core);
+  if (-1 != core_fd) close (core_fd);
 
   return 0;
 }
index 595a2de..251ca37 100644 (file)
@@ -31,11 +31,7 @@ typedef struct Mappings
   size_t elems;
 } Mappings;
 
-struct Regs;
-typedef struct Regs Regs;
-
-Regs *get_regs_struct (void);
 void *get_place_for_register_value (const char *regname, int regnum);
-void create_crash_stack (Regs *regs, Dwfl *dwfl, Elf *core, Mappings *mappings, Callstack *callstack);
+void create_crash_stack (Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack);
 
 #endif /* CRASH_STACK_H */