libunwind-devel
[Top][All Lists]
Advanced

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

Re: [Libunwind-devel] libunwind ARM port


From: Daniel Jacobowitz
Subject: Re: [Libunwind-devel] libunwind ARM port
Date: Wed, 2 Jan 2008 12:09:46 -0500
User-agent: Mutt/1.5.17 (2007-12-11)

On Wed, Jan 02, 2008 at 12:13:27PM -0400, Anderson Lizardo wrote:
> Good to know! I'm particularly interested in getting simple backtraces
> (just the addresses from each called function should suffice) from
> running applications using libunwind's ptrace support. Do you know
> whether is this possible with .debug_frame information generated by
> latest CodeSourcery ARM toolchains?

We have only tested local operation (within the same process).  Adding
ptrace support for ARM would be a little work, but not much.  In fact,
it might already work.  You'll need .debug_frame on the target system,
so applications can not be completely stripped.

Other than that, yes, it should do what you need.

> Is there any public snapshot where
> one could get current work on dwarf-2 support for ARM?

Not yet.  But here it is!

For the libunwind maintainers: we're interested in getting this work
merged into the libunwind repository.  I'd like to hear any comments
on the patch.  It implements:

  - ARM port, big and little endian.  Local unwinding only has been
    tested, but we filled in the remote portions also.  Uses DWARF-2
    only.

  - MIPS port, o32 / n32 / n64 ABIs, big and little endian.  Again,
    local unwinding only, but remote should work.  One quirk is that
    I could not see how to specify the ABI property when creating a
    remote unwinder, so it always defaults to o32.

  - DWARF-2 unwinding automatically falls back to .debug_frame after
    checking .eh_frame.  This has memory / performance cost and may
    be a little surprising if you entered through _Unwind_* instead of
    unw_*.

The ARM and MIPS versions of libunwind have _Unwind_* interfaces
disabled.  I couldn't find any way to allow use of libunwind without
replacing the system's standard unwinder, which we did not want to do.
It perturbs the application unnecessarily.  And it breaks exceptions
completely for ARM, since the ARM libgcc_s unwinder uses the same API
but a different kind of compact unwind tables, not supported by
libunwind.  The standard .eh_frame sections are not present.

Julian Brown and I wrote this patch.

-- 
Daniel Jacobowitz
CodeSourcery

--- libunwind-0.98.5/include/arm/jmpbuf.h       (revision 0)
+++ libunwind-0.98.5/include/arm/jmpbuf.h       (revision 189947)
@@ -0,0 +1,33 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2004 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.  */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+/* FIXME for ARM!  */
+
+#define JB_SP          4
+#define JB_RP          5
+#define JB_MASK_SAVED  6
+#define JB_MASK                7
--- libunwind-0.98.5/include/arm/dwarf-config.h (revision 0)
+++ libunwind-0.98.5/include/arm/dwarf-config.h (revision 189947)
@@ -0,0 +1,52 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+       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.  */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
+   explicitly defined.  */
+#define DWARF_NUM_PRESERVED_REGS       128
+
+/* FIXME: Probably unnecessary on ARM.  See arm/Gglobal.c.  */
+#define DWARF_REGNUM_MAP_LENGTH                16
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order.  */
+#define dwarf_is_big_endian(addr_space)        0
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+   unw_cursor_t.  */
+#define dwarf_to_cursor(c)     ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+  {
+    unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+    unw_word_t type;           /* see DWARF_LOC_TYPE_* macros.  */
+#endif
+  }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
--- libunwind-0.98.5/include/remote.h   (revision 186298)
+++ libunwind-0.98.5/include/remote.h   (revision 189947)
@@ -11,7 +11,7 @@ static inline int
 fetch8 (unw_addr_space_t as, unw_accessors_t *a,
        unw_word_t *addr, int8_t *valp, void *arg)
 {
-  *valp = *(int8_t *) *addr;
+  *valp = *(int8_t *) (uintptr_t) *addr;
   *addr += 1;
   return 0;
 }
@@ -20,7 +20,7 @@ static inline int
 fetch16 (unw_addr_space_t as, unw_accessors_t *a,
         unw_word_t *addr, int16_t *valp, void *arg)
 {
-  *valp = *(int16_t *) *addr;
+  *valp = *(int16_t *) (uintptr_t) *addr;
   *addr += 2;
   return 0;
 }
@@ -29,7 +29,7 @@ static inline int
 fetch32 (unw_addr_space_t as, unw_accessors_t *a,
         unw_word_t *addr, int32_t *valp, void *arg)
 {
-  *valp = *(int32_t *) *addr;
+  *valp = *(int32_t *) (uintptr_t) *addr;
   *addr += 4;
   return 0;
 }
@@ -38,7 +38,7 @@ static inline int
 fetchw (unw_addr_space_t as, unw_accessors_t *a,
        unw_word_t *addr, unw_word_t *valp, void *arg)
 {
-  *valp = *(unw_word_t *) *addr;
+  *valp = *(unw_word_t *) (uintptr_t) *addr;
   *addr += sizeof (unw_word_t);
   return 0;
 }
--- libunwind-0.98.5/include/libunwind-mips.h   (revision 0)
+++ libunwind-0.98.5/include/libunwind-mips.h   (revision 189947)
@@ -0,0 +1,154 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002-2004 Hewlett-Packard Co
+
+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_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <ucontext.h>
+
+#ifdef mips
+# undef mips
+#endif
+
+#define UNW_TARGET     mips
+#define UNW_TARGET_MIPS        1
+
+#define _U_TDEP_QP_TRUE        0       /* see libunwind-dynamic.h  */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+   leaving some slack for future expansion.  Changing this value will
+   require recompiling all users of this library.  Stack allocation is
+   relatively cheap and unwind-state copying is relatively rare, so we
+   want to err on making it rather too big than too small.  */
+   
+/* FIXME for MIPS. Too big?  What do other things use for similar tasks?  */
+#define UNW_TDEP_CURSOR_LEN    4096
+
+/* The size of a "word" varies on MIPS.  This type is used for memory
+   addresses and register values.  To allow a single library to support
+   multiple ABIs, and to support N32 at all, we must use a 64-bit type
+   even when addresses are only 32 bits.  */
+typedef uint64_t unw_word_t;
+
+/* FIXME: MIPS ABIs.  */
+typedef long double unw_tdep_fpreg_t;
+
+typedef enum
+  {
+    UNW_MIPS_R0,
+    UNW_MIPS_R1,
+    UNW_MIPS_R2,
+    UNW_MIPS_R3,
+    UNW_MIPS_R4,
+    UNW_MIPS_R5,
+    UNW_MIPS_R6,
+    UNW_MIPS_R7,
+    UNW_MIPS_R8,
+    UNW_MIPS_R9,
+    UNW_MIPS_R10,
+    UNW_MIPS_R11,
+    UNW_MIPS_R12,
+    UNW_MIPS_R13,
+    UNW_MIPS_R14,
+    UNW_MIPS_R15,
+    UNW_MIPS_R16,
+    UNW_MIPS_R17,
+    UNW_MIPS_R18,
+    UNW_MIPS_R19,
+    UNW_MIPS_R20,
+    UNW_MIPS_R21,
+    UNW_MIPS_R22,
+    UNW_MIPS_R23,
+    UNW_MIPS_R24,
+    UNW_MIPS_R25,
+    UNW_MIPS_R26,
+    UNW_MIPS_R27,
+    UNW_MIPS_R28,
+    UNW_MIPS_R29,
+    UNW_MIPS_R30,
+    UNW_MIPS_R31,
+
+    /* FIXME: Other registers!  */
+
+    /* For MIPS, the CFA is the value of SP (r29) at the call site in the
+       previous frame.  */
+    UNW_MIPS_CFA,
+
+    UNW_TDEP_LAST_REG = UNW_MIPS_R31,
+
+    UNW_TDEP_IP = UNW_MIPS_R31,
+    UNW_TDEP_SP = UNW_MIPS_R29,
+    UNW_TDEP_EH = UNW_MIPS_R0   /* FIXME.  */
+  }
+mips_regnum_t;
+
+typedef enum
+  {
+    UNW_MIPS_ABI_O32,
+    UNW_MIPS_ABI_N32,
+    UNW_MIPS_ABI_N64
+  }
+mips_abi_t;
+
+#define UNW_TDEP_NUM_EH_REGS   2       /* FIXME for MIPS.  */
+
+typedef struct unw_tdep_save_loc
+  {
+    /* Additional target-dependent info on a save location.  */
+  }
+unw_tdep_save_loc_t;
+
+/* On x86, we can directly use ucontext_t as the unwind context.  FIXME for
+   MIPS.  */
+typedef ucontext_t unw_tdep_context_t;
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+  {
+    unw_dyn_dwarf_fde_info_t dwarf_info;
+  }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+/* There is no getcontext() on MIPS.  Use a stub version which only saves GP
+   registers.  FIXME: Not ideal, may not be sufficient for all libunwind
+   use cases.  */
+#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
+extern int unw_tdep_getcontext (ucontext_t *uc);
+
+#define unw_tdep_is_fpreg              UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
--- libunwind-0.98.5/include/tdep-mips.h        (revision 0)
+++ libunwind-0.98.5/include/tdep-mips.h        (revision 189947)
@@ -0,0 +1,313 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002-2004 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.  */
+
+#ifndef TDEP_MIPS_H
+#define TDEP_MIPS_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+   to be shared with target-independent code.  */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#if !defined(UNW_REMOTE_ONLY) && _MIPS_SIM == _ABI64
+# include "elf64.h"
+#else
+# include "elf32.h"
+#endif
+#include "dwarf.h"
+
+struct unw_addr_space
+  {
+    struct unw_accessors acc;
+
+    int big_endian;
+    mips_abi_t abi;
+    int addr_size;
+
+    unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+    AO_t cache_generation;
+#else
+    uint32_t cache_generation;
+#endif
+    unw_word_t dyn_generation;         /* see dyn-common.h */
+    unw_word_t dyn_info_list_addr;     /* (cached) dyn_info_list_addr */
+    struct unw_debug_frame_list *debug_frames;
+  };
+
+#define tdep_big_endian(as)            ((as)->big_endian)
+
+struct cursor
+  {
+    struct dwarf_cursor dwarf;         /* must be first */
+    unw_word_t sigcontext_addr;
+  };
+
+#define DWARF_GET_LOC(l)       ((l).val)
+
+#ifndef UNW_REMOTE_ONLY
+# if _MIPS_SIM == _ABIN32
+typedef long long mips_reg_t;
+# else
+typedef long mips_reg_t;
+# endif
+#endif
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC                DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l)  (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t)       ((dwarf_loc_t) { .val = (r) })
+# define DWARF_REG_LOC(c,r)    (DWARF_LOC((unw_word_t) (intptr_t)           \
+                                tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_MEM_LOC(c,m)    DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r)  (DWARF_LOC((unw_word_t) (intptr_t)           \
+                                tdep_uc_addr((c)->as_arg, (r)), 0))
+
+/* FIXME: Implement these for the MIPS FPU.  */
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+  if (!DWARF_GET_LOC (loc))
+    return -1;
+  *val = *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc);
+  return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+  if (!DWARF_GET_LOC (loc))
+    return -1;
+  *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc) = val;
+  return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+  if (!DWARF_GET_LOC (loc))
+    return -1;
+  *val = *(mips_reg_t *) (intptr_t) DWARF_GET_LOC (loc);
+  return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+  if (!DWARF_GET_LOC (loc))
+    return -1;
+  *(mips_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val;
+  return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+# define DWARF_LOC_TYPE_FP     (1 << 0)
+# define DWARF_LOC_TYPE_REG    (1 << 1)
+# define DWARF_NULL_LOC                DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l)                                          \
+               ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t)       ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l)   (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l)    (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_REG_LOC(c,r)    DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_MEM_LOC(c,m)    DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r)  DWARF_LOC((r), (DWARF_LOC_TYPE_REG      \
+                                               | DWARF_LOC_TYPE_FP))
+
+static inline int
+read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val)
+{
+  int offset = addr & 4;
+  int ret;
+  unw_word_t memval;
+
+  ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg);
+  if (ret < 0)
+    return ret;
+
+  if ((offset != 0) == tdep_big_endian (c->as))
+    *val = (int32_t) memval;
+  else
+    *val = (int32_t) (memval >> 32);
+
+  return 0;
+}
+
+static inline int
+write_s32 (struct dwarf_cursor *c, unw_word_t addr, const unw_word_t *val)
+{
+  int offset = addr & 4;
+  int ret;
+  unw_word_t memval;
+
+  ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg);
+  if (ret < 0)
+    return ret;
+
+  if ((offset != 0) == tdep_big_endian (c->as))
+    memval = (memval & ~0xffffffffLL) | (uint32_t) *val;
+  else
+    memval = (memval & 0xffffffffLL) | (uint32_t) (*val << 32);
+
+  return (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 1, 
c->as_arg);
+}
+
+/* FIXME: Implement these for the MIPS FPU.  */
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+  char *valp = (char *) &val;
+  unw_word_t addr;
+  int ret;
+
+  if (DWARF_IS_NULL_LOC (loc))
+    return -UNW_EBADREG;
+
+  if (DWARF_IS_REG_LOC (loc))
+    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+                                      val, 0, c->as_arg);
+
+  addr = DWARF_GET_LOC (loc);
+  if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+                                      0, c->as_arg)) < 0)
+    return ret;
+
+  return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
+                                  c->as_arg);
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+  char *valp = (char *) &val;
+  unw_word_t addr;
+  int ret;
+
+  if (DWARF_IS_NULL_LOC (loc))
+    return -UNW_EBADREG;
+
+  if (DWARF_IS_REG_LOC (loc))
+    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+                                      &val, 1, c->as_arg);
+
+  addr = DWARF_GET_LOC (loc);
+  if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+                                      1, c->as_arg)) < 0)
+    return ret;
+
+  return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
+                                  1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+  if (DWARF_IS_NULL_LOC (loc))
+    return -UNW_EBADREG;
+
+  /* If a code-generator were to save a value of type unw_word_t in a
+     floating-point register, we would have to support this case.  I
+     suppose it could happen with MMX registers, but does it really
+     happen?  */
+  assert (!DWARF_IS_FP_LOC (loc));
+
+  if (DWARF_IS_REG_LOC (loc))
+    return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+                                    0, c->as_arg);
+  else if (c->as->abi == UNW_MIPS_ABI_O32)
+    return read_s32 (c, DWARF_GET_LOC (loc), val);
+  else
+    return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+                                    0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+  if (DWARF_IS_NULL_LOC (loc))
+    return -UNW_EBADREG;
+
+  /* If a code-generator were to save a value of type unw_word_t in a
+     floating-point register, we would have to support this case.  I
+     suppose it could happen with MMX registers, but does it really
+     happen?  */
+  assert (!DWARF_IS_FP_LOC (loc));
+
+  if (DWARF_IS_REG_LOC (loc))
+    return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+                                    1, c->as_arg);
+  else if (c->as->abi == UNW_MIPS_ABI_O32)
+    return write_s32 (c, DWARF_GET_LOC (loc), &val);
+  else
+    return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+                                    1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_needs_initialization      UNW_OBJ(needs_initialization)
+#define tdep_init                      UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+   tdep_search_unwind_table.  */
+#define tdep_search_unwind_table       dwarf_search_unwind_table
+#define tdep_uc_addr                   UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
+#define tdep_access_reg                        UNW_OBJ(access_reg)
+#define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n)                           \
+       dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n),      \
+                                      (c)->as_arg)
+# define tdep_put_unwind_info(c,pi)                            \
+       dwarf_put_unwind_info((c)->as, (pi), (c)->as_arg)
+#else
+# define tdep_find_proc_info(c,ip,n)                                   \
+       (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n),    \
+                                      (c)->as_arg)
+# define tdep_put_unwind_info(c,pi)                                    \
+       (*(c)->as->acc.put_unwind_info)((c)->as, (pi), (c)->as_arg)
+#endif
+
+#define tdep_get_as(c)                 ((c)->dwarf.as)
+#define tdep_get_as_arg(c)             ((c)->dwarf.as_arg)
+#define tdep_get_ip(c)                 ((c)->dwarf.ip)
+
+extern int tdep_needs_initialization;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+                                    unw_dyn_info_t *di, unw_proc_info_t *pi,
+                                    int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (ucontext_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+                              unsigned long *segbase, unsigned long *mapoff);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+                           unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+                             unw_fpreg_t *valp, int write);
+
+#endif /* TDEP_MIPS_H */
--- libunwind-0.98.5/include/dwarf.h    (revision 186298)
+++ libunwind-0.98.5/include/dwarf.h    (revision 189947)
@@ -266,6 +266,23 @@ typedef struct dwarf_cursor
   }
 dwarf_cursor_t;
 
+/* A list of descriptors for loaded .debug_frame sections.  */
+
+struct unw_debug_frame_list
+  {
+    /* The start (inclusive) and end (exclusive) of the described region.  */
+    unw_word_t start;
+    unw_word_t end;
+    /* The debug frame itself.  */
+    char *debug_frame;
+    size_t debug_frame_size;
+    /* Index (for binary search).  FIXME: Use proper type.  */
+    void *index;
+    size_t index_size;
+    /* Pointer to next descriptor.  */
+    struct unw_debug_frame_list *next;
+  };
+
 /* Convenience macros: */
 #define dwarf_init                     UNW_ARCH_OBJ (dwarf_init)
 #define dwarf_find_proc_info           UNW_OBJ (dwarf_find_proc_info)
@@ -296,7 +313,8 @@ extern int dwarf_eval_expr (struct dwarf
                            int *is_register);
 extern int dwarf_parse_fde (unw_addr_space_t as, unw_accessors_t *a,
                            unw_word_t *addr, unw_proc_info_t *pi,
-                           unw_dyn_dwarf_fde_info_t *dfi, void *arg);
+                           unw_dyn_dwarf_fde_info_t *dfi, unw_word_t base,
+                           void *arg);
 extern int dwarf_find_save_locs (struct dwarf_cursor *c);
 extern int dwarf_create_state_record (struct dwarf_cursor *c,
                                      dwarf_state_record_t *sr);
--- libunwind-0.98.5/include/libunwind-arm.h    (revision 0)
+++ libunwind-0.98.5/include/libunwind-arm.h    (revision 189947)
@@ -0,0 +1,285 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002-2004 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.  */
+
+#ifndef LIBUNWIND_H
+#define LIBUNWIND_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <ucontext.h>
+
+#define UNW_TARGET     arm
+#define UNW_TARGET_ARM 1
+
+#define _U_TDEP_QP_TRUE        0       /* see libunwind-dynamic.h  */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+   leaving some slack for future expansion.  Changing this value will
+   require recompiling all users of this library.  Stack allocation is
+   relatively cheap and unwind-state copying is relatively rare, so we
+   want to err on making it rather too big than too small.  */
+   
+/* FIXME for ARM. Too big?  What do other things use for similar tasks?  */
+#define UNW_TDEP_CURSOR_LEN    4096
+
+typedef uint32_t unw_word_t;
+
+typedef long double unw_tdep_fpreg_t;
+
+typedef enum
+  {
+    UNW_ARM_R0,
+    UNW_ARM_R1,
+    UNW_ARM_R2,
+    UNW_ARM_R3,
+    UNW_ARM_R4,
+    UNW_ARM_R5,
+    UNW_ARM_R6,
+    UNW_ARM_R7,
+    UNW_ARM_R8,
+    UNW_ARM_R9,
+    UNW_ARM_R10,
+    UNW_ARM_R11,
+    UNW_ARM_R12,
+    UNW_ARM_R13,
+    UNW_ARM_R14,
+    UNW_ARM_R15,
+    
+    /* VFPv2 s0-s31 (obsolescent numberings).  */
+    UNW_ARM_S0 = 64,
+    UNW_ARM_S1,
+    UNW_ARM_S2,
+    UNW_ARM_S3,
+    UNW_ARM_S4,
+    UNW_ARM_S5,
+    UNW_ARM_S6,
+    UNW_ARM_S7,
+    UNW_ARM_S8,
+    UNW_ARM_S9,
+    UNW_ARM_S10,
+    UNW_ARM_S11,
+    UNW_ARM_S12,
+    UNW_ARM_S13,
+    UNW_ARM_S14,
+    UNW_ARM_S15,
+    UNW_ARM_S16,
+    UNW_ARM_S17,
+    UNW_ARM_S18,
+    UNW_ARM_S19,
+    UNW_ARM_S20,
+    UNW_ARM_S21,
+    UNW_ARM_S22,
+    UNW_ARM_S23,
+    UNW_ARM_S24,
+    UNW_ARM_S25,
+    UNW_ARM_S26,
+    UNW_ARM_S27,
+    UNW_ARM_S28,
+    UNW_ARM_S29,
+    UNW_ARM_S30,
+    UNW_ARM_S31,
+    
+    /* FPA register numberings.  */
+    UNW_ARM_F0 = 96,
+    UNW_ARM_F1,
+    UNW_ARM_F2,
+    UNW_ARM_F3,
+    UNW_ARM_F4,
+    UNW_ARM_F5,
+    UNW_ARM_F6,
+    UNW_ARM_F7,
+    
+    /* iWMMXt GR register numberings.  */
+    UNW_ARM_wCGR0 = 104,
+    UNW_ARM_wCGR1,
+    UNW_ARM_wCGR2,
+    UNW_ARM_wCGR3,
+    UNW_ARM_wCGR4,
+    UNW_ARM_wCGR5,
+    UNW_ARM_wCGR6,
+    UNW_ARM_wCGR7,
+    
+    /* iWMMXt register numberings.  */
+    UNW_ARM_wR0 = 112,
+    UNW_ARM_wR1,
+    UNW_ARM_wR2,
+    UNW_ARM_wR3,
+    UNW_ARM_wR4,
+    UNW_ARM_wR5,
+    UNW_ARM_wR6,
+    UNW_ARM_wR7,
+    UNW_ARM_wR8,
+    UNW_ARM_wR9,
+    UNW_ARM_wR10,
+    UNW_ARM_wR11,
+    UNW_ARM_wR12,
+    UNW_ARM_wR13,
+    UNW_ARM_wR14,
+    UNW_ARM_wR15,
+    
+    /* Two-byte encodings from here on.  */
+    
+    /* SPSR.  */
+    UNW_ARM_SPSR = 128,
+    UNW_ARM_SPSR_FIQ,
+    UNW_ARM_SPSR_IRQ,
+    UNW_ARM_SPSR_ABT,
+    UNW_ARM_SPSR_UND,
+    UNW_ARM_SPSR_SVC,
+    
+    /* User mode registers.  */
+    UNW_ARM_R8_USR = 144,
+    UNW_ARM_R9_USR,
+    UNW_ARM_R10_USR,
+    UNW_ARM_R11_USR,
+    UNW_ARM_R12_USR,
+    UNW_ARM_R13_USR,
+    UNW_ARM_R14_USR,
+    
+    /* FIQ registers.  */
+    UNW_ARM_R8_FIQ = 151,
+    UNW_ARM_R9_FIQ,
+    UNW_ARM_R10_FIQ,
+    UNW_ARM_R11_FIQ,
+    UNW_ARM_R12_FIQ,
+    UNW_ARM_R13_FIQ,
+    UNW_ARM_R14_FIQ,
+    
+    /* IRQ registers.  */
+    UNW_ARM_R13_IRQ = 158,
+    UNW_ARM_R14_IRQ,
+    
+    /* ABT registers.  */
+    UNW_ARM_R13_ABT = 160,
+    UNW_ARM_R14_ABT,
+    
+    /* UND registers.  */
+    UNW_ARM_R13_UND = 162,
+    UNW_ARM_R14_UND,
+    
+    /* SVC registers.  */
+    UNW_ARM_R13_SVC = 164,
+    UNW_ARM_R14_SVC,
+    
+    /* iWMMXt control registers.  */
+    UNW_ARM_wC0 = 192,
+    UNW_ARM_wC1,
+    UNW_ARM_wC2,
+    UNW_ARM_wC3,
+    UNW_ARM_wC4,
+    UNW_ARM_wC5,
+    UNW_ARM_wC6,
+    UNW_ARM_wC7,
+
+    /* VFPv3/Neon 64-bit registers.  */
+    UNW_ARM_D0 = 256,
+    UNW_ARM_D1,
+    UNW_ARM_D2,
+    UNW_ARM_D3,
+    UNW_ARM_D4,
+    UNW_ARM_D5,
+    UNW_ARM_D6,
+    UNW_ARM_D7,
+    UNW_ARM_D8,
+    UNW_ARM_D9,
+    UNW_ARM_D10,
+    UNW_ARM_D11,
+    UNW_ARM_D12,
+    UNW_ARM_D13,
+    UNW_ARM_D14,
+    UNW_ARM_D15,
+    UNW_ARM_D16,
+    UNW_ARM_D17,
+    UNW_ARM_D18,
+    UNW_ARM_D19,
+    UNW_ARM_D20,
+    UNW_ARM_D21,
+    UNW_ARM_D22,
+    UNW_ARM_D23,
+    UNW_ARM_D24,
+    UNW_ARM_D25,
+    UNW_ARM_D26,
+    UNW_ARM_D27,
+    UNW_ARM_D28,
+    UNW_ARM_D29,
+    UNW_ARM_D30,
+    UNW_ARM_D31,
+
+    /* For ARM, the CFA is the value of SP (r13) at the call site in the
+       previous frame.  */
+    UNW_ARM_CFA,
+
+    UNW_TDEP_LAST_REG = UNW_ARM_D31,
+
+    UNW_TDEP_IP = UNW_ARM_R14,  /* A little white lie.  */
+    UNW_TDEP_SP = UNW_ARM_R13,
+    UNW_TDEP_EH = UNW_ARM_R0   /* FIXME.  */
+  }
+arm_regnum_t;
+
+#define UNW_TDEP_NUM_EH_REGS   2       /* FIXME for ARM.  */
+
+typedef struct unw_tdep_save_loc
+  {
+    /* Additional target-dependent info on a save location.  */
+  }
+unw_tdep_save_loc_t;
+
+/* On ARM, we can directly use ucontext_t as the unwind context.  */
+typedef ucontext_t unw_tdep_context_t;
+
+/* There is no getcontext() on ARM.  Use a stub version which only saves GP
+   registers.  FIXME: Not ideal, may not be sufficient for all libunwind
+   use cases.  Stores pc+8, which is only approximately correct, really.  */
+#define unw_tdep_getcontext(uc) (({                                    \
+  unw_tdep_context_t *unw_ctx = (uc);                                  \
+  register int unw_base asm ("r0")                                     \
+    = (int) (&unw_ctx->uc_mcontext.arm_r0);                            \
+  __asm__ __volatile__ (                                               \
+    "stmia %[base], {r0-r15}"                                          \
+    : : [base] "r" (unw_base) : "memory");                             \
+  }), 0)
+
+#include "libunwind-dynamic.h"
+
+typedef struct
+  {
+    unw_dyn_dwarf_fde_info_t dwarf_info;
+  }
+unw_tdep_proc_info_t;
+
+#include "libunwind-common.h"
+
+#define unw_tdep_is_fpreg              UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg (int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* LIBUNWIND_H */
--- libunwind-0.98.5/include/tdep-arm.h (revision 0)
+++ libunwind-0.98.5/include/tdep-arm.h (revision 189947)
@@ -0,0 +1,252 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002-2004 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.  */
+
+#ifndef TDEP_ARM_H
+#define TDEP_ARM_H
+
+/* Target-dependent definitions that are internal to libunwind but need
+   to be shared with target-independent code.  */
+
+#include <stdlib.h>
+#include <libunwind.h>
+
+#include "elf32.h"
+#include "dwarf.h"
+
+struct unw_addr_space
+  {
+    struct unw_accessors acc;
+    int big_endian;
+    unw_caching_policy_t caching_policy;
+#ifdef HAVE_ATOMIC_OPS_H
+    AO_t cache_generation;
+#else
+    uint32_t cache_generation;
+#endif
+    unw_word_t dyn_generation;         /* see dyn-common.h */
+    unw_word_t dyn_info_list_addr;     /* (cached) dyn_info_list_addr */
+    struct unw_debug_frame_list *debug_frames;
+  };
+
+struct cursor
+  {
+    struct dwarf_cursor dwarf;         /* must be first */
+    unw_word_t sigcontext_addr;
+  };
+
+#define DWARF_GET_LOC(l)       ((l).val)
+
+#ifdef UNW_LOCAL_ONLY
+# define DWARF_NULL_LOC                DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l)  (DWARF_GET_LOC (l) == 0)
+# define DWARF_LOC(r, t)       ((dwarf_loc_t) { .val = (r) })
+# define DWARF_REG_LOC(c,r)    (DWARF_LOC((unw_word_t)                      \
+                                tdep_uc_addr((c)->as_arg, (r)), 0))
+# define DWARF_MEM_LOC(c,m)    DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r)  (DWARF_LOC((unw_word_t)                      \
+                                tdep_uc_addr((c)->as_arg, (r)), 0))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+  if (!DWARF_GET_LOC (loc))
+    return -1;
+  *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
+  return 0;
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+  if (!DWARF_GET_LOC (loc))
+    return -1;
+  *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
+  return 0;
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+  if (!DWARF_GET_LOC (loc))
+    return -1;
+  *val = *(unw_word_t *) DWARF_GET_LOC (loc);
+  return 0;
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+  if (!DWARF_GET_LOC (loc))
+    return -1;
+  *(unw_word_t *) DWARF_GET_LOC (loc) = val;
+  return 0;
+}
+
+#else /* !UNW_LOCAL_ONLY */
+# define DWARF_LOC_TYPE_FP     (1 << 0)
+# define DWARF_LOC_TYPE_REG    (1 << 1)
+# define DWARF_NULL_LOC                DWARF_LOC (0, 0)
+# define DWARF_IS_NULL_LOC(l)                                          \
+               ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+# define DWARF_LOC(r, t)       ((dwarf_loc_t) { .val = (r), .type = (t) })
+# define DWARF_IS_REG_LOC(l)   (((l).type & DWARF_LOC_TYPE_REG) != 0)
+# define DWARF_IS_FP_LOC(l)    (((l).type & DWARF_LOC_TYPE_FP) != 0)
+# define DWARF_REG_LOC(c,r)    DWARF_LOC((r), DWARF_LOC_TYPE_REG)
+# define DWARF_MEM_LOC(c,m)    DWARF_LOC ((m), 0)
+# define DWARF_FPREG_LOC(c,r)  DWARF_LOC((r), (DWARF_LOC_TYPE_REG      \
+                                               | DWARF_LOC_TYPE_FP))
+
+static inline int
+dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
+{
+  char *valp = (char *) &val;
+  unw_word_t addr;
+  int ret;
+
+  if (DWARF_IS_NULL_LOC (loc))
+    return -UNW_EBADREG;
+
+  if (DWARF_IS_REG_LOC (loc))
+    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+                                      val, 0, c->as_arg);
+
+  addr = DWARF_GET_LOC (loc);
+  if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+                                      0, c->as_arg)) < 0)
+    return ret;
+
+  return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
+                                  c->as_arg);
+}
+
+static inline int
+dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
+{
+  char *valp = (char *) &val;
+  unw_word_t addr;
+  int ret;
+
+  if (DWARF_IS_NULL_LOC (loc))
+    return -UNW_EBADREG;
+
+  if (DWARF_IS_REG_LOC (loc))
+    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
+                                      &val, 1, c->as_arg);
+
+  addr = DWARF_GET_LOC (loc);
+  if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
+                                      1, c->as_arg)) < 0)
+    return ret;
+
+  return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
+                                  1, c->as_arg);
+}
+
+static inline int
+dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
+{
+  if (DWARF_IS_NULL_LOC (loc))
+    return -UNW_EBADREG;
+
+  /* If a code-generator were to save a value of type unw_word_t in a
+     floating-point register, we would have to support this case.  I
+     suppose it could happen with MMX registers, but does it really
+     happen?  */
+  assert (!DWARF_IS_FP_LOC (loc));
+
+  if (DWARF_IS_REG_LOC (loc))
+    return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
+                                    0, c->as_arg);
+  else
+    return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+                                    0, c->as_arg);
+}
+
+static inline int
+dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
+{
+  if (DWARF_IS_NULL_LOC (loc))
+    return -UNW_EBADREG;
+
+  /* If a code-generator were to save a value of type unw_word_t in a
+     floating-point register, we would have to support this case.  I
+     suppose it could happen with MMX registers, but does it really
+     happen?  */
+  assert (!DWARF_IS_FP_LOC (loc));
+
+  if (DWARF_IS_REG_LOC (loc))
+    return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
+                                    1, c->as_arg);
+  else
+    return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
+                                    1, c->as_arg);
+}
+
+#endif /* !UNW_LOCAL_ONLY */
+
+#define tdep_needs_initialization      UNW_OBJ(needs_initialization)
+#define tdep_init                      UNW_OBJ(init)
+/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
+   tdep_search_unwind_table.  */
+#define tdep_search_unwind_table       dwarf_search_unwind_table
+#define tdep_uc_addr                   UNW_ARCH_OBJ(uc_addr)
+#define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
+#define tdep_access_reg                        UNW_OBJ(access_reg)
+#define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+
+#ifdef UNW_LOCAL_ONLY
+# define tdep_find_proc_info(c,ip,n)                           \
+       dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n),      \
+                                      (c)->as_arg)
+# define tdep_put_unwind_info(c,pi)                            \
+       dwarf_put_unwind_info((c)->as, (pi), (c)->as_arg)
+#else
+# define tdep_find_proc_info(c,ip,n)                                   \
+       (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n),    \
+                                      (c)->as_arg)
+# define tdep_put_unwind_info(c,pi)                                    \
+       (*(c)->as->acc.put_unwind_info)((c)->as, (pi), (c)->as_arg)
+#endif
+
+#define tdep_get_as(c)                 ((c)->dwarf.as)
+#define tdep_get_as_arg(c)             ((c)->dwarf.as_arg)
+#define tdep_get_ip(c)                 ((c)->dwarf.ip)
+#define tdep_big_endian(as)            ((as)->big_endian)
+
+extern int tdep_needs_initialization;
+
+extern void tdep_init (void);
+extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
+                                    unw_dyn_info_t *di, unw_proc_info_t *pi,
+                                    int need_unwind_info, void *arg);
+extern void *tdep_uc_addr (ucontext_t *uc, int reg);
+extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
+                              unsigned long *segbase, unsigned long *mapoff);
+extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
+                           unw_word_t *valp, int write);
+extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
+                             unw_fpreg_t *valp, int write);
+
+#endif /* TDEP_ARM_H */
--- libunwind-0.98.5/include/dwarf_i.h  (revision 186298)
+++ libunwind-0.98.5/include/dwarf_i.h  (revision 189947)
@@ -9,6 +9,12 @@
 #include "dwarf.h"
 #include "tdep.h"
 
+/* Unless we are told otherwise, assume that a "machine address" is
+   the size of an unw_word_t.  */
+#ifndef dwarf_addr_size
+# define dwarf_addr_size(as) (sizeof (unw_word_t))
+#endif
+
 #define dwarf_to_unw_regnum_map                UNW_OBJ 
(dwarf_to_unw_regnum_map)
 
 extern uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH];
@@ -21,12 +27,16 @@ dwarf_to_unw_regnum (unw_word_t regnum)
   return 0;
 }
 
-#ifdef UNW_LOCAL_ONLY
+/* This looks pretty bogus to me.  In the functions in this #if block, a union
+   declared with __attribute__ ((packed)) is used to attempt to force
+   non-aligned accesses, but the compiler claims to ignore the attribute.
+   FIXME, make sure it DTRT on ARM, etc. before re-enabling.  */
+#if 0 && defined (UNW_LOCAL_ONLY)
 
 /* In the local-only case, we can let the compiler directly access
    memory and don't need to worry about differing byte-order.  */
 
-typedef union
+typedef union __attribute__ ((packed))
   {
     int8_t s8;
     int16_t s16;
@@ -39,7 +49,7 @@ typedef union
     unw_word_t w;
     void *ptr;
   }
-dwarf_misaligned_value_t __attribute__ ((packed));
+dwarf_misaligned_value_t;
 
 static inline int
 dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
@@ -129,17 +139,6 @@ dwarf_readu64 (unw_addr_space_t as, unw_
   return 0;
 }
 
-static inline int
-dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
-            unw_word_t *val, void *arg)
-{
-  dwarf_misaligned_value_t *mvp = (void *) *addr;
-
-  *val = mvp->w;
-  *addr += sizeof (mvp->w);
-  return 0;
-}
-
 #else /* !UNW_LOCAL_ONLY */
 
 static inline int
@@ -267,25 +266,35 @@ dwarf_reads64 (unw_addr_space_t as, unw_
   return 0;
 }
 
+#endif /* !UNW_LOCAL_ONLY */
+
 static inline int
 dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
             unw_word_t *val, void *arg)
 {
-  switch (sizeof (unw_word_t))
+  uint32_t u32;
+  uint64_t u64;
+  int ret;
+
+  switch (dwarf_addr_size (as))
     {
     case 4:
-      return dwarf_readu32 (as, a, addr, (uint32_t *) val, arg);
+      ret = dwarf_readu32 (as, a, addr, &u32, arg);
+      if (ret == 0)
+       *val = u32;
+      return ret;
 
     case 8:
-      return dwarf_readu64 (as, a, addr, (uint64_t *) val, arg);
+      ret = dwarf_readu64 (as, a, addr, &u64, arg);
+      if (ret == 0)
+       *val = u64;
+      return ret;
 
     default:
       abort ();
     }
 }
 
-#endif /* !UNW_LOCAL_ONLY */
-
 /* Read an unsigned "little-endian base 128" value.  See Chapter 7.6
    of DWARF spec v3.  */
 
--- libunwind-0.98.5/include/libunwind-dynamic.h        (revision 186298)
+++ libunwind-0.98.5/include/libunwind-dynamic.h        (revision 189947)
@@ -76,7 +76,9 @@ typedef enum
     UNW_INFO_FORMAT_DYNAMIC,           /* unw_dyn_proc_info_t */
     UNW_INFO_FORMAT_TABLE,             /* unw_dyn_table_t */
     UNW_INFO_FORMAT_REMOTE_TABLE,      /* unw_dyn_remote_table_t */
-    UNW_INFO_FORMAT_DWARF_FDE          /* unw_dyn_dwarf_fde_t */
+    UNW_INFO_FORMAT_DEBUG_FRAME_TABLE,
+    UNW_INFO_FORMAT_DWARF_FDE,         /* unw_dyn_dwarf_fde_t */
+    UNW_INFO_FORMAT_DEBUG_FRAME_FDE
   }
 unw_dyn_info_format_t;
 
@@ -127,6 +129,19 @@ typedef struct unw_dyn_remote_table_info
   }
 unw_dyn_remote_table_info_t;
 
+/* WARNING: Some of these fields are currently accessed as
+   unw_dyn_remote_table_info_t.  FIXME?  */
+
+typedef struct unw_dyn_debug_frame_info
+  {
+    unw_word_t name_ptr;
+    unw_word_t segbase;
+    unw_word_t table_len;
+    unw_word_t table_data;
+    unw_word_t frame_base;
+  }
+unw_dyn_debug_frame_info_t;
+
 /* The flags member encodes the pointer-encoding used in the FDE, the
    pointer-encoding used for the LSDA, and a bit flag that is set if
    the FDE's augmentation body starts with a length.  */
@@ -162,6 +177,7 @@ typedef struct unw_dyn_info
        unw_dyn_proc_info_t pi;
        unw_dyn_table_info_t ti;
        unw_dyn_remote_table_info_t rti;
+       unw_dyn_debug_frame_info_t debi;
        unw_dyn_dwarf_fde_info_t dfi;
       }
     u;
--- libunwind-0.98.5/include/tdep-x86.h (revision 186298)
+++ libunwind-0.98.5/include/tdep-x86.h (revision 189947)
@@ -46,7 +46,8 @@ struct unw_addr_space
 #endif
     unw_word_t dyn_generation;         /* see dyn-common.h */
     unw_word_t dyn_info_list_addr;     /* (cached) dyn_info_list_addr */
-   };
+    struct unw_debug_frame_list *debug_frames;
+  };
 
 struct cursor
   {
--- libunwind-0.98.5/include/mips/jmpbuf.h      (revision 0)
+++ libunwind-0.98.5/include/mips/jmpbuf.h      (revision 189947)
@@ -0,0 +1,33 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2004 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.  */
+
+/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
+
+/* FIXME for MIPS!  */
+
+#define JB_SP          4
+#define JB_RP          5
+#define JB_MASK_SAVED  6
+#define JB_MASK                7
--- libunwind-0.98.5/include/mips/dwarf-config.h        (revision 0)
+++ libunwind-0.98.5/include/mips/dwarf-config.h        (revision 189947)
@@ -0,0 +1,55 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+       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.  */
+
+#ifndef dwarf_config_h
+#define dwarf_config_h
+
+/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
+   explicitly defined.  */
+#define DWARF_NUM_PRESERVED_REGS       188
+
+/* FIXME: Probably unnecessary on MIPS.  See mips/Gglobal.c.  */
+#define DWARF_REGNUM_MAP_LENGTH                32
+
+/* Return TRUE if the ADDR_SPACE uses big-endian byte-order.  */
+#define dwarf_is_big_endian(addr_space)        ((addr_space)->big_endian)
+
+/* Return the size of an address, for DWARF purposes.  */
+#define dwarf_addr_size(addr_space) ((addr_space)->addr_size)
+
+/* Convert a pointer to a dwarf_cursor structure to a pointer to
+   unw_cursor_t.  */
+#define dwarf_to_cursor(c)     ((unw_cursor_t *) (c))
+
+typedef struct dwarf_loc
+  {
+    unw_word_t val;
+#ifndef UNW_LOCAL_ONLY
+    unw_word_t type;           /* see DWARF_LOC_TYPE_* macros.  */
+#endif
+  }
+dwarf_loc_t;
+
+#endif /* dwarf_config_h */
--- libunwind-0.98.5/include/tdep-x86_64.h      (revision 186298)
+++ libunwind-0.98.5/include/tdep-x86_64.h      (revision 189947)
@@ -44,6 +44,7 @@ struct unw_addr_space
     uint32_t cache_generation;
     unw_word_t dyn_generation;         /* see dyn-common.h */
     unw_word_t dyn_info_list_addr;     /* (cached) dyn_info_list_addr */
+    struct unw_debug_frame_list *debug_frames;
    };
 
 struct cursor
--- libunwind-0.98.5/configure.in       (revision 186298)
+++ libunwind-0.98.5/configure.in       (revision 189947)
@@ -59,24 +59,29 @@ AC_CHECK_FUNCS(dl_iterate_phdr dl_phdr_r
 
 get_arch() {
  case "$1" in
+  arm*) echo arm;;
   i?86) echo x86;;
   hppa*) echo hppa;;
+  mips*) echo mips;;
   *) echo $1;;
  esac
 }
 
 build_arch=`get_arch $build_cpu`
+host_arch=`get_arch $host_cpu`
 target_arch=`get_arch $target_cpu`
 
-AM_CONDITIONAL(REMOTE_ONLY, test x$target_arch != x$build_arch)
+AM_CONDITIONAL(REMOTE_ONLY, test x$target_arch != x$host_arch)
+AM_CONDITIONAL(ARCH_ARM, test x$target_arch = xarm)
 AM_CONDITIONAL(ARCH_IA64, test x$target_arch = xia64)
 AM_CONDITIONAL(ARCH_HPPA, test x$target_arch = xhppa)
+AM_CONDITIONAL(ARCH_MIPS, test x$target_arch = xmips)
 AM_CONDITIONAL(ARCH_X86, test x$target_arch = xx86)
 AM_CONDITIONAL(ARCH_X86_64, test x$target_arch = xx86_64)
 AM_CONDITIONAL(OS_LINUX, expr x$target_os : xlinux >/dev/null)
 AM_CONDITIONAL(OS_HPUX, expr x$target_os : xhpux >/dev/null)
 
-if test x$target_arch != x$build_arch; then
+if test x$target_arch != x$host_arch; then
   CPPFLAGS="${CPPFLAGS} -DUNW_REMOTE_ONLY"
 fi
 AC_CONFIG_LINKS(include/libunwind.h:include/libunwind-$target_arch.h
@@ -88,13 +93,14 @@ AC_ARG_ENABLE(debug,
 
 LIBUNWIND___THREAD
 
-save_LDFLAGS="$LDFLAGS"
-LDFLAGS="$LDFLAGS -static-libcxa"
-AC_TRY_LINK([], [], [have_static_libcxa=yes])
-LDFLAGS="$save_LDFLAGS"
-if test "x$have_static_libcxa" = xyes; then
-  LDFLAGS_STATIC_LIBCXA="-XCClinker -static-libcxa"
-fi
+dnl Something funny about this. FIXME!
+dnl save_LDFLAGS="$LDFLAGS"
+dnl LDFLAGS="$LDFLAGS -static-libcxa"
+dnl AC_TRY_LINK([], [], [have_static_libcxa=yes])
+dnl LDFLAGS="$save_LDFLAGS"
+dnl if test "x$have_static_libcxa" = xyes; then
+dnl   LDFLAGS_STATIC_LIBCXA="-XCClinker -static-libcxa"
+dnl fi
 
 AC_TRY_COMPILE([], [#ifndef __INTEL_COMPILER
 #error choke me
@@ -102,7 +108,8 @@ AC_TRY_COMPILE([], [#ifndef __INTEL_COMP
 
 if test x$GCC = xyes -a x$intel_compiler != xyes; then
   CFLAGS="${CFLAGS} -Wall -Wsign-compare"
-  LIBCRTS="-lgcc"
+   LIBCRTS="-lgcc --as-needed -lgcc_s --no-as-needed"
+#  LIBCRTS=""
 fi
 
 CCASFLAGS="${CCASFLAGS} ${CPPFLAGS}"
--- libunwind-0.98.5/src/arm/Lis_signal_frame.c (revision 0)
+++ libunwind-0.98.5/src/arm/Lis_signal_frame.c (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
--- libunwind-0.98.5/src/arm/is_fpreg.c (revision 0)
+++ libunwind-0.98.5/src/arm/is_fpreg.c (revision 189947)
@@ -0,0 +1,40 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
+       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 "tdep.h"
+
+/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful
+   on ARM.  Count all the FP or coprocessor registers we know about for now.  
*/
+
+PROTECTED int
+unw_is_fpreg (int regnum)
+{
+  return ((regnum >= UNW_ARM_S0 && regnum <= UNW_ARM_S31)
+         || (regnum >= UNW_ARM_F0 && regnum <= UNW_ARM_F7)
+         || (regnum >= UNW_ARM_wCGR0 && regnum <= UNW_ARM_wCGR7)
+         || (regnum >= UNW_ARM_wR0 && regnum <= UNW_ARM_wR15)
+         || (regnum >= UNW_ARM_wC0 && regnum <= UNW_ARM_wC7)
+         || (regnum >= UNW_ARM_D0 && regnum <= UNW_ARM_D31));
+}
--- libunwind-0.98.5/src/arm/Gget_save_loc.c    (revision 0)
+++ libunwind-0.98.5/src/arm/Gget_save_loc.c    (revision 189947)
@@ -0,0 +1,82 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2004 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 "unwind_i.h"
+
+PROTECTED int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  dwarf_loc_t loc;
+
+  loc = DWARF_NULL_LOC;                /* default to "not saved" */
+
+  switch (reg)
+    {
+    case UNW_ARM_R0:
+    case UNW_ARM_R1:
+    case UNW_ARM_R2:
+    case UNW_ARM_R3:
+    case UNW_ARM_R4:
+    case UNW_ARM_R5:
+    case UNW_ARM_R6:
+    case UNW_ARM_R7:
+    case UNW_ARM_R8:
+    case UNW_ARM_R9:
+    case UNW_ARM_R10:
+    case UNW_ARM_R11:
+    case UNW_ARM_R12:
+    case UNW_ARM_R13:
+    case UNW_ARM_R14:
+    case UNW_ARM_R15:
+      loc = c->dwarf.loc[reg - UNW_ARM_R0];
+      break;
+
+    default:
+      break;
+    }
+
+  memset (sloc, 0, sizeof (sloc));
+
+  if (DWARF_IS_NULL_LOC (loc))
+    {
+      sloc->type = UNW_SLT_NONE;
+      return 0;
+    }
+
+#if !defined(UNW_LOCAL_ONLY)
+  if (DWARF_IS_REG_LOC (loc))
+    {
+      sloc->type = UNW_SLT_REG;
+      sloc->u.regnum = DWARF_GET_LOC (loc);
+    }
+  else
+#endif
+    {
+      sloc->type = UNW_SLT_MEMORY;
+      sloc->u.addr = DWARF_GET_LOC (loc);
+    }
+  return 0;
+}
--- libunwind-0.98.5/src/arm/getcontext.S       (revision 0)
+++ libunwind-0.98.5/src/arm/getcontext.S       (revision 189947)
@@ -0,0 +1,28 @@
+#include "offsets.h"
+
+       .text
+       .arm
+
+       .global _Uarm_getcontext
+       .type   _Uarm_getcontext, %function
+       @ This is a stub version of getcontext() for ARM which only stores core
+       @ registers.  It must be called in a special way, not as a regular
+       @ function -- see also the libunwind-arm.h:unw_tdep_getcontext macro.
+_Uarm_getcontext:
+       stmfd sp!, {r0, r1}
+       @ store r0
+       str r0, [r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF]
+       add r0, r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF
+       @ store r1 to r12
+       stmib r0, {r1-r12}
+       @ reconstruct r13 at call site, then store
+       add r1, sp, #12
+       str r1, [r0, #13 * 4]
+       @ retrieve r14 from call site, then store
+       ldr r1, [sp, #8]
+       str r1, [r0, #14 * 4]
+       @ point lr to instruction after call site's stack adjustment
+       add r1, lr, #4
+       str r1, [r0, #15 * 4]
+       ldmfd sp!, {r0, r1}
+       bx lr
--- libunwind-0.98.5/src/arm/Lget_save_loc.c    (revision 0)
+++ libunwind-0.98.5/src/arm/Lget_save_loc.c    (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
--- libunwind-0.98.5/src/arm/Gresume.c  (revision 0)
+++ libunwind-0.98.5/src/arm/Gresume.c  (revision 189947)
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
+       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.  */
+
+/* FIXME for ARM.  */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+HIDDEN inline int
+arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+  return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+PROTECTED int
+unw_resume (unw_cursor_t *cursor)
+{
+  return -UNW_EINVAL;
+}
--- libunwind-0.98.5/src/arm/Gregs.c    (revision 0)
+++ libunwind-0.98.5/src/arm/Gregs.c    (revision 189947)
@@ -0,0 +1,82 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
+       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 "unwind_i.h"
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+                int write)
+{
+  dwarf_loc_t loc = DWARF_NULL_LOC;
+  
+  switch (reg)
+    {
+    case UNW_ARM_R0:
+    case UNW_ARM_R1:
+    case UNW_ARM_R2:
+    case UNW_ARM_R3:
+    case UNW_ARM_R4:
+    case UNW_ARM_R5:
+    case UNW_ARM_R6:
+    case UNW_ARM_R7:
+    case UNW_ARM_R8:
+    case UNW_ARM_R9:
+    case UNW_ARM_R10:
+    case UNW_ARM_R11:
+    case UNW_ARM_R12:
+    case UNW_ARM_R13:
+    case UNW_ARM_R14:
+    case UNW_ARM_R15:
+      loc = c->dwarf.loc[reg - UNW_ARM_R0];
+      break;
+
+    case UNW_ARM_CFA:
+      if (write)
+        return -UNW_EREADONLYREG;
+      *valp = c->dwarf.cfa;
+      return 0;
+
+    /* FIXME: Initialise coprocessor & shadow registers?  */
+
+    default:
+      Debug (1, "bad register number %u\n", reg);
+      return -UNW_EBADREG;
+    }
+
+  if (write)
+    return dwarf_put (&c->dwarf, loc, *valp);
+  else
+    return dwarf_get (&c->dwarf, loc, valp);
+}
+
+/* FIXME for ARM.  */
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+                  int write)
+{
+  Debug (1, "bad register number %u\n", reg);
+  return -UNW_EBADREG;
+}
--- libunwind-0.98.5/src/arm/Gglobal.c  (revision 0)
+++ libunwind-0.98.5/src/arm/Gglobal.c  (revision 189947)
@@ -0,0 +1,67 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+       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 <ucontext.h>
+#include "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN pthread_mutex_t arm_lock = PTHREAD_MUTEX_INITIALIZER;
+HIDDEN int tdep_needs_initialization = 1;
+
+/* FIXME: I'm pretty sure we don't need this at all for ARM, but "generic"
+   code (include/dwarf_i.h) seems to expect it to be here at present.  */
+
+HIDDEN uint8_t dwarf_to_unw_regnum_map[16] =
+  {
+    R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15
+  };
+
+HIDDEN void
+tdep_init (void)
+{
+  sigset_t saved_sigmask;
+
+  sigfillset (&unwi_full_sigmask);
+
+  sigprocmask (SIG_SETMASK, &unwi_full_sigmask, &saved_sigmask);
+  mutex_lock (&arm_lock);
+  {
+    if (!tdep_needs_initialization)
+      /* another thread else beat us to it... */
+      goto out;
+
+    mi_init ();
+
+    dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+    arm_local_addr_space_init ();
+#endif
+    tdep_needs_initialization = 0;     /* signal that we're initialized... */
+  }
+ out:
+  mutex_unlock (&arm_lock);
+  sigprocmask (SIG_SETMASK, &saved_sigmask, NULL);
+}
--- libunwind-0.98.5/src/arm/init.h     (revision 0)
+++ libunwind-0.98.5/src/arm/init.h     (revision 189947)
@@ -0,0 +1,65 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002 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 "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c)
+{
+  int ret, i;
+
+  c->dwarf.loc[R0] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R0);
+  c->dwarf.loc[R1] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R1);
+  c->dwarf.loc[R2] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R2);
+  c->dwarf.loc[R3] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R3);
+  c->dwarf.loc[R4] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R4);
+  c->dwarf.loc[R5] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R5);
+  c->dwarf.loc[R6] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R6);
+  c->dwarf.loc[R7] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R7);
+  c->dwarf.loc[R8] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R8);
+  c->dwarf.loc[R9] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R9);
+  c->dwarf.loc[R10] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R10);
+  c->dwarf.loc[R11] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R11);
+  c->dwarf.loc[R12] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R12);
+  c->dwarf.loc[R13] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13);
+  c->dwarf.loc[R14] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R14);
+  c->dwarf.loc[R15] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R15);
+  for (i = R15 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i)
+    c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+  ret = dwarf_get (&c->dwarf, c->dwarf.loc[R15], &c->dwarf.ip);
+  if (ret < 0)
+    return ret;
+
+  /* FIXME: correct for ARM?  */
+  ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13),
+                  &c->dwarf.cfa);
+  if (ret < 0)
+    return ret;
+
+  /* FIXME: Initialisation for other registers.  */
+
+  return 0;
+}
--- libunwind-0.98.5/src/arm/Ginit.c    (revision 0)
+++ libunwind-0.98.5/src/arm/Ginit.c    (revision 189947)
@@ -0,0 +1,208 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002 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 <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case.  */
+PROTECTED unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+static inline void *
+uc_addr (ucontext_t *uc, int reg)
+{
+  void *addr;
+
+  switch (reg)
+    {
+    case UNW_ARM_R0:  addr = &uc->uc_mcontext.arm_r0; break;
+    case UNW_ARM_R1:  addr = &uc->uc_mcontext.arm_r1; break;
+    case UNW_ARM_R2:  addr = &uc->uc_mcontext.arm_r2; break;
+    case UNW_ARM_R3:  addr = &uc->uc_mcontext.arm_r3; break;
+    case UNW_ARM_R4:  addr = &uc->uc_mcontext.arm_r4; break;
+    case UNW_ARM_R5:  addr = &uc->uc_mcontext.arm_r5; break;
+    case UNW_ARM_R6:  addr = &uc->uc_mcontext.arm_r6; break;
+    case UNW_ARM_R7:  addr = &uc->uc_mcontext.arm_r7; break;
+    case UNW_ARM_R8:  addr = &uc->uc_mcontext.arm_r8; break;
+    case UNW_ARM_R9:  addr = &uc->uc_mcontext.arm_r9; break;
+    case UNW_ARM_R10: addr = &uc->uc_mcontext.arm_r10; break;
+    case UNW_ARM_R11: addr = &uc->uc_mcontext.arm_fp; break;
+    case UNW_ARM_R12: addr = &uc->uc_mcontext.arm_ip; break;
+    case UNW_ARM_R13: addr = &uc->uc_mcontext.arm_sp; break;
+    case UNW_ARM_R14: addr = &uc->uc_mcontext.arm_lr; break;
+    case UNW_ARM_R15: addr = &uc->uc_mcontext.arm_pc; break;
+
+    default:
+      addr = NULL;
+    }
+  return addr;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+  return uc_addr (uc, reg);
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+       by a remote unwinder.  On ia64, this is done via a special
+       unwind-table entry.  Perhaps something similar can be done with
+       DWARF2 unwind info.  */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+  /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+                       void *arg)
+{
+  *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
+  return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+           void *arg)
+{
+  if (write)
+    {
+      Debug (16, "mem[%x] <- %x\n", addr, *val);
+      *(unw_word_t *) addr = *val;
+    }
+  else
+    {
+      *val = *(unw_word_t *) addr;
+      Debug (16, "mem[%x] -> %x\n", addr, *val);
+    }
+  return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+           void *arg)
+{
+  unw_word_t *addr;
+  ucontext_t *uc = arg;
+
+  if (unw_is_fpreg (reg))
+    goto badreg;
+
+Debug (16, "reg = %s\n", unw_regname (reg));
+  if (!(addr = uc_addr (uc, reg)))
+    goto badreg;
+
+  if (write)
+    {
+      *(unw_word_t *) addr = *val;
+      Debug (12, "%s <- %x\n", unw_regname (reg), *val);
+    }
+  else
+    {
+      *val = *(unw_word_t *) addr;
+      Debug (12, "%s -> %x\n", unw_regname (reg), *val);
+    }
+  return 0;
+
+ badreg:
+  Debug (1, "bad register number %u\n", reg);
+  return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+             int write, void *arg)
+{
+  ucontext_t *uc = arg;
+  unw_fpreg_t *addr;
+
+  if (!unw_is_fpreg (reg))
+    goto badreg;
+
+  if (!(addr = uc_addr (uc, reg)))
+    goto badreg;
+
+  if (write)
+    {
+      Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
+            ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+      *(unw_fpreg_t *) addr = *val;
+    }
+  else
+    {
+      *val = *(unw_fpreg_t *) addr;
+      Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
+            ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+    }
+  return 0;
+
+ badreg:
+  Debug (1, "bad register number %u\n", reg);
+  /* attempt to access a non-preserved register */
+  return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+                     char *buf, size_t buf_len, unw_word_t *offp,
+                     void *arg)
+{
+  return _Uelf32_get_proc_name (getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+arm_local_addr_space_init (void)
+{
+  memset (&local_addr_space, 0, sizeof (local_addr_space));
+  local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+  local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+  local_addr_space.acc.put_unwind_info = put_unwind_info;
+  local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+  local_addr_space.acc.access_mem = access_mem;
+  local_addr_space.acc.access_reg = access_reg;
+  local_addr_space.acc.access_fpreg = access_fpreg;
+  local_addr_space.acc.resume = 0;  /* arm_local_resume?  FIXME!  */
+  local_addr_space.acc.get_proc_name = get_static_proc_name;
+  unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
--- libunwind-0.98.5/src/arm/Lglobal.c  (revision 0)
+++ libunwind-0.98.5/src/arm/Lglobal.c  (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
--- libunwind-0.98.5/src/arm/Lregs.c    (revision 0)
+++ libunwind-0.98.5/src/arm/Lregs.c    (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
--- libunwind-0.98.5/src/arm/Lresume.c  (revision 0)
+++ libunwind-0.98.5/src/arm/Lresume.c  (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
--- libunwind-0.98.5/src/arm/offsets.h  (revision 0)
+++ libunwind-0.98.5/src/arm/offsets.h  (revision 189947)
@@ -0,0 +1,38 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation.  */
+
+/* FIXME: For ARM?  Might be incomplete.  Used where?  */
+
+/* Offsets for ARM Linux "ucontext_t":  */
+
+#define LINUX_UC_FLAGS_OFF     0x00
+#define LINUX_UC_LINK_OFF      0x04
+#define LINUX_UC_STACK_OFF     0x08
+#define LINUX_UC_MCONTEXT_OFF  0x14
+#define LINUX_UC_SIGMASK_OFF   0x68
+#define LINUX_UC_REGSPACE_OFF  0xE8
+
+/* Offsets for ARM Linux "struct sigcontext":  */
+
+#define LINUX_SC_TRAPNO_OFF    0x00
+#define LINUX_SC_ERRORCODE_OFF 0x04
+#define LINUX_SC_OLDMASK_OFF   0x08
+#define LINUX_SC_R0_OFF                0x0C
+#define LINUX_SC_R1_OFF                0x10
+#define LINUX_SC_R2_OFF                0x14
+#define LINUX_SC_R3_OFF                0x18
+#define LINUX_SC_R4_OFF                0x1C
+#define LINUX_SC_R5_OFF                0x20
+#define LINUX_SC_R6_OFF                0x24
+#define LINUX_SC_R7_OFF                0x28
+#define LINUX_SC_R8_OFF                0x2C
+#define LINUX_SC_R9_OFF                0x30
+#define LINUX_SC_R10_OFF       0x34
+#define LINUX_SC_FP_OFF                0x38
+#define LINUX_SC_IP_OFF                0x3C
+#define LINUX_SC_SP_OFF                0x40
+#define LINUX_SC_LR_OFF                0x44
+#define LINUX_SC_PC_OFF                0x48
+#define LINUX_SC_CPSR_OFF      0x4C
+#define LINUX_SC_FAULTADDR_OFF 0x50
--- libunwind-0.98.5/src/arm/regname.c  (revision 0)
+++ libunwind-0.98.5/src/arm/regname.c  (revision 189947)
@@ -0,0 +1,90 @@
+#include "unwind_i.h"
+
+static const char *regname[] =
+  {
+    /* 0.  */
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
+    /* 8.  */
+    "r8",  "r9",  "r10", "fp",  "ip",  "sp",  "lr",  "pc",
+    /* 16.  Obsolete FPA names.  */
+    "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
+    /* 24.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 32.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 40.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 48.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 56.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 64.  */
+    "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
+    /* 72.  */
+    "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
+    /* 80.  */
+    "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+    /* 88.  */
+    "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+    /* 96.  */
+    "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
+    /* 104.  */
+    "wCGR0", "wCGR1", "wCGR2", "wCGR3", "wCGR4", "wCGR5", "wCGR6", "wCGR7",
+    /* 112.  */
+    "wR0", "wR1", "wR2", "wR3", "wR4", "wR5", "wR6", "wR7",
+    /* 128.  */
+    "spsr", "spsr_fiq", "spsr_irq", "spsr_abt", "spsr_und", "spsr_svc", 0, 0,
+    /* 136.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 144.  */
+    "r8_usr", "r9_usr", "r10_usr", "r11_usr", "r12_usr", "r13_usr", "r14_usr",
+    /* 151.  */
+    "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "r14_fiq",
+    /* 158.  */
+    "r13_irq", "r14_irq",
+    /* 160.  */
+    "r13_abt", "r14_abt",
+    /* 162.  */
+    "r13_und", "r14_und",
+    /* 164.  */
+    "r13_svc", "r14_svc", 0, 0,
+    /* 168.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 176.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 184.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 192.  */
+    "wC0", "wC1", "wC2", "wC3", "wC4", "wC5", "wC6", "wC7",
+    /* 200.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 208.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 216.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 224.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 232.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 240.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 248.  */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    /* 256.  */
+    "d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
+    /* 264.  */
+    "d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",
+    /* 272.  */
+    "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+    /* 280.  */
+    "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+  };
+
+PROTECTED const char *
+unw_regname (unw_regnum_t reg)
+{
+  if (reg < (unw_regnum_t) NELEMS (regname))
+    return regname[reg];
+  else
+    return "???";
+}
--- libunwind-0.98.5/src/arm/Linit.c    (revision 0)
+++ libunwind-0.98.5/src/arm/Linit.c    (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
--- libunwind-0.98.5/src/arm/Gcreate_addr_space.c       (revision 0)
+++ libunwind-0.98.5/src/arm/Gcreate_addr_space.c       (revision 189947)
@@ -0,0 +1,60 @@
+/* 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 <stdlib.h>
+
+#include "unwind_i.h"
+
+PROTECTED unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+  return NULL;
+#else
+  unw_addr_space_t as = malloc (sizeof (*as));
+
+  if (!as)
+    return NULL;
+
+  memset (as, 0, sizeof (*as));
+
+  as->acc = *a;
+
+  /*
+   * ARM supports little-endian and big-endian.
+   */
+  if (byte_order != 0 && byte_order != __LITTLE_ENDIAN
+      && byte_order != __BIG_ENDIAN)
+    return NULL;
+  
+  /* Default to little-endian for ARM.  */
+  if (byte_order == 0 || byte_order == __LITTLE_ENDIAN)
+    as->big_endian = 0;
+  else
+    as->big_endian = 1;
+  
+  return as;
+#endif
+}
--- libunwind-0.98.5/src/arm/gen-offsets.c      (revision 0)
+++ libunwind-0.98.5/src/arm/gen-offsets.c      (revision 189947)
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <ucontext.h>
+#include <asm/sigcontext.h>
+
+#define UC(N,X) \
+  printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X))
+
+#define SC(N,X) \
+  printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, 
X))
+
+int
+main (void)
+{
+  printf (
+"/* Linux-specific definitions: */\n\n"
+
+"/* Define various structure offsets to simplify cross-compilation.  */\n\n"
+
+"/* Offsets for ARM Linux \"ucontext_t\":  */\n\n");
+
+  UC ("FLAGS", uc_flags);
+  UC ("LINK", uc_link);
+  UC ("STACK", uc_stack);
+  UC ("MCONTEXT", uc_mcontext);
+  UC ("SIGMASK", uc_sigmask);
+  UC ("REGSPACE", uc_regspace);
+
+  printf ("\n/* Offsets for ARM Linux \"struct sigcontext\":  */\n\n");
+
+  SC ("TRAPNO", trap_no);
+  SC ("ERRORCODE", error_code);
+  SC ("OLDMASK", oldmask);
+  SC ("R0", arm_r0);
+  SC ("R1", arm_r1);
+  SC ("R2", arm_r2);
+  SC ("R3", arm_r3);
+  SC ("R4", arm_r4);
+  SC ("R5", arm_r5);
+  SC ("R6", arm_r6);
+  SC ("R7", arm_r7);
+  SC ("R8", arm_r8);
+  SC ("R9", arm_r9);
+  SC ("R10", arm_r10);
+  SC ("FP", arm_fp);
+  SC ("IP", arm_ip);
+  SC ("SP", arm_sp);
+  SC ("LR", arm_lr);
+  SC ("PC", arm_pc);
+  SC ("CPSR", arm_cpsr);
+  SC ("FAULTADDR", fault_address);
+
+  return 0;
+}
--- libunwind-0.98.5/src/arm/unwind_i.h (revision 0)
+++ libunwind-0.98.5/src/arm/unwind_i.h (revision 189947)
@@ -0,0 +1,41 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002 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.  */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <memory.h>
+#include <stdint.h>
+
+#include <libunwind-arm.h>
+
+#include "internal.h"
+#include "tdep.h"
+
+#define arm_local_addr_space_init      UNW_OBJ(local_addr_space_init)
+
+extern void arm_local_addr_space_init (void);
+
+#endif /* unwind_i_h */
--- libunwind-0.98.5/src/arm/Gstep.c    (revision 0)
+++ libunwind-0.98.5/src/arm/Gstep.c    (revision 189947)
@@ -0,0 +1,49 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002-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 "unwind_i.h"
+#include "offsets.h"
+
+PROTECTED int
+unw_step (unw_cursor_t *cursor)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  int ret;
+
+  Debug (1, "(cursor=%p)\n", c);
+
+  /* Try DWARF-based unwinding...  this is the only method likely to work for
+     ARM.  */
+  ret = dwarf_step (&c->dwarf);
+
+  if (unlikely (ret == -UNW_ESTOPUNWIND))
+    return ret;
+
+  /* Dwarf unwinding didn't work, stop.  */
+  if (unlikely (ret < 0))
+    return 0;
+
+  return (c->dwarf.ip == 0) ? 0 : 1;
+}
--- libunwind-0.98.5/src/arm/Lcreate_addr_space.c       (revision 0)
+++ libunwind-0.98.5/src/arm/Lcreate_addr_space.c       (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
--- libunwind-0.98.5/src/arm/Ginit_local.c      (revision 0)
+++ libunwind-0.98.5/src/arm/Ginit_local.c      (revision 189947)
@@ -0,0 +1,54 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+       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 "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+PROTECTED int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+  return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+PROTECTED int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  if (tdep_needs_initialization)
+    tdep_init ();
+
+  Debug (1, "(cursor=%p)\n", c);
+
+  c->dwarf.as = unw_local_addr_space;
+  c->dwarf.as_arg = uc;
+  return common_init (c);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
--- libunwind-0.98.5/src/arm/Gget_proc_info.c   (revision 0)
+++ libunwind-0.98.5/src/arm/Gget_proc_info.c   (revision 189947)
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+       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 "unwind_i.h"
+
+PROTECTED int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  int ret;
+
+  /* We can only unwind using Dwarf into on ARM: return failure code
+     if it's not present.  */
+  ret = dwarf_make_proc_info (&c->dwarf);
+  if (ret < 0)
+    return ret;
+
+  *pi = c->dwarf.pi;
+  return 0;
+}
--- libunwind-0.98.5/src/arm/Ginit_remote.c     (revision 0)
+++ libunwind-0.98.5/src/arm/Ginit_remote.c     (revision 189947)
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+       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 "init.h"
+#include "unwind_i.h"
+
+PROTECTED int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+  return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+  struct cursor *c = (struct cursor *) cursor;
+
+  if (tdep_needs_initialization)
+    tdep_init ();
+
+  Debug (1, "(cursor=%p)\n", c);
+
+  c->dwarf.as = as;
+  c->dwarf.as_arg = as_arg;
+  return common_init (c);
+#endif /* !UNW_LOCAL_ONLY */
+}
--- libunwind-0.98.5/src/arm/Lstep.c    (revision 0)
+++ libunwind-0.98.5/src/arm/Lstep.c    (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
--- libunwind-0.98.5/src/arm/Lget_proc_info.c   (revision 0)
+++ libunwind-0.98.5/src/arm/Lget_proc_info.c   (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
--- libunwind-0.98.5/src/arm/Gis_signal_frame.c (revision 0)
+++ libunwind-0.98.5/src/arm/Gis_signal_frame.c (revision 189947)
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002-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 <stdio.h>
+#include "unwind_i.h"
+
+/* FIXME for ARM.  */
+
+PROTECTED int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+  printf ("%s: implement me\n", __FUNCTION__);
+  return -UNW_ENOINFO;
+}
--- libunwind-0.98.5/src/arm/Linit_local.c      (revision 0)
+++ libunwind-0.98.5/src/arm/Linit_local.c      (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
--- libunwind-0.98.5/src/arm/siglongjmp.S       (revision 0)
+++ libunwind-0.98.5/src/arm/siglongjmp.S       (revision 189947)
@@ -0,0 +1,11 @@
+       /* Dummy implementation for now.  Libunwind-based setjmp/longjmp
+          can't work on x86 until we take advantage of DWARF2 unwind info.  */
+
+       /* FIXME for ARM!  */
+
+       .globl _UI_siglongjmp_cont
+       .globl _UI_longjmp_cont
+
+_UI_siglongjmp_cont:
+_UI_longjmp_cont:
+       bx lr
--- libunwind-0.98.5/src/arm/Linit_remote.c     (revision 0)
+++ libunwind-0.98.5/src/arm/Linit_remote.c     (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
--- libunwind-0.98.5/src/longjmp.c      (revision 186298)
+++ libunwind-0.98.5/src/longjmp.c      (revision 189947)
@@ -102,7 +102,7 @@ _longjmp (jmp_buf env, int val)
          if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
              || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
              || unw_set_reg (&c, UNW_REG_IP,
-                             (unw_word_t) &_UI_longjmp_cont))
+                             (unw_word_t) (uintptr_t) &_UI_longjmp_cont))
            abort ();
        }
       else
--- libunwind-0.98.5/src/siglongjmp.c   (revision 186298)
+++ libunwind-0.98.5/src/siglongjmp.c   (revision 189947)
@@ -147,7 +147,7 @@ siglongjmp (sigjmp_buf env, int val)
 
       if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
          || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
-         || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) cont))
+         || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont))
        abort ();
 
       unw_resume (&c);
--- libunwind-0.98.5/src/dwarf/Gfind_proc_info-lsb.c    (revision 186298)
+++ libunwind-0.98.5/src/dwarf/Gfind_proc_info-lsb.c    (revision 189947)
@@ -30,6 +30,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
 #include <stdlib.h>
 #include <stddef.h>
 #include <string.h>
+#include <stdio.h>
 
 #include "dwarf_i.h"
 #include "dwarf-eh.h"
@@ -43,13 +44,350 @@ struct table_entry
 
 #ifndef UNW_REMOTE_ONLY
 
+/* Load .debug_frame section from FILE.  Allocates and returns space
+   in *BUF, and sets *BUFSIZE to its size.  IS_LOCAL is 1 if using the
+   local process, in which case we can search the system debug file
+   directory; 0 for other address spaces, in which case we do not; or
+   -1 for recursive calls following .gnu_debuglink.  Returns 0 on
+   success, 1 on error.  Succeeds even if the file contains no
+   .debug_frame.  */
+
+static int
+load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
+{
+  FILE *f;
+  Elf_W (Ehdr) ehdr;
+  Elf_W (Half) shstrndx;
+  Elf_W (Shdr) *sec_hdrs;
+  char *stringtab;
+  unsigned int i;
+  size_t linksize = 0;
+  char *linkbuf = NULL;
+  
+  *buf = NULL;
+  *bufsize = 0;
+  
+  f = fopen (file, "r");
+  
+  if (!f)
+    return 1;
+  
+  fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f);
+  
+  shstrndx = ehdr.e_shstrndx;
+  
+  Debug (4, "opened file '%s'. Section header at offset %d\n",
+         file, (int) ehdr.e_shoff);
+
+  fseek (f, ehdr.e_shoff, SEEK_SET);
+  sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr)));
+  fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f);
+  
+  Debug (4, "loading string table of size %d\n",
+          sec_hdrs[shstrndx].sh_size);
+  stringtab = malloc (sec_hdrs[shstrndx].sh_size);
+  fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
+  fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f);
+  
+  for (i = 1; i < ehdr.e_shnum && *buf == NULL; i++)
+    {
+      char *secname = &stringtab[sec_hdrs[i].sh_name];
+
+      if (strcmp (secname, ".debug_frame") == 0)
+        {
+         *bufsize = sec_hdrs[i].sh_size;
+         *buf = malloc (*bufsize);
+
+         fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
+         fread (*buf, 1, *bufsize, f);
+
+         Debug (4, "read %d bytes of .debug_frame from offset %d\n",
+                *bufsize, sec_hdrs[i].sh_offset);
+       }
+      else if (is_local >= 0 && strcmp (secname, ".gnu_debuglink") == 0)
+       {
+         linksize = sec_hdrs[i].sh_size;
+         linkbuf = malloc (linksize);
+
+         fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
+         fread (linkbuf, 1, linksize, f);
+
+         Debug (4, "read %d bytes of .gnu_debuglink from offset %d\n",
+                *bufsize, sec_hdrs[i].sh_offset);
+       }
+    }
+
+  free (stringtab);
+  free (sec_hdrs);
+
+  fclose (f);
+
+  if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL)
+    {
+      char *newname, *basedir, *p;
+      static const char *debugdir = "/usr/lib/debug";
+      int ret;
+
+      /* FIXME: Ignore the checksum; just search for the file.  */
+      basedir = malloc (strlen (file) + 1);
+      newname = malloc (strlen (linkbuf) + strlen (debugdir)
+                       + strlen (file) + 9);
+
+      p = strrchr (file, '/');
+      if (p != NULL)
+       {
+         memcpy (basedir, file, p - file);
+         basedir[p - file] = '\0';
+       }
+      else
+       basedir[0] = 0;
+
+      strcpy (newname, basedir);
+      strcat (newname, "/");
+      strcat (newname, linkbuf);
+      ret = load_debug_frame (newname, buf, bufsize, -1);
+
+      if (ret == 1)
+       {
+         strcpy (newname, basedir);
+         strcat (newname, "/.debug/");
+         strcat (newname, linkbuf);
+         ret = load_debug_frame (newname, buf, bufsize, -1);
+       }
+
+      if (ret == 1 && is_local == 1)
+       {
+         strcpy (newname, debugdir);
+         strcat (newname, basedir);
+         strcat (newname, "/");
+         strcat (newname, linkbuf);
+         ret = load_debug_frame (newname, buf, bufsize, -1);
+       }
+
+      free (basedir);
+      free (newname);
+    }
+  free (linkbuf);
+
+  return 0;
+}
+
+/* Locate the binary which originated the contents of address ADDR. Return
+   the name of the binary in *name (which is allocated on the heap, and must
+   be freed by the caller).  Returns 0 if a binary is successfully found, or 1
+   if an error occurs.  */
+
+static int
+find_binary_for_address (unw_word_t addr, char **name)
+{
+  FILE *f;
+  
+  *name = NULL;
+  
+  f = fopen ("/proc/self/maps", "r");
+  
+  if (!f)
+    return 1;
+  
+  while (!feof (f))
+    {
+      uint64_t start, end, offset, ino;
+      int dmajor, dminor;
+      size_t dummy = 0;
+      char *line = 0;
+      int parsed, chars;
+      
+      chars = getline (&line, &dummy, f);
+      
+      /* Remove newline.  */
+      if (line[chars - 1] == '\n')
+        line[chars - 1] = '\0';
+
+      parsed = sscanf (line, "%" PRIx64 "-%" PRIx64 " %*s %" PRIx64
+                      " %x:%x %" PRIi64 " %n", &start, &end, &offset,
+                      &dmajor, &dminor, &ino, &chars);
+
+      if (parsed == 6 && ino != 0 && addr >= start && addr < end)
+        {
+         Debug (4, "start:%" PRIx64 " end:%" PRIx64 " filename:'%s'\n",
+                start, end, &line[chars]);
+         
+         *name = strdup (&line[chars]);
+
+         free (line);
+         fclose (f);
+
+         return 0;
+       }
+      free (line);
+    }
+  
+  fclose (f);
+  
+  return 1;
+}
+
+/* Locate and/or try to load a debug_frame section for address ADDR.  Return
+   pointer to debug frame descriptor, or zero if not found.  */
+
+static struct unw_debug_frame_list *
+locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info,
+                  unw_word_t addr, const char *dlname)
+{
+  struct unw_debug_frame_list *w, *fdesc = 0;
+  char *name = 0;
+  int err;
+  uint64_t start = 0, end = 0;
+  char *buf;
+  size_t bufsize;
+  unsigned int i;
+
+  /* First, see if we loaded this frame already.  */
+
+  for (w = as->debug_frames; w; w = w->next)
+    {
+      Debug (4, "checking %p: %x-%x\n", w, (int)w->start, (int)w->end);
+      if (addr >= w->start && addr < w->end)
+       return w;
+    }
+
+  /* If the object name we receive is blank, there's still a chance of locating
+     the file by parsing /proc/self/maps.  */
+
+  if (strcmp (dlname, "") == 0)
+    {
+      err = find_binary_for_address (addr, &name);
+      if (err)
+        {
+         Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
+                (uint64_t) addr);
+          return 0;
+       }
+    }
+  else
+    name = (char*) dlname;
+
+  /* Find the start/end of the described region by parsing the
+     dl_phdr_info structure.  */
+
+  start = info->dlpi_addr + info->dlpi_phdr[0].p_vaddr;
+  end = start;
+
+  for (i = 0; i < info->dlpi_phnum; i++)
+    {
+      Elf_W (Addr) hdrbase = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr;
+      Elf_W (Addr) hdrlimit = hdrbase + info->dlpi_phdr[i].p_memsz;
+
+      if (info->dlpi_phdr[i].p_type != PT_LOAD)
+       continue;
+
+      if (hdrbase < start)
+       start = hdrbase;
+      if (hdrlimit > end)
+       end = hdrlimit;
+    }
+
+  Debug (4, "calculated bounds of %x-%x for '%s'\n", (int)start, (int)end,
+        name);
+  
+  err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
+  
+  if (!err)
+    {
+      fdesc = malloc (sizeof (struct unw_debug_frame_list));
+
+      fdesc->start = start;
+      fdesc->end = end;
+      fdesc->debug_frame = buf;
+      fdesc->debug_frame_size = bufsize;
+      fdesc->index = 0;
+      fdesc->next = as->debug_frames;
+      
+      as->debug_frames = fdesc;
+    }
+  
+  if (name && name != dlname)
+    free (name);
+  
+  return fdesc;
+}
+
+struct callback_ptr_info
+  {
+    unw_dyn_info_t *di;
+    unw_dyn_info_t *di_debug;
+    unw_addr_space_t as;
+  };
+
+struct debug_frame_tab
+  {
+    struct table_entry *tab;
+    uint32_t length;
+    uint32_t size;
+  };
+
+static struct debug_frame_tab *
+debug_frame_tab_new (unsigned int base_size)
+{
+  struct debug_frame_tab *tab = malloc (sizeof (struct debug_frame_tab));
+
+  tab->tab = calloc (base_size, sizeof (struct table_entry));
+  tab->length = 0;
+  tab->size = base_size;
+  
+  return tab;
+}
+
+static void
+debug_frame_tab_append (struct debug_frame_tab *tab,
+                       unw_word_t fde_offset, unw_word_t start_ip)
+{
+  unsigned int length = tab->length;
+
+  if (length == tab->size)
+    {
+      tab->size *= 2;
+      tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size);
+    }
+  
+  tab->tab[length].fde_offset = fde_offset;
+  tab->tab[length].start_ip_offset = start_ip;
+  
+  tab->length = length + 1;
+}
+
+static void
+debug_frame_tab_shrink (struct debug_frame_tab *tab)
+{
+  if (tab->size > tab->length)
+    {
+      tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length);
+      tab->size = tab->length;
+    }
+}
+
+static int
+debug_frame_tab_compare (const void *a, const void *b)
+{
+  const struct table_entry *fa = a, *fb = b;
+  
+  if (fa->start_ip_offset > fb->start_ip_offset)
+    return 1;
+  else if (fa->start_ip_offset < fb->start_ip_offset)
+    return -1;
+  else
+    return 0;
+}
+
 /* Info is a pointer to a unw_dyn_info_t structure and, on entry,
    member u.rti.segbase contains the instruction-pointer we're looking
    for.  */
 static int
 callback (struct dl_phdr_info *info, size_t size, void *ptr)
 {
-  unw_dyn_info_t *di = ptr;
+  struct callback_ptr_info *cinf = ptr;
+  unw_addr_space_t as = cinf->as;
+  unw_dyn_info_t *di = cinf->di;
   const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text;
   unw_word_t addr, eh_frame_ptr, fde_count;
   Elf_W(Addr) load_base, segbase = 0;
@@ -89,104 +427,254 @@ callback (struct dl_phdr_info *info, siz
       else if (phdr->p_type == PT_DYNAMIC)
        p_dynamic = phdr;
     }
-  if (!p_text || !p_eh_hdr)
+  
+  if (!p_text)
     return 0;
 
-  if (likely (p_eh_hdr->p_vaddr >= p_text->p_vaddr
-             && p_eh_hdr->p_vaddr < p_text->p_vaddr + p_text->p_memsz))
-    /* normal case: eh-hdr is inside text segment */
-    segbase = p_text->p_vaddr + load_base;
-  else
+  if (p_eh_hdr)
     {
-      /* Special case: eh-hdr is in some other segment; this may
-        happen, e.g., for the Linux kernel's gate DSO, for
-        example.  */
-      phdr = info->dlpi_phdr;
-      for (n = info->dlpi_phnum; --n >= 0; phdr++)
+      if (likely (p_eh_hdr->p_vaddr >= p_text->p_vaddr
+                 && p_eh_hdr->p_vaddr < p_text->p_vaddr + p_text->p_memsz))
+       /* normal case: eh-hdr is inside text segment */
+       segbase = p_text->p_vaddr + load_base;
+      else
        {
-         if (phdr->p_type == PT_LOAD && p_eh_hdr->p_vaddr >= phdr->p_vaddr
-             && p_eh_hdr->p_vaddr < phdr->p_vaddr + phdr->p_memsz)
+         /* Special case: eh-hdr is in some other segment; this may
+            happen, e.g., for the Linux kernel's gate DSO, for
+            example.  */
+         phdr = info->dlpi_phdr;
+         for (n = info->dlpi_phnum; --n >= 0; phdr++)
            {
-             segbase = phdr->p_vaddr + load_base;
-             break;
+             if (phdr->p_type == PT_LOAD && p_eh_hdr->p_vaddr >= phdr->p_vaddr
+                 && p_eh_hdr->p_vaddr < phdr->p_vaddr + phdr->p_memsz)
+               {
+                 segbase = phdr->p_vaddr + load_base;
+                 break;
+               }
            }
        }
-    }
 
-  if (p_dynamic)
-    {
-      /* For dynamicly linked executables and shared libraries,
-        DT_PLTGOT is the value that data-relative addresses are
-        relative to for that object.  We call this the "gp".  */
-      Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
-      for (; dyn->d_tag != DT_NULL; ++dyn)
-       if (dyn->d_tag == DT_PLTGOT)
-         {
-           /* Assume that _DYNAMIC is writable and GLIBC has
-              relocated it (true for x86 at least).  */
-           di->gp = dyn->d_un.d_ptr;
-           break;
-         }
-    }
-  else
-    /* Otherwise this is a static executable with no _DYNAMIC.  Assume
-       that data-relative addresses are relative to 0, i.e.,
-       absolute.  */
-    di->gp = 0;
+      if (p_dynamic)
+       {
+         /* For dynamicly linked executables and shared libraries,
+            DT_PLTGOT is the value that data-relative addresses are
+            relative to for that object.  We call this the "gp".  */
+         Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
+         for (; dyn->d_tag != DT_NULL; ++dyn)
+           if (dyn->d_tag == DT_PLTGOT)
+             {
+               /* Assume that _DYNAMIC is writable and GLIBC has
+                  relocated it (true for x86 at least).  */
+               di->gp = dyn->d_un.d_ptr;
+               break;
+             }
+       }
+      else
+       /* Otherwise this is a static executable with no _DYNAMIC.  Assume
+          that data-relative addresses are relative to 0, i.e.,
+          absolute.  */
+       di->gp = 0;
 
-  hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
-  if (hdr->version != DW_EH_VERSION)
-    {
-      Debug (1, "table `%s' has unexpected version %d\n",
-            info->dlpi_name, hdr->version);
-      return 0;
-    }
+      hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
+      if (hdr->version != DW_EH_VERSION)
+       {
+         Debug (1, "table `%s' has unexpected version %d\n",
+                info->dlpi_name, hdr->version);
+         return 0;
+       }
 
-  if (hdr->table_enc == DW_EH_PE_omit)
-    {
-      Debug (1, "table `%s' doesn't have a binary search table\n",
-            info->dlpi_name);
-      return 0;
-    }
-  /* For now, only support binary-search tables which are
-     data-relative and whose entries are 32 bits wide.  */
-  if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
-    {
-      Debug (1, "search table in `%s' has unexpected encoding 0x%x\n",
-            info->dlpi_name, hdr->table_enc);
-      return 0;
-    }
+      if (hdr->table_enc == DW_EH_PE_omit)
+       {
+         Debug (1, "table `%s' doesn't have a binary search table\n",
+                info->dlpi_name);
+         return 0;
+       }
+      /* For now, only support binary-search tables which are
+        data-relative and whose entries are 32 bits wide.  */
+      if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+       {
+         Debug (1, "search table in `%s' has unexpected encoding 0x%x\n",
+                info->dlpi_name, hdr->table_enc);
+         return 0;
+       }
 
-  addr = (unw_word_t) (hdr + 1);
-  a = unw_get_accessors (unw_local_addr_space);
-  pi.gp = di->gp;
+      addr = (unw_word_t) (uintptr_t) (hdr + 1);
+      a = unw_get_accessors (unw_local_addr_space);
+      pi.gp = di->gp;
+
+      /* Read eh_frame_ptr: */
+      if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
+                                            &addr, hdr->eh_frame_ptr_enc, &pi,
+                                            &eh_frame_ptr, NULL)) < 0)
+       return ret;
 
-  /* Read eh_frame_ptr: */
-  if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
-                                        &addr, hdr->eh_frame_ptr_enc, &pi,
-                                        &eh_frame_ptr, NULL)) < 0)
-    return ret;
+      /* Read fde_count: */
+      if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
+                                            &addr, hdr->fde_count_enc, &pi,
+                                            &fde_count, NULL)) < 0)
+       return ret;
 
-  /* Read fde_count: */
-  if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
-                                        &addr, hdr->fde_count_enc, &pi,
-                                        &fde_count, NULL)) < 0)
-    return ret;
+      di->format = UNW_INFO_FORMAT_REMOTE_TABLE;
+      di->start_ip = p_text->p_vaddr + load_base;
+      di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
+      di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
+      di->u.rti.table_data = addr;
+      assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
+      di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
+                            / sizeof (unw_word_t));
+      /* For the binary-search table in the eh_frame_hdr, data-relative
+        means relative to the start of that section... */
+      di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr;
+
+      Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
+            "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr,
+            (long) di->u.rti.segbase, (long) di->u.rti.table_len,
+            (long) di->gp, (long) di->u.rti.table_data);
+    }
+
+  di = cinf->di_debug;
+  if (1)
+    {
+      struct unw_debug_frame_list *fdesc = 0;
+
+      if (info->dlpi_phnum > 0)
+        {
+         unw_word_t saddr = info->dlpi_addr + info->dlpi_phdr[0].p_vaddr;
+         char *buf;
+         size_t bufsize;
+         unw_word_t item_start, item_end = 0;
+         uint32_t u32val = 0;
+         uint64_t cie_id = 0;
+         struct debug_frame_tab *tab;
+
+         Debug (15, "there was no .eh_frame_hdr, trying to find "
+                ".debug_frame\n");
+
+         fdesc = locate_debug_info (as, info, saddr, info->dlpi_name);
+         
+         if (!fdesc)
+           {
+             Debug (15, "couldn't load .debug_frame\n");
+             return 0;
+           }
+         else
+           Debug (15, "loaded .debug_frame\n");
+         
+         buf = fdesc->debug_frame;
+         bufsize = fdesc->debug_frame_size;
+         
+         if (bufsize == 0)
+           {
+             Debug (15, "zero-length .debug_frame\n");
+             return 0;
+           }
+         
+         /* Now create a binary-search table, if it does not already exist.  */
+         
+         if (!fdesc->index)
+           {
+             addr = (unw_word_t) (uintptr_t) buf;
+
+             a = unw_get_accessors (unw_local_addr_space);
+
+             /* Find all FDE entries in debug_frame, and make into a sorted
+                index.  */
+
+             tab = debug_frame_tab_new (16);
+
+             /*Debug (1, "buf = %p\n", buf);
+             for (i = 0; i < 32; i++)
+               Debug (1, "debug_frame[%d] = %d\n", i, buf[i]);*/
+
+             while (addr < (unw_word_t) (uintptr_t) (buf + bufsize))
+               {
+                 uint64_t id_for_cie;
+                 item_start = addr;
+
+                 dwarf_readu32 (as, a, &addr, &u32val, NULL);
+
+                 if (u32val == 0)
+                   break;
+                 else if (u32val != 0xffffffff)
+                   {
+                     uint32_t cie_id32 = 0;
+                     item_end = addr + u32val;
+                     dwarf_readu32 (as, a, &addr, &cie_id32, NULL);
+                     cie_id = cie_id32;
+                     id_for_cie = 0xffffffff;
+                   }
+                 else
+                   {
+                     uint64_t u64val = 0;
+                     /* Extended length.  */
+                     dwarf_readu64 (as, a, &addr, &u64val, NULL);
+                     item_end = addr + u64val;
+
+                     dwarf_readu64 (as, a, &addr, &cie_id, NULL);
+                     id_for_cie = 0xffffffffffffffffull;
+                   }
+
+                 /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/
+
+                 if (cie_id == id_for_cie)
+                   ;
+                   /*Debug (1, "Found CIE at %.8x.\n", item_start);*/
+                 else
+                   {
+                     unw_word_t fde_addr = item_start;
+                     unw_proc_info_t this_pi;
+                     unw_dyn_dwarf_fde_info_t this_dfi;
+                     int err;
+
+                     /*Debug (1, "Found FDE at %.8x\n", item_start);*/
+
+                     err = dwarf_parse_fde (as, a, &fde_addr, &this_pi,
+                                            &this_dfi,
+                                            (unw_word_t) (uintptr_t) buf,
+                                            NULL /* arg? */);
+                     if (err == 0)
+                       {
+                         Debug (15, "start_ip = %x, end_ip = %x\n",
+                                (int) this_pi.start_ip, (int) this_pi.end_ip);
+                         debug_frame_tab_append (tab,
+                           item_start - (unw_word_t) (uintptr_t) buf,
+                                                 this_pi.start_ip);
+                       }
+                     /*else
+                       Debug (1, "FDE parse failed\n");*/
+                   }
+
+                 addr = item_end;
+               }
+
+             debug_frame_tab_shrink (tab);
+             qsort (tab->tab, tab->length, sizeof (struct table_entry),
+                    debug_frame_tab_compare);
+            /* for (i = 0; i < tab->length; i++)
+               {
+                 fprintf (stderr, "ip %x, fde offset %x\n",
+                          (int) tab->tab[i].start_ip_offset,
+                          (int) tab->tab[i].fde_offset);
+               }*/
+             fdesc->index = tab->tab;
+             fdesc->index_size = tab->length;
+             free (tab);
+           }
+       }
 
-  di->format = UNW_INFO_FORMAT_REMOTE_TABLE;
-  di->start_ip = p_text->p_vaddr + load_base;
-  di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
-  di->u.rti.name_ptr = (unw_word_t) info->dlpi_name;
-  di->u.rti.table_data = addr;
-  assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
-  di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
-                        / sizeof (unw_word_t));
-  /* For the binary-search table in the eh_frame_hdr, data-relative
-     means relative to the start of that section... */
-  di->u.rti.segbase = (unw_word_t) hdr;
+      di->format = UNW_INFO_FORMAT_DEBUG_FRAME_TABLE;
+      di->start_ip = fdesc->start;
+      di->end_ip = fdesc->end;
+      di->u.debi.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
+      di->u.debi.table_data = (unw_word_t) (uintptr_t) fdesc->index;
+      di->u.debi.table_len = fdesc->index_size * sizeof (struct table_entry)
+                            / sizeof (unw_word_t);
+      di->u.debi.segbase = (unw_word_t) (uintptr_t) info->dlpi_addr;
+      di->u.debi.frame_base = (unw_word_t) (uintptr_t) fdesc->debug_frame;
+    }
 
   Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
-        "table_data=0x%lx\n", (char *) di->u.rti.name_ptr,
+        "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr,
         (long) di->u.rti.segbase, (long) di->u.rti.table_len,
         (long) di->gp, (long) di->u.rti.table_data);
   return 1;
@@ -197,14 +685,22 @@ dwarf_find_proc_info (unw_addr_space_t a
                      unw_proc_info_t *pi, int need_unwind_info, void *arg)
 {
   sigset_t saved_sigmask;
-  unw_dyn_info_t di;
+  unw_dyn_info_t di, di_debug;
+  struct callback_ptr_info cinf;
   int ret;
 
+  cinf.di = &di;
+  cinf.di_debug = &di_debug;
+  cinf.as = as;
+
   Debug (14, "looking for IP=0x%lx\n", (long) ip);
+  di.format = -1;
   di.u.rti.segbase = ip;       /* this is cheap... */
+  di_debug.format = -1;
+  di_debug.u.rti.segbase = ip;
 
   sigprocmask (SIG_SETMASK, &unwi_full_sigmask, &saved_sigmask);
-  ret = dl_iterate_phdr (callback, &di);
+  ret = dl_iterate_phdr (callback, &cinf);
   sigprocmask (SIG_SETMASK, &saved_sigmask, NULL);
 
   if (ret <= 0)
@@ -214,7 +710,15 @@ dwarf_find_proc_info (unw_addr_space_t a
     }
 
   /* now search the table: */
-  return dwarf_search_unwind_table (as, ip, &di, pi, need_unwind_info, arg);
+  if (di.format != -1)
+    ret = dwarf_search_unwind_table (as, ip, &di, pi, need_unwind_info, arg);
+  else
+    ret = -UNW_ENOINFO;
+
+  if (ret == -UNW_ENOINFO && di_debug.format != -1)
+    ret = dwarf_search_unwind_table (as, ip, &di_debug, pi,
+                                    need_unwind_info, arg);
+  return ret;
 }
 
 static inline const struct table_entry *
@@ -229,6 +733,7 @@ lookup (struct table_entry *table, size_
     {
       mid = (lo + hi) / 2;
       e = table + mid;
+      Debug (1, "e->start_ip_offset = %x\n", (int) e->start_ip_offset);
       if (rel_ip < e->start_ip_offset)
        hi = mid;
       else
@@ -293,11 +798,16 @@ dwarf_search_unwind_table (unw_addr_spac
   unw_accessors_t *a;
 #ifndef UNW_LOCAL_ONLY
   struct table_entry ent;
-  int ret;
 #endif
+  int ret;
+  unw_word_t debug_frame_base = 0;
 
   assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
-         && (ip >= di->start_ip && ip < di->end_ip));
+         || di->format == UNW_INFO_FORMAT_DEBUG_FRAME_TABLE);
+  assert (ip >= di->start_ip && ip < di->end_ip);
+
+  if (di->format == UNW_INFO_FORMAT_DEBUG_FRAME_TABLE)
+    debug_frame_base = di->u.debi.frame_base;
 
   a = unw_get_accessors (as);
 
@@ -311,7 +821,7 @@ dwarf_search_unwind_table (unw_addr_spac
   if (as == unw_local_addr_space)
     {
       segbase = di->u.rti.segbase;
-      e = lookup ((struct table_entry *) di->u.rti.table_data,
+      e = lookup ((struct table_entry *) (uintptr_t) di->u.rti.table_data,
                  di->u.rti.table_len * sizeof (unw_word_t), ip - segbase);
     }
   else
@@ -331,14 +841,38 @@ dwarf_search_unwind_table (unw_addr_spac
     }
   if (!e)
     {
+      Debug (1, "IP %x inside range %x-%x, but no explicit unwind info 
found\n",
+            (int) ip, (int) di->start_ip, (int) di->end_ip);
       /* IP is inside this table's range, but there is no explicit
         unwind info.  */
       return -UNW_ENOINFO;
     }
   Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
-        (long) ip, (long) (e->start_ip_offset + segbase));
-  fde_addr = e->fde_offset + segbase;
-  return dwarf_parse_fde (as, a, &fde_addr, pi, &pi->extra.dwarf_info, arg);
+        (long) ip, (long) (e->start_ip_offset));
+  if (debug_frame_base)
+    fde_addr = e->fde_offset + debug_frame_base;
+  else
+    fde_addr = e->fde_offset + segbase;
+  Debug (1, "e->fde_offset = %x, segbase = %x, debug_frame_base = %x, "
+           "fde_addr = %x\n", (int) e->fde_offset, (int) segbase,
+           (int) debug_frame_base, (int) fde_addr);
+  ret = dwarf_parse_fde (as, a, &fde_addr, pi, &pi->extra.dwarf_info,
+                        debug_frame_base, arg);
+  if (ret < 0)
+    return ret;
+
+  /* .debug_frame uses an absolute encoding that does not know about any
+     shared library relocation.  */
+  if (di->format == UNW_INFO_FORMAT_DEBUG_FRAME_TABLE)
+    {
+      pi->start_ip += segbase;
+      pi->end_ip += segbase;
+    }
+
+  if (pi->end_ip < ip)
+    return -UNW_ENOINFO;
+
+  return 0;
 }
 
 HIDDEN void
--- libunwind-0.98.5/src/dwarf/Gparser.c        (revision 186298)
+++ libunwind-0.98.5/src/dwarf/Gparser.c        (revision 189947)
@@ -459,6 +459,7 @@ create_state_record_for (struct dwarf_cu
   switch (c->pi.format)
     {
     case UNW_INFO_FORMAT_DWARF_FDE:
+    case UNW_INFO_FORMAT_DEBUG_FRAME_FDE:
       ret = parse_fde (c, ip, sr);
       break;
 
--- libunwind-0.98.5/src/dwarf/Gexpr.c  (revision 186298)
+++ libunwind-0.98.5/src/dwarf/Gexpr.c  (revision 189947)
@@ -47,10 +47,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
 #define ULEB128        0x4
 #define SLEB128        0x5
 #define OFFSET 0x6     /* 32-bit offset for 32-bit DWARF, 64-bit otherwise */
+#define ADDR   0x7     /* Machine address.  */
 
 static uint8_t operands[256] =
   {
-    [DW_OP_addr] =     OPND1 (sizeof (unw_word_t) == 4 ? VAL32 : VAL64),
+    [DW_OP_addr] =             OPND1 (ADDR),
     [DW_OP_const1u] =          OPND1 (VAL8),
     [DW_OP_const1s] =          OPND1 (VAL8),
     [DW_OP_const2u] =          OPND1 (VAL16),
@@ -107,9 +108,9 @@ static uint8_t operands[256] =
   };
 
 static inline unw_word_t
-sword (unw_word_t val)
+sword (unw_addr_space_t as, unw_word_t val)
 {
-  switch (sizeof (unw_word_t))
+  switch (dwarf_addr_size (as))
     {
     case 1: return (int8_t) val;
     case 2: return (int16_t) val;
@@ -129,6 +130,16 @@ read_operand (unw_addr_space_t as, unw_a
   uint64_t u64;
   int ret;
 
+  if (operand_type == ADDR)
+    switch (dwarf_addr_size (as))
+      {
+      case 1: operand_type = VAL8; break;
+      case 2: operand_type = VAL16; break;
+      case 4: operand_type = VAL32; break;
+      case 8: operand_type = VAL64; break;
+      default: abort ();
+      }
+
   switch (operand_type)
     {
     case VAL8:
@@ -420,7 +431,7 @@ do {                                                \
 
        case DW_OP_abs:
          tmp1 = pop ();
-         if (tmp1 & ((unw_word_t) 1 << (8 * sizeof (unw_word_t) - 1)))
+         if (tmp1 & ((unw_word_t) 1 << (8 * dwarf_addr_size (as) - 1)))
            tmp1 = -tmp1;
          push (tmp1);
          break;
@@ -435,7 +446,7 @@ do {                                                \
          tmp1 = pop ();
          tmp2 = pop ();
          if (tmp1)
-           tmp1 = sword (tmp2) / sword (tmp1);
+           tmp1 = sword (as, tmp2) / sword (as, tmp1);
          push (tmp1);
          break;
 
@@ -502,7 +513,7 @@ do {                                                \
        case DW_OP_shra:
          tmp1 = pop ();
          tmp2 = pop ();
-         push (sword (tmp2) >> tmp1);
+         push (sword (as, tmp2) >> tmp1);
          break;
 
        case DW_OP_xor:
@@ -514,37 +525,37 @@ do {                                              \
        case DW_OP_le:
          tmp1 = pop ();
          tmp2 = pop ();
-         push (sword (tmp1) <= sword (tmp2));
+         push (sword (as, tmp1) <= sword (as, tmp2));
          break;
 
        case DW_OP_ge:
          tmp1 = pop ();
          tmp2 = pop ();
-         push (sword (tmp1) >= sword (tmp2));
+         push (sword (as, tmp1) >= sword (as, tmp2));
          break;
 
        case DW_OP_eq:
          tmp1 = pop ();
          tmp2 = pop ();
-         push (sword (tmp1) == sword (tmp2));
+         push (sword (as, tmp1) == sword (as, tmp2));
          break;
 
        case DW_OP_lt:
          tmp1 = pop ();
          tmp2 = pop ();
-         push (sword (tmp1) < sword (tmp2));
+         push (sword (as, tmp1) < sword (as, tmp2));
          break;
 
        case DW_OP_gt:
          tmp1 = pop ();
          tmp2 = pop ();
-         push (sword (tmp1) > sword (tmp2));
+         push (sword (as, tmp1) > sword (as, tmp2));
          break;
 
        case DW_OP_ne:
          tmp1 = pop ();
          tmp2 = pop ();
-         push (sword (tmp1) != sword (tmp2));
+         push (sword (as, tmp1) != sword (as, tmp2));
          break;
 
        case DW_OP_skip:
--- libunwind-0.98.5/src/dwarf/Gfde.c   (revision 186298)
+++ libunwind-0.98.5/src/dwarf/Gfde.c   (revision 189947)
@@ -36,7 +36,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
 static inline int
 parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
           unw_proc_info_t *pi, unw_dyn_dwarf_fde_info_t *dfi,
-          int *lsda_encodingp, void *arg)
+          int *lsda_encodingp, unw_word_t base, void *arg)
 {
   uint8_t version, ch, augstr[5], fde_encoding, handler_encoding;
   unw_word_t len, cie_end_addr, aug_size, handler = 0;
@@ -52,7 +52,7 @@ parse_cie (unw_addr_space_t as, unw_acce
      "address-unit sized constants".  The `R' augmentation can be used
      to override this, but by default, we pick an address-sized unit
      for fde_encoding.  */
-  switch (sizeof (unw_word_t))
+  switch (dwarf_addr_size (as))
     {
     case 4:    fde_encoding = DW_EH_PE_udata4; break;
     case 8:    fde_encoding = DW_EH_PE_udata8; break;
@@ -69,13 +69,14 @@ parse_cie (unw_addr_space_t as, unw_acce
     {
       /* the CIE is in the 32-bit DWARF format */
       uint32_t cie_id;
+      /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
+      const uint32_t expected_id = (base) ? 0xffffffff : 0;
 
       len = u32val;
       cie_end_addr = *addr + len;
       if ((ret = dwarf_readu32 (as, a, addr, &cie_id, arg)) < 0)
        return ret;
-      /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
-      if (cie_id != 0)
+      if (cie_id != expected_id)
        {
          Debug (1, "Unexpected CIE id %x\n", cie_id);
          return -UNW_EINVAL;
@@ -85,6 +86,9 @@ parse_cie (unw_addr_space_t as, unw_acce
     {
       /* the CIE is in the 64-bit DWARF format */
       uint64_t cie_id;
+      /* DWARF says CIE id should be 0xffffffffffffffff, but in
+        .eh_frame, it's 0 */
+      const uint64_t expected_id = (base) ? 0xffffffffffffffffull : 0;
 
       if ((ret = dwarf_readu64 (as, a, addr, &u64val, arg)) < 0)
        return ret;
@@ -92,9 +96,7 @@ parse_cie (unw_addr_space_t as, unw_acce
       cie_end_addr = *addr + len;
       if ((ret = dwarf_readu64 (as, a, addr, &cie_id, arg)) < 0)
        return ret;
-      /* DWARF says CIE id should be 0xffffffffffffffff, but in
-        .eh_frame, it's 0 */
-      if (cie_id != 0)
+      if (cie_id != expected_id)
        {
          Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id);
          return -UNW_EINVAL;
@@ -141,15 +143,17 @@ parse_cie (unw_addr_space_t as, unw_acce
           < 0)
     return ret;
 
+  i = 0;
   if (augstr[0] == 'z')
     {
       dfi->flags |= UNW_DYN_DFI_FLAG_AUGMENTATION_HAS_SIZE;
       if ((ret = dwarf_read_uleb128 (as, a, addr, &aug_size, arg))
          < 0)
        return ret;
+      i++;
     }
 
-  for (i = 1; i < sizeof (augstr) && augstr[i]; ++i)
+  for (; i < sizeof (augstr) && augstr[i]; ++i)
     switch (augstr[i])
       {
       case 'L':
@@ -193,9 +197,13 @@ parse_cie (unw_addr_space_t as, unw_acce
   return 0;
 }
 
+/* Pass BASE as zero for eh_frame behaviour, or a pointer to debug_frame
+   base.  */
+
 HIDDEN int
 dwarf_parse_fde (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
-                unw_proc_info_t *pi, unw_dyn_dwarf_fde_info_t *dfi, void *arg)
+                unw_proc_info_t *pi, unw_dyn_dwarf_fde_info_t *dfi,
+                unw_word_t base, void *arg)
 {
   unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0;
   int ret, fde_encoding, ip_range_encoding, lsda_encoding;
@@ -222,11 +230,14 @@ dwarf_parse_fde (unw_addr_space_t as, un
       if ((ret = dwarf_reads32 (as, a, addr, &cie_offset, arg)) < 0)
        return ret;
 
-      /* DWARF says that the CIE_pointer in the FDE is a
-        .debug_frame-relative offset, but the GCC-generated .eh_frame
-        sections instead store a "pcrelative" offset, which is just
-        as fine as it's self-contained.  */
-      cie_addr = cie_offset_addr - cie_offset;
+      if (base != 0)
+        cie_addr = base + cie_offset;
+      else
+       /* DWARF says that the CIE_pointer in the FDE is a
+          .debug_frame-relative offset, but the GCC-generated .eh_frame
+          sections instead store a "pcrelative" offset, which is just
+          as fine as it's self-contained.  */
+       cie_addr = cie_offset_addr - cie_offset;
     }
   else
     {
@@ -243,16 +254,21 @@ dwarf_parse_fde (unw_addr_space_t as, un
       if ((ret = dwarf_reads64 (as, a, addr, &cie_offset, arg)) < 0)
        return ret;
 
-      /* DWARF says that the CIE_pointer in the FDE is a
-        .debug_frame-relative offset, but the GCC-generated .eh_frame
-        sections instead store a "pcrelative" offset, which is just
-        as fine as it's self-contained.  */
-      cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
+      if (base != 0)
+        cie_addr = (uint64_t) base + cie_offset;
+      else
+       /* DWARF says that the CIE_pointer in the FDE is a
+          .debug_frame-relative offset, but the GCC-generated .eh_frame
+          sections instead store a "pcrelative" offset, which is just
+          as fine as it's self-contained.  */
+       cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
     }
   pi->extra.dwarf_info.fde_instr_end = fde_end_addr;
 
+  Debug (15, "looking for CIE at address %x\n", (int) cie_addr);
+
   if ((ret = parse_cie (as, a, &cie_addr, pi, &pi->extra.dwarf_info,
-                       &lsda_encoding, arg)) < 0)
+                       &lsda_encoding, base, arg)) < 0)
     return ret;
 
   fde_encoding = pi->extra.dwarf_info.flags & UNW_DYN_DFI_FLAG_FDE_PE_MASK;
@@ -288,7 +304,8 @@ dwarf_parse_fde (unw_addr_space_t as, un
   /* Always set the unwind info, whether or not need_unwind_info is
      set.  We had to do all the work anyhow, so there is no point in
      not doing so.  */
-  pi->format = UNW_INFO_FORMAT_DWARF_FDE;
+  pi->format = (base) ? UNW_INFO_FORMAT_DEBUG_FRAME_FDE
+                     : UNW_INFO_FORMAT_DWARF_FDE;
   pi->unwind_info_size = sizeof (pi->extra.dwarf_info) / sizeof (unw_word_t);
   pi->unwind_info = &pi->extra.dwarf_info;
 
--- libunwind-0.98.5/src/dwarf/Gpe.c    (revision 186298)
+++ libunwind-0.98.5/src/dwarf/Gpe.c    (revision 189947)
@@ -26,6 +26,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
 #include "dwarf_i.h"
 #include "tdep.h"
 
+#include <assert.h>
+
 HIDDEN int
 dwarf_read_encoded_pointer (unw_addr_space_t as, unw_accessors_t *a,
                            unw_word_t *addr, unsigned char encoding,
@@ -50,7 +52,8 @@ dwarf_read_encoded_pointer (unw_addr_spa
     }
   else if (encoding == DW_EH_PE_aligned)
     {
-      *addr = (initial_addr + sizeof (unw_word_t) - 1) & -sizeof (unw_word_t);
+      int size = dwarf_addr_size (as);
+      *addr = (initial_addr + size - 1) & -size;
       return dwarf_readw (as, a, addr, valp, arg);
     }
 
@@ -149,6 +152,15 @@ dwarf_read_encoded_pointer (unw_addr_spa
       return -UNW_EINVAL;
     }
 
+  /* Trim off any extra bits.  Assume that sign extension isn't
+     required; the only place it is needed is MIPS kernel space
+     addresses.  */
+  if (sizeof (val) > dwarf_addr_size (as))
+    {
+      assert (dwarf_addr_size (as) == 4);
+      val = (uint32_t) val;
+    }
+
   if (encoding & DW_EH_PE_indirect)
     {
       unw_word_t indirect_addr = val;
--- libunwind-0.98.5/src/unwind/RaiseException.c        (revision 186298)
+++ libunwind-0.98.5/src/unwind/RaiseException.c        (revision 189947)
@@ -60,7 +60,7 @@ _Unwind_RaiseException (struct _Unwind_E
       if (unw_get_proc_info (&context.cursor, &pi) < 0)
        return _URC_FATAL_PHASE1_ERROR;
 
-      personality = (_Unwind_Personality_Fn) pi.handler;
+      personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler;
       if (personality)
        {
          reason = (*personality) (_U_VERSION, _UA_SEARCH_PHASE,
--- libunwind-0.98.5/src/unwind/unwind-internal.h       (revision 186298)
+++ libunwind-0.98.5/src/unwind/unwind-internal.h       (revision 189947)
@@ -104,7 +104,7 @@ _Unwind_Phase2 (struct _Unwind_Exception
          || unw_get_proc_info (&context->cursor, &pi) < 0)
        return _URC_FATAL_PHASE2_ERROR;
 
-      personality = (_Unwind_Personality_Fn) pi.handler;
+      personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler;
       if (personality)
        {
          if (!stop)
--- libunwind-0.98.5/src/unwind/FindEnclosingFunction.c (revision 186298)
+++ libunwind-0.98.5/src/unwind/FindEnclosingFunction.c (revision 189947)
@@ -30,11 +30,12 @@ _Unwind_FindEnclosingFunction (void *ip)
 {
   unw_proc_info_t pi;
 
-  if (unw_get_proc_info_by_ip (unw_local_addr_space, (unw_word_t) ip, &pi, 0)
+  if (unw_get_proc_info_by_ip (unw_local_addr_space,
+                              (unw_word_t) (uintptr_t) ip, &pi, 0)
       < 0)
     return NULL;
 
-  return (void *) pi.start_ip;
+  return (void *) (uintptr_t) pi.start_ip;
 }
 
 void *__libunwind_Unwind_FindEnclosingFunction (void *)
--- libunwind-0.98.5/src/mi/backtrace.c (revision 186298)
+++ libunwind-0.98.5/src/mi/backtrace.c (revision 189947)
@@ -49,7 +49,7 @@ backtrace (void **buffer, int size)
 
       if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0)
        return n;
-      buffer[n++] = (void *) ip;
+      buffer[n++] = (void *) (uintptr_t) ip;
     }
   return n;
 }
--- libunwind-0.98.5/src/mi/dyn-info-list.c     (revision 186298)
+++ libunwind-0.98.5/src/mi/dyn-info-list.c     (revision 189947)
@@ -30,5 +30,5 @@ HIDDEN unw_dyn_info_list_t _U_dyn_info_l
 PROTECTED unw_word_t
 _U_dyn_info_list_addr (void)
 {
-  return (unw_word_t) &_U_dyn_info_list;
+  return (unw_word_t) (uintptr_t) &_U_dyn_info_list;
 }
--- libunwind-0.98.5/src/mi/flush_cache.c       (revision 186298)
+++ libunwind-0.98.5/src/mi/flush_cache.c       (revision 189947)
@@ -29,9 +29,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
 PROTECTED void
 unw_flush_cache (unw_addr_space_t as, unw_word_t lo, unw_word_t hi)
 {
+  struct unw_debug_frame_list *w = as->debug_frames;
+  
   /* clear dyn_info_list_addr cache: */
   as->dyn_info_list_addr = 0;
 
+  for (; w; w = w->next)
+    {
+      if (w->index)
+        free (w->index);
+      free (w->debug_frame);
+    }
+
+  as->debug_frames = NULL;
+
   /* This lets us flush caches lazily.  The implementation currently
      ignores the flush range arguments (lo-hi).  This is OK because
      unw_flush_cache() is allowed to flush more than the requested
--- libunwind-0.98.5/src/mi/Gfind_dynamic_proc_info.c   (revision 186298)
+++ libunwind-0.98.5/src/mi/Gfind_dynamic_proc_info.c   (revision 189947)
@@ -52,7 +52,7 @@ local_find_proc_info (unw_addr_space_t a
     return -UNW_ENOINFO;
 #endif
 
-  list = (unw_dyn_info_list_t *) _U_dyn_info_list_addr ();
+  list = (unw_dyn_info_list_t *) (uintptr_t) _U_dyn_info_list_addr ();
   for (di = list->first; di; di = di->next)
     if (ip >= di->start_ip && ip < di->end_ip)
       return unwi_extract_dynamic_proc_info (as, ip, pi, di, need_unwind_info,
--- libunwind-0.98.5/src/mips/Lis_signal_frame.c        (revision 0)
+++ libunwind-0.98.5/src/mips/Lis_signal_frame.c        (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gis_signal_frame.c"
+#endif
--- libunwind-0.98.5/src/mips/is_fpreg.c        (revision 0)
+++ libunwind-0.98.5/src/mips/is_fpreg.c        (revision 189947)
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
+       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 "tdep.h"
+
+/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful
+   on MIPS.  */
+
+PROTECTED int
+unw_is_fpreg (int regnum)
+{
+  /* FIXME: Support FP.  */
+  return 0;
+}
--- libunwind-0.98.5/src/mips/Gget_save_loc.c   (revision 0)
+++ libunwind-0.98.5/src/mips/Gget_save_loc.c   (revision 189947)
@@ -0,0 +1,100 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2004 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 "unwind_i.h"
+
+/* FIXME for MIPS.  */
+
+PROTECTED int
+unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  dwarf_loc_t loc;
+
+  loc = DWARF_NULL_LOC;                /* default to "not saved" */
+
+  switch (reg)
+    {
+    case UNW_MIPS_R0:
+    case UNW_MIPS_R1:
+    case UNW_MIPS_R2:
+    case UNW_MIPS_R3:
+    case UNW_MIPS_R4:
+    case UNW_MIPS_R5:
+    case UNW_MIPS_R6:
+    case UNW_MIPS_R7:
+    case UNW_MIPS_R8:
+    case UNW_MIPS_R9:
+    case UNW_MIPS_R10:
+    case UNW_MIPS_R11:
+    case UNW_MIPS_R12:
+    case UNW_MIPS_R13:
+    case UNW_MIPS_R14:
+    case UNW_MIPS_R15:
+    case UNW_MIPS_R16:
+    case UNW_MIPS_R17:
+    case UNW_MIPS_R18:
+    case UNW_MIPS_R19:
+    case UNW_MIPS_R20:
+    case UNW_MIPS_R21:
+    case UNW_MIPS_R22:
+    case UNW_MIPS_R23:
+    case UNW_MIPS_R24:
+    case UNW_MIPS_R25:
+    case UNW_MIPS_R26:
+    case UNW_MIPS_R27:
+    case UNW_MIPS_R28:
+    case UNW_MIPS_R29:
+    case UNW_MIPS_R30:
+    case UNW_MIPS_R31:
+      loc = c->dwarf.loc[reg - UNW_MIPS_R0];
+      break;
+
+    default:
+      break;
+    }
+
+  memset (sloc, 0, sizeof (sloc));
+
+  if (DWARF_IS_NULL_LOC (loc))
+    {
+      sloc->type = UNW_SLT_NONE;
+      return 0;
+    }
+
+#if !defined(UNW_LOCAL_ONLY)
+  if (DWARF_IS_REG_LOC (loc))
+    {
+      sloc->type = UNW_SLT_REG;
+      sloc->u.regnum = DWARF_GET_LOC (loc);
+    }
+  else
+#endif
+    {
+      sloc->type = UNW_SLT_MEMORY;
+      sloc->u.addr = DWARF_GET_LOC (loc);
+    }
+  return 0;
+}
--- libunwind-0.98.5/src/mips/getcontext.S      (revision 0)
+++ libunwind-0.98.5/src/mips/getcontext.S      (revision 189947)
@@ -0,0 +1,61 @@
+#include "offsets.h"
+#include <endian.h>
+
+       .text
+
+#if _MIPS_SIM == _ABIO32
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define OFFSET 4
+# else
+#  define OFFSET 0
+# endif
+# define SREG(X) \
+ sw $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X + OFFSET) ($4); \
+ sra $1, $X, 31; \
+ sw $1, (LINUX_UC_MCONTEXT_GREGS + 8 * X + 4 - OFFSET) ($4)
+#else
+# define SREG(X) sd $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ($4)
+#endif
+
+       .global _Umips_getcontext
+       .type   _Umips_getcontext, %function
+       # This is a stub version of getcontext() for MIPS which only stores core
+       # registers.
+_Umips_getcontext:
+       .set noat
+       SREG (1)
+       SREG (0)
+       SREG (2)
+       SREG (3)
+       SREG (4)
+       SREG (5)
+       SREG (6)
+       SREG (7)
+       SREG (8)
+       SREG (9)
+       SREG (10)
+       SREG (11)
+       SREG (12)
+       SREG (13)
+       SREG (14)
+       SREG (15)
+       SREG (16)
+       SREG (17)
+       SREG (18)
+       SREG (19)
+       SREG (20)
+       SREG (21)
+       SREG (22)
+       SREG (23)
+       SREG (24)
+       SREG (25)
+       SREG (26)
+       SREG (27)
+       SREG (28)
+       SREG (29)
+       SREG (30)
+       SREG (31)
+       li      $2, 0
+       j $31
+
+       .size   _Umips_getcontext, .-_Umips_getcontext
--- libunwind-0.98.5/src/mips/Lget_save_loc.c   (revision 0)
+++ libunwind-0.98.5/src/mips/Lget_save_loc.c   (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_save_loc.c"
+#endif
--- libunwind-0.98.5/src/mips/Gresume.c (revision 0)
+++ libunwind-0.98.5/src/mips/Gresume.c (revision 189947)
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
+       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.  */
+
+/* FIXME for MIPS.  */
+
+#include <stdlib.h>
+
+#include "unwind_i.h"
+
+#ifndef UNW_REMOTE_ONLY
+
+HIDDEN inline int
+mips_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
+{
+  return -UNW_EINVAL;
+}
+
+#endif /* !UNW_REMOTE_ONLY */
+
+PROTECTED int
+unw_resume (unw_cursor_t *cursor)
+{
+  return -UNW_EINVAL;
+}
--- libunwind-0.98.5/src/mips/Gregs.c   (revision 0)
+++ libunwind-0.98.5/src/mips/Gregs.c   (revision 189947)
@@ -0,0 +1,100 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
+       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 "unwind_i.h"
+
+/* FIXME: The following is probably unfinished and/or at least partly bogus.  
*/
+
+HIDDEN int
+tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
+                int write)
+{
+  dwarf_loc_t loc = DWARF_NULL_LOC;
+  
+  switch (reg)
+    {
+    case UNW_MIPS_R0:
+    case UNW_MIPS_R1:
+    case UNW_MIPS_R2:
+    case UNW_MIPS_R3:
+    case UNW_MIPS_R4:
+    case UNW_MIPS_R5:
+    case UNW_MIPS_R6:
+    case UNW_MIPS_R7:
+    case UNW_MIPS_R8:
+    case UNW_MIPS_R9:
+    case UNW_MIPS_R10:
+    case UNW_MIPS_R11:
+    case UNW_MIPS_R12:
+    case UNW_MIPS_R13:
+    case UNW_MIPS_R14:
+    case UNW_MIPS_R15:
+    case UNW_MIPS_R16:
+    case UNW_MIPS_R17:
+    case UNW_MIPS_R18:
+    case UNW_MIPS_R19:
+    case UNW_MIPS_R20:
+    case UNW_MIPS_R21:
+    case UNW_MIPS_R22:
+    case UNW_MIPS_R23:
+    case UNW_MIPS_R24:
+    case UNW_MIPS_R25:
+    case UNW_MIPS_R26:
+    case UNW_MIPS_R27:
+    case UNW_MIPS_R28:
+    case UNW_MIPS_R29:
+    case UNW_MIPS_R30:
+    case UNW_MIPS_R31:
+      loc = c->dwarf.loc[reg - UNW_MIPS_R0];
+      break;
+
+    case UNW_MIPS_CFA:
+      if (write)
+        return -UNW_EREADONLYREG;
+      *valp = c->dwarf.cfa;
+      return 0;
+
+    /* FIXME: IP?  Copro & shadow registers?  */
+
+    default:
+      Debug (1, "bad register number %u\n", reg);
+      return -UNW_EBADREG;
+    }
+
+  if (write)
+    return dwarf_put (&c->dwarf, loc, *valp);
+  else
+    return dwarf_get (&c->dwarf, loc, valp);
+}
+
+/* FIXME for MIPS.  */
+
+HIDDEN int
+tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
+                  int write)
+{
+  Debug (1, "bad register number %u\n", reg);
+  return -UNW_EBADREG;
+}
--- libunwind-0.98.5/src/mips/Gglobal.c (revision 0)
+++ libunwind-0.98.5/src/mips/Gglobal.c (revision 189947)
@@ -0,0 +1,67 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+       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 "unwind_i.h"
+#include "dwarf_i.h"
+
+HIDDEN pthread_mutex_t mips_lock = PTHREAD_MUTEX_INITIALIZER;
+HIDDEN int tdep_needs_initialization = 1;
+
+/* FIXME: I'm pretty sure we don't need this at all for MIPS, but "generic"
+   code (include/dwarf_i.h) seems to expect it to be here at present.  */
+
+HIDDEN uint8_t dwarf_to_unw_regnum_map[] =
+  {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+  };
+
+HIDDEN void
+tdep_init (void)
+{
+  sigset_t saved_sigmask;
+
+  sigfillset (&unwi_full_sigmask);
+
+  sigprocmask (SIG_SETMASK, &unwi_full_sigmask, &saved_sigmask);
+  mutex_lock (&mips_lock);
+  {
+    if (!tdep_needs_initialization)
+      /* another thread else beat us to it... */
+      goto out;
+
+    mi_init ();
+
+    dwarf_init ();
+
+#ifndef UNW_REMOTE_ONLY
+    mips_local_addr_space_init ();
+#endif
+    tdep_needs_initialization = 0;     /* signal that we're initialized... */
+  }
+ out:
+  mutex_unlock (&mips_lock);
+  sigprocmask (SIG_SETMASK, &saved_sigmask, NULL);
+}
--- libunwind-0.98.5/src/mips/init.h    (revision 0)
+++ libunwind-0.98.5/src/mips/init.h    (revision 189947)
@@ -0,0 +1,50 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002 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 "unwind_i.h"
+
+static inline int
+common_init (struct cursor *c)
+{
+  int ret, i;
+
+  for (i = 0; i < 32; i++)
+    c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_MIPS_R0 + i);
+  for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i)
+    c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+  ret = dwarf_get (&c->dwarf, c->dwarf.loc[31], &c->dwarf.ip);
+  if (ret < 0)
+    return ret;
+
+  ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_MIPS_R29),
+                  &c->dwarf.cfa);
+  if (ret < 0)
+    return ret;
+
+  /* FIXME: Initialisation for other registers.  */
+
+  return 0;
+}
--- libunwind-0.98.5/src/mips/Ginit.c   (revision 0)
+++ libunwind-0.98.5/src/mips/Ginit.c   (revision 189947)
@@ -0,0 +1,209 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002 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 <stdlib.h>
+#include <string.h>
+
+#include "unwind_i.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+/* unw_local_addr_space is a NULL pointer in this case.  */
+PROTECTED unw_addr_space_t unw_local_addr_space;
+
+#else /* !UNW_REMOTE_ONLY */
+
+static struct unw_addr_space local_addr_space;
+
+PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space;
+
+/* Return the address of the 64-bit slot in UC for REG (even for o32,
+   where registers are 32-bit, the slots are still 64-bit).  */
+
+static inline void *
+uc_addr (ucontext_t *uc, int reg)
+{
+  if (reg >= UNW_MIPS_R0 && reg < UNW_MIPS_R0 + 32)
+    return &uc->uc_mcontext.gregs[reg - UNW_MIPS_R0];
+  else
+    return NULL;
+}
+
+# ifdef UNW_LOCAL_ONLY
+
+HIDDEN void *
+tdep_uc_addr (ucontext_t *uc, int reg)
+{
+  char *addr = uc_addr (uc, reg);
+
+  if (reg >= UNW_MIPS_R0 && reg <= UNW_MIPS_R31
+      && tdep_big_endian (unw_local_addr_space)
+      && unw_local_addr_space->abi == UNW_MIPS_ABI_O32)
+    addr += 4;
+
+  return addr;
+}
+
+# endif /* UNW_LOCAL_ONLY */
+
+HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
+
+/* XXX fix me: there is currently no way to locate the dyn-info list
+       by a remote unwinder.  On ia64, this is done via a special
+       unwind-table entry.  Perhaps something similar can be done with
+       DWARF2 unwind info.  */
+
+static void
+put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
+{
+  /* it's a no-op */
+}
+
+static int
+get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
+                       void *arg)
+{
+  *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list;
+  return 0;
+}
+
+static int
+access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
+           void *arg)
+{
+  if (write)
+    {
+      Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val);
+      *(unw_word_t *) (intptr_t) addr = *val;
+    }
+  else
+    {
+      *val = *(unw_word_t *) (intptr_t) addr;
+      Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val);
+    }
+  return 0;
+}
+
+static int
+access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
+           void *arg)
+{
+  unw_word_t *addr;
+  ucontext_t *uc = arg;
+
+  if (unw_is_fpreg (reg))
+    goto badreg;
+
+  Debug (16, "reg = %s\n", unw_regname (reg));
+  if (!(addr = uc_addr (uc, reg)))
+    goto badreg;
+
+  if (write)
+    {
+      *(unw_word_t *) (intptr_t) addr = (mips_reg_t) *val;
+      Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val);
+    }
+  else
+    {
+      *val = (mips_reg_t) *(unw_word_t *) (intptr_t) addr;
+      Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val);
+    }
+  return 0;
+
+ badreg:
+  Debug (1, "bad register number %u\n", reg);
+  return -UNW_EBADREG;
+}
+
+static int
+access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
+             int write, void *arg)
+{
+  ucontext_t *uc = arg;
+  unw_fpreg_t *addr;
+
+  if (!unw_is_fpreg (reg))
+    goto badreg;
+
+  if (!(addr = uc_addr (uc, reg)))
+    goto badreg;
+
+  if (write)
+    {
+      Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
+            ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+      *(unw_fpreg_t *) (intptr_t) addr = *val;
+    }
+  else
+    {
+      *val = *(unw_fpreg_t *) (intptr_t) addr;
+      Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
+            ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
+    }
+  return 0;
+
+ badreg:
+  Debug (1, "bad register number %u\n", reg);
+  /* attempt to access a non-preserved register */
+  return -UNW_EBADREG;
+}
+
+static int
+get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
+                     char *buf, size_t buf_len, unw_word_t *offp,
+                     void *arg)
+{
+
+  return elf_w (get_proc_name) (getpid (), ip, buf, buf_len, offp);
+}
+
+HIDDEN void
+mips_local_addr_space_init (void)
+{
+  memset (&local_addr_space, 0, sizeof (local_addr_space));
+  local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+#if _MIPS_SIM == _ABIO32
+  local_addr_space.abi = UNW_MIPS_ABI_O32;
+#elif _MIPS_SIM == _ABIN32
+  local_addr_space.abi = UNW_MIPS_ABI_N32;
+#elif _MIPS_SIM == _ABI64
+  local_addr_space.abi = UNW_MIPS_ABI_N64;
+#else
+# error Unsupported ABI
+#endif
+  local_addr_space.addr_size = sizeof (void *);
+  local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+  local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
+  local_addr_space.acc.put_unwind_info = put_unwind_info;
+  local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
+  local_addr_space.acc.access_mem = access_mem;
+  local_addr_space.acc.access_reg = access_reg;
+  local_addr_space.acc.access_fpreg = access_fpreg;
+  local_addr_space.acc.resume = 0;  /* mips_local_resume?  FIXME!  */
+  local_addr_space.acc.get_proc_name = get_static_proc_name;
+  unw_flush_cache (&local_addr_space, 0, 0);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
--- libunwind-0.98.5/src/mips/Lglobal.c (revision 0)
+++ libunwind-0.98.5/src/mips/Lglobal.c (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gglobal.c"
+#endif
--- libunwind-0.98.5/src/mips/Lregs.c   (revision 0)
+++ libunwind-0.98.5/src/mips/Lregs.c   (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gregs.c"
+#endif
--- libunwind-0.98.5/src/mips/Lresume.c (revision 0)
+++ libunwind-0.98.5/src/mips/Lresume.c (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gresume.c"
+#endif
--- libunwind-0.98.5/src/mips/offsets.h (revision 0)
+++ libunwind-0.98.5/src/mips/offsets.h (revision 189947)
@@ -0,0 +1,39 @@
+/* Linux-specific definitions: */
+
+/* Define various structure offsets to simplify cross-compilation.  */
+
+/* FIXME: Currently these are only used in getcontext.S, which is only used
+   for a local unwinder, so we can use the compile-time ABI.  At a later date
+   we will want all three here, to use for signal handlers.  Also, because
+   of the three ABIs, gen-offsets.c can not quite generate this file.  */
+
+/* Offsets for MIPS Linux "ucontext_t":  */
+
+#if _MIPS_SIM == _ABIO32
+
+# define LINUX_UC_FLAGS_OFF    0x0
+# define LINUX_UC_LINK_OFF     0x4
+# define LINUX_UC_STACK_OFF    0x8
+# define LINUX_UC_MCONTEXT_OFF 0x18
+# define LINUX_UC_SIGMASK_OFF  0x268
+# define LINUX_UC_MCONTEXT_GREGS       0x28
+
+#elif _MIPS_SIM == _ABIN32
+
+# define LINUX_UC_FLAGS_OFF    0x0
+# define LINUX_UC_LINK_OFF     0x4
+# define LINUX_UC_STACK_OFF    0x8
+# define LINUX_UC_MCONTEXT_OFF 0x18
+# define LINUX_UC_SIGMASK_OFF  0x270
+# define LINUX_UC_MCONTEXT_GREGS       0x18
+
+#elif _MIPS_SIM == _ABI64
+
+# define LINUX_UC_FLAGS_OFF    0x0
+# define LINUX_UC_LINK_OFF     0x8
+# define LINUX_UC_STACK_OFF    0x10
+# define LINUX_UC_MCONTEXT_OFF 0x28
+# define LINUX_UC_SIGMASK_OFF  0x280
+# define LINUX_UC_MCONTEXT_GREGS       0x28
+
+#endif
--- libunwind-0.98.5/src/mips/regname.c (revision 0)
+++ libunwind-0.98.5/src/mips/regname.c (revision 189947)
@@ -0,0 +1,22 @@
+#include "unwind_i.h"
+
+static const char *regname[] =
+  {
+    /* 0.  */
+    "$0",  "$1",  "$2",  "$3",  "$4",  "$5",  "$6",  "$7",
+    /* 8.  */
+    "$8",  "$9",  "$10", "$11",  "$12",  "$13",  "$14",  "$15",
+    /* 16.  */
+    "$16",  "$17",  "$18", "$19",  "$20",  "$21",  "$22",  "$23",
+    /* 24.  */
+    "$24",  "$25",  "$26", "$27",  "$28",  "$29",  "$30",  "$31",
+  };
+
+PROTECTED const char *
+unw_regname (unw_regnum_t reg)
+{
+  if (reg < (unw_regnum_t) NELEMS (regname))
+    return regname[reg];
+  else
+    return "???";
+}
--- libunwind-0.98.5/src/mips/Linit.c   (revision 0)
+++ libunwind-0.98.5/src/mips/Linit.c   (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit.c"
+#endif
--- libunwind-0.98.5/src/mips/Gcreate_addr_space.c      (revision 0)
+++ libunwind-0.98.5/src/mips/Gcreate_addr_space.c      (revision 189947)
@@ -0,0 +1,66 @@
+/* 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 <stdlib.h>
+
+#include "unwind_i.h"
+
+PROTECTED unw_addr_space_t
+unw_create_addr_space (unw_accessors_t *a, int byte_order)
+{
+#ifdef UNW_LOCAL_ONLY
+  return NULL;
+#else
+  unw_addr_space_t as = malloc (sizeof (*as));
+
+  if (!as)
+    return NULL;
+
+  memset (as, 0, sizeof (*as));
+
+  as->acc = *a;
+
+  /*
+   * MIPS supports only big or little-endian, not weird stuff like
+   * PDP_ENDIAN.
+   */
+  if (byte_order != 0
+      && byte_order != __LITTLE_ENDIAN
+      && byte_order != __BIG_ENDIAN)
+    return NULL;
+
+  if (byte_order == 0)
+    /* use host default: */
+    as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
+  else
+    as->big_endian = (byte_order == __BIG_ENDIAN);
+
+  /* FIXME!  There is no way to specify the ABI.  */
+  as->abi = UNW_MIPS_ABI_O32;
+  as->addr_size = 4;
+
+  return as;
+#endif
+}
--- libunwind-0.98.5/src/mips/gen-offsets.c     (revision 0)
+++ libunwind-0.98.5/src/mips/gen-offsets.c     (revision 189947)
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <ucontext.h>
+
+#define UC(N,X) \
+  printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X))
+
+#define SC(N,X) \
+  printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, 
X))
+
+int
+main (void)
+{
+  printf (
+"/* Linux-specific definitions: */\n\n"
+
+"/* Define various structure offsets to simplify cross-compilation.  */\n\n"
+
+"/* Offsets for MIPS Linux \"ucontext_t\":  */\n\n");
+
+  UC ("FLAGS", uc_flags);
+  UC ("LINK", uc_link);
+  UC ("STACK", uc_stack);
+  UC ("MCONTEXT", uc_mcontext);
+  UC ("SIGMASK", uc_sigmask);
+
+  UC ("MCONTEXT_GREGS", uc_mcontext.gregs);
+
+  return 0;
+}
--- libunwind-0.98.5/src/mips/unwind_i.h        (revision 0)
+++ libunwind-0.98.5/src/mips/unwind_i.h        (revision 189947)
@@ -0,0 +1,50 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002 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.  */
+
+#ifndef unwind_i_h
+#define unwind_i_h
+
+#include <memory.h>
+#include <stdint.h>
+
+#include <libunwind-mips.h>
+
+#include "internal.h"
+#include "tdep.h"
+
+/*
+#define x86_lock                       UNW_OBJ(lock)
+#define x86_local_resume               UNW_OBJ(local_resume)
+#define x86_local_addr_space_init      UNW_OBJ(local_addr_space_init)
+#define x86_scratch_loc                        UNW_OBJ(scratch_loc)
+
+extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
+                            void *arg);
+extern dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg);
+*/
+
+extern void mips_local_addr_space_init (void);
+
+#endif /* unwind_i_h */
--- libunwind-0.98.5/src/mips/Gstep.c   (revision 0)
+++ libunwind-0.98.5/src/mips/Gstep.c   (revision 189947)
@@ -0,0 +1,49 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002-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 "unwind_i.h"
+#include "offsets.h"
+
+PROTECTED int
+unw_step (unw_cursor_t *cursor)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  int ret;
+
+  Debug (1, "(cursor=%p)\n", c);
+
+  /* Try DWARF-based unwinding...  this is the only method likely to work for
+     MIPS.  */
+  ret = dwarf_step (&c->dwarf);
+
+  if (unlikely (ret == -UNW_ESTOPUNWIND))
+    return ret;
+
+  /* Dwarf unwinding didn't work, stop.  */
+  if (unlikely (ret < 0))
+    return 0;
+
+  return (c->dwarf.ip == 0) ? 0 : 1;
+}
--- libunwind-0.98.5/src/mips/Lcreate_addr_space.c      (revision 0)
+++ libunwind-0.98.5/src/mips/Lcreate_addr_space.c      (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gcreate_addr_space.c"
+#endif
--- libunwind-0.98.5/src/mips/Ginit_local.c     (revision 0)
+++ libunwind-0.98.5/src/mips/Ginit_local.c     (revision 189947)
@@ -0,0 +1,54 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+       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 "unwind_i.h"
+#include "init.h"
+
+#ifdef UNW_REMOTE_ONLY
+
+PROTECTED int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+  return -UNW_EINVAL;
+}
+
+#else /* !UNW_REMOTE_ONLY */
+
+PROTECTED int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  if (tdep_needs_initialization)
+    tdep_init ();
+
+  Debug (1, "(cursor=%p)\n", c);
+
+  c->dwarf.as = unw_local_addr_space;
+  c->dwarf.as_arg = uc;
+  return common_init (c);
+}
+
+#endif /* !UNW_REMOTE_ONLY */
--- libunwind-0.98.5/src/mips/Gget_proc_info.c  (revision 0)
+++ libunwind-0.98.5/src/mips/Gget_proc_info.c  (revision 189947)
@@ -0,0 +1,44 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+       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 "unwind_i.h"
+
+/* FIXME for MIPS.  */
+
+PROTECTED int
+unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  int ret;
+
+  /* We can only unwind using Dwarf into on MIPS: return failure code
+     if it's not present.  */
+  ret = dwarf_make_proc_info (&c->dwarf);
+  if (ret < 0)
+    return ret;
+
+  *pi = c->dwarf.pi;
+  return 0;
+}
--- libunwind-0.98.5/src/mips/Ginit_remote.c    (revision 0)
+++ libunwind-0.98.5/src/mips/Ginit_remote.c    (revision 189947)
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
+       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 "init.h"
+#include "unwind_i.h"
+
+PROTECTED int
+unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
+{
+#ifdef UNW_LOCAL_ONLY
+  return -UNW_EINVAL;
+#else /* !UNW_LOCAL_ONLY */
+  struct cursor *c = (struct cursor *) cursor;
+
+  if (tdep_needs_initialization)
+    tdep_init ();
+
+  Debug (1, "(cursor=%p)\n", c);
+
+  c->dwarf.as = as;
+  c->dwarf.as_arg = as_arg;
+  return common_init (c);
+#endif /* !UNW_LOCAL_ONLY */
+}
--- libunwind-0.98.5/src/mips/elfxx.c   (revision 0)
+++ libunwind-0.98.5/src/mips/elfxx.c   (revision 189947)
@@ -0,0 +1,27 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002 Hewlett-Packard Co
+
+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 "libunwind.h"
+
+#include "../src/elfxx.c"
--- libunwind-0.98.5/src/mips/Lstep.c   (revision 0)
+++ libunwind-0.98.5/src/mips/Lstep.c   (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gstep.c"
+#endif
--- libunwind-0.98.5/src/mips/Lget_proc_info.c  (revision 0)
+++ libunwind-0.98.5/src/mips/Lget_proc_info.c  (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gget_proc_info.c"
+#endif
--- libunwind-0.98.5/src/mips/Gis_signal_frame.c        (revision 0)
+++ libunwind-0.98.5/src/mips/Gis_signal_frame.c        (revision 189947)
@@ -0,0 +1,36 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2002-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 "unwind_i.h"
+#include <stdio.h>
+
+/* FIXME for MIPS.  */
+
+PROTECTED int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+  printf ("%s: implement me\n", __FUNCTION__);
+  return -UNW_ENOINFO;
+}
--- libunwind-0.98.5/src/mips/Linit_local.c     (revision 0)
+++ libunwind-0.98.5/src/mips/Linit_local.c     (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_local.c"
+#endif
--- libunwind-0.98.5/src/mips/siglongjmp.S      (revision 0)
+++ libunwind-0.98.5/src/mips/siglongjmp.S      (revision 189947)
@@ -0,0 +1,11 @@
+       /* Dummy implementation for now.  Libunwind-based setjmp/longjmp
+          can't work on x86 until we take advantage of DWARF2 unwind info.  */
+
+       /* FIXME for MIPS?  */
+
+       .globl _UI_siglongjmp_cont
+       .globl _UI_longjmp_cont
+
+_UI_siglongjmp_cont:
+_UI_longjmp_cont:
+       j       $31
--- libunwind-0.98.5/src/mips/Linit_remote.c    (revision 0)
+++ libunwind-0.98.5/src/mips/Linit_remote.c    (revision 189947)
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Ginit_remote.c"
+#endif
--- libunwind-0.98.5/src/Makefile.am    (revision 186298)
+++ libunwind-0.98.5/src/Makefile.am    (revision 189947)
@@ -33,10 +33,12 @@ libunwind_setjmp_la_LDFLAGS         = $(COMMON_
                                          -version-info $(SETJMP_SO_VERSION)
 libunwind_setjmp_la_LIBADD             = libunwind-$(arch).la -lc
 libunwind_setjmp_la_SOURCES_common     = longjmp.c siglongjmp.c
+libunwind_setjmp_la_SOURCES_arm                = arm/siglongjmp.S
 libunwind_setjmp_la_SOURCES_ia64       = ia64/setjmp.S  ia64/sigsetjmp.S  \
                                          ia64/longjmp.S ia64/siglongjmp.S
 libunwind_setjmp_la_SOURCES_hppa       = setjmp.c sigsetjmp.c  \
                                          hppa/siglongjmp.S
+libunwind_setjmp_la_SOURCES_mips       = mips/siglongjmp.S
 libunwind_setjmp_la_SOURCES_x86                = setjmp.c sigsetjmp.c 
x86/siglongjmp.S
 libunwind_setjmp_la_SOURCES_x86_64     = setjmp.c sigsetjmp.c \
                                          x86_64/siglongjmp.S
@@ -59,8 +61,17 @@ libunwind_la_SOURCES_generic =                               
                \
        mi/Gget_fpreg.c mi/Gset_fpreg.c                                 \
        mi/Gset_caching_policy.c
 
+libunwind_la_SOURCES_local_unwind =                                    \
+       unwind/Backtrace.c unwind/DeleteException.c                     \
+       unwind/FindEnclosingFunction.c unwind/ForcedUnwind.c            \
+       unwind/GetBSP.c unwind/GetCFA.c unwind/GetDataRelBase.c         \
+       unwind/GetGR.c unwind/GetIP.c unwind/GetLanguageSpecificData.c  \
+       unwind/GetRegionStart.c unwind/GetTextRelBase.c                 \
+       unwind/RaiseException.c unwind/Resume.c                         \
+       unwind/Resume_or_Rethrow.c unwind/SetGR.c unwind/SetIP.c
+
 # List of arch-independent files needed by local-only library (libunwind):
-libunwind_la_SOURCES_local =                                           \
+libunwind_la_SOURCES_local_nounwind =                                  \
        $(libunwind_la_SOURCES_os_local)                                \
        mi/backtrace.c                                                  \
        mi/dyn-cancel.c mi/dyn-info-list.c mi/dyn-register.c            \
@@ -70,14 +81,23 @@ libunwind_la_SOURCES_local =                                
                \
        mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c          \
        mi/Lget_reg.c   mi/Lset_reg.c                                   \
        mi/Lget_fpreg.c mi/Lset_fpreg.c                                 \
-       mi/Lset_caching_policy.c                                        \
-       unwind/Backtrace.c unwind/DeleteException.c                     \
-       unwind/FindEnclosingFunction.c unwind/ForcedUnwind.c            \
-       unwind/GetBSP.c unwind/GetCFA.c unwind/GetDataRelBase.c         \
-       unwind/GetGR.c unwind/GetIP.c unwind/GetLanguageSpecificData.c  \
-       unwind/GetRegionStart.c unwind/GetTextRelBase.c                 \
-       unwind/RaiseException.c unwind/Resume.c                         \
-       unwind/Resume_or_Rethrow.c unwind/SetGR.c unwind/SetIP.c
+       mi/Lset_caching_policy.c
+
+# On some platforms, defining _Unwind replacements really upsets
+# exception-handling.  Turn off those functions for those platforms.
+if ARCH_ARM
+libunwind_la_SOURCES_local =                                           \
+       $(libunwind_la_SOURCES_local_nounwind)
+else
+if ARCH_MIPS
+libunwind_la_SOURCES_local =                                           \
+       $(libunwind_la_SOURCES_local_nounwind)
+else
+libunwind_la_SOURCES_local =                                           \
+       $(libunwind_la_SOURCES_local_nounwind)                          \
+       $(libunwind_la_SOURCES_local_unwind)
+endif # ARCH_MIPS
+endif # ARCH_ARM
 
 libunwind_la_SOURCES_os_linux = os-linux.h os-linux.c
 
@@ -95,6 +115,30 @@ dwarf_SOURCES_local =                                       
                     \
 dwarf_SOURCES_generic =                                                        
     \
        dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c dwarf/Gstep.c
 
+# The list of files that go info libunwind and libunwind-arm:
+libunwind_la_SOURCES_arm_common = $(libunwind_la_SOURCES_common)           \
+       $(dwarf_SOURCES_common)                                             \
+       arm/init.h arm/offsets.h arm/regs.h                                 \
+       arm/is_fpreg.c arm/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common)              \
+       $(libunwind_la_SOURCES_local)                                       \
+       elf32.c elf32.h arm/getcontext.S                                    \
+       $(dwarf_SOURCES_local)                                              \
+       dwarf/Lfind_proc_info-lsb.c                                         \
+       arm/Lcreate_addr_space.c arm/Lget_proc_info.c arm/Lget_save_loc.c   \
+       arm/Lglobal.c arm/Linit.c arm/Linit_local.c arm/Linit_remote.c      \
+       arm/Lis_signal_frame.c arm/Lregs.c arm/Lresume.c arm/Lstep.c
+
+libunwind_arm_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common)          \
+       $(libunwind_la_SOURCES_generic)                                     \
+       $(dwarf_SOURCES_generic)                                            \
+       dwarf/Gfind_proc_info-lsb.c                                         \
+       arm/Gcreate_addr_space.c arm/Gget_proc_info.c arm/Gget_save_loc.c   \
+       arm/Gglobal.c arm/Ginit.c arm/Ginit_local.c arm/Ginit_remote.c      \
+       arm/Gis_signal_frame.c arm/Gregs.c arm/Gresume.c arm/Gstep.c
+
 # The list of files that go both into libunwind and libunwind-ia64:
 libunwind_la_SOURCES_ia64_common = $(libunwind_la_SOURCES_common)          \
        ia64/init.h ia64/offsets.h ia64/regs.h                              \
@@ -134,6 +178,30 @@ libunwind_la_SOURCES_hppa = $(libunwind_
        hppa/Lget_reg.c hppa/Lget_proc_name.c hppa/Linit.c hppa/Linit_local.c \
        hppa/Lget_proc_info.c hppa/Lregs.c hppa/Lstep.c
 
+# The list of files that go info libunwind and libunwind-mips:
+libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common)          \
+       $(dwarf_SOURCES_common)                                             \
+       mips/init.h mips/offsets.h mips/regs.h                              \
+       mips/is_fpreg.c mips/regname.c
+
+# The list of files that go into libunwind:
+libunwind_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common)                
    \
+       $(libunwind_la_SOURCES_local)                                       \
+       mips/elfxx.c mips/getcontext.S                                      \
+       $(dwarf_SOURCES_local)                                              \
+       dwarf/Lfind_proc_info-lsb.c                                         \
+       mips/Lcreate_addr_space.c mips/Lget_proc_info.c mips/Lget_save_loc.c   \
+       mips/Lglobal.c mips/Linit.c mips/Linit_local.c mips/Linit_remote.c      
    \
+       mips/Lis_signal_frame.c mips/Lregs.c mips/Lresume.c mips/Lstep.c
+
+libunwind_mips_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common)       \
+       $(libunwind_la_SOURCES_generic)                                     \
+       $(dwarf_SOURCES_generic)                                            \
+       dwarf/Gfind_proc_info-lsb.c                                         \
+       mips/Gcreate_addr_space.c mips/Gget_proc_info.c mips/Gget_save_loc.c   \
+       mips/Gglobal.c mips/Ginit.c mips/Ginit_local.c mips/Ginit_remote.c      
    \
+       mips/Gis_signal_frame.c mips/Gregs.c mips/Gresume.c mips/Gstep.c
+
 # The list of files that go both into libunwind and libunwind-x86:
 libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common)       \
        $(dwarf_SOURCES_common)                                         \
@@ -212,6 +280,17 @@ if OS_HPUX
  libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_hpux_local)
 endif
 
+if ARCH_ARM
+ lib_LTLIBRARIES_arch = libunwind-arm.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_arm)
+ libunwind_arm_la_SOURCES = $(libunwind_arm_la_SOURCES_arm)
+ libunwind_arm_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+if !REMOTE_ONLY
+ libunwind_arm_la_LIBADD = libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES   = $(libunwind_setjmp_la_SOURCES_common) \
+                                 $(libunwind_setjmp_la_SOURCES_arm)
+else
 if ARCH_IA64
  ia64_mk_Gcursor_i_SOURCES = ia64/mk_Gcursor_i.c
  ia64_mk_Lcursor_i_SOURCES = ia64/mk_Lcursor_i.c
@@ -242,6 +321,17 @@ endif
  libunwind_setjmp_la_SOURCES   = $(libunwind_setjmp_la_SOURCES_common) \
                                  $(libunwind_setjmp_la_SOURCES_hppa)
 else
+if ARCH_MIPS
+ lib_LTLIBRARIES_arch = libunwind-mips.la
+ libunwind_la_SOURCES = $(libunwind_la_SOURCES_mips)
+ libunwind_mips_la_SOURCES = $(libunwind_mips_la_SOURCES_mips)
+ libunwind_mips_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
+if !REMOTE_ONLY
+ libunwind_mips_la_LIBADD = libunwind.la -lc
+endif
+ libunwind_setjmp_la_SOURCES   = $(libunwind_setjmp_la_SOURCES_common) \
+                                 $(libunwind_setjmp_la_SOURCES_mips)
+else
 if ARCH_X86
  lib_LTLIBRARIES_arch = libunwind-x86.la
  libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86)
@@ -265,8 +355,10 @@ endif
                                  $(libunwind_setjmp_la_SOURCES_x86_64)
 endif # ARCH_X86_64
 endif # ARCH_X86
+endif # ARCH_MIPS
 endif # ARCH_HPPA
 endif # ARCH_IA64
+endif # ARCH_ARM
 
 libunwind_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
 libunwind_la_LIBADD  = -lc $(LIBCRTS)
--- libunwind-0.98.5/src/ptrace/_UPT_get_dyn_info_list_addr.c   (revision 
186298)
+++ libunwind-0.98.5/src/ptrace/_UPT_get_dyn_info_list_addr.c   (revision 
189947)
@@ -85,6 +85,7 @@ get_list_addr (unw_addr_space_t as, unw_
               int *countp)
 {
 # warning Implement get_list_addr(), please.
+  *countp = 0;
   return 0;
 }
 
--- libunwind-0.98.5/src/ptrace/_UPT_reg_offset.c       (revision 186298)
+++ libunwind-0.98.5/src/ptrace/_UPT_reg_offset.c       (revision 189947)
@@ -250,6 +250,61 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] =
 //  [UNW_X86_64_EFLAGS]        = 0x90,
 //  [UNW_X86_64_RSP]   = 0x98,
 //  [UNW_X86_64_SS]    = 0xa0
+#elif defined(UNW_TARGET_ARM)
+    /* FIXME, check!  */
+    [UNW_ARM_R0]       = 0x00,
+    [UNW_ARM_R1]       = 0x04,
+    [UNW_ARM_R2]       = 0x08,
+    [UNW_ARM_R3]       = 0x0C,
+    [UNW_ARM_R4]       = 0x10,
+    [UNW_ARM_R5]       = 0x14,
+    [UNW_ARM_R6]       = 0x18,
+    [UNW_ARM_R7]       = 0x1C,
+    [UNW_ARM_R8]       = 0x20,
+    [UNW_ARM_R9]       = 0x24,
+    [UNW_ARM_R10]      = 0x28,
+    [UNW_ARM_R11]      = 0x2C,
+    [UNW_ARM_R12]      = 0x30,
+    [UNW_ARM_R13]      = 0x34,
+    [UNW_ARM_R14]      = 0x38,
+    [UNW_ARM_R15]      = 0x3C
+#elif defined(UNW_TARGET_MIPS)
+    /* FIXME, add all the others or use PTRACE_GETREGS */
+    [UNW_MIPS_R0]      = 0x00,
+    [UNW_MIPS_R1]      = 0x01,
+    [UNW_MIPS_R2]      = 0x02,
+    [UNW_MIPS_R3]      = 0x03,
+    [UNW_MIPS_R4]      = 0x04,
+    [UNW_MIPS_R5]      = 0x05,
+    [UNW_MIPS_R6]      = 0x06,
+    [UNW_MIPS_R7]      = 0x07,
+    [UNW_MIPS_R8]      = 0x08,
+    [UNW_MIPS_R9]      = 0x09,
+    [UNW_MIPS_R10]     = 0x0A,
+    [UNW_MIPS_R11]     = 0x0B,
+    [UNW_MIPS_R12]     = 0x0C,
+    [UNW_MIPS_R13]     = 0x0D,
+    [UNW_MIPS_R14]     = 0x0E,
+    [UNW_MIPS_R15]     = 0x0F,
+    [UNW_MIPS_R16]     = 0x10,
+    [UNW_MIPS_R17]     = 0x11,
+    [UNW_MIPS_R18]     = 0x12,
+    [UNW_MIPS_R19]     = 0x13,
+    [UNW_MIPS_R20]     = 0x14,
+    [UNW_MIPS_R21]     = 0x15,
+    [UNW_MIPS_R22]     = 0x16,
+    [UNW_MIPS_R23]     = 0x17,
+    [UNW_MIPS_R24]     = 0x18,
+    [UNW_MIPS_R25]     = 0x19,
+    [UNW_MIPS_R26]     = 0x1A,
+    [UNW_MIPS_R27]     = 0x1B,
+    [UNW_MIPS_R28]     = 0x1C,
+    [UNW_MIPS_R29]     = 0x1D,
+    [UNW_MIPS_R30]     = 0x1E,
+    [UNW_MIPS_R31]     = 0x1F,
+#if 0
+    [UNW_MIPS_PC]      = 0x40,
+#endif
 #else
 # error Fix me.
 #endif
--- libunwind-0.98.5/Makefile.am        (revision 186298)
+++ libunwind-0.98.5/Makefile.am        (revision 189947)
@@ -1,9 +1,15 @@
+if ARCH_ARM
+include_HEADERS_tdep = include/libunwind-arm.h
+else
 if ARCH_IA64
 include_HEADERS_tdep = include/libunwind-ia64.h
 else
 if ARCH_HPPA
 include_HEADERS_tdep = include/libunwind-hppa.h
 else
+if ARCH_MIPS
+include_HEADERS_tdep = include/libunwind-mips.h
+else
 if ARCH_X86
 include_HEADERS_tdep = include/libunwind-x86.h
 else
@@ -11,8 +17,10 @@ if ARCH_X86_64
 include_HEADERS_tdep = include/libunwind-x86_64.h
 endif # ARCH_X86_64
 endif # ARCH_X86
+endif # ARCH_MIPS
 endif # ARCH_HPPA
 endif # ARCH_IA64
+endif # ARCH_ARM
 
 include_HEADERS_common = $(include_HEADERS_tdep)               \
        include/libunwind-dynamic.h include/libunwind-ptrace.h




reply via email to

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