libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] [PATCHv2 3/3] Add core dump unwinding support to libun


From: Denys Vlasenko
Subject: [Libunwind-devel] [PATCHv2 3/3] Add core dump unwinding support to libunwind
Date: Tue, 21 Feb 2012 18:22:47 +0100
User-agent: Mozilla/5.0 (X11; Linux i686; rv:10.0) Gecko/20120131 Thunderbird/10.0

On 02/21/2012 06:19 PM, Denys Vlasenko wrote:
Patch 3:
Add src/coredump/*. Took the review comments into an account:
uses code commonalized in patches 1, 2; reformatted to follow the style.

--
vda

diff -d -urpN libunwind.2/configure.in libunwind.3/configure.in
--- libunwind.2/configure.in    2012-02-13 18:43:50.000000000 +0100
+++ libunwind.3/configure.in    2012-02-21 17:58:31.210417230 +0100
@@ -44,6 +44,7 @@ AC_C_CONST
 AC_C_INLINE
 AC_TYPE_SIGNAL
 AC_TYPE_SIZE_T
+AC_CHECK_SIZEOF(off_t)

 CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE"

diff -d -urpN libunwind.2/include/libunwind-coredump.h 
libunwind.3/include/libunwind-coredump.h
--- libunwind.2/include/libunwind-coredump.h    1970-01-01 01:00:00.000000000 
+0100
+++ libunwind.3/include/libunwind-coredump.h    2012-02-21 17:58:31.210417230 
+0100
@@ -0,0 +1,66 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#ifndef libunwind_coredump_h
+#define libunwind_coredump_h
+
+#include <libunwind.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* Helper routines which make it easy to use libunwind on a coredump.
+   They're available only if UNW_REMOTE_ONLY is _not_ defined and they
+   aren't really part of the libunwind API.  They are implemented in a
+   archive library called libunwind-coredump.a.  */
+
+struct UCD_info;
+
+extern struct UCD_info *_UCD_create(const char *filename);
+extern void _UCD_destroy(struct UCD_info *);
+
+extern int _UCD_add_backing_file(struct UCD_info *, int phdr_no, const char 
*filename);
+
+extern int _UCD_find_proc_info (unw_addr_space_t, unw_word_t,
+                               unw_proc_info_t *, int, void *);
+extern void _UCD_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
+extern int _UCD_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
+                                       void *);
+extern int _UCD_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
+                           void *);
+extern int _UCD_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
+                           int, void *);
+extern int _UCD_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
+                             int, void *);
+extern int _UCD_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
+                              unw_word_t *, void *);
+extern int _UCD_resume (unw_addr_space_t, unw_cursor_t *, void *);
+extern unw_accessors_t _UCD_accessors;
+
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* libunwind_coredump_h */
diff -d -urpN libunwind.2/Makefile.am libunwind.3/Makefile.am
--- libunwind.2/Makefile.am     2012-02-13 18:43:50.000000000 +0100
+++ libunwind.3/Makefile.am     2012-02-21 17:58:31.210417230 +0100
@@ -1,4 +1,6 @@
-include_HEADERS = include/libunwind-dynamic.h include/libunwind-ptrace.h
+include_HEADERS = include/libunwind-dynamic.h \
+    include/libunwind-ptrace.h \
+    include/libunwind-coredump.h

 if ARCH_ARM
 include_HEADERS += include/libunwind-arm.h
diff -d -urpN libunwind.2/src/coredump/example-core-unwind.c 
libunwind.3/src/coredump/example-core-unwind.c
--- libunwind.2/src/coredump/example-core-unwind.c      1970-01-01 
01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/example-core-unwind.c      2012-02-21 
18:03:23.400383339 +0100
@@ -0,0 +1,310 @@
+/*
+ * Example program for unwinding core dumps.
+ *
+ * Compile a-la:
+ * gcc -Os -Wall \
+ *    -Wl,--start-group \
+ *        -lunwind -lunwind-x86 -lunwind-coredump \
+ *        example-core-unwind.c \
+ *    -Wl,--end-group \
+ *    -oexample-core-unwind
+ *
+ * Run:
+ * objdump -sx COREDUMP
+ * eu-unstrip -n --core COREDUMP
+ *   figure out which segments in COREDUMP correspond to which mapped 
executable files
+ *   (binary and libraries), then supply them like this:
+ * ./example-core-unwind COREDUMP 3:/bin/crashed_program 6:/lib/libc.so.6 [...]
+ */
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#undef __USE_GNU
+#define __USE_GNU 1
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdbool.h>
+/* Try to pull in PATH_MAX */
+#include <limits.h>
+#include <sys/param.h>
+#ifndef PATH_MAX
+# define PATH_MAX 256
+#endif
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+
+/* For SIGSEGV handler code */
+#include <execinfo.h>
+#include <sys/ucontext.h>
+
+#include <libunwind-coredump.h>
+
+
+/* Utility logging functions */
+
+enum {
+    LOGMODE_NONE = 0,
+    LOGMODE_STDIO = (1 << 0),
+    LOGMODE_SYSLOG = (1 << 1),
+    LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO,
+};
+const char *msg_prefix = "";
+const char *msg_eol = "\n";
+int logmode = LOGMODE_STDIO;
+int xfunc_error_retval = EXIT_FAILURE;
+
+void xfunc_die(void)
+{
+    exit(xfunc_error_retval);
+}
+
+static void verror_msg_helper(const char *s,
+                              va_list p,
+                              const char* strerr,
+                              int flags)
+{
+    char *msg;
+    int prefix_len, strerr_len, msgeol_len, used;
+
+    if (!logmode)
+        return;
+
+    used = vasprintf(&msg, s, p);
+    if (used < 0)
+        return;
+
+    /* This is ugly and costs +60 bytes compared to multiple
+     * fprintf's, but is guaranteed to do a single write.
+     * This is needed for e.g. when multiple children
+     * can produce log messages simultaneously. */
+
+    prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0;
+    strerr_len = strerr ? strlen(strerr) : 0;
+    msgeol_len = strlen(msg_eol);
+    /* +3 is for ": " before strerr and for terminating NUL */
+    char *msg1 = (char*) realloc(msg, prefix_len + used + strerr_len + 
msgeol_len + 3);
+    if (!msg1) {
+        free(msg);
+        return;
+    }
+    msg = msg1;
+    /* TODO: maybe use writev instead of memmoving? Need full_writev? */
+    if (prefix_len) {
+        char *p;
+        memmove(msg + prefix_len, msg, used);
+        used += prefix_len;
+        p = stpcpy(msg, msg_prefix);
+        p[0] = ':';
+        p[1] = ' ';
+    }
+    if (strerr) {
+        if (s[0]) {
+            msg[used++] = ':';
+            msg[used++] = ' ';
+        }
+        strcpy(&msg[used], strerr);
+        used += strerr_len;
+    }
+    strcpy(&msg[used], msg_eol);
+
+    if (flags & LOGMODE_STDIO) {
+        fflush(stdout);
+        write(STDERR_FILENO, msg, used + msgeol_len);
+    }
+    msg[used] = '\0'; /* remove msg_eol (usually "\n") */
+    if (flags & LOGMODE_SYSLOG) {
+        syslog(LOG_ERR, "%s", msg + prefix_len);
+    }
+    free(msg);
+}
+
+void log_msg(const char *s, ...)
+{
+    va_list p;
+    va_start(p, s);
+    verror_msg_helper(s, p, NULL, logmode);
+    va_end(p);
+}
+/* It's a macro, not function, since it collides with log() from math.h */
+#undef log
+#define log(...) log_msg(__VA_ARGS__)
+
+void error_msg(const char *s, ...)
+{
+    va_list p;
+    va_start(p, s);
+    verror_msg_helper(s, p, NULL, logmode);
+    va_end(p);
+}
+
+void error_msg_and_die(const char *s, ...)
+{
+    va_list p;
+    va_start(p, s);
+    verror_msg_helper(s, p, NULL, logmode);
+    va_end(p);
+    xfunc_die();
+}
+
+void perror_msg(const char *s, ...)
+{
+    va_list p;
+    va_start(p, s);
+    /* Guard against "<error message>: Success" */
+    verror_msg_helper(s, p, errno ? strerror(errno) : NULL, logmode);
+    va_end(p);
+}
+
+void perror_msg_and_die(const char *s, ...)
+{
+    va_list p;
+    va_start(p, s);
+    /* Guard against "<error message>: Success" */
+    verror_msg_helper(s, p, errno ? strerror(errno) : NULL, logmode);
+    va_end(p);
+    xfunc_die();
+}
+
+void die_out_of_memory(void)
+{
+    error_msg_and_die("Out of memory, exiting");
+}
+
+/* End of utility logging functions */
+
+
+
+static
+void handle_sigsegv(int sig, siginfo_t *info, void *ucontext)
+{
+       long ip;
+       ucontext_t *uc;
+
+       uc = ucontext;
+       ip = uc->uc_mcontext.gregs[REG_EIP];
+       dprintf(2, "signal:%d address:0x%lx ip:0x%lx\n",
+                       sig,
+                       /* this is void*, but using %p would print "(null)"
+                        * even for ptrs which are not exactly 0, but, say, 
0x123:
+                        */
+                       (long)info->si_addr,
+                       ip);
+       {
+               /* glibc extension */
+               void *array[50];
+               int size;
+               size = backtrace(array, 50);
+               backtrace_symbols_fd(array, size, 2);
+       }
+       _exit(1);
+}
+
+static void install_sigsegv_handler(void)
+{
+       struct sigaction sa;
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_sigaction = handle_sigsegv;
+       sa.sa_flags = SA_SIGINFO;
+       sigaction(SIGSEGV, &sa, NULL);
+       sigaction(SIGILL, &sa, NULL);
+       sigaction(SIGFPE, &sa, NULL);
+       sigaction(SIGBUS, &sa, NULL);
+}
+
+int
+main(int argc, char **argv)
+{
+       unw_addr_space_t as;
+       struct UCD_info *ui;
+       unw_cursor_t c;
+       int ret;
+
+       install_sigsegv_handler();
+
+       const char *progname = strrchr(argv[0], '/');
+       if (progname)
+               progname++;
+       else
+               progname = argv[0];
+
+       if (!argv[1])
+               error_msg_and_die("Usage: %s COREDUMP 
[SEGMENT_NO:BINARY_FILE]...", progname);
+
+       msg_prefix = progname;
+
+       as = unw_create_addr_space(&_UCD_accessors, 0);
+       if (!as)
+               error_msg_and_die("unw_create_addr_space() failed");
+
+       ui = _UCD_create(argv[1]);
+       if (!ui)
+               error_msg_and_die("_UCD_create('%s') failed", argv[1]);
+       ret = unw_init_remote(&c, as, ui);
+       if (ret < 0)
+               error_msg_and_die("unw_init_remote() failed: ret=%d\n", ret);
+
+       argv += 2;
+       while (*argv) {
+               char *colon = strchr(*argv, ':');
+               if (!colon)
+                       error_msg_and_die("Bad format: '%s'", *argv);
+               *colon = '\0';
+               unsigned n = atoi(*argv);
+               *colon = ':';
+               if (_UCD_add_backing_file(ui, n, colon + 1) < 0)
+                       error_msg_and_die("Can't add backing file '%s'", *argv);
+               argv++;
+       }
+
+       for (;;) {
+               unw_word_t ip;
+               ret = unw_get_reg(&c, UNW_REG_IP, &ip);
+               if (ret < 0)
+                       error_msg_and_die("unw_get_reg(UNW_REG_IP) failed: 
ret=%d\n", ret);
+
+               unw_proc_info_t pi;
+               ret = unw_get_proc_info(&c, &pi);
+               if (ret < 0)
+                       error_msg_and_die("unw_get_proc_info(ip=0x%lx) failed: 
ret=%d\n", (long) ip, ret);
+               printf("\tip=0x%08lx proc=%08lx-%08lx handler=0x%08lx 
lsda=0x%08lx\n",
+                               (long) ip,
+                               (long) pi.start_ip, (long) pi.end_ip,
+                               (long) pi.handler, (long) pi.lsda);
+
+               log("step");
+               ret = unw_step(&c);
+               log("step done:%d", ret);
+               if (ret < 0)
+                       error_msg_and_die("FAILURE: unw_step() returned %d", 
ret);
+               if (ret == 0)
+                       break;
+       }
+       log("stepping ended");
+
+       _UCD_destroy(ui);
+
+       return 0;
+}
diff -d -urpN libunwind.2/src/coredump/README libunwind.3/src/coredump/README
--- libunwind.2/src/coredump/README     1970-01-01 01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/README     2012-02-21 17:58:31.211417235 +0100
@@ -0,0 +1,8 @@
+This code is based on "unwinding via ptrace" code from ptrace/
+directory.
+
+Files with names starting with _UCD_ are substantially changed
+from their ptrace/_UPT_... progenitors.
+
+Files which still have _UPT_... names are either verbiatim copies
+from ptrace/, or unimplemented stubs.
diff -d -urpN libunwind.2/src/coredump/_UCD_access_mem.c 
libunwind.3/src/coredump/_UCD_access_mem.c
--- libunwind.2/src/coredump/_UCD_access_mem.c  1970-01-01 01:00:00.000000000 
+0100
+++ libunwind.3/src/coredump/_UCD_access_mem.c  2012-02-21 18:03:23.400383339 
+0100
@@ -0,0 +1,102 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+int
+_UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+                int write, void *arg)
+{
+  if (write)
+    {
+      Debug(0, "%s: write is not supported\n", __func__);
+      return -UNW_EINVAL;
+    }
+
+  struct UCD_info *ui = arg;
+
+  unw_word_t addr_last = addr + sizeof(*val)-1;
+  coredump_phdr_t *phdr;
+  unsigned i;
+  for (i = 0; i < ui->phdrs_count; i++)
+    {
+      phdr = &ui->phdrs[i];
+      if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz)
+       {
+         goto found;
+       }
+    }
+  Debug(1, "%s: addr 0x%llx is unmapped\n",
+               __func__, (unsigned long long)addr
+  );
+  return -UNW_EINVAL;
+
+ found: ;
+
+  const char *filename;
+  off_t fileofs;
+  int fd;
+  if (addr_last >= phdr->p_vaddr + phdr->p_filesz)
+    {
+      /* This part of mapped address space is not present in coredump file */
+      /* Do we have it in the backup file? */
+      if (phdr->backing_fd < 0)
+        {
+          Debug(1, "%s: access to not-present data in phdr[%d]: addr:0x%llx\n",
+                               __func__, i, (unsigned long long)addr
+                       );
+          return -UNW_EINVAL;
+        }
+      filename = phdr->backing_filename;
+      fileofs = addr - phdr->p_vaddr;
+      fd = phdr->backing_fd;
+      goto read;
+    }
+
+  filename = ui->coredump_filename;
+  fileofs = phdr->p_offset + (addr - phdr->p_vaddr);
+  fd = ui->coredump_fd;
+ read:
+  if (lseek(fd, fileofs, SEEK_SET) != fileofs)
+    goto read_error;
+  if (read(fd, val, sizeof(*val)) != sizeof(*val))
+    goto read_error;
+
+  Debug(1, "%s: 0x%llx <- [addr:0x%llx fileofs:0x%llx]\n",
+       __func__,
+       (unsigned long long)(*val),
+       (unsigned long long)addr,
+       (unsigned long long)fileofs
+  );
+  return 0;
+
+ read_error:
+  Debug(1, "%s: access out of file: addr:0x%llx fileofs:%llx file:'%s'\n",
+       __func__,
+       (unsigned long long)addr,
+       (unsigned long long)fileofs,
+       filename
+  );
+  return -UNW_EINVAL;
+}
diff -d -urpN libunwind.2/src/coredump/_UCD_accessors.c 
libunwind.3/src/coredump/_UCD_accessors.c
--- libunwind.2/src/coredump/_UCD_accessors.c   1970-01-01 01:00:00.000000000 
+0100
+++ libunwind.3/src/coredump/_UCD_accessors.c   2012-02-21 18:03:23.400383339 
+0100
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_internal.h"
+
+PROTECTED unw_accessors_t _UCD_accessors =
+  {
+    .find_proc_info            = _UCD_find_proc_info,
+    .put_unwind_info           = _UCD_put_unwind_info,
+    .get_dyn_info_list_addr    = _UCD_get_dyn_info_list_addr,
+    .access_mem                        = _UCD_access_mem,
+    .access_reg                        = _UCD_access_reg,
+    .access_fpreg              = _UCD_access_fpreg,
+    .resume                    = _UCD_resume,
+    .get_proc_name             = _UCD_get_proc_name
+  };
diff -d -urpN libunwind.2/src/coredump/_UCD_access_reg.c 
libunwind.3/src/coredump/_UCD_access_reg.c
--- libunwind.2/src/coredump/_UCD_access_reg.c  1970-01-01 01:00:00.000000000 
+0100
+++ libunwind.3/src/coredump/_UCD_access_reg.c  2012-02-21 18:03:23.400383339 
+0100
@@ -0,0 +1,92 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_lib.h"
+
+#include "_UCD_internal.h"
+
+int
+_UCD_access_reg (unw_addr_space_t as,
+                                unw_regnum_t regnum, unw_word_t *valp,
+                                int write, void *arg)
+{
+  if (write)
+    {
+      Debug(0, "%s: write is not supported\n", __func__);
+      return -UNW_EINVAL;
+    }
+
+#if defined(UNW_TARGET_X86)
+  static const uint8_t remap_regs[] =
+    {
+      /* names from libunwind-x86.h */
+      [UNW_X86_EAX]    = offsetof(struct user_regs_struct, eax) / sizeof(long),
+      [UNW_X86_EDX]    = offsetof(struct user_regs_struct, edx) / sizeof(long),
+      [UNW_X86_ECX]    = offsetof(struct user_regs_struct, ecx) / sizeof(long),
+      [UNW_X86_EBX]    = offsetof(struct user_regs_struct, ebx) / sizeof(long),
+      [UNW_X86_ESI]    = offsetof(struct user_regs_struct, esi) / sizeof(long),
+      [UNW_X86_EDI]    = offsetof(struct user_regs_struct, edi) / sizeof(long),
+      [UNW_X86_EBP]    = offsetof(struct user_regs_struct, ebp) / sizeof(long),
+      [UNW_X86_ESP]    = offsetof(struct user_regs_struct, esp) / sizeof(long),
+      [UNW_X86_EIP]    = offsetof(struct user_regs_struct, eip) / sizeof(long),
+      [UNW_X86_EFLAGS] = offsetof(struct user_regs_struct, eflags) / 
sizeof(long),
+      [UNW_X86_TRAPNO] = offsetof(struct user_regs_struct, orig_eax) / 
sizeof(long),
+    };
+#elif defined(UNW_TARGET_X86_64)
+  static const int8_t remap_regs[] =
+    {
+      [UNW_X86_RAX]    = offsetof(struct user_regs_struct, rax) / sizeof(long),
+      [UNW_X86_RDX]    = offsetof(struct user_regs_struct, rdx) / sizeof(long),
+      [UNW_X86_RCX]    = offsetof(struct user_regs_struct, rcx) / sizeof(long),
+      [UNW_X86_RBX]    = offsetof(struct user_regs_struct, rbx) / sizeof(long),
+      [UNW_X86_RSI]    = offsetof(struct user_regs_struct, rsi) / sizeof(long),
+      [UNW_X86_RDI]    = offsetof(struct user_regs_struct, rdi) / sizeof(long),
+      [UNW_X86_RBP]    = offsetof(struct user_regs_struct, rbp) / sizeof(long),
+      [UNW_X86_RSP]    = offsetof(struct user_regs_struct, rsp) / sizeof(long),
+      [UNW_X86_RIP]    = offsetof(struct user_regs_struct, rip) / sizeof(long),
+      [UNW_X86_RFLAGS] = offsetof(struct user_regs_struct, rflags) / 
sizeof(long),
+      [UNW_X86_TRAPNO] = offsetof(struct user_regs_struct, orig_rax) / 
sizeof(long),
+    };
+#else
+#error Port me
+#endif
+
+  struct UCD_info *ui = arg;
+  if (regnum < 0 || regnum >= ARRAY_SIZE(remap_regs))
+    {
+      Debug(0, "%s: bad regnum:%d\n", __func__, regnum);
+      return -UNW_EINVAL;
+    }
+  regnum = remap_regs[regnum];
+
+  /* pr_reg is a long[] array, but it contains struct user_regs_struct's
+   * image.
+   */
+  Debug(1 "pr_reg[%d]:%ld (0x%lx)", regnum,
+               (long)ui->prstatus->pr_reg[regnum],
+               (long)ui->prstatus->pr_reg[regnum]
+  );
+  *valp = ui->prstatus->pr_reg[regnum];
+
+  return 0;
+}
diff -d -urpN libunwind.2/src/coredump/_UCD_create.c 
libunwind.3/src/coredump/_UCD_create.c
--- libunwind.2/src/coredump/_UCD_create.c      1970-01-01 01:00:00.000000000 
+0100
+++ libunwind.3/src/coredump/_UCD_create.c      2012-02-21 18:03:23.400383339 
+0100
@@ -0,0 +1,363 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+/* Endian detection */
+#include <limits.h>
+#include <byteswap.h>
+#include <endian.h>
+#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
+# define WE_ARE_BIG_ENDIAN    1
+# define WE_ARE_LITTLE_ENDIAN 0
+#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+# define WE_ARE_BIG_ENDIAN    0
+# define WE_ARE_LITTLE_ENDIAN 1
+#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN
+# define WE_ARE_BIG_ENDIAN    1
+# define WE_ARE_LITTLE_ENDIAN 0
+#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN
+# define WE_ARE_BIG_ENDIAN    0
+# define WE_ARE_LITTLE_ENDIAN 1
+#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
+# define WE_ARE_BIG_ENDIAN    1
+# define WE_ARE_LITTLE_ENDIAN 0
+#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
+# define WE_ARE_BIG_ENDIAN    0
+# define WE_ARE_LITTLE_ENDIAN 1
+#elif defined(__386__)
+# define WE_ARE_BIG_ENDIAN    0
+# define WE_ARE_LITTLE_ENDIAN 1
+#else
+# error "Can't determine endianness"
+#endif
+
+#include <elf.h>
+#include <sys/procfs.h> /* struct elf_prstatus */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+struct UCD_info *
+_UCD_create(const char *filename)
+{
+  union
+    {
+      Elf32_Ehdr h32;
+      Elf64_Ehdr h64;
+    } elf_header;
+#define elf_header32 elf_header.h32
+#define elf_header64 elf_header.h64
+  bool _64bits;
+
+  struct UCD_info *ui = memset(malloc(sizeof(*ui)), 0, sizeof(*ui));
+  ui->edi.di_cache.format = -1;
+  ui->edi.di_debug.format = -1;
+#if UNW_TARGET_IA64
+  ui->edi.ktab.format = -1;
+#endif
+
+  int fd = ui->coredump_fd = open(filename, O_RDONLY);
+  if (fd < 0)
+    goto err;
+  ui->coredump_filename = strdup(filename);
+
+  /* No sane ELF32 file is going to be smaller then ELF64 _header_,
+   * so let's just read 64-bit sized one.
+   */
+  if (read(fd, &elf_header64, sizeof(elf_header64)) != sizeof(elf_header64))
+    {
+      Debug(0, "'%s' is not an ELF file\n", filename);
+      goto err;
+    }
+
+  if (memcmp(&elf_header32, "\x7f""ELF", 4) != 0)
+    {
+      Debug(0, "'%s' is not an ELF file\n", filename);
+      goto err;
+    }
+
+  if (elf_header32.e_ident[EI_CLASS] != ELFCLASS32
+   && elf_header32.e_ident[EI_CLASS] != ELFCLASS64)
+    {
+      Debug(0, "'%s' is not a 32/64 bit ELF file\n", filename);
+      goto err;
+    }
+
+  if (WE_ARE_LITTLE_ENDIAN != (elf_header32.e_ident[EI_DATA] == ELFDATA2LSB))
+    {
+      Debug(0, "'%s' is endian-incompatible\n", filename);
+      goto err;
+    }
+
+  _64bits = (elf_header32.e_ident[EI_CLASS] == ELFCLASS64);
+  if (_64bits && sizeof(elf_header64.e_entry) > sizeof(off_t))
+    {
+      Debug(0, "Can't process '%s': 64-bit file "
+                               "while only %d bits are supported",
+                               filename, 8 * sizeof(off_t));
+      goto err;
+    }
+
+  /* paranoia check */
+  if (_64bits
+           ? 0 /* todo: (elf_header64.e_ehsize != NN || 
elf_header64.e_phentsize != NN) */
+           : (elf_header32.e_ehsize != 52 || elf_header32.e_phentsize != 32)
+  )
+    {
+      Debug(0, "'%s' has wrong e_ehsize or e_phentsize\n", filename);
+      goto err;
+    }
+
+  off_t ofs = (_64bits ? elf_header64.e_phoff : elf_header32.e_phoff);
+  if (lseek(fd, ofs, SEEK_SET) != ofs)
+    {
+      Debug(0, "Can't read phdrs from '%s'\n", filename);
+      goto err;
+    }
+  unsigned size = ui->phdrs_count = (_64bits ? elf_header64.e_phnum : 
elf_header32.e_phnum);
+  coredump_phdr_t *phdrs = ui->phdrs = memset(malloc(size * sizeof(phdrs[0])), 
0, size * sizeof(phdrs[0]));
+  if (_64bits)
+    {
+      coredump_phdr_t *cur = phdrs;
+      unsigned i = 0;
+      while (i < size)
+       {
+          Elf64_Phdr hdr64;
+         if (read(fd, &hdr64, sizeof(hdr64)) != sizeof(hdr64))
+           {
+             Debug(0, "Can't read phdrs from '%s'\n", filename);
+             goto err;
+           }
+         cur->p_type   = hdr64.p_type  ;
+         cur->p_flags  = hdr64.p_flags ;
+         cur->p_offset = hdr64.p_offset;
+         cur->p_vaddr  = hdr64.p_vaddr ;
+         /*cur->p_paddr  = hdr32.p_paddr ; always 0 */
+//TODO: check that and abort if it isn't?
+         cur->p_filesz = hdr64.p_filesz;
+         cur->p_memsz  = hdr64.p_memsz ;
+         cur->p_align  = hdr64.p_align ;
+         /* cur->backing_filename = NULL; - done by memset */
+         cur->backing_fd = -1;
+         cur->backing_filesize = hdr64.p_filesz;
+         i++;
+         cur++;
+       }
+    } else {
+      coredump_phdr_t *cur = phdrs;
+      unsigned i = 0;
+      while (i < size)
+       {
+         Elf32_Phdr hdr32;
+         if (read(fd, &hdr32, sizeof(hdr32)) != sizeof(hdr32))
+           {
+             Debug(0, "Can't read phdrs from '%s'\n", filename);
+             goto err;
+           }
+         cur->p_type   = hdr32.p_type  ;
+         cur->p_flags  = hdr32.p_flags ;
+         cur->p_offset = hdr32.p_offset;
+         cur->p_vaddr  = hdr32.p_vaddr ;
+         /*cur->p_paddr  = hdr32.p_paddr ; always 0 */
+         cur->p_filesz = hdr32.p_filesz;
+         cur->p_memsz  = hdr32.p_memsz ;
+         cur->p_align  = hdr32.p_align ;
+         /* cur->backing_filename = NULL; - done by memset */
+         cur->backing_fd = -1;
+         cur->backing_filesize = hdr32.p_memsz;
+         i++;
+         cur++;
+       }
+    }
+
+    unsigned i = 0;
+    coredump_phdr_t *cur = phdrs;
+    while (i < size)
+      {
+       Debug(2, "phdr[%03d]: type:%d", i, cur->p_type);
+       if (cur->p_type == PT_NOTE)
+         {
+           ui->note_phdr = malloc(cur->p_filesz);
+           if (lseek(fd, cur->p_offset, SEEK_SET) != (off_t)cur->p_offset
+            || (uoff_t)read(fd, ui->note_phdr, cur->p_filesz) != cur->p_filesz
+           )
+             {
+               Debug(0, "Can't read PT_NOTE from '%s'\n", filename);
+               goto err;
+             }
+
+           /* Note is three 32-bit words: */
+           /* Elf32_Word n_namesz; Length of the note's name */
+           /* Elf32_Word n_descsz; Length of the note's descriptor */
+           /* Elf32_Word n_type;   Type */
+           /* followed by name (padded to 32 bits(?)) and then descr */
+           Elf32_Nhdr *note_hdr = ui->note_phdr;
+           if (cur->p_filesz >= 3*4
+            && note_hdr->n_type == NT_PRSTATUS
+            && cur->p_filesz >= (3*4 + note_hdr->n_namesz + note_hdr->n_descsz + 
sizeof(*ui->prstatus))
+           )
+             {
+               ui->prstatus = (void*) ((((long)note_hdr + sizeof(*note_hdr) + 
note_hdr->n_namesz) + 3) & ~3L);
+#if 0
+               printf("pid:%d\n", ui->prstatus->pr_pid);
+               printf("ebx:%ld\n", (long)ui->prstatus->pr_reg[0]);
+               printf("ecx:%ld\n", (long)ui->prstatus->pr_reg[1]);
+               printf("edx:%ld\n", (long)ui->prstatus->pr_reg[2]);
+               printf("esi:%ld\n", (long)ui->prstatus->pr_reg[3]);
+               printf("edi:%ld\n", (long)ui->prstatus->pr_reg[4]);
+               printf("ebp:%ld\n", (long)ui->prstatus->pr_reg[5]);
+               printf("eax:%ld\n", (long)ui->prstatus->pr_reg[6]);
+               printf("xds:%ld\n", (long)ui->prstatus->pr_reg[7]);
+               printf("xes:%ld\n", (long)ui->prstatus->pr_reg[8]);
+               printf("xfs:%ld\n", (long)ui->prstatus->pr_reg[9]);
+               printf("xgs:%ld\n", (long)ui->prstatus->pr_reg[10]);
+               printf("orig_eax:%ld\n", (long)ui->prstatus->pr_reg[11]);
+#endif
+             }
+         }
+       if (cur->p_type == PT_LOAD)
+         {
+           Debug(2, " ofs:%08llx va:%08llx filesize:%08llx memsize:%08llx 
flg:%x",
+                               (unsigned long long) cur->p_offset,
+                               (unsigned long long) cur->p_vaddr,
+                               (unsigned long long) cur->p_filesz,
+                               (unsigned long long) cur->p_memsz,
+                               cur->p_flags
+           );
+           if (cur->p_filesz < cur->p_memsz)
+             Debug(2, " partial");
+           if (cur->p_flags & PF_X)
+             Debug(2, " executable");
+         }
+       Debug(2, "\n");
+       i++;
+       cur++;
+      }
+
+    if (!ui->prstatus)
+      {
+       Debug(0, "No NT_PRSTATUS note found in '%s'\n", filename);
+       goto err;
+      }
+
+  return ui;
+
+ err:
+  _UCD_destroy(ui);
+  return NULL;
+}
+
+int _UCD_add_backing_file(struct UCD_info *ui, int phdr_no, const char 
*filename)
+{
+  if ((unsigned)phdr_no >= ui->phdrs_count)
+    {
+      Debug(0, "There is no segment %d in this coredump\n", phdr_no);
+      return -1;
+    }
+
+  struct coredump_phdr *phdr = &ui->phdrs[phdr_no];
+  if (phdr->backing_filename)
+    {
+      Debug(0, "Backing file already added to segment %d\n", phdr_no);
+      return -1;
+    }
+
+  int fd = open(filename, O_RDONLY);
+  if (fd < 0)
+    {
+      Debug(0, "Can't open '%s'\n", filename);
+      return -1;
+    }
+
+  phdr->backing_fd = fd;
+  phdr->backing_filename = strdup(filename);
+
+  struct stat statbuf;
+  if (fstat(fd, &statbuf) != 0)
+    {
+      Debug(0, "Can't stat '%s'\n", filename);
+      goto err;
+    }
+  phdr->backing_filesize = (uoff_t)statbuf.st_size;
+
+  if (phdr->p_flags != (PF_X | PF_R))
+    Debug(1, "Note: phdr[%u] is not r-x: flags are 0x%x\n", phdr_no, 
phdr->p_flags);
+
+  if (phdr->backing_filesize > phdr->p_memsz)
+    {
+      /* This is expected */
+      Debug(2, "Note: phdr[%u] is %lld bytes, file is larger: %lld bytes\n",
+                       phdr_no,
+                       (unsigned long long)phdr->p_memsz,
+                       (unsigned long long)phdr->backing_filesize
+      );
+    }
+//TODO: else loudly complain? Maybe even fail?
+
+  if (phdr->p_filesz != 0)
+    {
+//TODO: loop and compare in smaller blocks
+      char *core_buf = malloc(phdr->p_filesz);
+      char *file_buf = malloc(phdr->p_filesz);
+      if (lseek(ui->coredump_fd, phdr->p_offset, SEEK_SET) != 
(off_t)phdr->p_offset
+       || (uoff_t)read(ui->coredump_fd, core_buf, phdr->p_filesz) != 
phdr->p_filesz
+      )
+       {
+         Debug(0, "Error reading from coredump file\n");
+ err_read:
+         free(core_buf);
+         free(file_buf);
+         goto err;
+       }
+      if ((uoff_t)read(fd, file_buf, phdr->p_filesz) != phdr->p_filesz)
+       {
+         Debug(0, "Error reading from '%s'\n", filename);
+         goto err_read;
+       }
+      int r = memcmp(core_buf, file_buf, phdr->p_filesz);
+      free(core_buf);
+      free(file_buf);
+      if (r != 0)
+       {
+         Debug(1, "Note: phdr[%u] first %lld bytes in core dump and in file do not 
match\n",
+                               phdr_no, (unsigned long long)phdr->p_filesz
+         );
+       } else {
+         Debug(1, "Note: phdr[%u] first %lld bytes in core dump and in file 
match\n",
+                               phdr_no, (unsigned long long)phdr->p_filesz
+         );
+       }
+    }
+
+  /* Success */
+  return 0;
+
+ err:
+  if (phdr->backing_fd >= 0)
+    {
+      close(phdr->backing_fd);
+      phdr->backing_fd = -1;
+    }
+  free(phdr->backing_filename);
+  phdr->backing_filename = NULL;
+  return -1;
+}
diff -d -urpN libunwind.2/src/coredump/_UCD_destroy.c 
libunwind.3/src/coredump/_UCD_destroy.c
--- libunwind.2/src/coredump/_UCD_destroy.c     1970-01-01 01:00:00.000000000 
+0100
+++ libunwind.3/src/coredump/_UCD_destroy.c     2012-02-21 18:03:23.400383339 
+0100
@@ -0,0 +1,50 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_internal.h"
+
+void
+_UCD_destroy (struct UCD_info *ui)
+{
+  if (!ui)
+    return;
+
+  if (ui->coredump_fd >= 0)
+    close(ui->coredump_fd);
+  free(ui->coredump_filename);
+
+  invalidate_edi (&ui->edi);
+
+  unsigned i;
+  for (i = 0; i < ui->phdrs_count; i++)
+    {
+      struct coredump_phdr *phdr = &ui->phdrs[i];
+      free(phdr->backing_filename);
+      if (phdr->backing_fd >= 0)
+        close(phdr->backing_fd);
+    }
+
+  free(ui->note_phdr);
+
+  free(ui);
+}
diff -d -urpN libunwind.2/src/coredump/_UCD_find_proc_info.c 
libunwind.3/src/coredump/_UCD_find_proc_info.c
--- libunwind.2/src/coredump/_UCD_find_proc_info.c      1970-01-01 
01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/_UCD_find_proc_info.c      2012-02-21 
18:03:23.401383333 +0100
@@ -0,0 +1,234 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include <elf.h>
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+static coredump_phdr_t *
+CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr)
+{
+  struct elf_image *ei = &ui->edi.ei;
+
+  if (phdr->backing_fd < 0)
+    {
+      /* Note: coredump file contains only phdr->p_filesz bytes.
+       * We want to map bigger area (phdr->p_memsz bytes) to make sure
+       * these pages are allocated, but non-accessible.
+       */
+      /* addr, length, prot, flags, fd, fd_offset */
+      ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, 
ui->coredump_fd, phdr->p_offset);
+      if (ei->image == MAP_FAILED)
+       {
+         ei->image = NULL;
+         return NULL;
+       }
+      ei->size = phdr->p_filesz;
+      size_t remainder_len = phdr->p_memsz - phdr->p_filesz;
+      if (remainder_len > 0)
+       {
+         void *remainder_base = (char*) ei->image + phdr->p_filesz;
+         munmap(remainder_base, remainder_len);
+       }
+    } else {
+      /* We have a backing file for this segment.
+       * This file is always longer than phdr->p_memsz,
+       * and if phdr->p_filesz !=0, first phdr->p_filesz bytes in coredump
+       * are the same as first bytes in the file. (Thus no need to map 
coredump)
+       * We map the entire file:
+       * unwinding may need data which is past phdr->p_memsz bytes.
+       */
+      /* addr, length, prot, flags, fd, fd_offset */
+      ei->image = mmap(NULL, phdr->backing_filesize, PROT_READ, MAP_PRIVATE, 
phdr->backing_fd, 0);
+      if (ei->image == MAP_FAILED)
+       {
+         ei->image = NULL;
+         return NULL;
+       }
+      ei->size = phdr->backing_filesize;
+    }
+
+  /* Check ELF header for sanity */
+  if (!elf_w(valid_object)(ei))
+    {
+      munmap(ei->image, ei->size);
+      ei->image = NULL;
+      ei->size = 0;
+      return NULL;
+    }
+
+  return phdr;
+}
+
+static coredump_phdr_t *
+CD_get_elf_image(struct UCD_info *ui, unw_word_t ip)
+{
+  unsigned i;
+  for (i = 0; i < ui->phdrs_count; i++)
+    {
+      coredump_phdr_t *phdr = &ui->phdrs[i];
+      if (phdr->p_vaddr <= ip && ip < phdr->p_vaddr + phdr->p_memsz)
+       {
+         phdr = CD_elf_map_image(ui, phdr);
+         return phdr;
+       }
+    }
+  return NULL;
+}
+
+static int
+get_unwind_info(struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip)
+{
+  unsigned long segbase, mapoff;
+
+#if UNW_TARGET_IA64 && defined(__linux)
+  if (!ui->edi.ktab.start_ip && _Uia64_get_kernel_table (&ui->edi.ktab) < 0)
+    return -UNW_ENOINFO;
+
+  if (ui->edi.ktab.format != -1 && ip >= ui->edi.ktab.start_ip && ip < 
ui->edi.ktab.end_ip)
+    return 0;
+#endif
+
+  if ((ui->edi.di_cache.format != -1
+       && ip >= ui->edi.di_cache.start_ip && ip < ui->edi.di_cache.end_ip)
+#if UNW_TARGET_ARM
+      || (ui->edi.di_debug.format != -1
+       && ip >= ui->edi.di_arm.start_ip && ip < ui->edi.di_arm.end_ip)
+#endif
+      || (ui->edi.di_debug.format != -1
+       && ip >= ui->edi.di_debug.start_ip && ip < ui->edi.di_debug.end_ip))
+    return 0;
+
+  invalidate_edi (&ui->edi);
+
+  /* Used to be tdep_get_elf_image() in ptrace unwining code */
+  coredump_phdr_t *phdr = CD_get_elf_image(ui, ip);
+  if (!phdr)
+    {
+      Debug(1, "%s returns error: CD_get_elf_image failed\n", __func__);
+      return -UNW_ENOINFO;
+    }
+  /* segbase: where it is mapped in virtual memory */
+  /* mapoff: offset in the file */
+  segbase = phdr->p_vaddr;
+  /*mapoff  = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP 
file */
+  mapoff  = 0;
+///FIXME. text segment is USUALLY, not always, at offset 0 in the binary/.so 
file.
+// ensure that at initialization.
+
+  /* Here, SEGBASE is the starting-address of the (mmap'ped) segment
+     which covers the IP we're looking for.  */
+  if (find_unwind_table(&ui->edi, as, phdr->backing_filename, segbase, mapoff, 
ip) < 0)
+    {
+      Debug(1, "%s returns error: find_unwind_table failed\n", __func__);
+      return -UNW_ENOINFO;
+    }
+
+  /* This can happen in corner cases where dynamically generated
+     code falls into the same page that contains the data-segment
+     and the page-offset of the code is within the first page of
+     the executable.  */
+  if (ui->edi.di_cache.format != -1
+      && (ip < ui->edi.di_cache.start_ip || ip >= ui->edi.di_cache.end_ip))
+     ui->edi.di_cache.format = -1;
+
+  if (ui->edi.di_debug.format != -1
+      && (ip < ui->edi.di_debug.start_ip || ip >= ui->edi.di_debug.end_ip))
+     ui->edi.di_debug.format = -1;
+
+  if (ui->edi.di_cache.format == -1
+#if UNW_TARGET_ARM
+      && ui->edi.di_arm.format == -1
+#endif
+      && ui->edi.di_debug.format == -1)
+  {
+    Debug(1, "%s returns error: all formats are -1\n", __func__);
+    return -UNW_ENOINFO;
+  }
+
+  Debug(1, "%s returns success\n", __func__);
+  return 0;
+}
+
+int
+_UCD_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+                    int need_unwind_info, void *arg)
+{
+  struct UCD_info *ui = arg;
+
+  Debug(1, "%s: entering\n", __func__);
+
+  int ret = -UNW_ENOINFO;
+
+  if (get_unwind_info(ui, as, ip) < 0) {
+    Debug(1, "%s returns error: get_unwind_info failed\n", __func__);
+    return -UNW_ENOINFO;
+  }
+
+#if UNW_TARGET_IA64
+  if (ui->edi.ktab.format != -1)
+    {
+      /* The kernel unwind table resides in local memory, so we have
+        to use the local address space to search it.  Since
+        _UCD_put_unwind_info() has no easy way of detecting this
+        case, we simply make a copy of the unwind-info, so
+        _UCD_put_unwind_info() can always free() the unwind-info
+        without ill effects.  */
+      ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, 
pi,
+                                     need_unwind_info, arg);
+      if (ret >= 0)
+       {
+         if (!need_unwind_info)
+           pi->unwind_info = NULL;
+         else
+           {
+             void *mem = malloc (pi->unwind_info_size);
+
+             if (!mem)
+               return -UNW_ENOMEM;
+             memcpy (mem, pi->unwind_info, pi->unwind_info_size);
+             pi->unwind_info = mem;
+           }
+       }
+    }
+#endif
+
+  if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1)
+    ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache,
+                                   pi, need_unwind_info, arg);
+
+#if UNW_TARGET_ARM
+  if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1)
+    ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi,
+                                    need_unwind_info, arg);
+#endif
+
+  if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1)
+    ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi,
+                                   need_unwind_info, arg);
+
+  Debug(1, "%s: returns %d\n", __func__, ret);
+
+  return ret;
+}
diff -d -urpN libunwind.2/src/coredump/_UCD_internal.h 
libunwind.3/src/coredump/_UCD_internal.h
--- libunwind.2/src/coredump/_UCD_internal.h    1970-01-01 01:00:00.000000000 
+0100
+++ libunwind.3/src/coredump/_UCD_internal.h    2012-02-21 17:58:58.475519011 
+0100
@@ -0,0 +1,91 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#ifndef _UCD_internal_h
+#define _UCD_internal_h
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h> /* struct elf_prstatus */
+#endif
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libunwind-coredump.h>
+
+#include "libunwind_i.h"
+
+
+#if SIZEOF_OFF_T == 4
+typedef uint32_t uoff_t;
+#elif SIZEOF_OFF_T == 8
+typedef uint64_t uoff_t;
+#else
+# error Unknown size of off_t!
+#endif
+
+
+/* Similar to ELF phdrs. p_paddr element is absent,
+ * since it's always 0 in coredumps.
+ */
+struct coredump_phdr
+  {
+    uint32_t p_type;
+    uint32_t p_flags;
+    uoff_t   p_offset;
+    uoff_t   p_vaddr;
+    uoff_t   p_filesz;
+    uoff_t   p_memsz;
+    uoff_t   p_align;
+    /* Data for backing file. If backing_fd < 0, there is no file */
+    uoff_t   backing_filesize;
+    char    *backing_filename; /* for error meesages only */
+    int      backing_fd;
+  };
+
+typedef struct coredump_phdr coredump_phdr_t;
+
+
+struct UCD_info
+  {
+    int big_endian;  /* bool */
+    int coredump_fd;
+    char *coredump_filename; /* for error meesages only */
+    coredump_phdr_t *phdrs; /* array, allocated */
+    unsigned phdrs_count;
+    void *note_phdr; /* allocated or NULL */
+    struct elf_prstatus *prstatus; /* points inside note_phdr */
+
+    struct elf_dyn_info edi;
+  };
+
+#endif
diff -d -urpN libunwind.2/src/coredump/_UCD_lib.h 
libunwind.3/src/coredump/_UCD_lib.h
--- libunwind.2/src/coredump/_UCD_lib.h 1970-01-01 01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/_UCD_lib.h 2012-02-21 17:58:41.578456227 +0100
@@ -0,0 +1,53 @@
+/*
+    Copyright (C) 2010  ABRT team
+    Copyright (C) 2010  RedHat Inc
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef _UCD_lib_h
+#define _UCD_lib_h
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+
+#endif
diff -d -urpN libunwind.2/src/coredump/_UPT_access_fpreg.c 
libunwind.3/src/coredump/_UPT_access_fpreg.c
--- libunwind.2/src/coredump/_UPT_access_fpreg.c        1970-01-01 
01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/_UPT_access_fpreg.c        2012-02-21 
18:03:23.401383333 +0100
@@ -0,0 +1,34 @@
+/* libunwind - a platform-independent unwind library
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+int
+_UCD_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+                  int write, void *arg)
+{
+  print_error (__func__);
+  print_error (" not implemented\n");
+  return -UNW_EINVAL;
+}
diff -d -urpN libunwind.2/src/coredump/_UPT_elf.c 
libunwind.3/src/coredump/_UPT_elf.c
--- libunwind.2/src/coredump/_UPT_elf.c 1970-01-01 01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/_UPT_elf.c 2012-02-21 18:03:23.401383333 +0100
@@ -0,0 +1,5 @@
+/* We need to get a separate copy of the ELF-code into
+   libunwind-ptrace since it cannot (and must not) have any ELF
+   dependencies on libunwind.  */
+#include "libunwind_i.h"     /* get ELFCLASS defined */
+#include "../elfxx.c"
diff -d -urpN libunwind.2/src/coredump/_UPT_get_dyn_info_list_addr.c 
libunwind.3/src/coredump/_UPT_get_dyn_info_list_addr.c
--- libunwind.2/src/coredump/_UPT_get_dyn_info_list_addr.c      1970-01-01 
01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/_UPT_get_dyn_info_list_addr.c      2012-02-21 
18:03:23.401383333 +0100
@@ -0,0 +1,108 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2003-2005 Hewlett-Packard Co
+       Contributed by David Mosberger-Tang <address@hidden>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+#if UNW_TARGET_IA64 && defined(__linux)
+# include "elf64.h"
+# include "os-linux.h"
+
+static inline int
+get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
+              int *countp)
+{
+  unsigned long lo, hi, off;
+  struct UPT_info *ui = arg;
+  struct map_iterator mi;
+  char path[PATH_MAX];
+  unw_dyn_info_t *di;
+  unw_word_t res;
+  int count = 0;
+
+  maps_init (&mi, ui->pid);
+  while (maps_next (&mi, &lo, &hi, &off))
+    {
+      if (off)
+       continue;
+
+      invalidate_edi (&ui->edi);
+
+      if (elf_map_image (&ui->ei, path) < 0)
+       /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */
+       continue;
+
+      Debug (16, "checking object %s\n", path);
+
+      di = find_unwind_table (&ui->edi, as, path, lo, off);
+      if (di)
+       {
+         res = _Uia64_find_dyn_list (as, di, arg);
+         if (res && count++ == 0)
+           {
+             Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res);
+             *dil_addr = res;
+           }
+       }
+    }
+  maps_close (&mi);
+  *countp = count;
+  return 0;
+}
+
+#else
+
+static inline int
+get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
+              int *countp)
+{
+# warning Implement get_list_addr(), please.
+  *countp = 0;
+  return 0;
+}
+
+#endif
+
+int
+_UCD_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr,
+                            void *arg)
+{
+  int count, ret;
+
+  Debug (12, "looking for dyn_info list\n");
+
+  if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0)
+    return ret;
+
+  /* If multiple dynamic-info list addresses are found, we would have
+     to determine which was is the one actually in use (since the
+     dynamic name resolution algorithm will pick one "winner").
+     Perhaps we'd have to track them all until we find one that's
+     non-empty.  Hopefully, this case simply will never arise, since
+     only libunwind defines the dynamic info list head. */
+  assert (count <= 1);
+
+  return (count > 0) ? 0 : -UNW_ENOINFO;
+}
diff -d -urpN libunwind.2/src/coredump/_UPT_get_proc_name.c 
libunwind.3/src/coredump/_UPT_get_proc_name.c
--- libunwind.2/src/coredump/_UPT_get_proc_name.c       1970-01-01 
01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/_UPT_get_proc_name.c       2012-02-21 
18:03:23.401383333 +0100
@@ -0,0 +1,51 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2003 Hewlett-Packard Co
+   Copyright (C) 2007 David Mosberger-Tang
+       Contributed by David Mosberger-Tang <address@hidden>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+int
+_UCD_get_proc_name (unw_addr_space_t as, unw_word_t ip,
+                   char *buf, size_t buf_len, unw_word_t *offp, void *arg)
+{
+  print_error (__func__);
+  print_error (" not implemented\n");
+  return -UNW_EINVAL;
+}
+
+#if 0
+{
+  struct UPT_info *ui = arg;
+
+#if ELF_CLASS == ELFCLASS64
+  return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
+#elif ELF_CLASS == ELFCLASS32
+  return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
+#else
+  return -UNW_ENOINFO;
+#endif
+}
+#endif
diff -d -urpN libunwind.2/src/coredump/_UPT_put_unwind_info.c 
libunwind.3/src/coredump/_UPT_put_unwind_info.c
--- libunwind.2/src/coredump/_UPT_put_unwind_info.c     1970-01-01 
01:00:00.000000000 +0100
+++ libunwind.3/src/coredump/_UPT_put_unwind_info.c     2012-02-21 
18:03:23.401383333 +0100
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2003 Hewlett-Packard Co
+       Contributed by David Mosberger-Tang <address@hidden>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+void
+_UCD_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
+{
+  if (!pi->unwind_info)
+    return;
+  free (pi->unwind_info);
+  pi->unwind_info = NULL;
+}
diff -d -urpN libunwind.2/src/coredump/_UPT_resume.c 
libunwind.3/src/coredump/_UPT_resume.c
--- libunwind.2/src/coredump/_UPT_resume.c      1970-01-01 01:00:00.000000000 
+0100
+++ libunwind.3/src/coredump/_UPT_resume.c      2012-02-21 18:03:23.401383333 
+0100
@@ -0,0 +1,35 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2003 Hewlett-Packard Co
+       Contributed by David Mosberger-Tang <address@hidden>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#include "_UCD_lib.h"
+#include "_UCD_internal.h"
+
+int
+_UCD_resume (unw_addr_space_t as, unw_cursor_t *c, void *arg)
+{
+  print_error (__func__);
+  print_error (" not implemented\n");
+  return -UNW_EINVAL;
+}
diff -d -urpN libunwind.2/src/Makefile.am libunwind.3/src/Makefile.am
--- libunwind.2/src/Makefile.am 2012-02-21 17:57:16.863510404 +0100
+++ libunwind.3/src/Makefile.am 2012-02-21 17:58:41.579456231 +0100
@@ -8,7 +8,7 @@ COMMON_SO_LDFLAGS =     -XCClinker -nostartf
 lib_LIBRARIES =
 lib_LTLIBRARIES =
 if !REMOTE_ONLY
-lib_LIBRARIES += libunwind-ptrace.a
+lib_LIBRARIES += libunwind-ptrace.a libunwind-coredump.a
 lib_LTLIBRARIES += libunwind.la
 endif

@@ -26,6 +26,23 @@ libunwind_ptrace_a_SOURCES =                                 
          \
        ptrace/_UPT_reg_offset.c ptrace/_UPT_resume.c
 noinst_HEADERS += ptrace/_UPT_internal.h

+### libunwind-coredump:
+libunwind_coredump_a_SOURCES = \
+       coredump/_UCD_accessors.c \
+       coredump/_UCD_create.c \
+       coredump/_UCD_destroy.c \
+       coredump/_UCD_access_reg.c \
+       coredump/_UCD_access_mem.c \
+       coredump/_UCD_find_proc_info.c \
+       \
+       coredump/_UPT_elf.c \
+       coredump/_UPT_access_fpreg.c \
+       coredump/_UPT_get_dyn_info_list_addr.c \
+       coredump/_UPT_put_unwind_info.c \
+       coredump/_UPT_get_proc_name.c \
+       coredump/_UPT_resume.c
+noinst_HEADERS += coredump/_UCD_internal.h
+
 ### libunwind-setjmp:
 libunwind_setjmp_la_LDFLAGS            = $(COMMON_SO_LDFLAGS)               \
                                          -version-info $(SETJMP_SO_VERSION)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]