Imported Upstream version 1.3.1 40/247940/1 upstream/1.3.1
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Mon, 16 Nov 2020 11:52:09 +0000 (12:52 +0100)
committerMateusz Moscicki <m.moscicki2@partner.samsung.com>
Wed, 18 Nov 2020 11:39:38 +0000 (12:39 +0100)
Change-Id: Idf8eb0e923b852f847825d6ad592c9e4d0274e68

320 files changed:
Makefile.am
NEWS
README
configure.ac
doc/Makefile.am
doc/libunwind.man
doc/libunwind.tex
doc/unw_apply_reg_state.man [new file with mode: 0644]
doc/unw_apply_reg_state.tex [new file with mode: 0644]
doc/unw_flush_cache.man
doc/unw_flush_cache.tex
doc/unw_init_local.man
doc/unw_init_local.tex
doc/unw_init_local2.man [new file with mode: 0644]
doc/unw_reg_states_iterate.man [new file with mode: 0644]
doc/unw_reg_states_iterate.tex [new file with mode: 0644]
doc/unw_set_cache_size.man [new file with mode: 0644]
doc/unw_set_cache_size.tex [new file with mode: 0644]
doc/unw_set_caching_policy.man
doc/unw_set_caching_policy.tex
include/compiler.h
include/dwarf-eh.h
include/dwarf.h
include/dwarf_i.h
include/libunwind-aarch64.h
include/libunwind-arm.h
include/libunwind-common.h.in
include/libunwind-mips.h
include/libunwind_i.h
include/remote.h
include/tdep-aarch64/libunwind_i.h
include/tdep-arm/libunwind_i.h
include/tdep-hppa/libunwind_i.h
include/tdep-ia64/libunwind_i.h
include/tdep-mips/libunwind_i.h
include/tdep-ppc32/libunwind_i.h
include/tdep-ppc64/libunwind_i.h
include/tdep-sh/libunwind_i.h
include/tdep-tilegx/libunwind_i.h
include/tdep-x86/libunwind_i.h
include/tdep-x86_64/libunwind_i.h
include/tdep/jmpbuf.h
src/Makefile.am
src/aarch64/Gapply_reg_state.c [new file with mode: 0644]
src/aarch64/Gcreate_addr_space.c
src/aarch64/Gget_proc_info.c
src/aarch64/Gget_save_loc.c
src/aarch64/Ginit.c
src/aarch64/Ginit_local.c
src/aarch64/Ginit_remote.c
src/aarch64/Gis_signal_frame.c
src/aarch64/Greg_states_iterate.c [moved from src/dwarf/Gstep.c with 77% similarity]
src/aarch64/Gregs.c
src/aarch64/Gresume.c
src/aarch64/Gstash_frame.c
src/aarch64/Gstep.c
src/aarch64/Lapply_reg_state.c [new file with mode: 0644]
src/aarch64/Lreg_states_iterate.c [new file with mode: 0644]
src/aarch64/init.h
src/aarch64/is_fpreg.c
src/aarch64/regname.c
src/aarch64/unwind_i.h
src/arm/Gapply_reg_state.c [new file with mode: 0644]
src/arm/Gcreate_addr_space.c
src/arm/Gex_tables.c
src/arm/Gget_proc_info.c
src/arm/Gget_save_loc.c
src/arm/Ginit.c
src/arm/Ginit_local.c
src/arm/Ginit_remote.c
src/arm/Gis_signal_frame.c [deleted file]
src/arm/Gos-freebsd.c [new file with mode: 0644]
src/arm/Gos-linux.c [new file with mode: 0644]
src/arm/Gos-other.c [new file with mode: 0644]
src/arm/Greg_states_iterate.c [new file with mode: 0644]
src/arm/Gregs.c
src/arm/Gresume.c
src/arm/Gstash_frame.c
src/arm/Gstep.c
src/arm/Gtrace.c
src/arm/Lapply_reg_state.c [new file with mode: 0644]
src/arm/Los-freebsd.c [new file with mode: 0644]
src/arm/Los-linux.c [moved from src/dwarf/Lstep.c with 82% similarity]
src/arm/Los-other.c [new file with mode: 0644]
src/arm/Lreg_states_iterate.c [new file with mode: 0644]
src/arm/getcontext.S
src/arm/init.h
src/arm/is_fpreg.c
src/arm/offsets.h
src/arm/regname.c
src/arm/unwind_i.h
src/coredump/_UCD_access_reg_freebsd.c
src/coredump/_UCD_access_reg_linux.c
src/coredump/_UCD_accessors.c
src/coredump/_UCD_create.c
src/coredump/_UCD_destroy.c
src/dwarf/Gexpr.c
src/dwarf/Gfde.c
src/dwarf/Gfind_proc_info-lsb.c
src/dwarf/Gfind_unwind_table.c
src/dwarf/Gparser.c
src/dwarf/global.c
src/elfxx.c
src/elfxx.h
src/hppa/Gapply_reg_state.c [new file with mode: 0644]
src/hppa/Gcreate_addr_space.c
src/hppa/Gget_proc_info.c
src/hppa/Gget_save_loc.c
src/hppa/Ginit.c
src/hppa/Ginit_local.c
src/hppa/Ginit_remote.c
src/hppa/Gis_signal_frame.c
src/hppa/Greg_states_iterate.c [new file with mode: 0644]
src/hppa/Gresume.c
src/hppa/Gstep.c
src/hppa/Lapply_reg_state.c [new file with mode: 0644]
src/hppa/Lreg_states_iterate.c [new file with mode: 0644]
src/hppa/regname.c
src/ia64/Gapply_reg_state.c [new file with mode: 0644]
src/ia64/Gcreate_addr_space.c
src/ia64/Gget_proc_info.c
src/ia64/Gget_save_loc.c
src/ia64/Ginit.c
src/ia64/Ginit_local.c
src/ia64/Ginit_remote.c
src/ia64/Gis_signal_frame.c
src/ia64/Greg_states_iterate.c [new file with mode: 0644]
src/ia64/Gresume.c
src/ia64/Gscript.c
src/ia64/Gstep.c
src/ia64/Gtables.c
src/ia64/Lapply_reg_state.c [new file with mode: 0644]
src/ia64/Lreg_states_iterate.c [new file with mode: 0644]
src/ia64/regname.c
src/mi/Gdestroy_addr_space.c
src/mi/Gdyn-extract.c
src/mi/Gdyn-remote.c
src/mi/Gget_accessors.c
src/mi/Gget_fpreg.c
src/mi/Gget_proc_info_by_ip.c
src/mi/Gget_proc_name.c
src/mi/Gget_reg.c
src/mi/Gset_cache_size.c [new file with mode: 0644]
src/mi/Gset_caching_policy.c
src/mi/Gset_fpreg.c
src/mi/Gset_reg.c
src/mi/Ldyn-remote.c [new file with mode: 0644]
src/mi/Lset_cache_size.c [new file with mode: 0644]
src/mi/dyn-info-list.c
src/mi/flush_cache.c
src/mi/init.c
src/mips/Gapply_reg_state.c [new file with mode: 0644]
src/mips/Gcreate_addr_space.c
src/mips/Gget_proc_info.c
src/mips/Gget_save_loc.c
src/mips/Ginit.c
src/mips/Ginit_local.c
src/mips/Ginit_remote.c
src/mips/Gis_signal_frame.c
src/mips/Greg_states_iterate.c [new file with mode: 0644]
src/mips/Gregs.c
src/mips/Gresume.c
src/mips/Gstep.c
src/mips/Lapply_reg_state.c [new file with mode: 0644]
src/mips/Lreg_states_iterate.c [new file with mode: 0644]
src/mips/init.h
src/mips/is_fpreg.c
src/mips/regname.c
src/os-freebsd.c
src/os-hpux.c
src/os-linux.c
src/os-qnx.c
src/ppc/Gapply_reg_state.c [new file with mode: 0644]
src/ppc/Gget_proc_info.c
src/ppc/Gget_save_loc.c
src/ppc/Ginit_local.c
src/ppc/Ginit_remote.c
src/ppc/Gis_signal_frame.c
src/ppc/Greg_states_iterate.c [new file with mode: 0644]
src/ppc/Lapply_reg_state.c [new file with mode: 0644]
src/ppc/Lreg_states_iterate.c [new file with mode: 0644]
src/ppc32/Gapply_reg_state.c [new file with mode: 0644]
src/ppc32/Gcreate_addr_space.c
src/ppc32/Ginit.c
src/ppc32/Greg_states_iterate.c [new file with mode: 0644]
src/ppc32/Gresume.c
src/ppc32/Gstep.c
src/ppc32/Lapply_reg_state.c [new file with mode: 0644]
src/ppc32/Lreg_states_iterate.c [new file with mode: 0644]
src/ppc32/init.h
src/ppc32/is_fpreg.c
src/ppc32/regname.c
src/ppc32/setcontext.S [new file with mode: 0644]
src/ppc64/Gapply_reg_state.c [new file with mode: 0644]
src/ppc64/Gcreate_addr_space.c
src/ppc64/Ginit.c
src/ppc64/Greg_states_iterate.c [new file with mode: 0644]
src/ppc64/Gresume.c
src/ppc64/Gstep.c
src/ppc64/Lapply_reg_state.c [new file with mode: 0644]
src/ppc64/Lreg_states_iterate.c [new file with mode: 0644]
src/ppc64/get_func_addr.c
src/ppc64/init.h
src/ppc64/is_fpreg.c
src/ppc64/regname.c
src/ptrace/_UPT_access_fpreg.c
src/ptrace/_UPT_access_mem.c
src/ptrace/_UPT_access_reg.c
src/ptrace/_UPT_accessors.c
src/ptrace/_UPT_find_proc_info.c
src/ptrace/_UPT_reg_offset.c
src/sh/Gapply_reg_state.c [new file with mode: 0644]
src/sh/Gcreate_addr_space.c
src/sh/Gget_proc_info.c
src/sh/Gget_save_loc.c
src/sh/Ginit.c
src/sh/Ginit_local.c
src/sh/Ginit_remote.c
src/sh/Gis_signal_frame.c
src/sh/Greg_states_iterate.c [new file with mode: 0644]
src/sh/Gregs.c
src/sh/Gresume.c
src/sh/Gstep.c
src/sh/Lapply_reg_state.c [new file with mode: 0644]
src/sh/Lreg_states_iterate.c [new file with mode: 0644]
src/sh/init.h
src/sh/is_fpreg.c
src/sh/regname.c
src/tilegx/Gapply_reg_state.c [new file with mode: 0644]
src/tilegx/Gcreate_addr_space.c
src/tilegx/Gget_proc_info.c
src/tilegx/Gget_save_loc.c
src/tilegx/Ginit.c
src/tilegx/Ginit_local.c
src/tilegx/Ginit_remote.c
src/tilegx/Gis_signal_frame.c
src/tilegx/Greg_states_iterate.c [new file with mode: 0644]
src/tilegx/Gregs.c
src/tilegx/Gresume.c
src/tilegx/Gstep.c
src/tilegx/Lapply_reg_state.c [new file with mode: 0644]
src/tilegx/Lreg_states_iterate.c [new file with mode: 0644]
src/tilegx/init.h
src/tilegx/is_fpreg.c
src/tilegx/regname.c
src/unwind/Backtrace.c
src/unwind/DeleteException.c
src/unwind/FindEnclosingFunction.c
src/unwind/ForcedUnwind.c
src/unwind/GetBSP.c
src/unwind/GetCFA.c
src/unwind/GetDataRelBase.c
src/unwind/GetGR.c
src/unwind/GetIP.c
src/unwind/GetIPInfo.c
src/unwind/GetLanguageSpecificData.c
src/unwind/GetRegionStart.c
src/unwind/GetTextRelBase.c
src/unwind/RaiseException.c
src/unwind/Resume.c
src/unwind/Resume_or_Rethrow.c
src/unwind/SetGR.c
src/unwind/SetIP.c
src/x86/Gapply_reg_state.c [new file with mode: 0644]
src/x86/Gcreate_addr_space.c
src/x86/Gget_proc_info.c
src/x86/Gget_save_loc.c
src/x86/Ginit.c
src/x86/Ginit_local.c
src/x86/Ginit_remote.c
src/x86/Gos-freebsd.c
src/x86/Gos-linux.c
src/x86/Greg_states_iterate.c [new file with mode: 0644]
src/x86/Gresume.c
src/x86/Gstep.c
src/x86/Lapply_reg_state.c [new file with mode: 0644]
src/x86/Lreg_states_iterate.c [new file with mode: 0644]
src/x86/init.h
src/x86/is_fpreg.c
src/x86/regname.c
src/x86/unwind_i.h
src/x86_64/Gapply_reg_state.c [new file with mode: 0644]
src/x86_64/Gcreate_addr_space.c
src/x86_64/Gget_proc_info.c
src/x86_64/Gget_save_loc.c
src/x86_64/Ginit.c
src/x86_64/Ginit_local.c
src/x86_64/Ginit_remote.c
src/x86_64/Gos-freebsd.c
src/x86_64/Gos-linux.c
src/x86_64/Greg_states_iterate.c [new file with mode: 0644]
src/x86_64/Gresume.c
src/x86_64/Gstash_frame.c
src/x86_64/Gstep.c
src/x86_64/Gtrace.c
src/x86_64/Lapply_reg_state.c [new file with mode: 0644]
src/x86_64/Lreg_states_iterate.c [new file with mode: 0644]
src/x86_64/init.h
src/x86_64/is_fpreg.c
src/x86_64/regname.c
src/x86_64/setcontext.S
src/x86_64/unwind_i.h
tests/Gperf-simple.c
tests/Gperf-trace.c
tests/Gtest-bt.c
tests/Gtest-resume-sig.c
tests/Gtest-trace.c
tests/Ltest-init-local-signal-lib.c [new file with mode: 0644]
tests/Ltest-init-local-signal.c [new file with mode: 0644]
tests/Ltest-mem-validate.c [new file with mode: 0644]
tests/Makefile.am
tests/check-namespace.sh.in
tests/mapper.c
tests/run-coredump-unwind-mdi
tests/test-coredump-unwind.c
tests/test-flush-cache.c
tests/test-ptrace.c
tests/test-reg-state.c [new file with mode: 0644]
tests/test-static-link-gen.c
tests/test-static-link-loc.c

index 6a3ed9e..711d910 100644 (file)
@@ -1,6 +1,12 @@
-include_HEADERS = include/libunwind-dynamic.h \
-    include/libunwind-ptrace.h \
-    include/libunwind-coredump.h
+include_HEADERS = include/libunwind-dynamic.h
+
+if BUILD_PTRACE
+include_HEADERS += include/libunwind-ptrace.h
+endif BUILD_PTRACE
+
+if BUILD_COREDUMP
+include_HEADERS += include/libunwind-coredump.h
+endif BUILD_COREDUMP
 
 if ARCH_AARCH64
 include_HEADERS += include/libunwind-aarch64.h
@@ -42,7 +48,11 @@ endif
 
 nodist_include_HEADERS = include/libunwind-common.h
 
-SUBDIRS = src tests
+SUBDIRS = src
+
+if CONFIG_TESTS
+SUBDIRS += tests
+endif
 
 if CONFIG_DOCS
 SUBDIRS += doc
diff --git a/NEWS b/NEWS
index e26d1c9..ae6cbcf 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,23 @@
 -*-Mode: outline-*-
 
+* News for v1.3:
+
+** Iteration of unwind register states support
+   Doug Moore <dougm@rice.edu>
+** Freebsd/Armv6 support
+   Konstantin Belousov <kib@freebsd.org>
+** Many, many dwarf bugfixes
+** Mips remote unwind support
+** aarch64 ptrace support
+
+* News for v1.2:
+
+** aarch64 port
+** dwarf parsing improvements
+** Fast stacktraces for aarch64 & arm
+** tilegx port
+** powerpc64 port
+
 * News for v1.1:
 
 ** coredump unwind support
diff --git a/README b/README
index cadffc1..694f600 100644 (file)
--- a/README
+++ b/README
@@ -1,18 +1,21 @@
 -*- mode: Outline -*-
 
-This is version 1.0 of the unwind library.  This library supports
+[![Build Status](https://travis-ci.org/libunwind/libunwind.svg?branch=master)](https://travis-ci.org/libunwind/libunwind)
+
+This is version 1.3 of the unwind library.  This library supports
 several architecture/operating-system combinations:
 
  Linux/x86-64: Works well.
  Linux/x86:    Works well.
  Linux/ARM:    Works well.
- Linux/IA-64:  Fully tested and supported.
+ Linux/IA-64:  Works well.
  Linux/PARISC: Works well, but C library missing unwind-info.
  HP-UX/IA-64:  Mostly works but known to have some serious limitations.
- Linux/AArch64:        Newly added.
+ MIPS:          Newly added.
+ Linux/AArch64:        Works well.
  Linux/PPC64:  Newly added.
  Linux/SuperH: Newly added.
- FreeBSD/i386: Newly added.
+ FreeBSD/i386: Works well.
  FreeBSD/x86-64: Newly added (FreeBSD architecture is known as amd64).
  Linux/Tilegx:  Newly added (64-bit mode only).
 
@@ -125,26 +128,12 @@ Note: If you get lots of errors in Gia64-test-nat and Lia64-test-nat, it's
 
 The following tests are expected to fail on x86 Linux:
 
-       Gtest-resume-sig        (fails to get SIGUSR2)
-       Ltest-resume-sig        (likewise)
-       Gtest-dyn1              (no dynamic unwind info support yet)
-       Ltest-dyn1              (no dynamic unwind info support yet)
-       test-setjmp             (longjmp() not implemented yet)
-       run-check-namespace     (no _Ux86_getcontext yet)
        test-ptrace
 
 ** Expected results on x86-64 Linux
 
 The following tests are expected to fail on x86-64 Linux:
 
-       Gtest-dyn1              (no dynamic unwind info support yet)
-       Ltest-dyn1              (no dynamic unwind info support yet)
-       Gtest-init (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18743)
-       Ltest-init              (likewise)
-       test-async-sig          (crashes due to bad unwind-info?)
-       test-setjmp             (longjmp() not implemented yet)
-       run-check-namespace     (no _Ux86_64_getcontext yet)
-       run-ptrace-mapper       (??? investigate)
        run-ptrace-misc (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18748
                         and http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18749)
 
@@ -212,3 +201,7 @@ or you can subscribe and manage your subscription via the
 web-interface at:
 
        https://savannah.nongnu.org/mail/?group=libunwind
+
+Or interact at the gihub page:
+
+       https://github.com/libunwind/libunwind
index 863fb8f..31d2817 100644 (file)
@@ -1,8 +1,8 @@
 define(pkg_major, 1)
-define(pkg_minor, 2)
-define(pkg_extra, )
+define(pkg_minor, 3)
+define(pkg_extra, 1)
 define(pkg_maintainer, libunwind-devel@nongnu.org)
-define(mkvers, $1.$2$3)
+define(mkvers, $1.$2.$3)
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT([libunwind],[mkvers(pkg_major, pkg_minor, pkg_extra)],[pkg_maintainer])
 AC_CONFIG_SRCDIR(src/mi/backtrace.c)
@@ -17,6 +17,7 @@ AC_PROG_CC
 AC_PROG_CXX
 AC_PROG_INSTALL
 AC_PROG_MAKE_SET
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 LT_INIT
 AM_PROG_AS
 AM_PROG_CC_C_O
@@ -55,7 +56,7 @@ AC_CHECK_TYPES([struct elf_prstatus, struct prstatus], [], [],
 #endif
 ])
 
-AC_CHECK_DECLS([PTRACE_POKEUSER, PTRACE_POKEDATA,
+AC_CHECK_DECLS([PTRACE_POKEUSER, PTRACE_POKEDATA, PTRACE_SETREGSET,
 PTRACE_TRACEME, PTRACE_CONT, PTRACE_SINGLESTEP,
 PTRACE_SYSCALL, PT_IO, PT_GETREGS,
 PT_GETFPREGS, PT_CONTINUE, PT_TRACE_ME,
@@ -104,6 +105,19 @@ SET_ARCH([$build_cpu],[build_arch])
 SET_ARCH([$host_cpu],[host_arch])
 SET_ARCH([$target_cpu],[target_arch])
 
+# Check for Android
+AC_MSG_CHECKING([for Android])
+android="no"
+case "$host_os" in
+  *android*)
+    android="yes"
+    AC_MSG_RESULT([yes])
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+esac
+
 AC_ARG_ENABLE(coredump,
        AS_HELP_STRING([--enable-coredump],[building libunwind-coredump library]),,
         [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*], [enable_coredump=yes], [enable_coredump=no])]
@@ -129,6 +143,10 @@ AC_ARG_ENABLE(documentation,
        AS_HELP_STRING([--disable-documentation],[Disable generating the man pages]),,
        [enable_documentation=yes])
 
+AC_ARG_ENABLE(tests,
+ AS_HELP_STRING([--disable-tests],[Disable tests build]),,
+ [enable_tests=yes])
+
 AC_MSG_CHECKING([if we should build libunwind-setjmp])
 AC_MSG_RESULT([$enable_setjmp])
 
@@ -144,6 +162,7 @@ AC_MSG_RESULT([$target_os])
 AM_CONDITIONAL(BUILD_COREDUMP, test x$enable_coredump = xyes)
 AM_CONDITIONAL(BUILD_PTRACE, test x$enable_ptrace = xyes)
 AM_CONDITIONAL(BUILD_SETJMP, test x$enable_setjmp = xyes)
+AM_CONDITIONAL(NO_PTRACE_TEST, test x$build_arch != x$host_arch)
 AM_CONDITIONAL(REMOTE_ONLY, test x$target_arch != x$host_arch)
 AM_CONDITIONAL(ARCH_AARCH64, test x$target_arch = xaarch64)
 AM_CONDITIONAL(ARCH_ARM, test x$target_arch = xarm)
@@ -229,6 +248,7 @@ AC_ARG_ENABLE(debug_frame,
 AS_HELP_STRING([--enable-debug-frame],[Load the ".debug_frame" section if available]),, [
 case "${target_arch}" in
   (arm) enable_debug_frame=yes;;
+  (aarch64) enable_debug_frame=yes;;
   (*)   enable_debug_frame=no;;
 esac])
 if test x$enable_debug_frame = xyes; then
@@ -280,7 +300,16 @@ fi
 AC_SUBST([LIBLZMA])
 AM_CONDITIONAL(HAVE_LZMA, test x$enable_minidebuginfo = xyes)
 
-LIBUNWIND___THREAD
+AC_MSG_CHECKING([whether to support UNW_CACHE_PER_THREAD])
+AC_ARG_ENABLE([per-thread-cache],
+AS_HELP_STRING([--enable-per-thread-cache], [build with support for UNW_CACHE_PER_THREAD (which imposes a hight TLS memory usage) (default: disabled)]))
+AC_MSG_RESULT([$enable_per_thread_cache])
+AS_IF([test x$enable_per_thread_cache = xyes], [
+  LIBUNWIND___THREAD
+  AS_IF([test x$libc_cv_gcc___thread = xno], [
+    AC_MSG_FAILURE([UNW_CACHE_PER_THREAD requires __thread])
+  ])
+])
 
 AC_MSG_CHECKING([for Intel compiler])
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[#ifndef __INTEL_COMPILER
@@ -314,7 +343,7 @@ else
     LDFLAGS_NOSTARTFILES="-XCClinker -nostartfiles"
 fi
 
-if test x$GCC = xyes -a x$intel_compiler != xyes -a x$qcc_compiler != xyes; then
+if test x$GCC = xyes -a x$intel_compiler != xyes -a x$qcc_compiler != xyes -a x$android != xyes; then
   LIBCRTS="-lgcc_s"
 fi
 
@@ -369,6 +398,11 @@ old_LIBS="$LIBS"
 LIBS=""
 AC_SEARCH_LIBS(backtrace, execinfo)
 LIBS="$old_LIBS"
+case "$ac_cv_search_backtrace" in
+  -l*) BACKTRACELIB=$ac_cv_search_backtrace;;
+  *) BACKTRACELIB="";;
+esac
+
 
 AC_SUBST(build_arch)
 AC_SUBST(target_os)
@@ -384,6 +418,7 @@ AC_SUBST(PKG_MAINTAINER)
 AC_SUBST(enable_cxx_exceptions)
 AC_SUBST(enable_debug_frame)
 AC_SUBST(DLLIB)
+AC_SUBST(BACKTRACELIB)
 
 AC_PATH_PROG([LATEX2MAN],[latex2man])
 if test "x$LATEX2MAN" = "x"; then
@@ -396,8 +431,13 @@ if test "x$enable_documentation" = "xyes"; then
   AC_CONFIG_FILES(doc/Makefile doc/common.tex)
 fi
 
-AC_CONFIG_FILES(Makefile src/Makefile tests/Makefile tests/check-namespace.sh
-               include/libunwind-common.h
+AM_CONDITIONAL([CONFIG_TESTS], [test x$enable_tests = xyes])
+if test "x$enable_tests" = "xyes"; then
+  AC_CONFIG_FILES(tests/Makefile tests/check-namespace.sh)
+fi
+
+AC_CONFIG_FILES(Makefile src/Makefile
+                include/libunwind-common.h
                 include/libunwind.h include/tdep/libunwind_i.h)
 AC_CONFIG_FILES(src/unwind/libunwind.pc src/coredump/libunwind-coredump.pc
                 src/ptrace/libunwind-ptrace.pc src/setjmp/libunwind-setjmp.pc
index 2534066..bfe4669 100644 (file)
@@ -1,6 +1,7 @@
 # man pages that go into section 3:
 man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man     \
        libunwind-ptrace.man libunwind-setjmp.man                       \
+       unw_apply_reg_state.man                                         \
        unw_backtrace.man                                               \
        unw_flush_cache.man                                             \
        unw_get_accessors.man                                           \
@@ -11,12 +12,15 @@ man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man  \
        unw_get_reg.man                                                 \
        unw_getcontext.man                                              \
        unw_init_local.man unw_init_remote.man                          \
+       unw_init_local2.man                                             \
        unw_is_fpreg.man                                                \
        unw_is_signal_frame.man                                         \
        unw_create_addr_space.man                                       \
        unw_destroy_addr_space.man                                      \
        unw_regname.man unw_resume.man                                  \
+       unw_reg_states_iterate.man                                      \
        unw_set_caching_policy.man                                      \
+       unw_set_cache_size.man                                          \
        unw_set_fpreg.man                                               \
        unw_set_reg.man                                                 \
        unw_step.man                                                    \
@@ -27,6 +31,7 @@ man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man    \
 EXTRA_DIST = NOTES libunwind.trans                                     \
        libunwind.tex libunwind-dynamic.tex libunwind-ia64.tex          \
        libunwind-ptrace.tex libunwind-setjmp.tex                       \
+       unw_apply_reg_state.tex                                         \
        unw_backtrace.tex                                               \
        unw_flush_cache.tex                                             \
        unw_get_accessors.tex                                           \
@@ -41,6 +46,8 @@ EXTRA_DIST = NOTES libunwind.trans                                    \
        unw_is_signal_frame.tex                                         \
        unw_create_addr_space.tex unw_destroy_addr_space.tex            \
        unw_regname.tex unw_resume.tex unw_set_caching_policy.tex       \
+       unw_reg_states_iterate.tex                                      \
+       unw_set_cache_size.tex                                          \
        unw_set_fpreg.tex                                               \
        unw_set_reg.tex                                                 \
        unw_step.tex                                                    \
index c6046e2..02ab6b8 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.\" Manual page created with latex2man on Thu Aug 16 09:44:43 MDT 2007
+.\" Manual page created with latex2man on Thu Jan 12 06:50:29 PST 2017
 .\" NOTE: This file is generated, DO NOT EDIT.
 .de Vb
 .ft CW
@@ -10,7 +10,7 @@
 
 .fi
 ..
-.TH "LIBUNWIND" "3" "16 August 2007" "Programming Library " "Programming Library "
+.TH "LIBUNWIND" "3" "12 January 2017" "Programming Library " "Programming Library "
 .SH NAME
 libunwind
 \-\- a (mostly) platform\-independent unwind API 
@@ -82,6 +82,11 @@ int
 unw_set_caching_policy(unw_addr_space_t,
 unw_caching_policy_t);
 .br
+int
+unw_set_cache_size(unw_addr_space_t,
+size_t,
+int);
+.br
 .PP
 const char *unw_regname(unw_regnum_t);
 .br
@@ -428,7 +433,9 @@ UNW_CACHE_NONE,
 it is possible to turn off caching 
 completely, therefore eliminating the risk of stale data alltogether 
 (at the cost of slower execution). By default, caching is enabled for 
-local unwinding only. 
+local unwinding only. The cache size can be dynamically changed with 
+unw_set_cache_size(),
+which also fluches the current cache. 
 .PP
 .SH FILES
 
@@ -482,6 +489,7 @@ unw_is_signal_frame(3),
 unw_regname(3),
 unw_resume(3),
 unw_set_caching_policy(3),
+unw_set_cache_size(3),
 unw_set_fpreg(3),
 unw_set_reg(3),
 unw_step(3),
index 534bd4d..6cbb476 100644 (file)
@@ -43,6 +43,8 @@
 \Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t});\\
 \noindent
 \Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t}, \Type{unw\_caching\_policy\_t});\\
+\noindent
+\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t}, \Type{size\_t}, \Type{int});\\
 
 \noindent
 \Type{const char *}\Func{unw\_regname}(\Type{unw\_regnum\_t});\\
@@ -293,7 +295,8 @@ object.  In particular, by selecting the policy
 \Const{UNW\_CACHE\_NONE}, it is possible to turn off caching
 completely, therefore eliminating the risk of stale data alltogether
 (at the cost of slower execution).  By default, caching is enabled for
-local unwinding only.
+local unwinding only.  The cache size can be dynamically changed with
+\Func{unw\_set\_cache\_size}(), which also fluches the current cache.
 
 
 \section{Files}
@@ -337,6 +340,7 @@ local unwinding only.
 \SeeAlso{unw\_regname(3)},
 \SeeAlso{unw\_resume(3)},
 \SeeAlso{unw\_set\_caching\_policy(3)},
+\SeeAlso{unw\_set\_cache\_size(3)},
 \SeeAlso{unw\_set\_fpreg(3)},
 \SeeAlso{unw\_set\_reg(3)},
 \SeeAlso{unw\_step(3)},
diff --git a/doc/unw_apply_reg_state.man b/doc/unw_apply_reg_state.man
new file mode 100644 (file)
index 0000000..457f0c4
--- /dev/null
@@ -0,0 +1,90 @@
+'\" t
+.\" Manual page created with latex2man on Wed Aug 16 11:09:44 PDT 2017
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_APPLY\\_REG\\_STATE" "3" "16 August 2017" "Programming Library " "Programming Library "
+.SH NAME
+unw_apply_reg_state
+\-\- apply a register state update to a cursor 
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_apply_reg_state(unw_cursor_t *cp,
+void *reg_states_data);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_apply_reg_state()
+routine updates the register values 
+of a cursor according to the instructions in reg_states_data,
+which have been obtained by calling unw_reg_states_iterate\&.
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_apply_reg_state()
+returns 0. 
+Otherwise the negative value of one of the error\-codes below is 
+returned. 
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_apply_reg_state()
+is thread\-safe. If cursor cp
+is 
+in the local address\-space, this routine is also safe to use from a 
+signal handler. 
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred. 
+.TP
+UNW_ENOINFO
+ Libunwind
+was unable to locate 
+unwind\-info for the procedure. 
+.TP
+UNW_EBADVERSION
+ The unwind\-info for the procedure has 
+version or format that is not understood by libunwind\&.
+.PP
+In addition, unw_apply_reg_state()
+may return any error 
+returned by the access_mem()
+call\-back (see 
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_reg_states_iterate(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/doc/unw_apply_reg_state.tex b/doc/unw_apply_reg_state.tex
new file mode 100644 (file)
index 0000000..c67cc3e
--- /dev/null
@@ -0,0 +1,63 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_apply\_reg\_state}{David Mosberger-Tang}{Programming Library}{unw\_apply\_reg\_state}unw\_apply\_reg\_state -- apply a register state update to a cursor
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int}
+\Func{unw\_apply\_reg\_state}(\Type{unw\_cursor\_t~*}\Var{cp},
+\Type{void~*}\Var{reg\_states\_data});\\
+
+\section{Description}
+
+The \Func{unw\_apply\_reg\_state}() routine updates the register values
+of a cursor according to the instructions in \Var{reg\_states\_data},
+which have been obtained by calling \Var{unw\_reg\_states\_iterate}.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_apply\_reg\_state}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_apply\_reg\_state}() is thread-safe.  If cursor \Var{cp} is
+in the local address-space, this routine is also safe to use from a
+signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate
+  unwind-info for the procedure.
+\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has
+  version or format that is not understood by \Prog{libunwind}.
+\end{Description}
+In addition, \Func{unw\_apply\_reg\_state}() may return any error
+returned by the \Func{access\_mem}() call-back (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_reg\_states\_iterate(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
index 2c05bc2..627449e 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
+.\" Manual page created with latex2man on Fri Dec  2 16:09:33 PST 2016
 .\" NOTE: This file is generated, DO NOT EDIT.
 .de Vb
 .ft CW
@@ -10,7 +10,7 @@
 
 .fi
 ..
-.TH "UNW\\_FLUSH\\_CACHE" "3" "16 August 2007" "Programming Library " "Programming Library "
+.TH "UNW\\_FLUSH\\_CACHE" "3" "02 December 2016" "Programming Library " "Programming Library "
 .SH NAME
 unw_flush_cache
 \-\- flush cached info 
@@ -80,6 +80,7 @@ use from a signal handler.
 .PP
 libunwind(3),
 unw_set_caching_policy(3)
+unw_set_cache_size(3)
 .PP
 .SH AUTHOR
 
index 9b61dfc..32319db 100644 (file)
@@ -45,6 +45,7 @@ use from a signal handler.
 
 \SeeAlso{libunwind(3)},
 \SeeAlso{unw\_set\_caching\_policy(3)}
+\SeeAlso{unw\_set\_cache\_size(3)}
 
 \section{Author}
 
index 73b7988..301dd6f 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" Manual page created with latex2man on Wed Aug 16 12:11:05 PDT 2017
 .\" NOTE: This file is generated, DO NOT EDIT.
 .de Vb
 .ft CW
@@ -10,7 +10,7 @@
 
 .fi
 ..
-.TH "UNW\\_INIT\\_LOCAL" "3" "16 August 2007" "Programming Library " "Programming Library "
+.TH "UNW\\_INIT\\_LOCAL" "3" "16 August 2017" "Programming Library " "Programming Library "
 .SH NAME
 unw_init_local
 \-\- initialize cursor for local unwinding 
@@ -25,6 +25,12 @@ int
 unw_init_local(unw_cursor_t *c,
 unw_context_t *ctxt);
 .br
+int
+unw_init_local2(unw_cursor_t *c,
+unw_context_t *ctxt,
+int
+flag);
+.br
 .PP
 .SH DESCRIPTION
 
@@ -37,7 +43,11 @@ pointed to by ctxt\&.
 As such, the machine\-state pointed to by 
 ctxt
 identifies the initial stack frame at which unwinding 
-starts. The machine\-state must remain valid for the duration for 
+starts. The machine\-state is expected to be one provided by a call to 
+unw_getcontext; as such, the instruction pointer may point to the 
+instruction after the last instruction of a function, and libunwind 
+will back\-up the instruction pointer before beginning a walk up the 
+call stack. The machine\-state must remain valid for the duration for 
 which the cursor c
 is in use. 
 .PP
@@ -46,17 +56,6 @@ routine can be used only for unwinding in
 the address space of the current process (i.e., for local unwinding). 
 For all other cases, unw_init_remote()
 must be used instead. 
-From a behavioral point of view, the call: 
-.PP
-.Vb
-    ret = unw_init_local(&cursor, &ucontext);
-.Ve
-is equivalent to: 
-.PP
-.Vb
-    ret = unw_init_remote(&cursor, unw_local_addr_space,
-                          &ucontext);
-.Ve
 However, unwind performance may be better when using 
 unw_init_local().
 Also, unw_init_local()
@@ -67,6 +66,12 @@ including <libunwind.h>,
 whereas unw_init_remote()
 is not. 
 .PP
+If the unw_context_t is known to be a signal frame (i.e., from the 
+third argument in a sigaction handler on linux), 
+unw_init_local2()
+should be used for correct initialization 
+on some platforms, passing the UNW_INIT_SIGNAL_FRAME flag. 
+.PP
 .SH RETURN VALUE
 
 .PP
index 5cea673..ff0d03b 100644 (file)
@@ -13,6 +13,7 @@
 \File{\#include $<$libunwind.h$>$}\\
 
 \Type{int} \Func{unw\_init\_local}(\Type{unw\_cursor\_t~*}\Var{c}, \Type{unw\_context\_t~*}\Var{ctxt});\\
+\Type{int} \Func{unw\_init\_local2}(\Type{unw\_cursor\_t~*}\Var{c}, \Type{unw\_context\_t~*}\Var{ctxt}, \Type{int} \Var{flag});\\
 
 \section{Description}
 
@@ -20,29 +21,27 @@ The \Func{unw\_init\_local}() routine initializes the unwind cursor
 pointed to by \Var{c} with the machine-state in the context structure
 pointed to by \Var{ctxt}.  As such, the machine-state pointed to by
 \Var{ctxt} identifies the initial stack frame at which unwinding
-starts.  The machine-state must remain valid for the duration for
+starts.  The machine-state is expected to be one provided by a call to
+unw_getcontext; as such, the instruction pointer may point to the
+instruction after the last instruction of a function, and libunwind
+will back-up the instruction pointer before beginning a walk up the
+call stack.  The machine-state must remain valid for the duration for
 which the cursor \Var{c} is in use.
 
 The \Func{unw\_init\_local}() routine can be used only for unwinding in
 the address space of the current process (i.e., for local unwinding).
 For all other cases, \Func{unw\_init\_remote}() must be used instead.
-From a behavioral point of view, the call:
-
-\begin{verbatim}
-    ret = unw_init_local(&cursor, &ucontext);
-\end{verbatim}
-is equivalent to:
-
-\begin{verbatim}
-    ret = unw_init_remote(&cursor, unw_local_addr_space,
-                          &ucontext);
-\end{verbatim}
 However, unwind performance may be better when using
 \Func{unw\_init\_local}().  Also, \Func{unw\_init\_local}() is
 available even when \Const{UNW\_LOCAL\_ONLY} has been defined before
 including \File{$<$libunwind.h$>$}, whereas \Func{unw\_init\_remote}()
 is not.
 
+If the unw_context_t is known to be a signal frame (i.e., from the
+third argument in a sigaction handler on linux),
+\Func{unw\_init\_local2}() should be used for correct initialization
+on some platforms, passing the UNW_INIT_SIGNAL_FRAME flag.
+
 \section{Return Value}
 
 On successful completion, \Func{unw\_init\_local}() returns 0.
diff --git a/doc/unw_init_local2.man b/doc/unw_init_local2.man
new file mode 100644 (file)
index 0000000..6cbbf00
--- /dev/null
@@ -0,0 +1 @@
+.so man3/unw_init_local.3
diff --git a/doc/unw_reg_states_iterate.man b/doc/unw_reg_states_iterate.man
new file mode 100644 (file)
index 0000000..e328ad2
--- /dev/null
@@ -0,0 +1,137 @@
+'\" t
+.\" Manual page created with latex2man on Wed Aug 16 11:09:44 PDT 2017
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_REG\\_STATES\\_ITERATE" "3" "16 August 2017" "Programming Library " "Programming Library "
+.SH NAME
+unw_reg_states_iterate
+\-\- get register state info on current procedure 
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_reg_states_iterate(unw_cursor_t *cp,
+unw_reg_states_callbackcb,
+void *token);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_reg_states_iterate()
+routine provides 
+information about the procedure that created the stack frame 
+identified by argument cp\&.
+The cb
+argument is a pointer 
+to a function of type unw_reg_states_callback
+which is used to 
+return the information. The function unw_reg_states_callback
+has the 
+following definition: 
+.PP
+int
+( *unw_reg_states_callback)(void *token,
+void *reg_states_data,
+size_t
+reg_states_data_size,
+unw_word_t
+start_ip,
+unw_word_t
+end_ip);
+.PP
+The callback function may be invoked several times for each call of unw_reg_states_iterate\&.
+Each call is associcated with a instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range. For each invocation, the arguments to the callback function are: 
+.TP
+void * token
+ The token value passed to unw_reg_states_callback\&.
+.br
+.TP
+void * reg_states_data
+ A pointer to data about 
+updating register values. This data, or a copy of it, can be passed 
+to unw_apply_reg_state\&.
+.br
+.TP
+int reg_states_data_size
+ The size of the register update data. 
+.br
+.TP
+unw_word_t start_ip
+ The address of the first 
+instruction of the address range. 
+.br
+.TP
+unw_word_t end_ip
+ The address of the first 
+instruction \fIbeyond\fP
+the end of the address range. 
+.br
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_reg_states_iterate()
+returns 
+0. If the callback function returns a nonzero value, that indicates 
+failure and the function returns immediately. Otherwise the negative 
+value of one of the error\-codes below is returned. 
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_reg_states_iterate()
+is thread\-safe. If cursor cp
+is 
+in the local address\-space, this routine is also safe to use from a 
+signal handler. 
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_EUNSPEC
+ An unspecified error occurred. 
+.TP
+UNW_ENOINFO
+ Libunwind
+was unable to locate 
+unwind\-info for the procedure. 
+.TP
+UNW_EBADVERSION
+ The unwind\-info for the procedure has 
+version or format that is not understood by libunwind\&.
+.PP
+In addition, unw_reg_states_iterate()
+may return any error 
+returned by the access_mem()
+call\-back (see 
+unw_create_addr_space(3)).
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_apply_reg_state(3)
+.PP
+.SH AUTHOR
+
+.PP
+David Mosberger\-Tang
+.br
+Email: \fBdmosberger@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/doc/unw_reg_states_iterate.tex b/doc/unw_reg_states_iterate.tex
new file mode 100644 (file)
index 0000000..36c9b54
--- /dev/null
@@ -0,0 +1,83 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_reg\_states\_iterate}{David Mosberger-Tang}{Programming Library}{unw\_reg\_states\_iterate}unw\_reg\_states\_iterate -- get register state info on current procedure
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_reg\_states\_iterate}(\Type{unw\_cursor\_t~*}\Var{cp}, \Type{unw\_reg\_states\_callback}\Var{cb}, \Type{void~*}\Var{token});\\
+
+\section{Description}
+
+The \Func{unw\_reg\_states\_iterate}() routine provides
+information about the procedure that created the stack frame
+identified by argument \Var{cp}.  The \Var{cb} argument is a pointer
+to a function of type \Type{unw\_reg\_states\_callback} which is used to
+return the information.  The function \Type{unw\_reg\_states\_callback} has the
+following definition:
+
+\Type{int} (~*\Var{unw\_reg\_states\_callback})(\Type{void~*}\Var{token},
+                       \Type{void~*}\Var{reg\_states\_data},
+                       \Type{size\_t} \Var{reg\_states\_data\_size},
+                       \Type{unw\_word\_t} \Var{start\_ip}, \Type{unw\_word\_t} \Var{end\_ip});
+
+The callback function may be invoked several times for each call of \Func{unw\_reg\_states\_iterate}. Each call is associcated with a instruction address range and a set of instructions on how to update register values when returning from the procedure in that address range.  For each invocation, the arguments to the callback function are:
+\begin{description}
+\item[\Type{void~*} \Var{token}] The token value passed to \Var{unw\_reg\_states\_callback}. \\
+\item[\Type{void~*} \Var{reg\_states\_data}] A pointer to data about
+  updating register values. This data, or a copy of it, can be passed
+  to \Var{unw\_apply\_reg\_state}.\\
+\item[\Type{int} \Var{reg\_states\_data\_size}] The size of the register update data. \\
+\item[\Type{unw\_word\_t} \Var{start\_ip}] The address of the first
+  instruction of the address range.  \\
+\item[\Type{unw\_word\_t} \Var{end\_ip}] The address of the first
+  instruction \emph{beyond} the end of the address range.  \\
+\end{description}
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_reg\_states\_iterate}() returns
+0.  If the callback function returns a nonzero value, that indicates
+failure and the function returns immediately.  Otherwise the negative
+value of one of the error-codes below is returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_reg\_states\_iterate}() is thread-safe.  If cursor \Var{cp} is
+in the local address-space, this routine is also safe to use from a
+signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
+\item[\Const{UNW\_ENOINFO}] \Prog{Libunwind} was unable to locate
+  unwind-info for the procedure.
+\item[\Const{UNW\_EBADVERSION}] The unwind-info for the procedure has
+  version or format that is not understood by \Prog{libunwind}.
+\end{Description}
+In addition, \Func{unw\_reg\_states\_iterate}() may return any error
+returned by the \Func{access\_mem}() call-back (see
+\Func{unw\_create\_addr\_space}(3)).
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_apply\_reg\_state(3)}
+
+\section{Author}
+
+\noindent
+David Mosberger-Tang\\
+Email: \Email{dmosberger@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
diff --git a/doc/unw_set_cache_size.man b/doc/unw_set_cache_size.man
new file mode 100644 (file)
index 0000000..34bbc53
--- /dev/null
@@ -0,0 +1,88 @@
+'\" t
+.\" Manual page created with latex2man on Fri Jan 13 08:33:21 PST 2017
+.\" NOTE: This file is generated, DO NOT EDIT.
+.de Vb
+.ft CW
+.nf
+..
+.de Ve
+.ft R
+
+.fi
+..
+.TH "UNW\\_SET\\_CACHE\\_SIZE" "3" "13 January 2017" "Programming Library " "Programming Library "
+.SH NAME
+unw_set_cache_size
+\-\- set unwind cache size 
+.PP
+.SH SYNOPSIS
+
+.PP
+#include <libunwind.h>
+.br
+.PP
+int
+unw_set_cache_size(unw_addr_space_t
+as,
+size_t
+size,
+int
+flag);
+.br
+.PP
+.SH DESCRIPTION
+
+.PP
+The unw_set_cache_size()
+routine sets the cache size of 
+address space as
+to hold at least as many items as given by 
+argument size\&.
+It may hold more items as determined by the 
+implementation. To disable caching, call 
+unw_set_caching_policy)
+with a policy of 
+UNW_CACHE_NONE\&.
+Flag is currently unused and must be 0. 
+.PP
+.SH RETURN VALUE
+
+.PP
+On successful completion, unw_set_cache_size()
+returns 0. 
+Otherwise the negative value of one of the error\-codes below is 
+returned. 
+.PP
+.SH THREAD AND SIGNAL SAFETY
+
+.PP
+unw_set_cache_size()
+is thread\-safe but \fInot\fP
+safe 
+to use from a signal handler. 
+.PP
+.SH ERRORS
+
+.PP
+.TP
+UNW_ENOMEM
+ The desired cache size could not be 
+established because the application is out of memory. 
+.PP
+.SH SEE ALSO
+
+.PP
+libunwind(3),
+unw_create_addr_space(3),
+unw_set_caching_policy(3),
+unw_flush_cache(3)
+.PP
+.SH AUTHOR
+
+.PP
+Dave Watson
+.br
+Email: \fBdade.watson@gmail.com\fP
+.br
+WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
+.\" NOTE: This file is generated, DO NOT EDIT.
diff --git a/doc/unw_set_cache_size.tex b/doc/unw_set_cache_size.tex
new file mode 100644 (file)
index 0000000..1bd7e00
--- /dev/null
@@ -0,0 +1,59 @@
+\documentclass{article}
+\usepackage[fancyhdr,pdf]{latex2man}
+
+\input{common.tex}
+
+\begin{document}
+
+\begin{Name}{3}{unw\_set\_cache\_size}{Dave Watson}{Programming Library}{unw\_set\_cache\_size}unw\_set\_cache\_size -- set unwind cache size
+\end{Name}
+
+\section{Synopsis}
+
+\File{\#include $<$libunwind.h$>$}\\
+
+\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{size\_t} \Var{size}, \Type{int} \Var{flag});\\
+
+\section{Description}
+
+The \Func{unw\_set\_cache\_size}() routine sets the cache size of
+address space \Var{as} to hold at least as many items as given by
+argument \Var{size}.  It may hold more items as determined by the
+implementation.  To disable caching, call
+\Func{unw\_set\_caching\_policy}) with a policy of
+\Const{UNW\_CACHE\_NONE}.  Flag is currently unused and must be 0.
+
+\section{Return Value}
+
+On successful completion, \Func{unw\_set\_cache\_size}() returns 0.
+Otherwise the negative value of one of the error-codes below is
+returned.
+
+\section{Thread and Signal Safety}
+
+\Func{unw\_set\_cache\_size}() is thread-safe but \emph{not} safe
+to use from a signal handler.
+
+\section{Errors}
+
+\begin{Description}
+\item[\Const{UNW\_ENOMEM}] The desired cache size could not be
+  established because the application is out of memory.
+\end{Description}
+
+\section{See Also}
+
+\SeeAlso{libunwind(3)},
+\SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_set\_caching\_policy(3)},
+\SeeAlso{unw\_flush\_cache(3)}
+
+\section{Author}
+
+\noindent
+Dave Watson\\
+Email: \Email{dade.watson@gmail.com}\\
+WWW: \URL{http://www.nongnu.org/libunwind/}.
+\LatexManEnd
+
+\end{document}
index a21d84a..4862ea5 100644 (file)
@@ -1,5 +1,5 @@
 '\" t
-.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
+.\" Manual page created with latex2man on Fri Dec  2 16:09:33 PST 2016
 .\" NOTE: This file is generated, DO NOT EDIT.
 .de Vb
 .ft CW
@@ -10,7 +10,7 @@
 
 .fi
 ..
-.TH "UNW\\_SET\\_CACHING\\_POLICY" "3" "16 August 2007" "Programming Library " "Programming Library "
+.TH "UNW\\_SET\\_CACHING\\_POLICY" "3" "02 December 2016" "Programming Library " "Programming Library "
 .SH NAME
 unw_set_caching_policy
 \-\- set unwind caching policy 
@@ -105,6 +105,7 @@ established because the application is out of memory.
 .PP
 libunwind(3),
 unw_create_addr_space(3),
+unw_set_cache_size(3),
 unw_flush_cache(3)
 .PP
 .SH AUTHOR
index a84e020..3a4b07e 100644 (file)
@@ -67,6 +67,7 @@ to use from a signal handler.
 
 \SeeAlso{libunwind(3)},
 \SeeAlso{unw\_create\_addr\_space(3)},
+\SeeAlso{unw\_set\_cache\_size(3)},
 \SeeAlso{unw\_flush\_cache(3)}
 
 \section{Author}
index abd424d..2fa59ef 100644 (file)
@@ -36,15 +36,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 # define UNUSED         __attribute__((unused))
 # define NOINLINE       __attribute__((noinline))
 # define NORETURN       __attribute__((noreturn))
-# define ALIAS(name)    __attribute__((alias (#name)))
+# define ALIAS2(name)   #name
+# define ALIAS(name)    __attribute__((alias (ALIAS2(name))))
 # if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
 #  define ALWAYS_INLINE inline __attribute__((always_inline))
 #  define HIDDEN        __attribute__((visibility ("hidden")))
-#  define PROTECTED     __attribute__((visibility ("protected")))
 # else
 #  define ALWAYS_INLINE
 #  define HIDDEN
-#  define PROTECTED
 # endif
 # define WEAK           __attribute__((weak))
 # if (__GNUC__ >= 3)
@@ -63,7 +62,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 # define NORETURN
 # define ALIAS(name)
 # define HIDDEN
-# define PROTECTED
 # define WEAK
 # define likely(x)      (x)
 # define unlikely(x)    (x)
index e81aaef..e037507 100644 (file)
@@ -106,16 +106,16 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #define DW_EH_VERSION           1       /* The version we're implementing */
 
-struct dwarf_eh_frame_hdr
+struct __attribute__((packed)) dwarf_eh_frame_hdr
   {
     unsigned char version;
     unsigned char eh_frame_ptr_enc;
     unsigned char fde_count_enc;
     unsigned char table_enc;
+    Elf_W (Addr) eh_frame;
     /* The rest of the header is variable-length and consists of the
        following members:
 
-        encoded_t eh_frame_ptr;
         encoded_t fde_count;
         struct
           {
index 633868b..fab93c6 100644 (file)
@@ -37,13 +37,6 @@ struct elf_dyn_info;
 # include "config.h"
 #endif
 
-#ifdef HAVE___THREAD
-  /* For now, turn off per-thread caching.  It uses up too much TLS
-     memory per thread even when the thread never uses libunwind at
-     all.  */
-# undef HAVE___THREAD
-#endif
-
 #ifndef UNW_REMOTE_ONLY
   #if defined(HAVE_LINK_H)
     #include <link.h>
@@ -142,7 +135,8 @@ typedef enum
   }
 dwarf_expr_op_t;
 
-#define DWARF_CIE_VERSION       3       /* GCC emits version 1??? */
+#define DWARF_CIE_VERSION       3
+#define DWARF_CIE_VERSION_MAX   4
 
 #define DWARF_CFA_OPCODE_MASK   0xc0
 #define DWARF_CFA_OPERAND_MASK  0x3f
@@ -236,13 +230,6 @@ typedef enum
   }
 dwarf_where_t;
 
-typedef struct
-  {
-    dwarf_where_t where;        /* how is the register saved? */
-    unw_word_t val;             /* where it's saved */
-  }
-dwarf_save_loc_t;
-
 /* For uniformity, we'd like to treat the CFA save-location like any
    other register save-location, but this doesn't quite work, because
    the CFA can be expressed as a (REGISTER,OFFSET) pair.  To handle
@@ -256,19 +243,36 @@ dwarf_save_loc_t;
 #define DWARF_CFA_REG_COLUMN    DWARF_NUM_PRESERVED_REGS
 #define DWARF_CFA_OFF_COLUMN    (DWARF_NUM_PRESERVED_REGS + 1)
 
+typedef struct dwarf_reg_only_state
+  {
+    char where[DWARF_NUM_PRESERVED_REGS + 2];        /* how is the register saved? */
+    unw_word_t val[DWARF_NUM_PRESERVED_REGS + 2];             /* where it's saved */
+  }
+dwarf_reg_only_state_t;
+
 typedef struct dwarf_reg_state
   {
-    struct dwarf_reg_state *next;       /* for rs_stack */
-    dwarf_save_loc_t reg[DWARF_NUM_PRESERVED_REGS + 2];
+    unw_word_t ret_addr_column;        /* which column in rule table represents return address */
+    dwarf_reg_only_state_t reg;
+  }
+dwarf_reg_state_t;
+
+typedef struct dwarf_stackable_reg_state
+  {
+    struct dwarf_stackable_reg_state *next;       /* for rs_stack */
+    dwarf_reg_state_t state;
+  }
+dwarf_stackable_reg_state_t;
+
+typedef struct dwarf_reg_cache_entry
+  {
     unw_word_t ip;                        /* ip this rs is for */
-    unw_word_t ret_addr_column;           /* indicates which column in the rule table represents return address */
-    unsigned short lru_chain;     /* used for least-recently-used chain */
     unsigned short coll_chain;  /* used for hash collisions */
     unsigned short hint;              /* hint for next rs to try (or -1) */
     unsigned short valid : 1;         /* optional machine-dependent signal info */
     unsigned short signal_frame : 1;  /* optional machine-dependent signal info */
   }
-dwarf_reg_state_t;
+dwarf_reg_cache_entry_t;
 
 typedef struct dwarf_cie_info
   {
@@ -308,7 +312,6 @@ typedef struct dwarf_cursor
     unw_word_t cfa;     /* canonical frame address; aka frame-/stack-pointer */
     unw_word_t ip;              /* instruction pointer */
     unw_word_t args_size;       /* size of arguments */
-    unw_word_t ret_addr_column; /* column for return-address */
     unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS];
     unsigned int eh_valid_mask;
 
@@ -325,27 +328,35 @@ typedef struct dwarf_cursor
   }
 dwarf_cursor_t;
 
-#define DWARF_LOG_UNW_CACHE_SIZE        7
-#define DWARF_UNW_CACHE_SIZE    (1 << DWARF_LOG_UNW_CACHE_SIZE)
+#define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE        7
+#define DWARF_DEFAULT_UNW_CACHE_SIZE    (1 << DWARF_DEFAULT_LOG_UNW_CACHE_SIZE)
 
-#define DWARF_LOG_UNW_HASH_SIZE (DWARF_LOG_UNW_CACHE_SIZE + 1)
-#define DWARF_UNW_HASH_SIZE     (1 << DWARF_LOG_UNW_HASH_SIZE)
+#define DWARF_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1)
+#define DWARF_DEFAULT_UNW_HASH_SIZE     (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE)
 
 typedef unsigned char unw_hash_index_t;
 
 struct dwarf_rs_cache
   {
     pthread_mutex_t lock;
-    unsigned short lru_head;    /* index of lead-recently used rs */
-    unsigned short lru_tail;    /* index of most-recently used rs */
+    unsigned short rr_head;    /* index of least-recently allocated rs */
+
+    unsigned short log_size;
+    unsigned short prev_log_size;
 
     /* hash table that maps instruction pointer to rs index: */
-    unsigned short hash[DWARF_UNW_HASH_SIZE];
+    unsigned short *hash;
 
     uint32_t generation;        /* generation number */
 
     /* rs cache: */
-    dwarf_reg_state_t buckets[DWARF_UNW_CACHE_SIZE];
+    dwarf_reg_state_t *buckets;
+    dwarf_reg_cache_entry_t *links;
+
+    /* default memory, loaded in BSS segment */
+    unsigned short default_hash[DWARF_DEFAULT_UNW_HASH_SIZE];
+    dwarf_reg_state_t default_buckets[DWARF_DEFAULT_UNW_CACHE_SIZE];
+    dwarf_reg_cache_entry_t default_links[DWARF_DEFAULT_UNW_CACHE_SIZE];
   };
 
 /* A list of descriptors for loaded .debug_frame sections.  */
@@ -365,18 +376,6 @@ struct unw_debug_frame_list
     struct unw_debug_frame_list *next;
   };
 
-struct dwarf_callback_data
-  {
-    /* in: */
-    unw_word_t ip;              /* instruction-pointer we're looking for */
-    unw_proc_info_t *pi;        /* proc-info pointer */
-    int need_unwind_info;
-    /* out: */
-    int single_fde;             /* did we find a single FDE? (vs. a table) */
-    unw_dyn_info_t di;          /* table info (if single_fde is false) */
-    unw_dyn_info_t di_debug;    /* additional table info for .debug_frame */
-  };
-
 /* Convenience macros: */
 #define dwarf_init                      UNW_ARCH_OBJ (dwarf_init)
 #define dwarf_callback                  UNW_OBJ (dwarf_callback)
@@ -387,13 +386,16 @@ struct dwarf_callback_data
 #define dwarf_put_unwind_info           UNW_OBJ (dwarf_put_unwind_info)
 #define dwarf_put_unwind_info           UNW_OBJ (dwarf_put_unwind_info)
 #define dwarf_eval_expr                 UNW_OBJ (dwarf_eval_expr)
+#define dwarf_stack_aligned             UNW_OBJ (dwarf_stack_aligned)
 #define dwarf_extract_proc_info_from_fde \
                 UNW_OBJ (dwarf_extract_proc_info_from_fde)
 #define dwarf_find_save_locs            UNW_OBJ (dwarf_find_save_locs)
-#define dwarf_create_state_record       UNW_OBJ (dwarf_create_state_record)
 #define dwarf_make_proc_info            UNW_OBJ (dwarf_make_proc_info)
+#define dwarf_apply_reg_state           UNW_OBJ (dwarf_apply_reg_state)
+#define dwarf_reg_states_iterate        UNW_OBJ (dwarf_reg_states_iterate)
 #define dwarf_read_encoded_pointer      UNW_OBJ (dwarf_read_encoded_pointer)
 #define dwarf_step                      UNW_OBJ (dwarf_step)
+#define dwarf_flush_rs_cache            UNW_OBJ (dwarf_flush_rs_cache)
 
 extern int dwarf_init (void);
 #ifndef UNW_REMOTE_ONLY
@@ -411,6 +413,7 @@ extern int dwarf_search_unwind_table (unw_addr_space_t as,
                                       unw_dyn_info_t *di,
                                       unw_proc_info_t *pi,
                                       int need_unwind_info, void *arg);
+
 extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
                                     char *path, unw_word_t segbase, unw_word_t mapoff,
                                     unw_word_t ip);
@@ -419,6 +422,10 @@ extern void dwarf_put_unwind_info (unw_addr_space_t as,
 extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
                             unw_word_t len, unw_word_t *valp,
                             int *is_register);
+extern int
+dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr,
+                    unw_word_t rbp_addr, unw_word_t *offset);
+
 extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
                                              unw_accessors_t *a,
                                              unw_word_t *fde_addr,
@@ -428,9 +435,9 @@ extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
                                              int is_debug_frame,
                                              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);
 extern int dwarf_make_proc_info (struct dwarf_cursor *c);
+extern int dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs);
+extern int dwarf_reg_states_iterate (struct dwarf_cursor *c, unw_reg_states_callback cb, void *token);
 extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
                                        unw_accessors_t *a,
                                        unw_word_t *addr,
@@ -438,5 +445,6 @@ extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
                                        const unw_proc_info_t *pi,
                                        unw_word_t *valp, void *arg);
 extern int dwarf_step (struct dwarf_cursor *c);
+extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache);
 
 #endif /* dwarf_h */
index 4a02a7d..983b9f5 100644 (file)
@@ -352,9 +352,9 @@ dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
   uint16_t uval16;
   uint32_t uval32;
   uint64_t uval64;
-  int16_t sval16;
-  int32_t sval32;
-  int64_t sval64;
+  int16_t sval16 = 0;
+  int32_t sval32 = 0;
+  int64_t sval64 = 0;
   int ret;
 
   /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal
index cd01e57..85812e1 100644 (file)
@@ -46,7 +46,7 @@ extern "C" {
    relatively cheap and unwind-state copying is relatively rare, so we
    want to err on making it rather too big than too small.  */
 
-#define UNW_TDEP_CURSOR_LEN     4096
+#define UNW_TDEP_CURSOR_LEN     512
 
 typedef uint64_t unw_word_t;
 typedef int64_t unw_sword_t;
@@ -175,8 +175,31 @@ typedef ucontext_t unw_tdep_context_t;
 #include "libunwind-common.h"
 #include "libunwind-dynamic.h"
 
-#define unw_tdep_getcontext(uc)         (getcontext (uc), 0)
-#define unw_tdep_is_fpreg               UNW_ARCH_OBJ(is_fpreg)
+#define unw_tdep_getcontext(uc) (({                                    \
+  unw_tdep_context_t *unw_ctx = (uc);                                  \
+  register uint64_t *unw_base asm ("x0") = (uint64_t*) unw_ctx->uc_mcontext.regs;              \
+  __asm__ __volatile__ (                                               \
+     "stp x0, x1, [%[base], #0]\n" \
+     "stp x2, x3, [%[base], #16]\n" \
+     "stp x4, x5, [%[base], #32]\n" \
+     "stp x6, x7, [%[base], #48]\n" \
+     "stp x8, x9, [%[base], #64]\n" \
+     "stp x10, x11, [%[base], #80]\n" \
+     "stp x12, x13, [%[base], #96]\n" \
+     "stp x14, x13, [%[base], #112]\n" \
+     "stp x16, x17, [%[base], #128]\n" \
+     "stp x18, x19, [%[base], #144]\n" \
+     "stp x20, x21, [%[base], #160]\n" \
+     "stp x22, x23, [%[base], #176]\n" \
+     "stp x24, x25, [%[base], #192]\n" \
+     "stp x26, x27, [%[base], #208]\n" \
+     "stp x28, x29, [%[base], #224]\n" \
+     "str x30, [%[base], #240]\n" \
+     "mov x1, sp\n" \
+     "stp x1, x30, [%[base], #248]\n" \
+     : [base] "+r" (unw_base) : : "x1", "memory"); \
+  }), 0)
+#define unw_tdep_is_fpreg              UNW_ARCH_OBJ(is_fpreg)
 
 extern int unw_tdep_is_fpreg (int);
 
index f208487..6709b7a 100644 (file)
@@ -265,7 +265,7 @@ unw_tdep_context_t;
 #ifndef __thumb__
 #define unw_tdep_getcontext(uc) (({                                     \
   unw_tdep_context_t *unw_ctx = (uc);                                   \
-  register unsigned long *unw_base asm ("r0") = unw_ctx->regs;          \
+  register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs;      \
   __asm__ __volatile__ (                                                \
     "stmia %[base], {r0-r15}"                                           \
     : : [base] "r" (unw_base) : "memory");                              \
@@ -273,11 +273,12 @@ unw_tdep_context_t;
 #else /* __thumb__ */
 #define unw_tdep_getcontext(uc) (({                                     \
   unw_tdep_context_t *unw_ctx = (uc);                                   \
-  register unsigned long *unw_base asm ("r0") = unw_ctx->regs;          \
+  register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs;      \
   __asm__ __volatile__ (                                                \
     ".align 2\nbx pc\nnop\n.code 32\n"                                  \
     "stmia %[base], {r0-r15}\n"                                         \
-    "orr %[base], pc, #1\nbx %[base]"                                   \
+    "orr %[base], pc, #1\nbx %[base]\n"                                 \
+    ".code 16\n"                                                       \
     : [base] "+r" (unw_base) : : "memory", "cc");                       \
   }), 0)
 #endif
index fa753ba..8d96ddc 100644 (file)
@@ -86,6 +86,12 @@ typedef enum
   }
 unw_caching_policy_t;
 
+typedef enum
+  {
+    UNW_INIT_SIGNAL_FRAME = 1,          /* We know this is a signal frame */
+  }
+unw_init_local2_flags_t;
+
 typedef int unw_regnum_t;
 
 /* The unwind cursor starts at the youngest (most deeply nested) frame
@@ -126,6 +132,9 @@ typedef struct unw_proc_info
   {
     unw_word_t start_ip;       /* first IP covered by this procedure */
     unw_word_t end_ip;         /* first IP NOT covered by this procedure */
+#if defined(NEED_LAST_IP)
+    unw_word_t last_ip;                /* first IP that could begin another procedure */
+#endif
     unw_word_t lsda;           /* address of lang.-spec. data area (if any) */
     unw_word_t handler;                /* optional personality routine */
     unw_word_t gp;             /* global-pointer value for this procedure */
@@ -138,6 +147,11 @@ typedef struct unw_proc_info
   }
 unw_proc_info_t;
 
+typedef int (*unw_reg_states_callback)(void *token,
+                                      void *reg_states_data,
+                                      size_t reg_states_data_size,
+                                      unw_word_t start_ip, unw_word_t end_ip);
+
 /* These are backend callback routines that provide access to the
    state of a "remote" process.  This can be used, for example, to
    unwind another process through the ptrace() interface.  */
@@ -210,12 +224,16 @@ unw_save_loc_t;
 #define unw_create_addr_space  UNW_OBJ(create_addr_space)
 #define unw_destroy_addr_space UNW_OBJ(destroy_addr_space)
 #define unw_get_accessors      UNW_ARCH_OBJ(get_accessors)
+#define unw_get_accessors_int  UNW_ARCH_OBJ(get_accessors_int)
 #define unw_init_local         UNW_OBJ(init_local)
+#define unw_init_local2                UNW_OBJ(init_local2)
 #define unw_init_remote                UNW_OBJ(init_remote)
 #define unw_step               UNW_OBJ(step)
 #define unw_resume             UNW_OBJ(resume)
 #define unw_get_proc_info      UNW_OBJ(get_proc_info)
 #define unw_get_proc_info_by_ip        UNW_OBJ(get_proc_info_by_ip)
+#define unw_reg_states_iterate  UNW_OBJ(reg_states_iterate)
+#define unw_apply_reg_state     UNW_OBJ(apply_reg_state)
 #define unw_get_reg            UNW_OBJ(get_reg)
 #define unw_set_reg            UNW_OBJ(set_reg)
 #define unw_get_fpreg          UNW_OBJ(get_fpreg)
@@ -225,6 +243,7 @@ unw_save_loc_t;
 #define unw_handle_signal_frame        UNW_OBJ(handle_signal_frame)
 #define unw_get_proc_name      UNW_OBJ(get_proc_name)
 #define unw_set_caching_policy UNW_OBJ(set_caching_policy)
+#define unw_set_cache_size     UNW_OBJ(set_cache_size)
 #define unw_regname            UNW_ARCH_OBJ(regname)
 #define unw_flush_cache                UNW_ARCH_OBJ(flush_cache)
 #define unw_strerror           UNW_ARCH_OBJ(strerror)
@@ -232,17 +251,22 @@ unw_save_loc_t;
 extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int);
 extern void unw_destroy_addr_space (unw_addr_space_t);
 extern unw_accessors_t *unw_get_accessors (unw_addr_space_t);
+extern unw_accessors_t *unw_get_accessors_int (unw_addr_space_t);
 extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t);
 extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t);
+extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
 extern const char *unw_regname (unw_regnum_t);
 
 extern int unw_init_local (unw_cursor_t *, unw_context_t *);
+extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int);
 extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *);
 extern int unw_step (unw_cursor_t *);
 extern int unw_resume (unw_cursor_t *);
 extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *);
 extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t,
                                    unw_proc_info_t *, void *);
+extern int unw_reg_states_iterate (unw_cursor_t *, unw_reg_states_callback, void *);
+extern int unw_apply_reg_state (unw_cursor_t *, void *);
 extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *);
 extern int unw_set_reg (unw_cursor_t *, int, unw_word_t);
 extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *);
index 4591d06..97c95e2 100644 (file)
@@ -30,7 +30,7 @@ extern "C" {
 #endif
 
 #include <inttypes.h>
-#include <ucontext.h>
+#include <sys/ucontext.h>
 
 #ifdef mips
 # undef mips
@@ -50,11 +50,14 @@ extern "C" {
 /* 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.  */
+/* The size of a "word" varies on MIPS. This type is used for memory
+   addresses and register values, which are 32-bit wide for O32 and N32 
+   ABIs, and 64-bit wide for N64 ABI. */
+#if _MIPS_SIM == _ABI64
 typedef uint64_t unw_word_t;
+#else
+typedef uint32_t unw_word_t;
+#endif
 typedef int32_t unw_sword_t;
 
 /* FIXME: MIPS ABIs.  */
@@ -103,7 +106,7 @@ typedef enum
        previous frame.  */
     UNW_MIPS_CFA,
 
-    UNW_TDEP_LAST_REG = UNW_MIPS_R31,
+    UNW_TDEP_LAST_REG = UNW_MIPS_PC,
 
     UNW_TDEP_IP = UNW_MIPS_R31,
     UNW_TDEP_SP = UNW_MIPS_R29,
index ee2ea2f..36cf7a1 100644 (file)
@@ -37,11 +37,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "compiler.h"
 
-#ifdef HAVE___THREAD
-  /* For now, turn off per-thread caching.  It uses up too much TLS
-     memory per thread even when the thread never uses libunwind at
-     all.  */
-# undef HAVE___THREAD
+#if defined(HAVE___THREAD) && HAVE___THREAD
+#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_PER_THREAD
+#else
+#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_GLOBAL
 #endif
 
 /* Platform-independent libunwind-internal declarations.  */
@@ -69,6 +68,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 # include <endian.h>
 #elif defined(HAVE_SYS_ENDIAN_H)
 # include <sys/endian.h>
+# if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
+#   define __LITTLE_ENDIAN _LITTLE_ENDIAN
+# endif
+# if defined(_BIG_ENDIAN) && !defined(__BIG_ENDIAN)
+#   define __BIG_ENDIAN _BIG_ENDIAN
+# endif
+# if defined(_BYTE_ORDER) && !defined(__BYTE_ORDER)
+#   define __BYTE_ORDER _BYTE_ORDER
+# endif
 #else
 # define __LITTLE_ENDIAN        1234
 # define __BIG_ENDIAN           4321
index 6fdf64c..064d630 100644 (file)
@@ -74,7 +74,8 @@ fetch16 (unw_addr_space_t as, unw_accessors_t *a,
   unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
   int ret;
 
-  assert ((off & 0x1) == 0);
+  if ((off & 0x1) != 0)
+    return -UNW_EINVAL;
 
   *addr += 2;
 
@@ -96,7 +97,8 @@ fetch32 (unw_addr_space_t as, unw_accessors_t *a,
   unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
   int ret;
 
-  assert ((off & 0x3) == 0);
+  if ((off & 0x3) != 0)
+    return -UNW_EINVAL;
 
   *addr += 4;
 
index ca28155..b91273f 100644 (file)
@@ -269,11 +269,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame                UNW_OBJ(tdep_stash_frame)
 #define tdep_trace                      UNW_OBJ(tdep_trace)
 
@@ -306,6 +307,7 @@ extern void *tdep_uc_addr (unw_tdep_context_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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index d3a279c..2602f41 100644 (file)
@@ -38,6 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 typedef enum
   {
+    UNW_ARM_FRAME_SYSCALL = -3,      /* r7 saved in r12, sp offset zero */
     UNW_ARM_FRAME_STANDARD = -2,     /* regular r7, sp +/- offset */
     UNW_ARM_FRAME_SIGRETURN = -1,    /* special sigreturn frame */
     UNW_ARM_FRAME_OTHER = 0,         /* not cacheable (special or unrecognised) */
@@ -48,7 +49,7 @@ unw_tdep_frame_type_t;
 typedef struct
   {
     uint32_t virtual_address;
-    int32_t frame_type     : 2;  /* unw_tdep_frame_type_t classification */
+    int32_t frame_type     : 3;  /* unw_tdep_frame_type_t classification */
     int32_t last_frame     : 1;  /* non-zero if last frame in chain */
     int32_t cfa_reg_sp     : 1;  /* cfa dwarf base register is sp vs. r7 */
     int32_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
@@ -86,7 +87,9 @@ struct cursor
         ARM_SCF_LINUX_SIGFRAME,         /* non-RT signal frame, kernel >=2.6.18 */
         ARM_SCF_LINUX_RT_SIGFRAME,      /* RT signal frame, kernel >=2.6.18 */
         ARM_SCF_LINUX_OLD_SIGFRAME,     /* non-RT signal frame, kernel < 2.6.18 */
-        ARM_SCF_LINUX_OLD_RT_SIGFRAME   /* RT signal frame, kernel < 2.6.18 */
+        ARM_SCF_LINUX_OLD_RT_SIGFRAME,  /* RT signal frame, kernel < 2.6.18 */
+        ARM_SCF_FREEBSD_SIGFRAME,      /* FreeBSD sigframe */
+       ARM_SCF_FREEBSD_SYSCALL,        /* FreeBSD syscall stub */
       }
     sigcontext_format;
     unw_word_t sigcontext_addr;
@@ -257,11 +260,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_ARCH_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame                UNW_OBJ(tdep_stash_frame)
 #define tdep_trace                      UNW_OBJ(tdep_trace)
 
@@ -299,6 +303,7 @@ extern void *tdep_uc_addr (unw_tdep_context_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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index d5cc1b9..72649aa 100644 (file)
@@ -232,11 +232,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_ARCH_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame(c,rs)          do {} while(0)
 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
 
@@ -269,6 +270,7 @@ 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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index 7e57c7b..1d9770b 100644 (file)
@@ -226,11 +226,12 @@ struct ia64_global_unwind_state
 #define tdep_find_proc_info             UNW_OBJ(find_proc_info)
 #define tdep_uc_addr                    UNW_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame(c,rs)          do {} while(0)
 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
 #define tdep_get_as(c)                  ((c)->as)
@@ -245,7 +246,7 @@ struct ia64_global_unwind_state
 /* This can't be an UNW_ARCH_OBJ() because we need separate
    unw.initialized flags for the local-only and generic versions of
    the library.  Also, if we wanted to have a single, shared global
-   data structure, we couldn't declare "unw" as HIDDEN/PROTECTED.  */
+   data structure, we couldn't declare "unw" as HIDDEN.  */
 #define unw                             UNW_OBJ(data)
 
 extern void tdep_init (void);
@@ -263,6 +264,7 @@ extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum,
 extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
                                unsigned long *segbase, unsigned long *mapoff,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index d11894d..3fe40c0 100644 (file)
@@ -285,11 +285,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_ARCH_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame(c,rs)          do {} while(0)
 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
 
@@ -321,6 +322,7 @@ 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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index cc113c5..4cf6d13 100644 (file)
@@ -260,11 +260,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_ARCH_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame(c,rs)          do {} while(0)
 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
 #define tdep_get_func_addr              UNW_OBJ(get_func_addr)
@@ -302,6 +303,7 @@ 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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index 5a5bddb..975f3bb 100644 (file)
@@ -315,11 +315,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_ARCH_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame(c,rs)          do {} while(0)
 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
 #define tdep_get_func_addr              UNW_OBJ(get_func_addr)
@@ -357,6 +358,7 @@ 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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index 7bbb29b..8ced491 100644 (file)
@@ -233,11 +233,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_ARCH_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame(c,rs)          do {} while(0)
 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
 
@@ -270,6 +271,7 @@ extern void *tdep_uc_addr (unw_tdep_context_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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index 9a4ec6a..2cfed45 100644 (file)
@@ -36,10 +36,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "mempool.h"
 #include "dwarf.h"
 
-#ifdef HAVE___THREAD
-# undef HAVE___THREAD
-#endif
-
 typedef struct
 {
   /* no Tilegx-specific fast trace */
@@ -212,11 +208,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_ARCH_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame(c,rs)          do {} while(0)
 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
 
@@ -253,6 +250,7 @@ extern int tdep_get_elf_image (struct elf_image *ei,
                                unsigned long *segbase,
                                unsigned long *mapoff,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 extern int tdep_access_reg (struct cursor *c,
                             unw_regnum_t reg,
                             unw_word_t *valp,
index b1c8b98..5231189 100644 (file)
@@ -246,11 +246,12 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_uc_addr                    UNW_ARCH_OBJ(uc_addr)
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
-#define tdep_cache_frame(c,rs)          do {} while(0)
-#define tdep_reuse_frame(c,rs)          do {} while(0)
+#define tdep_cache_frame(c)             0
+#define tdep_reuse_frame(c,frame)       do {} while(0)
 #define tdep_stash_frame(c,rs)          do {} while(0)
 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
 
@@ -283,6 +284,7 @@ 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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
index d19c705..283525c 100644 (file)
@@ -40,6 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 typedef enum
   {
+    UNW_X86_64_FRAME_ALIGNED = -3,       /* frame stack pointer aligned */
     UNW_X86_64_FRAME_STANDARD = -2,     /* regular rbp, rsp +/- offset */
     UNW_X86_64_FRAME_SIGRETURN = -1,    /* special sigreturn frame */
     UNW_X86_64_FRAME_OTHER = 0,         /* not cacheable (special or unrecognised) */
@@ -50,10 +51,10 @@ unw_tdep_frame_type_t;
 typedef struct
   {
     uint64_t virtual_address;
-    int64_t frame_type     : 2;  /* unw_tdep_frame_type_t classification */
+    int64_t frame_type     : 3;  /* unw_tdep_frame_type_t classification */
     int64_t last_frame     : 1;  /* non-zero if last frame in chain */
     int64_t cfa_reg_rsp    : 1;  /* cfa dwarf base register is rsp vs. rbp */
-    int64_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
+    int64_t cfa_reg_offset : 29; /* cfa is at this offset from base register value */
     int64_t rbp_cfa_offset : 15; /* rbp saved at this offset from cfa (-1 = not saved) */
     int64_t rsp_cfa_offset : 15; /* rsp saved at this offset from cfa (-1 = not saved) */
   }
@@ -196,6 +197,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_search_unwind_table        dwarf_search_unwind_table
 #define tdep_find_unwind_table          dwarf_find_unwind_table
 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
+#define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
 #define tdep_access_reg                 UNW_OBJ(access_reg)
 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
 #if __linux__
@@ -204,8 +206,8 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 # define tdep_reuse_frame               UNW_OBJ(reuse_frame)
 #else
 # define tdep_fetch_frame(c,ip,n)       do {} while(0)
-# define tdep_cache_frame(c,rs)         do {} while(0)
-# define tdep_reuse_frame(c,rs)         do {} while(0)
+# define tdep_cache_frame(c)            0
+# define tdep_reuse_frame(c,frame)      do {} while(0)
 #endif
 #define tdep_stash_frame                UNW_OBJ(stash_frame)
 #define tdep_trace                      UNW_OBJ(tdep_trace)
@@ -241,6 +243,7 @@ extern void *x86_64_r_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,
                                char *path, size_t pathlen);
+extern void tdep_get_exe_image_path (char *path);
 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,
@@ -248,10 +251,9 @@ extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
 #if __linux__
 extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip,
                               int need_unwind_info);
-extern void tdep_cache_frame (struct dwarf_cursor *c,
-                              struct dwarf_reg_state *rs);
+extern int tdep_cache_frame (struct dwarf_cursor *c);
 extern void tdep_reuse_frame (struct dwarf_cursor *c,
-                              struct dwarf_reg_state *rs);
+                              int frame);
 extern void tdep_stash_frame (struct dwarf_cursor *c,
                               struct dwarf_reg_state *rs);
 #endif
index 4eae183..13093a0 100644 (file)
@@ -5,7 +5,7 @@
 
 #if defined __aarch64__
 # include "tdep-aarch64/jmpbuf.h"
-#if defined __arm__
+#elif defined __arm__
 # include "tdep-arm/jmpbuf.h"
 #elif defined __hppa__
 # include "tdep-hppa/jmpbuf.h"
index 5d87475..a557d8d 100644 (file)
@@ -109,7 +109,8 @@ libunwind_la_SOURCES_generic =                                              \
        mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c          \
        mi/Gget_reg.c mi/Gset_reg.c                                     \
        mi/Gget_fpreg.c mi/Gset_fpreg.c                                 \
-       mi/Gset_caching_policy.c
+       mi/Gset_caching_policy.c                                        \
+       mi/Gset_cache_size.c
 
 if SUPPORT_CXX_EXCEPTIONS
 libunwind_la_SOURCES_local_unwind =                                    \
@@ -137,7 +138,8 @@ libunwind_la_SOURCES_local_nounwind =                                       \
        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
+       mi/Lset_caching_policy.c                                        \
+       mi/Lset_cache_size.c
 
 libunwind_la_SOURCES_local =                                           \
        $(libunwind_la_SOURCES_local_nounwind)                          \
@@ -155,13 +157,13 @@ libunwind_la_SOURCES_os_qnx = os-qnx.c
 libunwind_dwarf_common_la_SOURCES = dwarf/global.c
 
 libunwind_dwarf_local_la_SOURCES = \
-       dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c dwarf/Lstep.c \
+       dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c \
        dwarf/Lfind_proc_info-lsb.c \
        dwarf/Lfind_unwind_table.c
 libunwind_dwarf_local_la_LIBADD = libunwind-dwarf-common.la
 
 libunwind_dwarf_generic_la_SOURCES = \
-       dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c dwarf/Gstep.c \
+       dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c \
        dwarf/Gfind_proc_info-lsb.c \
        dwarf/Gfind_unwind_table.c
 libunwind_dwarf_generic_la_LIBADD = libunwind-dwarf-common.la
@@ -194,6 +196,7 @@ libunwind_la_SOURCES_aarch64_common = $(libunwind_la_SOURCES_common)            \
 # The list of files that go into libunwind:
 libunwind_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common)      \
        $(libunwind_la_SOURCES_local)                                       \
+       aarch64/Lapply_reg_state.c aarch64/Lreg_states_iterate.c            \
        aarch64/Lcreate_addr_space.c aarch64/Lget_proc_info.c               \
        aarch64/Lget_save_loc.c aarch64/Lglobal.c aarch64/Linit.c           \
        aarch64/Linit_local.c aarch64/Linit_remote.c                        \
@@ -203,6 +206,7 @@ libunwind_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common)           \
 
 libunwind_aarch64_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common) \
        $(libunwind_la_SOURCES_generic)                                       \
+       aarch64/Gapply_reg_state.c aarch64/Greg_states_iterate.c              \
        aarch64/Gcreate_addr_space.c aarch64/Gget_proc_info.c                 \
        aarch64/Gget_save_loc.c aarch64/Gglobal.c aarch64/Ginit.c             \
        aarch64/Ginit_local.c aarch64/Ginit_remote.c                          \
@@ -216,18 +220,23 @@ libunwind_la_SOURCES_arm_common = $(libunwind_la_SOURCES_common)      \
 
 # The list of files that go into libunwind:
 libunwind_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common)              \
+       $(libunwind_la_SOURCES_arm_os_local)                                \
        $(libunwind_la_SOURCES_local)                                       \
        arm/getcontext.S                                                    \
+       arm/Lapply_reg_state.c arm/Lreg_states_iterate.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        \
+       arm/Lregs.c arm/Lresume.c arm/Lstep.c                               \
        arm/Lex_tables.c arm/Lstash_frame.c arm/Ltrace.c
 
+# The list of files that go into libunwind-arm:
 libunwind_arm_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common)          \
+       $(libunwind_la_SOURCES_arm_os)                                      \
        $(libunwind_la_SOURCES_generic)                                     \
+       arm/Gapply_reg_state.c arm/Greg_states_iterate.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        \
+       arm/Gregs.c arm/Gresume.c arm/Gstep.c                               \
        arm/Gex_tables.c arm/Gstash_frame.c arm/Gtrace.c
 
 # The list of files that go both into libunwind and libunwind-ia64:
@@ -242,6 +251,7 @@ libunwind_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common)                  \
                                                                             \
        ia64/dyn_info_list.S ia64/getcontext.S                               \
                                                                             \
+       ia64/Lapply_reg_state.c ia64/Lreg_states_iterate.c                   \
        ia64/Lcreate_addr_space.c ia64/Lget_proc_info.c ia64/Lget_save_loc.c \
        ia64/Lglobal.c ia64/Linit.c ia64/Linit_local.c ia64/Linit_remote.c   \
        ia64/Linstall_cursor.S ia64/Lis_signal_frame.c ia64/Lparser.c        \
@@ -251,6 +261,7 @@ libunwind_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common)                  \
 # The list of files that go into libunwind-ia64:
 libunwind_ia64_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common)        \
        $(libunwind_la_SOURCES_generic)                                      \
+       ia64/Gapply_reg_state.c ia64/Greg_states_iterate.c                   \
        ia64/Gcreate_addr_space.c ia64/Gget_proc_info.c ia64/Gget_save_loc.c \
        ia64/Gglobal.c ia64/Ginit.c ia64/Ginit_local.c ia64/Ginit_remote.c   \
        ia64/Ginstall_cursor.S ia64/Gis_signal_frame.c ia64/Gparser.c        \
@@ -266,6 +277,7 @@ libunwind_la_SOURCES_hppa_common = $(libunwind_la_SOURCES_common)   \
 libunwind_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common)                \
        $(libunwind_la_SOURCES_local)                                   \
        hppa/getcontext.S hppa/setcontext.S                             \
+       hppa/Lapply_reg_state.c hppa/Lreg_states_iterate.c              \
        hppa/Lcreate_addr_space.c hppa/Lget_save_loc.c hppa/Lglobal.c   \
        hppa/Linit.c hppa/Linit_local.c hppa/Linit_remote.c             \
        hppa/Lis_signal_frame.c hppa/Lget_proc_info.c hppa/Lregs.c      \
@@ -274,13 +286,14 @@ libunwind_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common)           \
 # The list of files that go into libunwind-hppa:
 libunwind_hppa_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common)   \
        $(libunwind_la_SOURCES_generic)                                 \
+       hppa/Gapply_reg_state.c hppa/Greg_states_iterate.c              \
        hppa/Gcreate_addr_space.c hppa/Gget_save_loc.c hppa/Gglobal.c   \
        hppa/Ginit.c hppa/Ginit_local.c hppa/Ginit_remote.c             \
        hppa/Gis_signal_frame.c hppa/Gget_proc_info.c hppa/Gregs.c      \
        hppa/Gresume.c hppa/Gstep.c
 
 # The list of files that go info libunwind and libunwind-mips:
-noinst_HEADERS += mips/init.h mips/offsets.h
+noinst_HEADERS += mips/init.h mips/offsets.h mips/unwind_i.h
 libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common)          \
        mips/is_fpreg.c mips/regname.c
 
@@ -288,18 +301,20 @@ libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common)     \
 libunwind_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common)                    \
        $(libunwind_la_SOURCES_local)                                       \
        mips/getcontext.S                                                   \
+       mips/Lapply_reg_state.c mips/Lreg_states_iterate.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)                                     \
+       mips/Gapply_reg_state.c mips/Greg_states_iterate.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 info libunwind and libunwind-tilegx:
-noinst_HEADERS += tilegx/init.h tilegx/offsets.h
+noinst_HEADERS += tilegx/init.h tilegx/offsets.h tilegx/unwind_i.h
 libunwind_la_SOURCES_tilegx_common = $(libunwind_la_SOURCES_common)        \
        tilegx/is_fpreg.c tilegx/regname.c
 
@@ -307,12 +322,14 @@ libunwind_la_SOURCES_tilegx_common = $(libunwind_la_SOURCES_common)           \
 libunwind_la_SOURCES_tilegx = $(libunwind_la_SOURCES_tilegx_common)                \
        $(libunwind_la_SOURCES_local)                                       \
        tilegx/getcontext.S                                             \
+       tilegx/Lapply_reg_state.c tilegx/Lreg_states_iterate.c              \
        tilegx/Lcreate_addr_space.c tilegx/Lget_proc_info.c tilegx/Lget_save_loc.c   \
        tilegx/Lglobal.c tilegx/Linit.c tilegx/Linit_local.c tilegx/Linit_remote.c  \
        tilegx/Lis_signal_frame.c tilegx/Lregs.c tilegx/Lresume.c tilegx/Lstep.c
 
 libunwind_tilegx_la_SOURCES_tilegx = $(libunwind_la_SOURCES_tilegx_common)         \
        $(libunwind_la_SOURCES_generic)                                     \
+       tilegx/Gapply_reg_state.c tilegx/Greg_states_iterate.c                       \
        tilegx/Gcreate_addr_space.c tilegx/Gget_proc_info.c tilegx/Gget_save_loc.c   \
        tilegx/Gglobal.c tilegx/Ginit.c tilegx/Ginit_local.c tilegx/Ginit_remote.c          \
        tilegx/Gis_signal_frame.c tilegx/Gregs.c tilegx/Gresume.c tilegx/Gstep.c
@@ -327,6 +344,7 @@ libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common)    \
 libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common)          \
         $(libunwind_la_SOURCES_x86_os_local)                           \
        $(libunwind_la_SOURCES_local)                                   \
+       x86/Lapply_reg_state.c x86/Lreg_states_iterate.c                \
        x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c      \
        x86/Linit.c x86/Linit_local.c x86/Linit_remote.c                \
        x86/Lget_proc_info.c x86/Lregs.c                                \
@@ -336,6 +354,7 @@ libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common)               \
 libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common)      \
         $(libunwind_la_SOURCES_x86_os)                                 \
        $(libunwind_la_SOURCES_generic)                                 \
+       x86/Gapply_reg_state.c x86/Greg_states_iterate.c                \
        x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c      \
        x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c                \
        x86/Gget_proc_info.c x86/Gregs.c                                \
@@ -352,6 +371,7 @@ libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common)     \
         $(libunwind_la_SOURCES_x86_64_os_local)                                    \
        $(libunwind_la_SOURCES_local)                                       \
        x86_64/setcontext.S                                                 \
+       x86_64/Lapply_reg_state.c x86_64/Lreg_states_iterate.c              \
        x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c \
        x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c           \
        x86_64/Lget_proc_info.c x86_64/Lregs.c x86_64/Lresume.c             \
@@ -361,6 +381,7 @@ libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common)     \
 libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common)  \
         $(libunwind_la_SOURCES_x86_64_os)                                  \
        $(libunwind_la_SOURCES_generic)                                     \
+       x86_64/Gapply_reg_state.c x86_64/Greg_states_iterate.c              \
        x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c \
        x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c           \
        x86_64/Gget_proc_info.c x86_64/Gregs.c x86_64/Gresume.c             \
@@ -385,6 +406,7 @@ libunwind_la_SOURCES_ppc32_common = $(libunwind_la_SOURCES_common)      \
 libunwind_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common)       \
        $(libunwind_la_SOURCES_local)                                   \
        $(libunwind_la_SOURCES_ppc)                                     \
+       ppc32/Lapply_reg_state.c ppc32/Lreg_states_iterate.c            \
        ppc32/Lcreate_addr_space.c                                      \
        ppc32/Lglobal.c ppc32/Linit.c                                   \
        ppc32/Lregs.c ppc32/Lresume.c ppc32/Lstep.c
@@ -393,6 +415,7 @@ libunwind_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common)       \
 libunwind_ppc32_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \
        $(libunwind_la_SOURCES_generic)                                 \
        $(libunwind_ppc_la_SOURCES_ppc_generic)                         \
+       ppc32/Gapply_reg_state.c ppc32/Greg_states_iterate.c            \
        ppc32/Gcreate_addr_space.c                                      \
        ppc32/Gglobal.c ppc32/Ginit.c                                   \
        ppc32/Gregs.c ppc32/Gresume.c ppc32/Gstep.c
@@ -406,6 +429,7 @@ libunwind_la_SOURCES_ppc64_common = $(libunwind_la_SOURCES_common)      \
 libunwind_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common)       \
         $(libunwind_la_SOURCES_local)                                   \
        $(libunwind_la_SOURCES_ppc)                                     \
+       ppc64/Lapply_reg_state.c ppc64/Lreg_states_iterate.c            \
        ppc64/Lcreate_addr_space.c                                      \
        ppc64/Lglobal.c ppc64/Linit.c                                   \
        ppc64/Lregs.c ppc64/Lresume.c ppc64/Lstep.c
@@ -414,6 +438,7 @@ libunwind_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common)       \
 libunwind_ppc64_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \
         $(libunwind_la_SOURCES_generic)                                 \
        $(libunwind_ppc_la_SOURCES_ppc_generic)                         \
+       ppc64/Gapply_reg_state.c ppc64/Greg_states_iterate.c            \
        ppc64/Gcreate_addr_space.c                                      \
        ppc64/Gglobal.c ppc64/Ginit.c                                   \
        ppc64/Gregs.c ppc64/Gresume.c ppc64/Gstep.c
@@ -426,12 +451,14 @@ libunwind_la_SOURCES_sh_common = $(libunwind_la_SOURCES_common)           \
 # The list of files that go into libunwind:
 libunwind_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common)            \
        $(libunwind_la_SOURCES_local)                                   \
+       sh/Lapply_reg_state.c sh/Lreg_states_iterate.c                  \
        sh/Lcreate_addr_space.c sh/Lget_proc_info.c sh/Lget_save_loc.c  \
        sh/Lglobal.c sh/Linit.c sh/Linit_local.c sh/Linit_remote.c      \
        sh/Lis_signal_frame.c sh/Lregs.c sh/Lresume.c sh/Lstep.c
 
 libunwind_sh_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common)         \
        $(libunwind_la_SOURCES_generic)                                 \
+       sh/Gapply_reg_state.c sh/Greg_states_iterate.c                  \
        sh/Gcreate_addr_space.c sh/Gget_proc_info.c sh/Gget_save_loc.c  \
        sh/Gglobal.c sh/Ginit.c sh/Ginit_local.c sh/Ginit_remote.c      \
        sh/Gis_signal_frame.c sh/Gregs.c sh/Gresume.c sh/Gstep.c
@@ -447,7 +474,9 @@ else
 # to be there if the user configured with --disable-shared.
 #
 install-exec-hook:
-       cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).a libunwind-generic.a
+       if test -f $(DESTDIR)$(libdir)/libunwind-$(arch).a; then \
+               cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).a libunwind-generic.a; \
+       fi
        if test -f $(DESTDIR)$(libdir)/libunwind-$(arch).so; then \
                cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).so \
                libunwind-generic.so; \
@@ -462,6 +491,8 @@ if OS_LINUX
  libunwind_la_SOURCES_x86_os_local    = x86/Los-linux.c
  libunwind_la_SOURCES_x86_64_os       = x86_64/Gos-linux.c
  libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-linux.c
+ libunwind_la_SOURCES_arm_os          = arm/Gos-linux.c
+ libunwind_la_SOURCES_arm_os_local    = arm/Los-linux.c
  libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_linux.c
 endif
 
@@ -478,12 +509,16 @@ if OS_FREEBSD
  libunwind_la_SOURCES_x86_os_local    = x86/Los-freebsd.c
  libunwind_la_SOURCES_x86_64_os       = x86_64/Gos-freebsd.c
  libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-freebsd.c
+ libunwind_la_SOURCES_arm_os          = arm/Gos-freebsd.c
+ libunwind_la_SOURCES_arm_os_local    = arm/Los-freebsd.c
  libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_freebsd.c
 endif
 
 if OS_QNX
  libunwind_la_SOURCES_os       = $(libunwind_la_SOURCES_os_qnx)
  libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_qnx_local)
+ libunwind_la_SOURCES_arm_os          = arm/Gos-other.c
+ libunwind_la_SOURCES_arm_os_local    = arm/Los-other.c
 endif
 
 if ARCH_AARCH64
diff --git a/src/aarch64/Gapply_reg_state.c b/src/aarch64/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index b0f2b04..f217adc 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index de9199f..c363d24 100644 (file)
@@ -24,7 +24,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index 5ccf5cf..86bbbd0 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   struct cursor *c = (struct cursor *) cursor;
index b9181ef..9c4eae8 100644 (file)
@@ -32,19 +32,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 static inline void *
 uc_addr (ucontext_t *uc, int reg)
 {
-  if (reg >= UNW_AARCH64_X0 && reg <= UNW_AARCH64_V31)
+  if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_V0)
     return &uc->uc_mcontext.regs[reg];
+  else if (reg >= UNW_AARCH64_V0 && reg <= UNW_AARCH64_V31)
+    return &GET_FPCTX(uc)->vregs[reg - UNW_AARCH64_V0];
   else
     return NULL;
 }
@@ -172,7 +174,7 @@ HIDDEN void
 aarch64_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.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
index dee6fd3..cd60ca8 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
 {
   return -UNW_EINVAL;
@@ -36,8 +36,8 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+static int
+unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -49,7 +49,30 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
   c->dwarf.as = unw_local_addr_space;
   c->dwarf.as_arg = uc;
 
-  return common_init (c, 1);
+  return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
 }
 
 #endif /* !UNW_REMOTE_ONLY */
index f284e99..9b8ba5b 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index 53e32de..67159d8 100644 (file)
@@ -31,7 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
    d4000001        svc     #0x0
 */
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
 #ifdef __linux__
@@ -43,7 +43,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   int ret;
 
   as = c->dwarf.as;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   arg = c->dwarf.as_arg;
 
   ip = c->dwarf.ip;
similarity index 77%
rename from src/dwarf/Gstep.c
rename to src/aarch64/Greg_states_iterate.c
index d251af9..a17dc1b 100644 (file)
@@ -1,7 +1,9 @@
 /* libunwind - a platform-independent unwind library
-   Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
         Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
 This file is part of libunwind.
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -23,19 +25,13 @@ 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 "dwarf.h"
-#include "libunwind_i.h"
+#include "unwind_i.h"
 
-HIDDEN int
-dwarf_step (struct dwarf_cursor *c)
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
 {
-  int ret;
-
-  if ((ret = dwarf_find_save_locs (c)) >= 0) {
-    c->pi_valid = 0;
-    ret = 1;
-  }
+  struct cursor *c = (struct cursor *) cursor;
 
-  Debug (15, "returning %d\n", ret);
-  return ret;
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
 }
index 6288275..a884373 100644 (file)
@@ -55,6 +55,9 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
         loc = c->dwarf.loc[reg];
       break;
 
+    case UNW_AARCH64_X30:
+      if (write)
+        c->dwarf.ip = *valp;            /* update the IP cache */
     case UNW_AARCH64_X4:
     case UNW_AARCH64_X5:
     case UNW_AARCH64_X6:
@@ -81,7 +84,6 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
     case UNW_AARCH64_X27:
     case UNW_AARCH64_X28:
     case UNW_AARCH64_X29:
-    case UNW_AARCH64_X30:
     case UNW_AARCH64_PC:
     case UNW_AARCH64_PSTATE:
       loc = c->dwarf.loc[reg];
@@ -108,6 +110,9 @@ 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;
+  dwarf_loc_t loc = c->dwarf.loc[reg];
+  if (write)
+    return dwarf_putfp (&c->dwarf, loc, *valp);
+  else
+    return dwarf_getfp (&c->dwarf, loc, valp);
 }
index d9acfa7..3d82739 100644 (file)
@@ -40,7 +40,7 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
     {
       /* Since there are no signals involved here we restore EH and non scratch
          registers only.  */
-      unsigned long regs[15];
+      unsigned long regs[24];
       regs[0] = uc->uc_mcontext.regs[0];
       regs[1] = uc->uc_mcontext.regs[1];
       regs[2] = uc->uc_mcontext.regs[2];
@@ -55,7 +55,16 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
       regs[11] = uc->uc_mcontext.regs[26];
       regs[12] = uc->uc_mcontext.regs[27];
       regs[13] = uc->uc_mcontext.regs[28];
-      regs[14] = uc->uc_mcontext.regs[30]; /* LR */
+      regs[14] = uc->uc_mcontext.regs[29]; /* FP */
+      regs[15] = uc->uc_mcontext.regs[30]; /* LR */
+      regs[16] = GET_FPCTX(uc)->vregs[8];
+      regs[17] = GET_FPCTX(uc)->vregs[9];
+      regs[18] = GET_FPCTX(uc)->vregs[10];
+      regs[19] = GET_FPCTX(uc)->vregs[11];
+      regs[20] = GET_FPCTX(uc)->vregs[12];
+      regs[21] = GET_FPCTX(uc)->vregs[13];
+      regs[22] = GET_FPCTX(uc)->vregs[14];
+      regs[23] = GET_FPCTX(uc)->vregs[15];
       unsigned long sp = uc->uc_mcontext.sp;
 
       struct regs_overlay {
@@ -72,7 +81,11 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
         "ldp x23, x24, [x4,64]\n"
         "ldp x25, x26, [x4,80]\n"
         "ldp x27, x28, [x4,96]\n"
-        "ldr x30, [x4,112]\n"
+        "ldp x29, x30, [x4,112]\n"
+        "ldp d8, d9,   [x4,128]\n"
+        "ldp d10, d11, [x4,144]\n"
+        "ldp d12, d13, [x4,160]\n"
+        "ldp d14, d15, [x4,176]\n"
         "mov sp, x5\n"
         "ret \n"
         :
@@ -147,7 +160,7 @@ establish_machine_state (struct cursor *c)
 
   Debug (8, "copying out cursor state\n");
 
-  for (reg = 0; reg <= UNW_AARCH64_PSTATE; ++reg)
+  for (reg = 0; reg <= UNW_AARCH64_V31; ++reg)
     {
       Debug (16, "copying %s %d\n", unw_regname (reg), reg);
       if (unw_is_fpreg (reg))
@@ -163,7 +176,7 @@ establish_machine_state (struct cursor *c)
     }
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 9c1a54d..6689af1 100644 (file)
@@ -36,13 +36,13 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
          " ra=0x%lx fp [where=%d val=%ld @0x%lx] lr [where=%d val=%ld @0x%lx] "
          "sp [where=%d val=%ld @0x%lx]\n",
          d->ip, d->cfa, f->frame_type,
-         rs->reg[DWARF_CFA_REG_COLUMN].where,
-         rs->reg[DWARF_CFA_REG_COLUMN].val,
-         rs->reg[DWARF_CFA_OFF_COLUMN].val,
-         DWARF_GET_LOC(d->loc[d->ret_addr_column]),
-         rs->reg[FP].where, rs->reg[FP].val, DWARF_GET_LOC(d->loc[FP]),
-         rs->reg[LR].where, rs->reg[LR].val, DWARF_GET_LOC(d->loc[LR]),
-         rs->reg[SP].where, rs->reg[SP].val, DWARF_GET_LOC(d->loc[SP]));
+         rs->reg.where[DWARF_CFA_REG_COLUMN],
+         rs->reg.val[DWARF_CFA_REG_COLUMN],
+         rs->reg.val[DWARF_CFA_OFF_COLUMN],
+         DWARF_GET_LOC(d->loc[rs->ret_addr_column]),
+         rs->reg.where[FP], rs->reg.val[FP], DWARF_GET_LOC(d->loc[FP]),
+         rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]),
+         rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP]));
 
   /* A standard frame is defined as:
       - CFA is register-relative offset off FP or SP;
@@ -51,37 +51,37 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
       - LR is unsaved or saved at CFA+offset, offset != -1;
       - SP is unsaved or saved at CFA+offset, offset != -1.  */
   if (f->frame_type == UNW_AARCH64_FRAME_OTHER
-      && (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
-      && (rs->reg[DWARF_CFA_REG_COLUMN].val == FP
-          || rs->reg[DWARF_CFA_REG_COLUMN].val == SP)
-      && labs(rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
-      && d->ret_addr_column == LR
-      && (rs->reg[FP].where == DWARF_WHERE_UNDEF
-          || rs->reg[FP].where == DWARF_WHERE_SAME
-          || (rs->reg[FP].where == DWARF_WHERE_CFAREL
-              && labs(rs->reg[FP].val) < (1 << 29)
-              && rs->reg[FP].val+1 != 0))
-      && (rs->reg[LR].where == DWARF_WHERE_UNDEF
-          || rs->reg[LR].where == DWARF_WHERE_SAME
-          || (rs->reg[LR].where == DWARF_WHERE_CFAREL
-              && labs(rs->reg[LR].val) < (1 << 29)
-              && rs->reg[LR].val+1 != 0))
-      && (rs->reg[SP].where == DWARF_WHERE_UNDEF
-          || rs->reg[SP].where == DWARF_WHERE_SAME
-          || (rs->reg[SP].where == DWARF_WHERE_CFAREL
-              && labs(rs->reg[SP].val) < (1 << 29)
-              && rs->reg[SP].val+1 != 0)))
+      && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
+      && (rs->reg.val[DWARF_CFA_REG_COLUMN] == FP
+          || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP)
+      && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29)
+      && rs->ret_addr_column == LR
+      && (rs->reg.where[FP] == DWARF_WHERE_UNDEF
+          || rs->reg.where[FP] == DWARF_WHERE_SAME
+          || (rs->reg.where[FP] == DWARF_WHERE_CFAREL
+              && labs(rs->reg.val[FP]) < (1 << 29)
+              && rs->reg.val[FP]+1 != 0))
+      && (rs->reg.where[LR] == DWARF_WHERE_UNDEF
+          || rs->reg.where[LR] == DWARF_WHERE_SAME
+          || (rs->reg.where[LR] == DWARF_WHERE_CFAREL
+              && labs(rs->reg.val[LR]) < (1 << 29)
+              && rs->reg.val[LR]+1 != 0))
+      && (rs->reg.where[SP] == DWARF_WHERE_UNDEF
+          || rs->reg.where[SP] == DWARF_WHERE_SAME
+          || (rs->reg.where[SP] == DWARF_WHERE_CFAREL
+              && labs(rs->reg.val[SP]) < (1 << 29)
+              && rs->reg.val[SP]+1 != 0)))
   {
     /* Save information for a standard frame. */
     f->frame_type = UNW_AARCH64_FRAME_STANDARD;
-    f->cfa_reg_sp = (rs->reg[DWARF_CFA_REG_COLUMN].val == SP);
-    f->cfa_reg_offset = rs->reg[DWARF_CFA_OFF_COLUMN].val;
-    if (rs->reg[FP].where == DWARF_WHERE_CFAREL)
-      f->fp_cfa_offset = rs->reg[FP].val;
-    if (rs->reg[LR].where == DWARF_WHERE_CFAREL)
-      f->lr_cfa_offset = rs->reg[LR].val;
-    if (rs->reg[SP].where == DWARF_WHERE_CFAREL)
-      f->sp_cfa_offset = rs->reg[SP].val;
+    f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP);
+    f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN];
+    if (rs->reg.where[FP] == DWARF_WHERE_CFAREL)
+      f->fp_cfa_offset = rs->reg.val[FP];
+    if (rs->reg.where[LR] == DWARF_WHERE_CFAREL)
+      f->lr_cfa_offset = rs->reg.val[LR];
+    if (rs->reg.where[SP] == DWARF_WHERE_CFAREL)
+      f->sp_cfa_offset = rs->reg.val[SP];
     Debug (4, " standard frame\n");
   }
   else
index 0c35f98..fdf64a7 100644 (file)
@@ -27,8 +27,32 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "offsets.h"
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
+/* Recognise PLT entries such as:
+  40ddf0:       b0000570        adrp    x16, 4ba000 <_GLOBAL_OFFSET_TABLE_+0x2a8>
+  40ddf4:       f9433611        ldr     x17, [x16,#1640]
+  40ddf8:       9119a210        add     x16, x16, #0x668
+  40ddfc:       d61f0220        br      x17 */
+static int
+is_plt_entry (struct dwarf_cursor *c)
+{
+  unw_word_t w0, w1;
+  unw_accessors_t *a;
+  int ret;
+
+  a = unw_get_accessors_int (c->as);
+  if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0
+      || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0)
+    return 0;
+
+  ret = (((w0 & 0xff0000009f000000) == 0xf900000090000000)
+         && ((w1 & 0xffffffffff000000) == 0xd61f022091000000));
+
+  Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret);
+  return ret;
+}
+
+static int
+aarch64_handle_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
   int ret;
@@ -101,11 +125,12 @@ unw_handle_signal_frame (unw_cursor_t *cursor)
   dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);
 
   c->dwarf.pi_valid = 0;
+  c->dwarf.use_prev_instr = 0;
 
   return 1;
 }
 
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -115,8 +140,8 @@ unw_step (unw_cursor_t *cursor)
          c, c->dwarf.ip, c->dwarf.cfa);
 
   /* Check if this is a signal frame. */
-  if (unw_is_signal_frame (cursor))
-    return unw_handle_signal_frame (cursor);
+  if (unw_is_signal_frame (cursor) > 0)
+    return aarch64_handle_signal_frame (cursor);
 
   ret = dwarf_step (&c->dwarf);
   Debug(1, "dwarf_step()=%d\n", ret);
@@ -125,7 +150,40 @@ unw_step (unw_cursor_t *cursor)
     return ret;
 
   if (unlikely (ret < 0))
-    return 0;
+    {
+      /* DWARF failed. */
+      if (is_plt_entry (&c->dwarf))
+        {
+          Debug (2, "found plt entry\n");
+          c->frame_info.frame_type = UNW_AARCH64_FRAME_STANDARD;
+        }
+      else
+        {
+          Debug (2, "fallback\n");
+          c->frame_info.frame_type = UNW_AARCH64_FRAME_GUESSED;
+        }
+      /* Use link register (X30). */
+      c->frame_info.cfa_reg_offset = 0;
+      c->frame_info.cfa_reg_sp = 0;
+      c->frame_info.fp_cfa_offset = -1;
+      c->frame_info.lr_cfa_offset = -1;
+      c->frame_info.sp_cfa_offset = -1;
+      c->dwarf.loc[UNW_AARCH64_PC] = c->dwarf.loc[UNW_AARCH64_X30];
+      c->dwarf.loc[UNW_AARCH64_X30] = DWARF_NULL_LOC;
+      if (!DWARF_IS_NULL_LOC (c->dwarf.loc[UNW_AARCH64_PC]))
+        {
+          ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);
+          if (ret < 0)
+            {
+              Debug (2, "failed to get pc from link register: %d\n", ret);
+              return ret;
+            }
+          Debug (2, "link register (x30) = 0x%016lx\n", c->dwarf.ip);
+          ret = 1;
+        }
+      else
+        c->dwarf.ip = 0;
+    }
 
   return (c->dwarf.ip == 0) ? 0 : 1;
 }
diff --git a/src/aarch64/Lapply_reg_state.c b/src/aarch64/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/aarch64/Lreg_states_iterate.c b/src/aarch64/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index 0cedc1a..5dab60b 100644 (file)
@@ -115,7 +115,6 @@ common_init (struct cursor *c, unsigned use_prev_instr)
   c->sigcontext_pc = 0;
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = 0;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
index 7c32693..2981d27 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_is_fpreg (int regnum)
 {
   return (regnum >= UNW_AARCH64_V0 && regnum <= UNW_AARCH64_V31);
index 8c97342..0f7a8bd 100644 (file)
@@ -96,7 +96,7 @@ static const char *const regname[] =
     [UNW_AARCH64_FPCR] = "fpcr",
   };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname) && regname[reg] != NULL)
index 79b342c..3d324c2 100644 (file)
@@ -59,4 +59,6 @@ extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
   } while (0)
 #endif
 
+#define GET_FPCTX(uc) ((struct fpsimd_context *)(&uc->uc_mcontext.__reserved))
+
 #endif /* unwind_i_h */
diff --git a/src/arm/Gapply_reg_state.c b/src/arm/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index 4d59a20..7b2d6ba 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index 34706cf..d6573a6 100644 (file)
@@ -381,71 +381,77 @@ arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf)
   return nbuf;
 }
 
-PROTECTED 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)
+int
+arm_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)
 {
-  if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)
-      && di->format == UNW_INFO_FORMAT_ARM_EXIDX)
-    {
-      /* The .ARM.exidx section contains a sorted list of key-value pairs -
-         the unwind entries.  The 'key' is a prel31 offset to the start of a
-         function.  We binary search this section in order to find the
-         appropriate unwind entry.  */
-      unw_word_t first = di->u.rti.table_data;
-      unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8;
-      unw_word_t entry, val;
-
-      if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val)
-        return -UNW_ENOINFO;
-
-      if (prel31_to_addr (as, arg, last, &val) < 0)
-        return -UNW_EINVAL;
+  /* The .ARM.exidx section contains a sorted list of key-value pairs -
+     the unwind entries.  The 'key' is a prel31 offset to the start of a
+     function.  We binary search this section in order to find the
+     appropriate unwind entry.  */
+  unw_word_t first = di->u.rti.table_data;
+  unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8;
+  unw_word_t entry, val;
+
+  if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val)
+    return -UNW_ENOINFO;
+
+  if (prel31_to_addr (as, arg, last, &val) < 0)
+    return -UNW_EINVAL;
 
-      if (ip >= val)
-        {
-          entry = last;
+  if (ip >= val)
+    {
+      entry = last;
 
-          if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
-            return -UNW_EINVAL;
+      if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
+       return -UNW_EINVAL;
 
-          pi->end_ip = di->end_ip -1;
-        }
-      else
-        {
-          while (first < last - 8)
-            {
-              entry = first + (((last - first) / 8 + 1) >> 1) * 8;
+      pi->end_ip = di->end_ip -1;
+    }
+  else
+    {
+      while (first < last - 8)
+       {
+         entry = first + (((last - first) / 8 + 1) >> 1) * 8;
 
-              if (prel31_to_addr (as, arg, entry, &val) < 0)
-                return -UNW_EINVAL;
+         if (prel31_to_addr (as, arg, entry, &val) < 0)
+           return -UNW_EINVAL;
 
-              if (ip < val)
-                last = entry;
-              else
-                first = entry;
-            }
+         if (ip < val)
+           last = entry;
+         else
+           first = entry;
+       }
 
-          entry = first;
+      entry = first;
 
-          if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
-            return -UNW_EINVAL;
+      if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
+       return -UNW_EINVAL;
 
-          if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
-            return -UNW_EINVAL;
+      if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
+       return -UNW_EINVAL;
 
-          pi->end_ip--;
-        }
+      pi->end_ip--;
+    }
 
-      if (need_unwind_info)
-        {
-          pi->unwind_info_size = 8;
-          pi->unwind_info = (void *) entry;
-          pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
-        }
-      return 0;
+  if (need_unwind_info)
+    {
+      pi->unwind_info_size = 8;
+      pi->unwind_info = (void *) entry;
+      pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
     }
+  return 0;
+}
+
+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)
+{
+  if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)
+      && di->format == UNW_INFO_FORMAT_ARM_EXIDX)
+    return arm_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
   else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)
            && di->format != UNW_INFO_FORMAT_ARM_EXIDX)
     return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
@@ -509,30 +515,7 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
   Debug (14, "looking for IP=0x%lx\n", (long) ip);
 
   if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF))
-    {
-      struct dwarf_callback_data cb_data;
-
-      memset (&cb_data, 0, sizeof (cb_data));
-      cb_data.ip = ip;
-      cb_data.pi = pi;
-      cb_data.need_unwind_info = need_unwind_info;
-      cb_data.di.format = -1;
-      cb_data.di_debug.format = -1;
-
-      SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
-      ret = dl_iterate_phdr (dwarf_callback, &cb_data);
-      SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
-
-      if (cb_data.single_fde)
-        /* already got the result in *pi */
-        return 0;
-
-      if (cb_data.di_debug.format != -1)
-        ret = tdep_search_unwind_table (as, ip, &cb_data.di_debug, pi,
-                                        need_unwind_info, arg);
-      else
-        ret = -UNW_ENOINFO;
-    }
+    ret = dwarf_find_proc_info (as, ip, pi, need_unwind_info, arg);
 
   if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
     {
@@ -548,15 +531,12 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
       SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
 
       if (cb_data.di.format != -1)
-        ret = tdep_search_unwind_table (as, ip, &cb_data.di, pi,
-                                        need_unwind_info, arg);
+        ret = arm_search_unwind_table (as, ip, &cb_data.di, pi,
+                                      need_unwind_info, arg);
       else
         ret = -UNW_ENOINFO;
     }
 
-  if (ret < 0)
-    Debug (14, "IP=0x%lx not found\n", (long) ip);
-
   return ret;
 }
 
index acb78a4..4051a10 100644 (file)
@@ -24,7 +24,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index 63b711d..9fb0704 100644 (file)
@@ -24,7 +24,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   struct cursor *c = (struct cursor *) cursor;
index 1ed3dbf..2720d06 100644 (file)
@@ -30,13 +30,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 static inline void *
 uc_addr (unw_tdep_context_t *uc, int reg)
@@ -126,6 +126,11 @@ static int
 access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
             void *arg)
 {
+  /* validate address */
+    const struct cursor *c = (const struct cursor *) arg;
+    if (c && validate_mem(addr))
+      return -1;
+
   if (write)
     {
       Debug (16, "mem[%x] <- %x\n", addr, *val);
@@ -133,11 +138,6 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
     }
   else
     {
-      /* validate address */
-      const struct cursor *c = (const struct cursor *) arg;
-      if (c && validate_mem(addr))
-        return -1;
-
       *val = *(unw_word_t *) addr;
       Debug (16, "mem[%x] -> %x\n", addr, *val);
     }
@@ -220,7 +220,7 @@ 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.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   local_addr_space.acc.find_proc_info = arm_find_proc_info;
   local_addr_space.acc.put_unwind_info = arm_put_unwind_info;
   local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
index e1cc30c..e13519b 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
 {
   return -UNW_EINVAL;
@@ -36,8 +36,8 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+static int
+unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -49,7 +49,30 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
   c->dwarf.as = unw_local_addr_space;
   c->dwarf.as_arg = uc;
 
-  return common_init (c, 1);
+  return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, unw_context_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
 }
 
 #endif /* !UNW_REMOTE_ONLY */
index f284e99..9b8ba5b 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
diff --git a/src/arm/Gis_signal_frame.c b/src/arm/Gis_signal_frame.c
deleted file mode 100644 (file)
index e8efe7f..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* libunwind - a platform-independent unwind library
-   Copyright (C) 2008 CodeSourcery
-   Copyright 2011 Linaro Limited
-
-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"
-
-#ifdef __linux__
-#define ARM_NR_sigreturn 119
-#define ARM_NR_rt_sigreturn 173
-#define ARM_NR_OABI_SYSCALL_BASE 0x900000
-
-/* ARM EABI sigreturn (the syscall number is loaded into r7) */
-#define MOV_R7_SIGRETURN (0xe3a07000UL | ARM_NR_sigreturn)
-#define MOV_R7_RT_SIGRETURN (0xe3a07000UL | ARM_NR_rt_sigreturn)
-
-/* ARM OABI sigreturn (using SWI) */
-#define ARM_SIGRETURN \
-  (0xef000000UL | ARM_NR_sigreturn | ARM_NR_OABI_SYSCALL_BASE)
-#define ARM_RT_SIGRETURN \
-  (0xef000000UL | ARM_NR_rt_sigreturn | ARM_NR_OABI_SYSCALL_BASE)
-
-/* Thumb sigreturn (two insns, syscall number is loaded into r7) */
-#define THUMB_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_sigreturn)
-#define THUMB_RT_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_rt_sigreturn)
-#endif /* __linux__ */
-
-/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal
-   frame. */
-PROTECTED int
-unw_is_signal_frame (unw_cursor_t *cursor)
-{
-#ifdef __linux__
-  struct cursor *c = (struct cursor *) cursor;
-  unw_word_t w0, ip;
-  unw_addr_space_t as;
-  unw_accessors_t *a;
-  void *arg;
-  int ret;
-
-  as = c->dwarf.as;
-  a = unw_get_accessors (as);
-  arg = c->dwarf.as_arg;
-
-  ip = c->dwarf.ip;
-
-  if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
-    return ret;
-
-  /* Return 1 if the IP points to a non-RT sigreturn sequence.  */
-  if (w0 == MOV_R7_SIGRETURN || w0 == ARM_SIGRETURN || w0 == THUMB_SIGRETURN)
-    return 1;
-  /* Return 2 if the IP points to a RT sigreturn sequence.  */
-  else if (w0 == MOV_R7_RT_SIGRETURN || w0 == ARM_RT_SIGRETURN
-           || w0 == THUMB_RT_SIGRETURN)
-    return 2;
-
-  return 0;
-#elif defined(__QNX__)
-  /* Not supported yet */
-  return 0;
-#else
-  printf ("%s: implement me\n", __FUNCTION__);
-  return -UNW_ENOINFO;
-#endif
-}
diff --git a/src/arm/Gos-freebsd.c b/src/arm/Gos-freebsd.c
new file mode 100644 (file)
index 0000000..a106922
--- /dev/null
@@ -0,0 +1,129 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2008 CodeSourcery
+   Copyright 2011 Linaro Limited
+   Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+   Copyright 2015 The FreeBSD Foundation
+
+   Portions of this software were developed by Konstantin Belousov
+   under sponsorship from the FreeBSD Foundation.
+
+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 <signal.h>
+#include "unwind_i.h"
+#include "offsets.h"
+#include "ex_tables.h"
+
+HIDDEN int
+arm_handle_signal_frame (unw_cursor_t *cursor)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  int ret, fmt;
+  unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
+  struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
+
+  if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
+    return -UNW_EUNSPEC;
+  fmt = unw_is_signal_frame(cursor);
+
+  c->dwarf.pi_valid = 0;
+
+  if (fmt == UNW_ARM_FRAME_SYSCALL)
+   {
+    c->sigcontext_format = ARM_SCF_FREEBSD_SYSCALL;
+    c->frame_info.frame_type = UNW_ARM_FRAME_SYSCALL;
+    c->frame_info.cfa_reg_offset = 0;
+    c->dwarf.loc[UNW_ARM_R7] = c->dwarf.loc[UNW_ARM_R12];
+    dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R14], &c->dwarf.ip);
+    return 1;
+   }
+
+  c->sigcontext_format = ARM_SCF_FREEBSD_SIGFRAME;
+  sc_addr = sp_addr;
+
+  /* Save the SP and PC to be able to return execution at this point
+     later in time (unw_resume).  */
+  c->sigcontext_sp = c->dwarf.cfa;
+  c->sigcontext_pc = c->dwarf.ip;
+
+  c->sigcontext_addr = sc_addr;
+  c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN;
+  c->frame_info.cfa_reg_offset = sc_addr - sp_addr;
+
+  /* Update the dwarf cursor.
+     Set the location of the registers to the corresponding addresses of the
+     uc_mcontext / sigcontext structure contents.  */
+#define ROFF(n)        (FREEBSD_SC_UCONTEXT_OFF + FREEBSD_UC_MCONTEXT_OFF + \
+  FREEBSD_MC_R0_OFF + (n) * 4)
+#define SL(n) \
+  c->dwarf.loc[UNW_ARM_R ## n] = DWARF_LOC (sc_addr + ROFF(n), 0);
+  SL(0); SL(1); SL(2); SL(3); SL(4); SL(5); SL(6); SL(7);
+  SL(8); SL(9); SL(10); SL(11); SL(12); SL(13); SL(14); SL(15);
+#undef SL
+#undef ROFF
+
+  /* Set SP/CFA and PC/IP.  */
+  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa);
+  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip);
+
+  return 1;
+}
+
+/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal
+   frame. */
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  unw_word_t w0, w1, w2, w3, ip;
+  unw_addr_space_t as;
+  unw_accessors_t *a;
+  void *arg;
+  int ret;
+
+  as = c->dwarf.as;
+  a = unw_get_accessors_int (as);
+  arg = c->dwarf.as_arg;
+
+  ip = c->dwarf.ip;
+
+  if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
+    return ret;
+  if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0)
+    return ret;
+  if ((ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0)
+    return ret;
+  if ((ret = (*a->access_mem) (as, ip + 12, &w3, 0, arg)) < 0)
+    return ret;
+
+  if (w0 == 0xe1a0000d && w1 == 0xe2800040 && w2 == 0xe59f700c &&
+    w3 == 0xef0001a1)
+     return UNW_ARM_FRAME_SIGRETURN;
+
+  if ((ret = (*a->access_mem) (as, ip - 4, &w0, 0, arg)) < 0)
+    return ret;
+  if (w0 == 0xef000000)
+    return UNW_ARM_FRAME_SYSCALL;
+
+  return 0;
+}
diff --git a/src/arm/Gos-linux.c b/src/arm/Gos-linux.c
new file mode 100644 (file)
index 0000000..260e086
--- /dev/null
@@ -0,0 +1,182 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2008 CodeSourcery
+   Copyright 2011 Linaro Limited
+   Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+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 <signal.h>
+#include "unwind_i.h"
+#include "offsets.h"
+
+HIDDEN int
+arm_handle_signal_frame (unw_cursor_t *cursor)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  int ret;
+  unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
+  struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
+
+  if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
+    return -UNW_EUNSPEC;
+
+  /* Obtain signal frame type (non-RT or RT). */
+  ret = unw_is_signal_frame (cursor);
+
+  /* Save the SP and PC to be able to return execution at this point
+     later in time (unw_resume).  */
+  c->sigcontext_sp = c->dwarf.cfa;
+  c->sigcontext_pc = c->dwarf.ip;
+
+  /* Since kernel version 2.6.18 the non-RT signal frame starts with a
+     ucontext while the RT signal frame starts with a siginfo, followed
+     by a sigframe whose first element is an ucontext.
+     Prior 2.6.18 the non-RT signal frame starts with a sigcontext while
+     the RT signal frame starts with two pointers followed by a siginfo
+     and an ucontext. The first pointer points to the start of the siginfo
+     structure and the second one to the ucontext structure.  */
+
+  if (ret == 1)
+    {
+      /* Handle non-RT signal frames. Check if the first word on the stack
+         is the magic number.  */
+      if (sp == 0x5ac3c35a)
+        {
+          c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME;
+          sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF;
+        }
+      else
+        {
+          c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME;
+          sc_addr = sp_addr;
+        }
+    }
+  else if (ret == 2)
+    {
+      /* Handle RT signal frames. Check if the first word on the stack is a
+         pointer to the siginfo structure.  */
+      if (sp == sp_addr + 8)
+        {
+          c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME;
+          sc_addr = sp_addr + 8 + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
+        }
+      else
+        {
+          c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME;
+          sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
+        }
+    }
+  else
+    return -UNW_EUNSPEC;
+
+  c->sigcontext_addr = sc_addr;
+  c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN;
+  c->frame_info.cfa_reg_offset = sc_addr - sp_addr;
+
+  /* Update the dwarf cursor.
+     Set the location of the registers to the corresponding addresses of the
+     uc_mcontext / sigcontext structure contents.  */
+  c->dwarf.loc[UNW_ARM_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R11] = DWARF_LOC (sc_addr + LINUX_SC_FP_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R12] = DWARF_LOC (sc_addr + LINUX_SC_IP_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R13] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R14] = DWARF_LOC (sc_addr + LINUX_SC_LR_OFF, 0);
+  c->dwarf.loc[UNW_ARM_R15] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);
+
+  /* Set SP/CFA and PC/IP.  */
+  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa);
+  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip);
+
+  c->dwarf.pi_valid = 0;
+
+  return 1;
+}
+
+#define ARM_NR_sigreturn 119
+#define ARM_NR_rt_sigreturn 173
+#define ARM_NR_OABI_SYSCALL_BASE 0x900000
+
+/* ARM EABI sigreturn (the syscall number is loaded into r7) */
+#define MOV_R7_SIGRETURN (0xe3a07000UL | ARM_NR_sigreturn)
+#define MOV_R7_RT_SIGRETURN (0xe3a07000UL | ARM_NR_rt_sigreturn)
+
+/* ARM OABI sigreturn (using SWI) */
+#define ARM_SIGRETURN \
+  (0xef000000UL | ARM_NR_sigreturn | ARM_NR_OABI_SYSCALL_BASE)
+#define ARM_RT_SIGRETURN \
+  (0xef000000UL | ARM_NR_rt_sigreturn | ARM_NR_OABI_SYSCALL_BASE)
+
+/* Thumb sigreturn (two insns, syscall number is loaded into r7) */
+#define THUMB_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_sigreturn)
+#define THUMB_RT_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_rt_sigreturn)
+
+/* Thumb2 sigreturn (mov.w r7, $SYS_ify(rt_sigreturn/sigreturn)) */
+#define THUMB2_SIGRETURN (((0x0700 | ARM_NR_sigreturn) << 16) | \
+                                       0xf04f)
+#define THUMB2_RT_SIGRETURN (((0x0700 | ARM_NR_rt_sigreturn) << 16) | \
+                                       0xf04f)
+/* TODO: with different toolchains, there are a lot more possibilities */
+
+/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal
+   frame. */
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  unw_word_t w0, ip;
+  unw_addr_space_t as;
+  unw_accessors_t *a;
+  void *arg;
+  int ret;
+
+  as = c->dwarf.as;
+  a = unw_get_accessors_int (as);
+  arg = c->dwarf.as_arg;
+
+  /* The least bit denotes thumb/arm mode. Do not read there. */
+  ip = c->dwarf.ip & ~0x1;
+
+  if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
+    return ret;
+
+  /* Return 1 if the IP points to a non-RT sigreturn sequence.  */
+  if (w0 == MOV_R7_SIGRETURN || w0 == ARM_SIGRETURN || w0 == THUMB_SIGRETURN
+           || w0 == THUMB2_SIGRETURN)
+    return 1;
+  /* Return 2 if the IP points to a RT sigreturn sequence.  */
+  else if (w0 == MOV_R7_RT_SIGRETURN || w0 == ARM_RT_SIGRETURN
+           || w0 == THUMB_RT_SIGRETURN || w0 == THUMB2_RT_SIGRETURN)
+    return 2;
+
+  return 0;
+}
diff --git a/src/arm/Gos-other.c b/src/arm/Gos-other.c
new file mode 100644 (file)
index 0000000..73c102c
--- /dev/null
@@ -0,0 +1,48 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2008 CodeSourcery
+   Copyright 2011 Linaro Limited
+   Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
+
+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 <signal.h>
+#include "unwind_i.h"
+#include "offsets.h"
+
+HIDDEN int
+arm_handle_signal_frame (unw_cursor_t *cursor)
+{
+  return -UNW_EUNSPEC;
+}
+
+int
+unw_is_signal_frame (unw_cursor_t *cursor)
+{
+#if defined(__QNX__)
+  /* Not supported yet */
+  return 0;
+#else
+  printf ("%s: implement me\n", __FUNCTION__);
+  return -UNW_ENOINFO;
+#endif
+}
diff --git a/src/arm/Greg_states_iterate.c b/src/arm/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index 688771f..0d52f0b 100644 (file)
@@ -32,6 +32,9 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
   
   switch (reg)
     {
+    case UNW_ARM_R15:
+      if (write)
+        c->dwarf.ip = *valp;            /* update the IP cache */
     case UNW_ARM_R0:
     case UNW_ARM_R1:
     case UNW_ARM_R2:
@@ -46,7 +49,6 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
     case UNW_ARM_R11:
     case UNW_ARM_R12:
     case UNW_ARM_R14:
-    case UNW_ARM_R15:
       loc = c->dwarf.loc[reg - UNW_ARM_R0];
       break;
 
index 9fe264e..a828862 100644 (file)
@@ -132,7 +132,7 @@ establish_machine_state (struct cursor *c)
     }
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 2cce409..c5a76b8 100644 (file)
@@ -36,13 +36,13 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
          " ra=0x%x r7 [where=%d val=%d @0x%x] lr [where=%d val=%d @0x%x] "
          "sp [where=%d val=%d @0x%x]\n",
          d->ip, d->cfa, f->frame_type,
-         rs->reg[DWARF_CFA_REG_COLUMN].where,
-         rs->reg[DWARF_CFA_REG_COLUMN].val,
-         rs->reg[DWARF_CFA_OFF_COLUMN].val,
-         DWARF_GET_LOC(d->loc[d->ret_addr_column]),
-         rs->reg[R7].where, rs->reg[R7].val, DWARF_GET_LOC(d->loc[R7]),
-         rs->reg[LR].where, rs->reg[LR].val, DWARF_GET_LOC(d->loc[LR]),
-         rs->reg[SP].where, rs->reg[SP].val, DWARF_GET_LOC(d->loc[SP]));
+         rs->reg.where[DWARF_CFA_REG_COLUMN],
+         rs->reg.val[DWARF_CFA_REG_COLUMN],
+         rs->reg.val[DWARF_CFA_OFF_COLUMN],
+         DWARF_GET_LOC(d->loc[rs->ret_addr_column]),
+         rs->reg.where[R7], rs->reg.val[R7], DWARF_GET_LOC(d->loc[R7]),
+         rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]),
+         rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP]));
 
   /* A standard frame is defined as:
       - CFA is register-relative offset off R7 or SP;
@@ -51,37 +51,37 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
       - LR is unsaved or saved at CFA+offset, offset != -1;
       - SP is unsaved or saved at CFA+offset, offset != -1.  */
   if (f->frame_type == UNW_ARM_FRAME_OTHER
-      && (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
-      && (rs->reg[DWARF_CFA_REG_COLUMN].val == R7
-          || rs->reg[DWARF_CFA_REG_COLUMN].val == SP)
-      && labs(rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
-      && d->ret_addr_column == LR
-      && (rs->reg[R7].where == DWARF_WHERE_UNDEF
-          || rs->reg[R7].where == DWARF_WHERE_SAME
-          || (rs->reg[R7].where == DWARF_WHERE_CFAREL
-              && labs(rs->reg[R7].val) < (1 << 29)
-              && rs->reg[R7].val+1 != 0))
-      && (rs->reg[LR].where == DWARF_WHERE_UNDEF
-          || rs->reg[LR].where == DWARF_WHERE_SAME
-          || (rs->reg[LR].where == DWARF_WHERE_CFAREL
-              && labs(rs->reg[LR].val) < (1 << 29)
-              && rs->reg[LR].val+1 != 0))
-      && (rs->reg[SP].where == DWARF_WHERE_UNDEF
-          || rs->reg[SP].where == DWARF_WHERE_SAME
-          || (rs->reg[SP].where == DWARF_WHERE_CFAREL
-              && labs(rs->reg[SP].val) < (1 << 29)
-              && rs->reg[SP].val+1 != 0)))
+      && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
+      && (rs->reg.val[DWARF_CFA_REG_COLUMN] == R7
+          || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP)
+      && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29)
+      && rs->ret_addr_column == LR
+      && (rs->reg.where[R7] == DWARF_WHERE_UNDEF
+          || rs->reg.where[R7] == DWARF_WHERE_SAME
+          || (rs->reg.where[R7] == DWARF_WHERE_CFAREL
+              && labs(rs->reg.val[R7]) < (1 << 29)
+              && rs->reg.val[R7]+1 != 0))
+      && (rs->reg.where[LR] == DWARF_WHERE_UNDEF
+          || rs->reg.where[LR] == DWARF_WHERE_SAME
+          || (rs->reg.where[LR] == DWARF_WHERE_CFAREL
+              && labs(rs->reg.val[LR]) < (1 << 29)
+              && rs->reg.val[LR]+1 != 0))
+      && (rs->reg.where[SP] == DWARF_WHERE_UNDEF
+          || rs->reg.where[SP] == DWARF_WHERE_SAME
+          || (rs->reg.where[SP] == DWARF_WHERE_CFAREL
+              && labs(rs->reg.val[SP]) < (1 << 29)
+              && rs->reg.val[SP]+1 != 0)))
   {
     /* Save information for a standard frame. */
     f->frame_type = UNW_ARM_FRAME_STANDARD;
-    f->cfa_reg_sp = (rs->reg[DWARF_CFA_REG_COLUMN].val == SP);
-    f->cfa_reg_offset = rs->reg[DWARF_CFA_OFF_COLUMN].val;
-    if (rs->reg[R7].where == DWARF_WHERE_CFAREL)
-      f->r7_cfa_offset = rs->reg[R7].val;
-    if (rs->reg[LR].where == DWARF_WHERE_CFAREL)
-      f->lr_cfa_offset = rs->reg[LR].val;
-    if (rs->reg[SP].where == DWARF_WHERE_CFAREL)
-      f->sp_cfa_offset = rs->reg[SP].val;
+    f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP);
+    f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN];
+    if (rs->reg.where[R7] == DWARF_WHERE_CFAREL)
+      f->r7_cfa_offset = rs->reg.val[R7];
+    if (rs->reg.where[LR] == DWARF_WHERE_CFAREL)
+      f->lr_cfa_offset = rs->reg.val[LR];
+    if (rs->reg.where[SP] == DWARF_WHERE_CFAREL)
+      f->sp_cfa_offset = rs->reg.val[SP];
     Debug (4, " standard frame\n");
   }
   else
index 79f2dd2..516c9f4 100644 (file)
@@ -44,9 +44,18 @@ arm_exidx_step (struct cursor *c)
 
   /* mark PC unsaved */
   c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC;
-
-  if ((ret = tdep_find_proc_info (&c->dwarf, c->dwarf.ip, 1)) < 0)
-     return ret;
+  unw_word_t ip = c->dwarf.ip;
+  if (c->dwarf.use_prev_instr)
+    --ip;
+
+  /* check dynamic info first --- it overrides everything else */
+  ret = unwi_find_dynamic_proc_info (c->dwarf.as, ip, &c->dwarf.pi, 1,
+                                     c->dwarf.as_arg);
+  if (ret == -UNW_ENOINFO)
+    {
+      if ((ret = tdep_find_proc_info (&c->dwarf, ip, 1)) < 0)
+        return ret;
+    }
 
   if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX)
     return -UNW_ENOINFO;
@@ -73,100 +82,7 @@ arm_exidx_step (struct cursor *c)
   return (c->dwarf.ip == 0) ? 0 : 1;
 }
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
-{
-  struct cursor *c = (struct cursor *) cursor;
-  int ret;
-  unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
-  struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);
-
-  if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
-    return -UNW_EUNSPEC;
-
-  /* Obtain signal frame type (non-RT or RT). */
-  ret = unw_is_signal_frame (cursor);
-
-  /* Save the SP and PC to be able to return execution at this point
-     later in time (unw_resume).  */
-  c->sigcontext_sp = c->dwarf.cfa;
-  c->sigcontext_pc = c->dwarf.ip;
-
-  /* Since kernel version 2.6.18 the non-RT signal frame starts with a
-     ucontext while the RT signal frame starts with a siginfo, followed
-     by a sigframe whose first element is an ucontext.
-     Prior 2.6.18 the non-RT signal frame starts with a sigcontext while
-     the RT signal frame starts with two pointers followed by a siginfo
-     and an ucontext. The first pointer points to the start of the siginfo
-     structure and the second one to the ucontext structure.  */
-
-  if (ret == 1)
-    {
-      /* Handle non-RT signal frames. Check if the first word on the stack
-         is the magic number.  */
-      if (sp == 0x5ac3c35a)
-        {
-          c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME;
-          sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF;
-        }
-      else
-        {
-          c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME;
-          sc_addr = sp_addr;
-        }
-    }
-  else if (ret == 2)
-    {
-      /* Handle RT signal frames. Check if the first word on the stack is a
-         pointer to the siginfo structure.  */
-      if (sp == sp_addr + 8)
-        {
-          c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME;
-          sc_addr = sp_addr + 8 + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
-        }
-      else
-        {
-          c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME;
-          sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
-        }
-    }
-  else
-    return -UNW_EUNSPEC;
-
-  c->sigcontext_addr = sc_addr;
-  c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN;
-  c->frame_info.cfa_reg_offset = sc_addr - sp_addr;
-
-  /* Update the dwarf cursor.
-     Set the location of the registers to the corresponding addresses of the
-     uc_mcontext / sigcontext structure contents.  */
-  c->dwarf.loc[UNW_ARM_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R11] = DWARF_LOC (sc_addr + LINUX_SC_FP_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R12] = DWARF_LOC (sc_addr + LINUX_SC_IP_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R13] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R14] = DWARF_LOC (sc_addr + LINUX_SC_LR_OFF, 0);
-  c->dwarf.loc[UNW_ARM_R15] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);
-
-  /* Set SP/CFA and PC/IP.  */
-  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa);
-  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip);
-
-  c->dwarf.pi_valid = 0;
-
-  return 1;
-}
-
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -175,8 +91,8 @@ unw_step (unw_cursor_t *cursor)
   Debug (1, "(cursor=%p)\n", c);
 
   /* Check if this is a signal frame. */
-  if (unw_is_signal_frame (cursor))
-     return unw_handle_signal_frame (cursor);
+  if (unw_is_signal_frame (cursor) > 0)
+     return arm_handle_signal_frame (cursor);
 
 #ifdef CONFIG_DEBUG_FRAME
   /* First, try DWARF-based unwinding. */
@@ -210,14 +126,18 @@ unw_step (unw_cursor_t *cursor)
 
   /* Fall back on APCS frame parsing.
      Note: This won't work in case the ARM EABI is used. */
+#ifdef __FreeBSD__
+  if (0)
+#else
   if (unlikely (ret < 0))
+#endif
     {
       if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME))
         {
+          Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
           ret = UNW_ESUCCESS;
           /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */
           unw_word_t instr, i;
-          Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
           dwarf_loc_t ip_loc, fp_loc;
           unw_word_t frame;
           /* Mark all registers unsaved, since we don't know where
@@ -260,7 +180,7 @@ unw_step (unw_cursor_t *cursor)
               c->dwarf.loc[UNW_ARM_R12] = ip_loc;
               c->dwarf.loc[UNW_ARM_R11] = fp_loc;
               c->dwarf.pi_valid = 0;
-              Debug(15, "ip=%lx\n", c->dwarf.ip);
+              Debug(15, "ip=%x\n", c->dwarf.ip);
             }
           else
             {
@@ -268,5 +188,5 @@ unw_step (unw_cursor_t *cursor)
             }
         }
     }
-  return ret == -UNW_ENOINFO ? 0 : 1;
+  return ret == -UNW_ENOINFO ? 0 : ret;
 }
index 135563a..2f27752 100644 (file)
@@ -503,7 +503,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
 
     case UNW_ARM_FRAME_SIGRETURN:
       cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t.  */
-
+#if defined(__linux__)
       ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc);
       if (likely(ret >= 0))
         ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_R7_OFF, r7);
@@ -513,6 +513,9 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
          doesn't save the link register in the prologue, e.g. kill. */
       if (likely(ret >= 0))
         ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_LR_OFF, lr);
+#elif defined(__FreeBSD__)
+      printf("XXX\n");
+#endif
 
       /* Resume stack at signal restoration point. The stack is not
          necessarily continuous here, especially with sigaltstack(). */
@@ -522,6 +525,10 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
       d->use_prev_instr = 0;
       break;
 
+    case UNW_ARM_FRAME_SYSCALL:
+      printf("XXX1\n");
+      break;
+
     default:
       /* We cannot trace through this frame, give up and tell the
           caller we had to stop.  Data collected so far may still be
diff --git a/src/arm/Lapply_reg_state.c b/src/arm/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/arm/Los-freebsd.c b/src/arm/Los-freebsd.c
new file mode 100644 (file)
index 0000000..a75a205
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-freebsd.c"
+#endif
similarity index 82%
rename from src/dwarf/Lstep.c
rename to src/arm/Los-linux.c
index c1ac3c7..3cc18aa 100644 (file)
@@ -1,5 +1,5 @@
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
 #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
-#include "Gstep.c"
+#include "Gos-linux.c"
 #endif
diff --git a/src/arm/Los-other.c b/src/arm/Los-other.c
new file mode 100644 (file)
index 0000000..a75a205
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gos-freebsd.c"
+#endif
diff --git a/src/arm/Lreg_states_iterate.c b/src/arm/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index c52992b..7e18784 100644 (file)
@@ -35,8 +35,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 _Uarm_getcontext:
        stmfd sp!, {r0, r1}
        @ store r0
+#if defined(__linux__)
        str r0, [r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF]
        add r0, r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF
+#elif defined(__FreeBSD__)
+       str r0, [r0, #FREEBSD_UC_MCONTEXT_OFF + FREEBSD_MC_R0_OFF]
+       add r0, r0, #FREEBSD_UC_MCONTEXT_OFF + FREEBSD_MC_R0_OFF
+#else
+#error Fix me
+#endif
        @ store r1 to r12
        stmib r0, {r1-r12}
        @ reconstruct r13 at call site, then store
@@ -50,7 +57,7 @@ _Uarm_getcontext:
        str r1, [r0, #15 * 4]
        ldmfd sp!, {r0, r1}
        bx lr
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
  /* We do not need executable stack.  */
  .section  .note.GNU-stack,"",%progbits
 #endif
index 6379d8e..7d765ec 100644 (file)
@@ -66,7 +66,6 @@ common_init (struct cursor *c, unsigned use_prev_instr)
   /* FIXME: Initialisation for other registers.  */
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = 0;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
index 3b36a03..e55bcff 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 /* 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
+int
 unw_is_fpreg (int regnum)
 {
   return ((regnum >= UNW_ARM_S0 && regnum <= UNW_ARM_S31)
index a63847b..6217011 100644 (file)
@@ -34,3 +34,9 @@
 #define LINUX_SC_PC_OFF         0x48
 #define LINUX_SC_CPSR_OFF       0x4C
 #define LINUX_SC_FAULTADDR_OFF  0x50
+
+/* FreeBSD-specific definitions: */
+
+#define FREEBSD_SC_UCONTEXT_OFF                0x40
+#define        FREEBSD_UC_MCONTEXT_OFF         0x10
+#define FREEBSD_MC_R0_OFF              0
index 474337a..7cac630 100644 (file)
@@ -80,7 +80,7 @@ static const char *regname[] =
     "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
   };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
index 4dabf21..fe0bca0 100644 (file)
@@ -44,6 +44,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 extern void arm_local_addr_space_init (void);
 extern int arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
                              void *arg);
+#define arm_handle_signal_frame UNW_OBJ(handle_signal_frame)
+extern int arm_handle_signal_frame(unw_cursor_t *cursor);
+
 /* By-pass calls to access_mem() when known to be safe. */
 #ifdef UNW_LOCAL_ONLY
 # undef ACCESS_MEM_FAST
index 585b7e2..0e3a83b 100644 (file)
@@ -76,7 +76,7 @@ _UCD_access_reg (unw_addr_space_t as,
   default:
       Debug(0, "bad regnum:%d\n", regnum);
       return -UNW_EINVAL;
-  };
+  }
 #elif defined(UNW_TARGET_X86_64)
   switch (regnum) {
   case UNW_X86_64_RAX:
@@ -109,7 +109,26 @@ _UCD_access_reg (unw_addr_space_t as,
   default:
       Debug(0, "bad regnum:%d\n", regnum);
       return -UNW_EINVAL;
-  };
+  }
+#elif defined(UNW_TARGET_ARM)
+  if (regnum >= UNW_ARM_R0 && regnum <= UNW_ARM_R12) {
+     *valp = ui->prstatus->pr_reg.r[regnum];
+  } else {
+     switch (regnum) {
+     case UNW_ARM_R13:
+       *valp = ui->prstatus->pr_reg.r_sp;
+       break;
+     case UNW_ARM_R14:
+       *valp = ui->prstatus->pr_reg.r_lr;
+       break;
+     case UNW_ARM_R15:
+       *valp = ui->prstatus->pr_reg.r_pc;
+       break;
+     default:
+       Debug(0, "bad regnum:%d\n", regnum);
+       return -UNW_EINVAL;
+     }
+  }
 #else
 #error Port me
 #endif
index 4b5994f..208d8d2 100644 (file)
@@ -39,17 +39,20 @@ _UCD_access_reg (unw_addr_space_t as,
       return -UNW_EINVAL;
     }
 
+  if (regnum < 0)
+    goto badreg;
+
 #if defined(UNW_TARGET_AARCH64)
-  if (regnum < 0 || regnum >= UNW_AARCH64_FPCR)
+  if (regnum >= UNW_AARCH64_FPCR)
     goto badreg;
 #elif defined(UNW_TARGET_ARM)
-  if (regnum < 0 || regnum >= 16)
+  if (regnum >= 16)
     goto badreg;
 #elif defined(UNW_TARGET_SH)
-  if (regnum < 0 || regnum > UNW_SH_PR)
+  if (regnum > UNW_SH_PR)
     goto badreg;
 #elif defined(UNW_TARGET_TILEGX)
-  if (regnum < 0 || regnum > UNW_TILEGX_CFA)
+  if (regnum > UNW_TILEGX_CFA)
     goto badreg;
 #else
 #if defined(UNW_TARGET_MIPS)
@@ -120,7 +123,7 @@ _UCD_access_reg (unw_addr_space_t as,
 #error Port me
 #endif
 
-  if (regnum < 0 || regnum >= (unw_regnum_t)ARRAY_SIZE(remap_regs))
+  if (regnum >= (unw_regnum_t)ARRAY_SIZE(remap_regs))
     goto badreg;
 
   regnum = remap_regs[regnum];
index f081180..ae5c23d 100644 (file)
@@ -23,7 +23,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "_UCD_internal.h"
 
-PROTECTED unw_accessors_t _UCD_accessors =
+unw_accessors_t _UCD_accessors =
   {
     .find_proc_info             = _UCD_find_proc_info,
     .put_unwind_info            = _UCD_put_unwind_info,
index f22664b..62f6ee0 100644 (file)
@@ -67,7 +67,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "_UCD_internal.h"
 
 #define NOTE_DATA(_hdr) STRUCT_MEMBER_P((_hdr), sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4))
-#define NOTE_SIZE(_hdr) (sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4) + (_hdr)->n_descsz)
+#define NOTE_SIZE(_hdr) (sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4) + UNW_ALIGN((_hdr)->n_descsz, 4))
 #define NOTE_NEXT(_hdr) STRUCT_MEMBER_P((_hdr), NOTE_SIZE(_hdr))
 #define NOTE_FITS_IN(_hdr, _size) ((_size) >= sizeof (Elf32_Nhdr) && (_size) >= NOTE_SIZE (_hdr))
 #define NOTE_FITS(_hdr, _end) NOTE_FITS_IN((_hdr), (unsigned long)((char *)(_end) - (char *)(_hdr)))
index 5aff989..ddc36ec 100644 (file)
@@ -44,7 +44,9 @@ _UCD_destroy (struct UCD_info *ui)
         close(phdr->backing_fd);
     }
 
+  free(ui->phdrs);
   free(ui->note_phdr);
+  free(ui->threads);
 
   free(ui);
 }
index b56bb31..f63c3d2 100644 (file)
@@ -187,10 +187,58 @@ read_operand (unw_addr_space_t as, unw_accessors_t *a,
 }
 
 HIDDEN int
+dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr,
+                    unw_word_t rbp_addr, unw_word_t *cfa_offset) {
+  unw_accessors_t *a;
+  int ret;
+  void *arg;
+  unw_word_t len;
+  uint8_t opcode;
+  unw_word_t operand1;
+
+  a = unw_get_accessors_int (c->as);
+  arg = c->as_arg;
+
+  ret = dwarf_read_uleb128(c->as, a, &rbp_addr, &len, arg);
+  if (len != 2 || ret < 0)
+    return 0;
+
+  ret = dwarf_readu8(c->as, a, &rbp_addr, &opcode, arg);
+  if (ret < 0 || opcode != DW_OP_breg6)
+    return 0;
+
+  ret = read_operand(c->as, a, &rbp_addr,
+                     OPND1_TYPE(operands[opcode]), &operand1, arg);
+
+  if (ret < 0 || operand1 != 0)
+    return 0;
+
+  ret = dwarf_read_uleb128(c->as, a, &cfa_addr, &len, arg);
+  if (ret < 0 || len != 3)
+    return 0;
+
+  ret = dwarf_readu8(c->as, a, &cfa_addr, &opcode, arg);
+  if (ret < 0 || opcode != DW_OP_breg6)
+    return 0;
+
+  ret = read_operand(c->as, a, &cfa_addr,
+                     OPND1_TYPE(operands[opcode]), &operand1, arg);
+  if (ret < 0)
+    return 0;
+
+  ret = dwarf_readu8(c->as, a, &cfa_addr, &opcode, arg);
+  if (ret < 0 || opcode != DW_OP_deref)
+    return 0;
+
+  *cfa_offset = operand1;
+  return 1;
+}
+
+HIDDEN int
 dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr, unw_word_t len,
                  unw_word_t *valp, int *is_register)
 {
-  unw_word_t operand1 = 0, operand2 = 0, tmp1, tmp2, tmp3, end_addr;
+  unw_word_t operand1 = 0, operand2 = 0, tmp1, tmp2 = 0, tmp3, end_addr;
   uint8_t opcode, operands_signature, u8;
   unw_addr_space_t as;
   unw_accessors_t *a;
@@ -233,7 +281,7 @@ do {                                            \
 
   as = c->as;
   arg = c->as_arg;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   end_addr = *addr + len;
   *is_register = 0;
 
index dc973fe..9250b89 100644 (file)
@@ -32,7 +32,7 @@ is_cie_id (unw_word_t val, int is_debug_frame)
      0xffffffffffffffff (for 64-bit ELF).  However, .eh_frame
      uses 0.  */
   if (is_debug_frame)
-    return (val == - (uint32_t) 1 || val == - (uint64_t) 1);
+      return (val == (uint32_t)(-1) || val == (uint64_t)(-1));
   else
     return (val == 0);
 }
@@ -116,10 +116,11 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
   if ((ret = dwarf_readu8 (as, a, &addr, &version, arg)) < 0)
     return ret;
 
-  if (version != 1 && version != DWARF_CIE_VERSION)
+  /* GCC emits version 1??? */
+  if (version != 1 && (version < DWARF_CIE_VERSION || version > DWARF_CIE_VERSION_MAX))
     {
-      Debug (1, "Got CIE version %u, expected version 1 or "
-             STR (DWARF_CIE_VERSION) "\n", version);
+      Debug (1, "Got CIE version %u, expected version 1 or between "
+             STR (DWARF_CIE_VERSION) " and " STR (DWARF_CIE_VERSION_MAX) "\n", version);
       return -UNW_EBADVERSION;
     }
 
@@ -240,7 +241,7 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
 
   if (u32val != 0xffffffff)
     {
-      int32_t cie_offset;
+      int32_t cie_offset = 0;
 
       /* In some configurations, an FDE with a 0 length indicates the
          end of the FDE-table.  */
@@ -270,7 +271,7 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
     }
   else
     {
-      int64_t cie_offset;
+      int64_t cie_offset = 0;
 
       /* the FDE is in the 64-bit DWARF format */
 
index 6e1f4c3..5e27a50 100644 (file)
@@ -46,13 +46,24 @@ struct table_entry
 #include "os-linux.h"
 #endif
 
+#ifndef __clang__
+static ALIAS(dwarf_search_unwind_table) int
+dwarf_search_unwind_table_int (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);
+#else
+#define dwarf_search_unwind_table_int dwarf_search_unwind_table
+#endif
+
 static int
 linear_search (unw_addr_space_t as, unw_word_t ip,
                unw_word_t eh_frame_start, unw_word_t eh_frame_end,
                unw_word_t fde_count,
                unw_proc_info_t *pi, int need_unwind_info, void *arg)
 {
-  unw_accessors_t *a = unw_get_accessors (unw_local_addr_space);
+  unw_accessors_t *a = unw_get_accessors_int (unw_local_addr_space);
   unw_word_t i = 0, fde_addr, addr = eh_frame_start;
   int ret;
 
@@ -86,151 +97,42 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
 /* 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.  */
+   directory; 0 for other address spaces, in which case we do
+   not. Returns 0 on success, 1 on error.  Succeeds even if the file
+   contains no .debug_frame.  */
 /* XXX: Could use mmap; but elf_map_image keeps tons mapped in.  */
 
 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 = NULL;
-  char *stringtab = NULL;
-  unsigned int i;
-  size_t linksize = 0;
-  char *linkbuf = NULL;
-  
-  *buf = NULL;
-  *bufsize = 0;
-  
-  f = fopen (file, "r");
-  
-  if (!f)
-    return 1;
-  
-  if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1)
-    goto file_error;
-  
-  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)));
-  if (fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f) != ehdr.e_shnum)
-    goto file_error;
-  
-  Debug (4, "loading string table of size %zd\n",
-           sec_hdrs[shstrndx].sh_size);
-  stringtab = malloc (sec_hdrs[shstrndx].sh_size);
-  fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
-  if (fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f) != sec_hdrs[shstrndx].sh_size)
-    goto file_error;
-  
-  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);
-          if (fread (*buf, 1, *bufsize, f) != *bufsize)
-            goto file_error;
-
-          Debug (4, "read %zd bytes of .debug_frame from offset %zd\n",
-                 *bufsize, sec_hdrs[i].sh_offset);
-        }
-      else if (strcmp (secname, ".gnu_debuglink") == 0)
-        {
-          linksize = sec_hdrs[i].sh_size;
-          linkbuf = malloc (linksize);
-
-          fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
-          if (fread (linkbuf, 1, linksize, f) != linksize)
-            goto file_error;
-
-          Debug (4, "read %zd bytes of .gnu_debuglink from offset %zd\n",
-                 linksize, sec_hdrs[i].sh_offset);
-        }
-    }
+  struct elf_image ei;
+  Elf_W (Shdr) *shdr;
+  int ret;
 
-  free (stringtab);
-  free (sec_hdrs);
+  ei.image = NULL;
 
-  fclose (f);
+  ret = elf_w (load_debuglink) (file, &ei, is_local);
+  if (ret != 0)
+    return ret;
 
-  /* Ignore separate debug files which contain a .gnu_debuglink section. */
-  if (linkbuf && is_local == -1)
+  shdr = elf_w (find_section) (&ei, ".debug_frame");
+  if (!shdr ||
+      (shdr->sh_offset + shdr->sh_size > ei.size))
     {
-      free (linkbuf);
+      munmap(ei.image, ei.size);
       return 1;
     }
 
-  if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL)
-    {
-      char *newname, *basedir, *p;
-      static const char *debugdir = "/usr/lib/debug";
-      int ret;
+  *bufsize = shdr->sh_size;
+  *buf = malloc (*bufsize);
 
-      /* XXX: Don't bother with the checksum; just search for the file.  */
-      basedir = malloc (strlen (file) + 1);
-      newname = malloc (strlen (linkbuf) + strlen (debugdir)
-                        + strlen (file) + 9);
+  memcpy(*buf, shdr->sh_offset + ei.image, *bufsize);
 
-      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);
+  Debug (4, "read %zd bytes of .debug_frame from offset %zd\n",
+        *bufsize, shdr->sh_offset);
 
+  munmap(ei.image, ei.size);
   return 0;
-
-/* An error reading image file. Release resources and return error code */
-file_error:
-  free(stringtab);
-  free(sec_hdrs);
-  free(linkbuf);
-  fclose(f);
-
-  return 1;
 }
 
 /* Locate the binary which originated the contents of address ADDR. Return
@@ -246,7 +148,9 @@ find_binary_for_address (unw_word_t ip, char *name, size_t name_size)
   int pid = getpid ();
   unsigned long segbase, mapoff, hi;
 
-  maps_init (&mi, pid);
+  if (maps_init (&mi, pid) != 0)
+    return 1;
+
   while (maps_next (&mi, &segbase, &hi, &mapoff))
     if (ip >= segbase && ip < hi)
       {
@@ -306,7 +210,7 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
     name = (char*) dlname;
 
   err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
-  
+
   if (!err)
     {
       fdesc = malloc (sizeof (struct unw_debug_frame_list));
@@ -317,10 +221,10 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
       fdesc->debug_frame_size = bufsize;
       fdesc->index = NULL;
       fdesc->next = as->debug_frames;
-      
+
       as->debug_frames = fdesc;
     }
-  
+
   return fdesc;
 }
 
@@ -342,10 +246,10 @@ debug_frame_tab_append (struct debug_frame_tab *tab,
       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;
 }
 
@@ -363,7 +267,7 @@ 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)
@@ -372,7 +276,7 @@ debug_frame_tab_compare (const void *a, const void *b)
     return 0;
 }
 
-PROTECTED int
+int
 dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
                         unw_word_t segbase, const char* obj_name,
                         unw_word_t start, unw_word_t end)
@@ -417,7 +321,7 @@ dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
        {
          addr = (unw_word_t) (uintptr_t) buf;
 
-         a = unw_get_accessors (unw_local_addr_space);
+         a = unw_get_accessors_int (unw_local_addr_space);
 
          /* Find all FDE entries in debug_frame, and make into a sorted
             index.  */
@@ -523,6 +427,55 @@ dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
 
 #ifndef UNW_REMOTE_ONLY
 
+static Elf_W (Addr)
+dwarf_find_eh_frame_section(struct dl_phdr_info *info)
+{
+  int rc;
+  struct elf_image ei;
+  Elf_W (Addr) eh_frame = 0;
+  Elf_W (Shdr)* shdr;
+  const char *file = info->dlpi_name;
+  char exepath[PATH_MAX];
+
+  if (strlen(file) == 0)
+    {
+      tdep_get_exe_image_path(exepath);
+      file = exepath;
+    }
+
+  Debug (1, "looking for .eh_frame section in %s\n",
+         file);
+
+  rc = elf_map_image (&ei, file);
+  if (rc != 0)
+    return 0;
+
+  shdr = elf_w (find_section) (&ei, ".eh_frame");
+  if (!shdr)
+    goto out;
+
+  eh_frame = shdr->sh_addr + info->dlpi_addr;
+  Debug (4, "found .eh_frame at address %lx\n",
+         eh_frame);
+
+out:
+  munmap (ei.image, ei.size);
+
+  return eh_frame;
+}
+
+struct dwarf_callback_data
+  {
+    /* in: */
+    unw_word_t ip;              /* instruction-pointer we're looking for */
+    unw_proc_info_t *pi;        /* proc-info pointer */
+    int need_unwind_info;
+    /* out: */
+    int single_fde;             /* did we find a single FDE? (vs. a table) */
+    unw_dyn_info_t di;          /* table info (if single_fde is false) */
+    unw_dyn_info_t di_debug;    /* additional table info for .debug_frame */
+  };
+
 /* ptr is a pointer to a dwarf_callback_data structure and, on entry,
    member ip contains the instruction-pointer we're looking
    for.  */
@@ -536,10 +489,11 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
   Elf_W(Addr) load_base, max_load_addr = 0;
   int ret, need_unwind_info = cb_data->need_unwind_info;
   unw_proc_info_t *pi = cb_data->pi;
-  struct dwarf_eh_frame_hdr *hdr;
+  struct dwarf_eh_frame_hdr *hdr = NULL;
   unw_accessors_t *a;
   long n;
   int found = 0;
+  struct dwarf_eh_frame_hdr synth_eh_frame_hdr;
 #ifdef CONFIG_DEBUG_FRAME
   unw_word_t start, end;
 #endif /* CONFIG_DEBUG_FRAME*/
@@ -579,12 +533,35 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
       else if (phdr->p_type == PT_DYNAMIC)
         p_dynamic = phdr;
     }
-  
+
   if (!p_text)
     return 0;
 
   if (p_eh_hdr)
     {
+      hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
+    }
+  else
+    {
+      Elf_W (Addr) eh_frame;
+      Debug (1, "no .eh_frame_hdr section found\n");
+      eh_frame = dwarf_find_eh_frame_section (info);
+      if (eh_frame)
+        {
+          Debug (1, "using synthetic .eh_frame_hdr section for %s\n",
+                 info->dlpi_name);
+         synth_eh_frame_hdr.version = DW_EH_VERSION;
+         synth_eh_frame_hdr.eh_frame_ptr_enc = DW_EH_PE_absptr |
+           ((sizeof(Elf_W (Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8);
+          synth_eh_frame_hdr.fde_count_enc = DW_EH_PE_omit;
+          synth_eh_frame_hdr.table_enc = DW_EH_PE_omit;
+         synth_eh_frame_hdr.eh_frame = eh_frame;
+          hdr = &synth_eh_frame_hdr;
+        }
+    }
+
+  if (hdr)
+    {
       if (p_dynamic)
         {
           /* For dynamicly linked executables and shared libraries,
@@ -607,7 +584,6 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
         di->gp = 0;
       pi->gp = di->gp;
 
-      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",
@@ -615,8 +591,8 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
           return 0;
         }
 
-      a = unw_get_accessors (unw_local_addr_space);
-      addr = (unw_word_t) (uintptr_t) (hdr + 1);
+      a = unw_get_accessors_int (unw_local_addr_space);
+      addr = (unw_word_t) (uintptr_t) (&hdr->eh_frame);
 
       /* (Optionally) read eh_frame_ptr: */
       if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
@@ -648,14 +624,18 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
           if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
             abort ();
 
+          Debug (1, "eh_frame_start = %lx eh_frame_end = %lx\n",
+                 eh_frame_start, eh_frame_end);
+
           /* XXX we know how to build a local binary search table for
              .debug_frame, so we could do that here too.  */
-          cb_data->single_fde = 1;
           found = linear_search (unw_local_addr_space, ip,
                                  eh_frame_start, eh_frame_end, fde_count,
                                  pi, need_unwind_info, NULL);
           if (found != 1)
             found = 0;
+         else
+           cb_data->single_fde = 1;
         }
       else
         {
@@ -729,26 +709,26 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
   ret = dl_iterate_phdr (dwarf_callback, &cb_data);
   SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
 
-  if (ret <= 0)
+  if (ret > 0)
     {
-      Debug (14, "IP=0x%lx not found\n", (long) ip);
-      return -UNW_ENOINFO;
-    }
-
-  if (cb_data.single_fde)
-    /* already got the result in *pi */
-    return 0;
+      if (cb_data.single_fde)
+       /* already got the result in *pi */
+       return 0;
+
+      /* search the table: */
+      if (cb_data.di.format != -1)
+       ret = dwarf_search_unwind_table_int (as, ip, &cb_data.di,
+                                            pi, need_unwind_info, arg);
+      else
+       ret = -UNW_ENOINFO;
 
-  /* search the table: */
-  if (cb_data.di.format != -1)
-    ret = dwarf_search_unwind_table (as, ip, &cb_data.di,
-                                      pi, need_unwind_info, arg);
+      if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
+       ret = dwarf_search_unwind_table_int (as, ip, &cb_data.di_debug, pi,
+                                            need_unwind_info, arg);
+    }
   else
     ret = -UNW_ENOINFO;
 
-  if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
-    ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi,
-                                     need_unwind_info, arg);
   return ret;
 }
 
@@ -786,13 +766,13 @@ lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
 static int
 remote_lookup (unw_addr_space_t as,
                unw_word_t table, size_t table_size, int32_t rel_ip,
-               struct table_entry *e, void *arg)
+               struct table_entry *e, int32_t *last_ip_offset, void *arg)
 {
   unsigned long table_len = table_size / sizeof (struct table_entry);
-  unw_accessors_t *a = unw_get_accessors (as);
+  unw_accessors_t *a = unw_get_accessors_int (as);
   unsigned long lo, hi, mid;
   unw_word_t e_addr = 0;
-  int32_t start;
+  int32_t start = 0;
   int ret;
 
   /* do a binary search for right entry: */
@@ -812,7 +792,9 @@ remote_lookup (unw_addr_space_t as,
     return 0;
   e_addr = table + (hi - 1) * sizeof (struct table_entry);
   if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0
-   || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0)
+   || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0
+   || (hi < table_len &&
+       (ret = dwarf_reads32 (as, a, &e_addr, last_ip_offset, arg)) < 0))
     return ret;
   return 1;
 }
@@ -825,13 +807,13 @@ static int is_remote_table(int format)
           format == UNW_INFO_FORMAT_IP_OFFSET);
 }
 
-PROTECTED int
+int
 dwarf_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)
 {
   const struct table_entry *e = NULL, *table;
-  unw_word_t ip_base = 0, segbase = 0, fde_addr;
+  unw_word_t ip_base = 0, segbase = 0, last_ip, fde_addr;
   unw_accessors_t *a;
 #ifndef UNW_LOCAL_ONLY
   struct table_entry ent;
@@ -871,7 +853,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
 #endif
     }
 
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
 
   segbase = di->u.rti.segbase;
   if (di->format == UNW_INFO_FORMAT_IP_OFFSET) {
@@ -884,17 +866,25 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
   if (as == unw_local_addr_space)
     {
       e = lookup (table, table_len, ip - ip_base);
+      if (e && &e[1] < &table[table_len])
+       last_ip = e[1].start_ip_offset + ip_base;
+      else
+       last_ip = di->end_ip;
     }
   else
 #endif
     {
 #ifndef UNW_LOCAL_ONLY
+      int32_t last_ip_offset = di->end_ip - ip_base;
       segbase = di->u.rti.segbase;
       if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
-                                ip - ip_base, &ent, arg)) < 0)
+                                ip - ip_base, &ent, &last_ip_offset, arg)) < 0)
         return ret;
       if (ret)
-        e = &ent;
+       {
+         e = &ent;
+         last_ip = last_ip_offset + ip_base;
+       }
       else
         e = NULL;       /* no info found */
 #endif
@@ -932,6 +922,11 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
       pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
     }
 
+#if defined(NEED_LAST_IP)
+  pi->last_ip = last_ip;
+#else
+  (void)last_ip;
+#endif
   if (ip < pi->start_ip || ip >= pi->end_ip)
     return -UNW_ENOINFO;
 
index a51c611..6a2ad50 100644 (file)
@@ -33,6 +33,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "dwarf-eh.h"
 #include "dwarf_i.h"
 
+#define to_unw_word(p) ((unw_word_t) (uintptr_t) (p))
+
 int
 dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
                          char *path, unw_word_t segbase, unw_word_t mapoff,
@@ -41,7 +43,7 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
   Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
   unw_word_t addr, eh_frame_start, fde_count, load_base;
   unw_word_t max_load_addr = 0;
-  unw_word_t start_ip = (unw_word_t) -1;
+  unw_word_t start_ip = to_unw_word (-1);
   unw_word_t end_ip = 0;
   struct dwarf_eh_frame_hdr *hdr;
   unw_proc_info_t pi;
@@ -136,8 +138,8 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
           return -UNW_ENOINFO;
         }
 
-      a = unw_get_accessors (unw_local_addr_space);
-      addr = (unw_word_t) (hdr + 1);
+      a = unw_get_accessors_int (unw_local_addr_space);
+      addr = to_unw_word (&hdr->eh_frame);
 
       /* Fill in a dummy proc_info structure.  We just need to fill in
          enough to ensure that dwarf_read_encoded_pointer() can do it's
@@ -193,13 +195,14 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
       /* two 32-bit values (ip_offset/fde_offset) per table-entry: */
       edi->di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t);
       edi->di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr)
-                                       + (addr - (unw_word_t) edi->ei.image
+                                       + (addr - to_unw_word (edi->ei.image)
                                           - peh_hdr->p_offset));
 
       /* For the binary-search table in the eh_frame_hdr, data-relative
          means relative to the start of that section... */
       edi->di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr)
-                                    + ((unw_word_t) hdr - (unw_word_t) edi->ei.image
+                                    + (to_unw_word (hdr) -
+                                       to_unw_word (edi->ei.image)
                                        - peh_hdr->p_offset));
       found = 1;
     }
@@ -210,7 +213,7 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
       edi->di_arm.format = UNW_INFO_FORMAT_ARM_EXIDX;
       edi->di_arm.start_ip = start_ip;
       edi->di_arm.end_ip = end_ip;
-      edi->di_arm.u.rti.name_ptr = (unw_word_t) path;
+      edi->di_arm.u.rti.name_ptr = to_unw_word (path);
       edi->di_arm.u.rti.table_data = load_base + parm_exidx->p_vaddr;
       edi->di_arm.u.rti.table_len = parm_exidx->p_memsz;
       found = 1;
index 3a47255..7d255ae 100644 (file)
@@ -23,13 +23,17 @@ 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 <stddef.h>
 #include "dwarf_i.h"
 #include "libunwind_i.h"
+#include <stddef.h>
+#include <limits.h>
 
 #define alloc_reg_state()       (mempool_alloc (&dwarf_reg_state_pool))
 #define free_reg_state(rs)      (mempool_free (&dwarf_reg_state_pool, rs))
 
+#define DWARF_UNW_CACHE_SIZE(log_size)   (1 << log_size)
+#define DWARF_UNW_HASH_SIZE(log_size)    (1 << (log_size + 1))
+
 static inline int
 read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
              unw_word_t *valp, void *arg)
@@ -51,44 +55,72 @@ static inline void
 set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
          unw_word_t val)
 {
-  sr->rs_current.reg[regnum].where = where;
-  sr->rs_current.reg[regnum].val = val;
+  sr->rs_current.reg.where[regnum] = where;
+  sr->rs_current.reg.val[regnum] = val;
+}
+
+static inline int
+push_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
+{
+  dwarf_stackable_reg_state_t *old_rs = *rs_stack;
+  if (NULL == (*rs_stack = alloc_reg_state ()))
+    {
+      *rs_stack = old_rs;
+      return -1;
+    }
+  (*rs_stack)->next = old_rs;
+  return 0;
+}
+
+static inline void
+pop_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
+{
+  dwarf_stackable_reg_state_t *old_rs = *rs_stack;
+  *rs_stack = old_rs->next;
+  free_reg_state (old_rs);
+}
+
+static inline void
+empty_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
+{
+  while (*rs_stack)
+    pop_rstate_stack(rs_stack);
 }
 
 /* Run a CFI program to update the register state.  */
 static int
 run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
-                 unw_word_t ip, unw_word_t *addr, unw_word_t end_addr,
+                 unw_word_t *ip, unw_word_t end_ip,
+                unw_word_t *addr, unw_word_t end_addr,
+                dwarf_stackable_reg_state_t **rs_stack,
                  struct dwarf_cie_info *dci)
 {
-  unw_word_t curr_ip, operand = 0, regnum, val, len, fde_encoding;
-  dwarf_reg_state_t *rs_stack = NULL, *new_rs, *old_rs;
   unw_addr_space_t as;
-  unw_accessors_t *a;
-  uint8_t u8, op;
-  uint16_t u16;
-  uint32_t u32;
   void *arg;
-  int ret;
 
-  as = c->as;
-  arg = c->as_arg;
   if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME)
     {
       /* .debug_frame CFI is stored in local address space.  */
       as = unw_local_addr_space;
       arg = NULL;
     }
-  a = unw_get_accessors (as);
-  curr_ip = c->pi.start_ip;
+  else
+    {
+      as = c->as;
+      arg = c->as_arg;
+    }
+  unw_accessors_t *a = unw_get_accessors_int (as);
+  int ret = 0;
 
-  /* Process everything up to and including the current 'ip',
-     including all the DW_CFA_advance_loc instructions.  See
-     'c->use_prev_instr' use in 'fetch_proc_info' for details. */
-  while (curr_ip <= ip && *addr < end_addr)
+  while (*ip <= end_ip && *addr < end_addr && ret >= 0)
     {
+      unw_word_t operand = 0, regnum, val, len;
+      uint8_t u8, op;
+      uint16_t u16;
+      uint32_t u32;
+
       if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
-        return ret;
+        break;
 
       if (op & DWARF_CFA_OPCODE_MASK)
         {
@@ -98,46 +130,46 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
       switch ((dwarf_cfa_t) op)
         {
         case DW_CFA_advance_loc:
-          curr_ip += operand * dci->code_align;
-          Debug (15, "CFA_advance_loc to 0x%lx\n", (long) curr_ip);
+          *ip += operand * dci->code_align;
+          Debug (15, "CFA_advance_loc to 0x%lx\n", (long) *ip);
           break;
 
         case DW_CFA_advance_loc1:
           if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0)
-            goto fail;
-          curr_ip += u8 * dci->code_align;
-          Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) curr_ip);
+            break;
+          *ip += u8 * dci->code_align;
+          Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) *ip);
           break;
 
         case DW_CFA_advance_loc2:
           if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0)
-            goto fail;
-          curr_ip += u16 * dci->code_align;
-          Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) curr_ip);
+            break;
+          *ip += u16 * dci->code_align;
+          Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) *ip);
           break;
 
         case DW_CFA_advance_loc4:
           if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0)
-            goto fail;
-          curr_ip += u32 * dci->code_align;
-          Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) curr_ip);
+            break;
+          *ip += u32 * dci->code_align;
+          Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) *ip);
           break;
 
         case DW_CFA_MIPS_advance_loc8:
 #ifdef UNW_TARGET_MIPS
           {
-            uint64_t u64;
+            uint64_t u64 = 0;
 
             if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0)
-              goto fail;
-            curr_ip += u64 * dci->code_align;
+              break;
+            *ip += u64 * dci->code_align;
             Debug (15, "CFA_MIPS_advance_loc8\n");
             break;
           }
 #else
           Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n");
           ret = -UNW_EINVAL;
-          goto fail;
+          break;
 #endif
 
         case DW_CFA_offset:
@@ -147,10 +179,10 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
               Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n",
                      (unsigned int) regnum);
               ret = -UNW_EBADREG;
-              goto fail;
+              break;
             }
           if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
-            goto fail;
+            break;
           set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
           Debug (15, "CFA_offset r%lu at cfa+0x%lx\n",
                  (long) regnum, (long) (val * dci->data_align));
@@ -159,7 +191,7 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
         case DW_CFA_offset_extended:
           if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
               || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
-            goto fail;
+            break;
           set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
           Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n",
                  (long) regnum, (long) (val * dci->data_align));
@@ -168,7 +200,7 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
         case DW_CFA_offset_extended_sf:
           if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
               || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
-            goto fail;
+            break;
           set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
           Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
                  (long) regnum, (long) (val * dci->data_align));
@@ -181,23 +213,25 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
               Debug (1, "Invalid register number %u in DW_CFA_restore\n",
                      (unsigned int) regnum);
               ret = -UNW_EINVAL;
-              goto fail;
+              break;
             }
-          sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum];
+          sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum];
+          sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum];
           Debug (15, "CFA_restore r%lu\n", (long) regnum);
           break;
 
         case DW_CFA_restore_extended:
           if ((ret = dwarf_read_uleb128 (as, a, addr, &regnum, arg)) < 0)
-            goto fail;
+            break;
           if (regnum >= DWARF_NUM_PRESERVED_REGS)
             {
               Debug (1, "Invalid register number %u in "
                      "DW_CFA_restore_extended\n", (unsigned int) regnum);
               ret = -UNW_EINVAL;
-              goto fail;
+              break;
             }
-          sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum];
+          sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum];
+          sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum];
           Debug (15, "CFA_restore_extended r%lu\n", (long) regnum);
           break;
 
@@ -205,24 +239,23 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
           break;
 
         case DW_CFA_set_loc:
-          fde_encoding = dci->fde_encoding;
-          if ((ret = dwarf_read_encoded_pointer (as, a, addr, fde_encoding,
-                                                 &c->pi, &curr_ip,
+          if ((ret = dwarf_read_encoded_pointer (as, a, addr, dci->fde_encoding,
+                                                 &c->pi, ip,
                                                  arg)) < 0)
-            goto fail;
-          Debug (15, "CFA_set_loc to 0x%lx\n", (long) curr_ip);
+            break;
+          Debug (15, "CFA_set_loc to 0x%lx\n", (long) *ip);
           break;
 
         case DW_CFA_undefined:
           if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
-            goto fail;
+            break;
           set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0);
           Debug (15, "CFA_undefined r%lu\n", (long) regnum);
           break;
 
         case DW_CFA_same_value:
           if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
-            goto fail;
+            break;
           set_reg (sr, regnum, DWARF_WHERE_SAME, 0);
           Debug (15, "CFA_same_value r%lu\n", (long) regnum);
           break;
@@ -230,44 +263,38 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
         case DW_CFA_register:
           if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
               || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
-            goto fail;
+            break;
           set_reg (sr, regnum, DWARF_WHERE_REG, val);
           Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val);
           break;
 
         case DW_CFA_remember_state:
-          new_rs = alloc_reg_state ();
-          if (!new_rs)
-            {
+         if (push_rstate_stack(rs_stack) < 0)
+           {
               Debug (1, "Out of memory in DW_CFA_remember_state\n");
               ret = -UNW_ENOMEM;
-              goto fail;
-            }
-
-          memcpy (new_rs->reg, sr->rs_current.reg, sizeof (new_rs->reg));
-          new_rs->next = rs_stack;
-          rs_stack = new_rs;
+              break;
+           }
+          (*rs_stack)->state = sr->rs_current;
           Debug (15, "CFA_remember_state\n");
           break;
 
         case DW_CFA_restore_state:
-          if (!rs_stack)
+          if (!*rs_stack)
             {
               Debug (1, "register-state stack underflow\n");
               ret = -UNW_EINVAL;
-              goto fail;
+              break;
             }
-          memcpy (&sr->rs_current.reg, &rs_stack->reg, sizeof (rs_stack->reg));
-          old_rs = rs_stack;
-          rs_stack = rs_stack->next;
-          free_reg_state (old_rs);
+          sr->rs_current = (*rs_stack)->state;
+          pop_rstate_stack(rs_stack);
           Debug (15, "CFA_restore_state\n");
           break;
 
         case DW_CFA_def_cfa:
           if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
               || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
-            goto fail;
+            break;
           set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
           set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val);   /* NOT factored! */
           Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val);
@@ -276,7 +303,7 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
         case DW_CFA_def_cfa_sf:
           if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
               || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
-            goto fail;
+            break;
           set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
           set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
                    val * dci->data_align);              /* factored! */
@@ -286,21 +313,21 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
 
         case DW_CFA_def_cfa_register:
           if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
-            goto fail;
+            break;
           set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
           Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum);
           break;
 
         case DW_CFA_def_cfa_offset:
           if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
-            goto fail;
+            break;
           set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val);   /* NOT factored! */
           Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val);
           break;
 
         case DW_CFA_def_cfa_offset_sf:
           if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)
-            goto fail;
+            break;
           set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
                    val * dci->data_align);      /* factored! */
           Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n",
@@ -312,7 +339,7 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
           set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr);
 
           if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
-            goto fail;
+            break;
 
           Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n",
                  (long) *addr, (long) len);
@@ -321,13 +348,13 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
 
         case DW_CFA_expression:
           if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
-            goto fail;
+            break;
 
           /* Save the address of the DW_FORM_block for later evaluation. */
           set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr);
 
           if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
-            goto fail;
+            break;
 
           Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n",
                  (long) regnum, (long) addr, (long) len);
@@ -336,13 +363,13 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
 
         case DW_CFA_val_expression:
           if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
-            goto fail;
+            break;
 
           /* Save the address of the DW_FORM_block for later evaluation. */
           set_reg (sr, regnum, DWARF_WHERE_VAL_EXPR, *addr);
 
           if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
-            goto fail;
+            break;
 
           Debug (15, "CFA_val_expression r%lu @ 0x%lx [%lu bytes]\n",
                  (long) regnum, (long) addr, (long) len);
@@ -351,7 +378,7 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
 
         case DW_CFA_GNU_args_size:
           if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
-            goto fail;
+            break;
           sr->args_size = val;
           Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
           break;
@@ -362,7 +389,7 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
              PowerPC code.  */
           if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
               || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
-            goto fail;
+            break;
           set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align));
           Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n",
                  (long) -(val * dci->data_align));
@@ -384,24 +411,17 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
         case DW_CFA_hi_user:
           Debug (1, "Unexpected CFA opcode 0x%x\n", op);
           ret = -UNW_EINVAL;
-          goto fail;
+          break;
         }
     }
-  ret = 0;
 
- fail:
-  /* Free the register-state stack, if not empty already.  */
-  while (rs_stack)
-    {
-      old_rs = rs_stack;
-      rs_stack = rs_stack->next;
-      free_reg_state (old_rs);
-    }
+  if (ret > 0)
+    ret = 0;
   return ret;
 }
 
 static int
-fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
+fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip)
 {
   int ret, dynamic = 1;
 
@@ -415,7 +435,7 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
      and b) so that run_cfi_program() runs locations up to the call
      but not more.
 
-     For execution resume, we need to do the exact opposite and look
+     For signal frame, we need to do the exact opposite and look
      up using the current 'ip' value.  That is where execution will
      continue, and it's important we get this right, as 'ip' could be
      right at the function entry and hence FDE edge, or at instruction
@@ -423,18 +443,15 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
   if (c->use_prev_instr)
     --ip;
 
-  if (c->pi_valid && !need_unwind_info)
-    return 0;
-
   memset (&c->pi, 0, sizeof (c->pi));
 
   /* check dynamic info first --- it overrides everything else */
-  ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
+  ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, 1,
                                      c->as_arg);
   if (ret == -UNW_ENOINFO)
     {
       dynamic = 0;
-      if ((ret = tdep_find_proc_info (c, ip, need_unwind_info)) < 0)
+      if ((ret = tdep_find_proc_info (c, ip, 1)) < 0)
         return ret;
     }
 
@@ -448,15 +465,7 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
 
   /* Let system/machine-dependent code determine frame-specific attributes. */
   if (ret >= 0)
-    tdep_fetch_frame (c, ip, need_unwind_info);
-
-  /* Update use_prev_instr for the next frame. */
-  if (need_unwind_info)
-  {
-    assert(c->pi.unwind_info);
-    struct dwarf_cie_info *dci = c->pi.unwind_info;
-    c->use_prev_instr = ! dci->signal_frame;
-  }
+    tdep_fetch_frame (c, ip, 1);
 
   return ret;
 }
@@ -465,10 +474,6 @@ static int
 parse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
 {
   Debug (1, "Not yet implemented\n");
-#if 0
-  /* Don't forget to set the ret_addr_column!  */
-  c->ret_addr_column = XXX;
-#endif
   return -UNW_ENOINFO;
 }
 
@@ -482,50 +487,102 @@ put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi)
       mempool_free (&dwarf_cie_info_pool, pi->unwind_info);
       pi->unwind_info = NULL;
     }
+  c->pi_valid = 0;
 }
 
 static inline int
-parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
+setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr)
 {
-  struct dwarf_cie_info *dci;
-  unw_word_t addr;
-  int ret;
+  int i, ret;
+
+  assert (c->pi_valid);
 
-  dci = c->pi.unwind_info;
-  c->ret_addr_column = dci->ret_addr_column;
+  memset (sr, 0, sizeof (*sr));
+  for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i)
+    set_reg (sr, i, DWARF_WHERE_SAME, 0);
 
-  addr = dci->cie_instr_start;
-  if ((ret = run_cfi_program (c, sr, ~(unw_word_t) 0, &addr,
-                              dci->cie_instr_end, dci)) < 0)
+  struct dwarf_cie_info *dci = c->pi.unwind_info;
+  sr->rs_current.ret_addr_column  = dci->ret_addr_column;
+  unw_word_t addr = dci->cie_instr_start;
+  unw_word_t curr_ip = 0;
+  dwarf_stackable_reg_state_t *rs_stack = NULL;
+  ret = run_cfi_program (c, sr, &curr_ip, ~(unw_word_t) 0, &addr,
+                        dci->cie_instr_end,
+                        &rs_stack, dci);
+  empty_rstate_stack(&rs_stack);
+  if (ret < 0)
     return ret;
 
   memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
+  return 0;
+}
 
-  addr = dci->fde_instr_start;
-  if ((ret = run_cfi_program (c, sr, ip, &addr, dci->fde_instr_end, dci)) < 0)
+static inline int
+parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
+{
+  int ret;
+  struct dwarf_cie_info *dci = c->pi.unwind_info;
+  unw_word_t addr = dci->fde_instr_start;
+  unw_word_t curr_ip = c->pi.start_ip;
+  dwarf_stackable_reg_state_t *rs_stack = NULL;
+  /* Process up to current `ip` for signal frame and `ip - 1` for normal call frame
+     See `c->use_prev_instr` use in `fetch_proc_info` for details. */
+  ret = run_cfi_program (c, sr, &curr_ip, ip - c->use_prev_instr, &addr, dci->fde_instr_end,
+                        &rs_stack, dci);
+  empty_rstate_stack(&rs_stack);
+  if (ret < 0)
     return ret;
 
   return 0;
 }
 
-static inline void
-flush_rs_cache (struct dwarf_rs_cache *cache)
+HIDDEN int
+dwarf_flush_rs_cache (struct dwarf_rs_cache *cache)
 {
   int i;
 
-  cache->lru_head = DWARF_UNW_CACHE_SIZE - 1;
-  cache->lru_tail = 0;
+  if (cache->log_size == DWARF_DEFAULT_LOG_UNW_CACHE_SIZE
+      || !cache->hash) {
+    cache->hash = cache->default_hash;
+    cache->buckets = cache->default_buckets;
+    cache->links = cache->default_links;
+    cache->log_size = DWARF_DEFAULT_LOG_UNW_CACHE_SIZE;
+  } else {
+    if (cache->hash && cache->hash != cache->default_hash)
+      munmap(cache->hash, DWARF_UNW_HASH_SIZE(cache->prev_log_size)
+                           * sizeof (cache->hash[0]));
+    if (cache->buckets && cache->buckets != cache->default_buckets)
+      munmap(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->prev_log_size)
+                             * sizeof (cache->buckets[0]));
+    if (cache->links && cache->links != cache->default_links)
+      munmap(cache->links, DWARF_UNW_CACHE_SIZE(cache->prev_log_size)
+                             * sizeof (cache->links[0]));
+    GET_MEMORY(cache->hash, DWARF_UNW_HASH_SIZE(cache->log_size)
+                             * sizeof (cache->hash[0]));
+    GET_MEMORY(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->log_size)
+                                * sizeof (cache->buckets[0]));
+    GET_MEMORY(cache->links, DWARF_UNW_CACHE_SIZE(cache->log_size)
+                                * sizeof (cache->links[0]));
+    if (!cache->hash || !cache->buckets || !cache->links)
+      {
+        Debug (1, "Unable to allocate cache memory");
+        return -UNW_ENOMEM;
+      }
+    cache->prev_log_size = cache->log_size;
+  }
+
+  cache->rr_head = 0;
 
-  for (i = 0; i < DWARF_UNW_CACHE_SIZE; ++i)
+  for (i = 0; i < DWARF_UNW_CACHE_SIZE(cache->log_size); ++i)
     {
-      if (i > 0)
-        cache->buckets[i].lru_chain = (i - 1);
-      cache->buckets[i].coll_chain = -1;
-      cache->buckets[i].ip = 0;
-      cache->buckets[i].valid = 0;
+      cache->links[i].coll_chain = -1;
+      cache->links[i].ip = 0;
+      cache->links[i].valid = 0;
     }
-  for (i = 0; i<DWARF_UNW_HASH_SIZE; ++i)
+  for (i = 0; i< DWARF_UNW_HASH_SIZE(cache->log_size); ++i)
     cache->hash[i] = -1;
+
+  return 0;
 }
 
 static inline struct dwarf_rs_cache *
@@ -537,15 +594,29 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
   if (caching == UNW_CACHE_NONE)
     return NULL;
 
+#if defined(HAVE___THREAD) && HAVE___THREAD
+  if (likely (caching == UNW_CACHE_PER_THREAD))
+    {
+      static __thread struct dwarf_rs_cache tls_cache __attribute__((tls_model("initial-exec")));
+      Debug (16, "using TLS cache\n");
+      cache = &tls_cache;
+    }
+  else
+#else
   if (likely (caching == UNW_CACHE_GLOBAL))
+#endif
     {
       Debug (16, "acquiring lock\n");
       lock_acquire (&cache->lock, *saved_maskp);
     }
 
-  if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
+  if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
+       || !cache->hash)
     {
-      flush_rs_cache (cache);
+      /* cache_size is only set in the global_cache, copy it over before flushing */
+      cache->log_size = as->global_cache.log_size;
+      if (dwarf_flush_rs_cache (cache) < 0)
+        return NULL;
       cache->generation = as->cache_generation;
     }
 
@@ -564,125 +635,90 @@ put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
 }
 
 static inline unw_hash_index_t CONST_ATTR
-hash (unw_word_t ip)
+hash (unw_word_t ip, unsigned short log_size)
 {
   /* based on (sqrt(5)/2-1)*2^64 */
 # define magic  ((unw_word_t) 0x9e3779b97f4a7c16ULL)
 
-  return ip * magic >> ((sizeof(unw_word_t) * 8) - DWARF_LOG_UNW_HASH_SIZE);
+  return ip * magic >> ((sizeof(unw_word_t) * 8) - (log_size + 1));
 }
 
 static inline long
-cache_match (dwarf_reg_state_t *rs, unw_word_t ip)
+cache_match (struct dwarf_rs_cache *cache, unsigned short index, unw_word_t ip)
 {
-  if (rs->valid && (ip == rs->ip))
-    return 1;
-  return 0;
+  return (cache->links[index].valid && (ip == cache->links[index].ip));
 }
 
 static dwarf_reg_state_t *
 rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
 {
-  dwarf_reg_state_t *rs = cache->buckets + c->hint;
   unsigned short index;
-  unw_word_t ip;
+  unw_word_t ip = c->ip;
 
-  ip = c->ip;
-
-  if (cache_match (rs, ip))
-    return rs;
-
-  index = cache->hash[hash (ip)];
-  if (index >= DWARF_UNW_CACHE_SIZE)
-    return NULL;
+  if (c->hint > 0)
+    {
+      index = c->hint - 1;
+      if (cache_match (cache, index, ip))
+       return &cache->buckets[index];
+    }
 
-  rs = cache->buckets + index;
-  while (1)
+  for (index = cache->hash[hash (ip, cache->log_size)];
+       index < DWARF_UNW_CACHE_SIZE(cache->log_size);
+       index = cache->links[index].coll_chain)
     {
-      if (cache_match (rs, ip))
-        {
-          /* update hint; no locking needed: single-word writes are atomic */
-          c->hint = cache->buckets[c->prev_rs].hint =
-            (rs - cache->buckets);
-          return rs;
-        }
-      if (rs->coll_chain >= DWARF_UNW_HASH_SIZE)
-        return NULL;
-      rs = cache->buckets + rs->coll_chain;
+      if (cache_match (cache, index, ip))
+       return &cache->buckets[index];
     }
+  return NULL;
 }
 
 static inline dwarf_reg_state_t *
 rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
 {
-  dwarf_reg_state_t *rs, *prev, *tmp;
   unw_hash_index_t index;
   unsigned short head;
 
-  head = cache->lru_head;
-  rs = cache->buckets + head;
-  cache->lru_head = rs->lru_chain;
-
-  /* re-insert rs at the tail of the LRU chain: */
-  cache->buckets[cache->lru_tail].lru_chain = head;
-  cache->lru_tail = head;
+  head = cache->rr_head;
+  cache->rr_head = (head + 1) & (DWARF_UNW_CACHE_SIZE(cache->log_size) - 1);
 
   /* remove the old rs from the hash table (if it's there): */
-  if (rs->ip)
+  if (cache->links[head].ip)
     {
-      index = hash (rs->ip);
-      tmp = cache->buckets + cache->hash[index];
-      prev = NULL;
-      while (1)
-        {
-          if (tmp == rs)
-            {
-              if (prev)
-                prev->coll_chain = tmp->coll_chain;
-              else
-                cache->hash[index] = tmp->coll_chain;
-              break;
-            }
-          else
-            prev = tmp;
-          if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE)
-            /* old rs wasn't in the hash-table */
-            break;
-          tmp = cache->buckets + tmp->coll_chain;
-        }
+      unsigned short *pindex;
+      for (pindex = &cache->hash[hash (cache->links[head].ip, cache->log_size)];
+          *pindex < DWARF_UNW_CACHE_SIZE(cache->log_size);
+          pindex = &cache->links[*pindex].coll_chain)
+       {
+         if (*pindex == head)
+           {
+             *pindex = cache->links[*pindex].coll_chain;
+             break;
+           }
+       }
     }
 
   /* enter new rs in the hash table */
-  index = hash (c->ip);
-  rs->coll_chain = cache->hash[index];
-  cache->hash[index] = rs - cache->buckets;
-
-  rs->hint = 0;
-  rs->ip = c->ip;
-  rs->valid = 1;
-  rs->ret_addr_column = c->ret_addr_column;
-  rs->signal_frame = 0;
-  tdep_cache_frame (c, rs);
-
-  return rs;
+  index = hash (c->ip, cache->log_size);
+  cache->links[head].coll_chain = cache->hash[index];
+  cache->hash[index] = head;
+
+  cache->links[head].ip = c->ip;
+  cache->links[head].valid = 1;
+  cache->links[head].signal_frame = tdep_cache_frame(c);
+  return cache->buckets + head;
 }
 
 static int
 create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
                          unw_word_t ip)
 {
-  int i, ret;
-
-  assert (c->pi_valid);
-
-  memset (sr, 0, sizeof (*sr));
-  for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i)
-    set_reg (sr, i, DWARF_WHERE_SAME, 0);
-
+  int ret;
   switch (c->pi.format)
     {
     case UNW_INFO_FORMAT_TABLE:
     case UNW_INFO_FORMAT_REMOTE_TABLE:
+      if ((ret = setup_fde(c, sr)) < 0)
+       return ret;
       ret = parse_fde (c, ip, sr);
       break;
 
@@ -737,37 +773,37 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
 
   as = c->as;
   arg = c->as_arg;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
 
   /* Evaluate the CFA first, because it may be referred to by other
      expressions.  */
 
-  if (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
+  if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
     {
       /* CFA is equal to [reg] + offset: */
 
       /* As a special-case, if the stack-pointer is the CFA and the
          stack-pointer wasn't saved, popping the CFA implicitly pops
          the stack-pointer as well.  */
-      if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP)
-          && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg))
-          && (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME))
+      if ((rs->reg.val[DWARF_CFA_REG_COLUMN] == UNW_TDEP_SP)
+          && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg.val))
+          && (rs->reg.where[UNW_TDEP_SP] == DWARF_WHERE_SAME))
           cfa = c->cfa;
       else
         {
-          regnum = dwarf_to_unw_regnum (rs->reg[DWARF_CFA_REG_COLUMN].val);
+          regnum = dwarf_to_unw_regnum (rs->reg.val[DWARF_CFA_REG_COLUMN]);
           if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0)
             return ret;
         }
-      cfa += rs->reg[DWARF_CFA_OFF_COLUMN].val;
+      cfa += rs->reg.val[DWARF_CFA_OFF_COLUMN];
     }
   else
     {
       /* CFA is equal to EXPR: */
 
-      assert (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_EXPR);
+      assert (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR);
 
-      addr = rs->reg[DWARF_CFA_REG_COLUMN].val;
+      addr = rs->reg.val[DWARF_CFA_REG_COLUMN];
       if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0)
         return ret;
       /* the returned location better be a memory location... */
@@ -776,50 +812,59 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
       cfa = DWARF_GET_LOC (cfa_loc);
     }
 
+  dwarf_loc_t new_loc[DWARF_NUM_PRESERVED_REGS];
+  memcpy(new_loc, c->loc, sizeof(new_loc));
+
   for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
     {
-      switch ((dwarf_where_t) rs->reg[i].where)
+      switch ((dwarf_where_t) rs->reg.where[i])
         {
         case DWARF_WHERE_UNDEF:
-          c->loc[i] = DWARF_NULL_LOC;
+          new_loc[i] = DWARF_NULL_LOC;
           break;
 
         case DWARF_WHERE_SAME:
           break;
 
         case DWARF_WHERE_CFAREL:
-          c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val);
+          new_loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg.val[i]);
           break;
 
         case DWARF_WHERE_REG:
-          c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val));
+          new_loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg.val[i]));
           break;
 
         case DWARF_WHERE_EXPR:
-          addr = rs->reg[i].val;
-          if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
+          addr = rs->reg.val[i];
+          if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0)
             return ret;
           break;
 
         case DWARF_WHERE_VAL_EXPR:
-          addr = rs->reg[i].val;
-          if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
+          addr = rs->reg.val[i];
+          if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0)
             return ret;
-          c->loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (c->loc[i]));
+          new_loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (new_loc[i]));
           break;
         }
     }
 
+  memcpy(c->loc, new_loc, sizeof(new_loc));
+
   c->cfa = cfa;
   /* DWARF spec says undefined return address location means end of stack. */
-  if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column]))
-    c->ip = 0;
+  if (DWARF_IS_NULL_LOC (c->loc[rs->ret_addr_column]))
+    {
+      c->ip = 0;
+      ret = 0;
+    }
   else
   {
-    ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip);
+    ret = dwarf_get (c, c->loc[rs->ret_addr_column], &ip);
     if (ret < 0)
       return ret;
     c->ip = ip;
+    ret = 1;
   }
 
   /* XXX: check for ip to be code_aligned */
@@ -833,99 +878,182 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
   if (c->stash_frames)
     tdep_stash_frame (c, rs);
 
-  return 0;
+  return ret;
 }
 
+/* Find the saved locations. */
 static int
-uncached_dwarf_find_save_locs (struct dwarf_cursor *c)
+find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr)
 {
-  dwarf_state_record_t sr;
-  int ret;
+  dwarf_reg_state_t *rs;
+  struct dwarf_rs_cache *cache;
+  int ret = 0;
+  intrmask_t saved_mask;
 
-  if ((ret = fetch_proc_info (c, c->ip, 1)) < 0)
+  if ((cache = get_rs_cache(c->as, &saved_mask)) &&
+      (rs = rs_lookup(cache, c)))
     {
+      /* update hint; no locking needed: single-word writes are atomic */
+      unsigned short index = rs - cache->buckets;
+      c->use_prev_instr = ! cache->links[index].signal_frame;
+      memcpy (&sr->rs_current, rs, sizeof (*rs));
+    }
+  else
+    {
+      ret = fetch_proc_info (c, c->ip);
+      int next_use_prev_instr = c->use_prev_instr;
+      if (ret >= 0)
+       {
+         /* Update use_prev_instr for the next frame. */
+         assert(c->pi.unwind_info);
+         struct dwarf_cie_info *dci = c->pi.unwind_info;
+         next_use_prev_instr = ! dci->signal_frame;
+         ret = create_state_record_for (c, sr, c->ip);
+       }
       put_unwind_info (c, &c->pi);
-      return ret;
+      c->use_prev_instr = next_use_prev_instr;
+
+      if (cache && ret >= 0)
+       {
+         rs = rs_new (cache, c);
+         cache->links[rs - cache->buckets].hint = 0;
+         memcpy(rs, &sr->rs_current, sizeof(*rs));
+       }
     }
 
-  if ((ret = create_state_record_for (c, &sr, c->ip)) < 0)
-    return ret;
-
-  if ((ret = apply_reg_state (c, &sr.rs_current)) < 0)
-    return ret;
-
-  put_unwind_info (c, &c->pi);
+  unsigned short index = -1;
+  if (cache)
+    {
+      put_rs_cache (c->as, cache, &saved_mask);
+      if (rs)
+       {
+         index = rs - cache->buckets;
+         c->hint = cache->links[index].hint;
+         cache->links[c->prev_rs].hint = index + 1;
+         c->prev_rs = index;
+       }
+    }
+  if (ret < 0)
+      return ret;
+  if (cache)
+    tdep_reuse_frame (c, cache->links[index].signal_frame);
   return 0;
 }
 
 /* The function finds the saved locations and applies the register
    state as well. */
 HIDDEN int
-dwarf_find_save_locs (struct dwarf_cursor *c)
+dwarf_step (struct dwarf_cursor *c)
 {
+  int ret;
   dwarf_state_record_t sr;
-  dwarf_reg_state_t *rs, rs_copy;
-  struct dwarf_rs_cache *cache;
-  int ret = 0;
-  intrmask_t saved_mask;
-
-  if (c->as->caching_policy == UNW_CACHE_NONE)
-    return uncached_dwarf_find_save_locs (c);
+  if ((ret = find_reg_state (c, &sr)) < 0)
+    return ret;
+  return apply_reg_state (c, &sr.rs_current);
+}
 
-  cache = get_rs_cache(c->as, &saved_mask);
-  rs = rs_lookup(cache, c);
+HIDDEN int
+dwarf_make_proc_info (struct dwarf_cursor *c)
+{
+#if 0
+  if (c->as->caching_policy == UNW_CACHE_NONE
+      || get_cached_proc_info (c) < 0)
+#endif
+  /* Need to check if current frame contains
+     args_size, and set cursor appropriately.  Only
+     needed for unw_resume */
+  dwarf_state_record_t sr;
+  int ret;
 
-  if (rs)
-    {
-      c->ret_addr_column = rs->ret_addr_column;
-      c->use_prev_instr = ! rs->signal_frame;
-    }
-  else
-    {
-      if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 ||
-          (ret = create_state_record_for (c, &sr, c->ip)) < 0)
-        {
-          put_rs_cache (c->as, cache, &saved_mask);
-          put_unwind_info (c, &c->pi);
-          return ret;
-        }
+  /* Lookup it up the slow way... */
+  ret = fetch_proc_info (c, c->ip);
+  if (ret >= 0)
+      ret = create_state_record_for (c, &sr, c->ip);
+  put_unwind_info (c, &c->pi);
+  if (ret < 0)
+    return ret;
+  c->args_size = sr.args_size;
 
-      rs = rs_new (cache, c);
-      memcpy(rs, &sr.rs_current, offsetof(struct dwarf_reg_state, ip));
-      cache->buckets[c->prev_rs].hint = rs - cache->buckets;
+  return 0;
+}
 
-      c->hint = rs->hint;
-      c->prev_rs = rs - cache->buckets;
+static int
+dwarf_reg_states_dynamic_iterate(struct dwarf_cursor *c,
+                                unw_reg_states_callback cb,
+                                void *token)
+{
+  Debug (1, "Not yet implemented\n");
+  return -UNW_ENOINFO;
+}
 
-      put_unwind_info (c, &c->pi);
+static int
+dwarf_reg_states_table_iterate(struct dwarf_cursor *c,
+                              unw_reg_states_callback cb,
+                              void *token)
+{
+  dwarf_state_record_t sr;
+  int ret = setup_fde(c, &sr);
+  struct dwarf_cie_info *dci = c->pi.unwind_info;
+  unw_word_t addr = dci->fde_instr_start;
+  unw_word_t curr_ip = c->pi.start_ip;
+  dwarf_stackable_reg_state_t *rs_stack = NULL;
+  while (ret >= 0 && curr_ip < c->pi.end_ip && addr < dci->fde_instr_end)
+    {
+      unw_word_t prev_ip = curr_ip;
+      ret = run_cfi_program (c, &sr, &curr_ip, prev_ip, &addr, dci->fde_instr_end,
+                            &rs_stack, dci);
+      if (ret >= 0 && prev_ip < curr_ip)
+       ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), prev_ip, curr_ip);
     }
-
-  memcpy (&rs_copy, rs, sizeof (rs_copy));
-  put_rs_cache (c->as, cache, &saved_mask);
-
-  tdep_reuse_frame (c, &rs_copy);
-  if ((ret = apply_reg_state (c, &rs_copy)) < 0)
-    return ret;
-
-  return 0;
+  empty_rstate_stack(&rs_stack);
+#if defined(NEED_LAST_IP)
+  if (ret >= 0 && curr_ip < c->pi.last_ip)
+    /* report the dead zone after the procedure ends */
+    ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.last_ip);
+#else
+  if (ret >= 0 && curr_ip < c->pi.end_ip)
+    /* report for whatever is left before procedure end */
+    ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.end_ip);
+#endif
+  return ret;
 }
 
-/* The proc-info must be valid for IP before this routine can be
-   called.  */
 HIDDEN int
-dwarf_create_state_record (struct dwarf_cursor *c, dwarf_state_record_t *sr)
+dwarf_reg_states_iterate(struct dwarf_cursor *c,
+                        unw_reg_states_callback cb,
+                        void *token)
 {
-  return create_state_record_for (c, sr, c->ip);
+  int ret = fetch_proc_info (c, c->ip);
+  int next_use_prev_instr = c->use_prev_instr;
+  if (ret >= 0)
+    {
+      /* Update use_prev_instr for the next frame. */
+      assert(c->pi.unwind_info);
+      struct dwarf_cie_info *dci = c->pi.unwind_info;
+      next_use_prev_instr = ! dci->signal_frame;
+      switch (c->pi.format)
+       {
+       case UNW_INFO_FORMAT_TABLE:
+       case UNW_INFO_FORMAT_REMOTE_TABLE:
+         ret = dwarf_reg_states_table_iterate(c, cb, token);
+         break;
+
+       case UNW_INFO_FORMAT_DYNAMIC:
+         ret = dwarf_reg_states_dynamic_iterate (c, cb, token);
+         break;
+
+       default:
+         Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
+         ret = -UNW_EINVAL;
+       }
+    }
+  put_unwind_info (c, &c->pi);
+  c->use_prev_instr = next_use_prev_instr;
+  return ret;
 }
 
 HIDDEN int
-dwarf_make_proc_info (struct dwarf_cursor *c)
+dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
 {
-#if 0
-  if (c->as->caching_policy == UNW_CACHE_NONE
-      || get_cached_proc_info (c) < 0)
-#endif
-    /* Lookup it up the slow way... */
-    return fetch_proc_info (c, c->ip, 0);
-  return 0;
+  return apply_reg_state(c, rs);
 }
index 8d0957d..7098507 100644 (file)
@@ -31,7 +31,7 @@ HIDDEN struct mempool dwarf_cie_info_pool;
 HIDDEN int
 dwarf_init (void)
 {
-  mempool_init (&dwarf_reg_state_pool, sizeof (dwarf_reg_state_t), 0);
+  mempool_init (&dwarf_reg_state_pool, sizeof (dwarf_stackable_reg_state_t), 0);
   mempool_init (&dwarf_cie_info_pool, sizeof (struct dwarf_cie_info), 0);
   return 0;
 }
index 33fccba..b03dfcb 100644 (file)
@@ -214,50 +214,17 @@ xz_uncompressed_size (uint8_t *compressed, size_t length)
 static int
 elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
 {
-  Elf_W (Ehdr) *ehdr = ei->image;
   Elf_W (Shdr) *shdr;
-  char *strtab;
-  int i;
   uint8_t *compressed = NULL;
   uint64_t memlimit = UINT64_MAX; /* no memory limit */
   size_t compressed_len, uncompressed_len;
 
-  if (!elf_w (valid_object) (ei))
-    return 0;
-
-  shdr = elf_w (section_table) (ei);
+  shdr = elf_w (find_section) (ei, ".gnu_debugdata");
   if (!shdr)
     return 0;
 
-  strtab = elf_w (string_table) (ei, ehdr->e_shstrndx);
-  if (!strtab)
-    return 0;
-
-  for (i = 0; i < ehdr->e_shnum; ++i)
-    {
-      if (strcmp (strtab + shdr->sh_name, ".gnu_debugdata") == 0)
-        {
-          if (shdr->sh_offset + shdr->sh_size > ei->size)
-            {
-              Debug (1, ".gnu_debugdata outside image? (0x%lu > 0x%lu)\n",
-                     (unsigned long) shdr->sh_offset + shdr->sh_size,
-                     (unsigned long) ei->size);
-              return 0;
-            }
-
-          Debug (16, "found .gnu_debugdata at 0x%lx\n",
-                 (unsigned long) shdr->sh_offset);
-          compressed = ((uint8_t *) ei->image) + shdr->sh_offset;
-          compressed_len = shdr->sh_size;
-          break;
-        }
-
-      shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
-    }
-
-  /* not found */
-  if (!compressed)
-    return 0;
+  compressed = ((uint8_t *) ei->image) + shdr->sh_offset;
+  compressed_len = shdr->sh_size;
 
   uncompressed_len = xz_uncompressed_size (compressed, compressed_len);
   if (uncompressed_len == 0)
@@ -345,8 +312,13 @@ elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip,
   unsigned long segbase, mapoff;
   struct elf_image ei;
   int ret;
+  char file[PATH_MAX];
+
+  ret = tdep_get_elf_image (&ei, pid, ip, &segbase, &mapoff, file, PATH_MAX);
+  if (ret < 0)
+    return ret;
 
-  ret = tdep_get_elf_image (&ei, pid, ip, &segbase, &mapoff, NULL, 0);
+  ret = elf_w (load_debuglink) (file, &ei, 1);
   if (ret < 0)
     return ret;
 
@@ -357,3 +329,153 @@ elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip,
 
   return ret;
 }
+
+HIDDEN Elf_W (Shdr)*
+elf_w (find_section) (struct elf_image *ei, const char* secname)
+{
+  Elf_W (Ehdr) *ehdr = ei->image;
+  Elf_W (Shdr) *shdr;
+  char *strtab;
+  int i;
+
+  if (!elf_w (valid_object) (ei))
+    return 0;
+
+  shdr = elf_w (section_table) (ei);
+  if (!shdr)
+    return 0;
+
+  strtab = elf_w (string_table) (ei, ehdr->e_shstrndx);
+  if (!strtab)
+    return 0;
+
+  for (i = 0; i < ehdr->e_shnum; ++i)
+    {
+      if (strcmp (strtab + shdr->sh_name, secname) == 0)
+        {
+          if (shdr->sh_offset + shdr->sh_size > ei->size)
+            {
+              Debug (1, "section \"%s\" outside image? (0x%lu > 0x%lu)\n",
+                     secname,
+                     (unsigned long) shdr->sh_offset + shdr->sh_size,
+                     (unsigned long) ei->size);
+              return 0;
+            }
+
+          Debug (16, "found section \"%s\" at 0x%lx\n",
+                 secname, (unsigned long) shdr->sh_offset);
+          return shdr;
+        }
+
+      shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
+    }
+
+  /* section not found */
+  return 0;
+}
+
+/* Load a debug section, following .gnu_debuglink if appropriate
+ * Loads ei from file if not already mapped.
+ * If is_local, will also search sys directories /usr/local/dbg
+ *
+ * Returns 0 on success, failure otherwise.
+ * ei will be mapped to file or the located .gnu_debuglink from file
+ */
+HIDDEN int
+elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local)
+{
+  int ret;
+  Elf_W (Shdr) *shdr;
+  Elf_W (Ehdr) *prev_image;
+  off_t prev_size;
+
+  if (!ei->image)
+    {
+      ret = elf_map_image(ei, file);
+      if (ret)
+       return ret;
+    }
+
+  prev_image = ei->image;
+  prev_size = ei->size;
+
+  /* Ignore separate debug files which contain a .gnu_debuglink section. */
+  if (is_local == -1) {
+    return 0;
+  }
+
+  shdr = elf_w (find_section) (ei, ".gnu_debuglink");
+  if (shdr) {
+    if (shdr->sh_size >= PATH_MAX ||
+       (shdr->sh_offset + shdr->sh_size > ei->size))
+      {
+       return 0;
+      }
+
+    {
+      char linkbuf[shdr->sh_size];
+      char *link = ((char *) ei->image) + shdr->sh_offset;
+      char *p;
+      static const char *debugdir = "/usr/lib/debug";
+      char basedir[strlen(file) + 1];
+      char newname[shdr->sh_size + strlen (debugdir) + strlen (file) + 9];
+
+      memcpy(linkbuf, link, shdr->sh_size);
+
+      if (memchr (linkbuf, 0, shdr->sh_size) == NULL)
+       return 0;
+
+      ei->image = NULL;
+
+      Debug(1, "Found debuglink section, following %s\n", linkbuf);
+
+      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 = elf_w (load_debuglink) (newname, ei, -1);
+
+      if (ret == -1)
+       {
+         strcpy (newname, basedir);
+         strcat (newname, "/.debug/");
+         strcat (newname, linkbuf);
+         ret = elf_w (load_debuglink) (newname, ei, -1);
+       }
+
+      if (ret == -1 && is_local == 1)
+       {
+         strcpy (newname, debugdir);
+         strcat (newname, basedir);
+         strcat (newname, "/");
+         strcat (newname, linkbuf);
+         ret = elf_w (load_debuglink) (newname, ei, -1);
+       }
+
+      if (ret == -1)
+        {
+          /* No debuglink file found even though .gnu_debuglink existed */
+          ei->image = prev_image;
+          ei->size = prev_size;
+
+          return 0;
+        }
+      else
+        {
+          munmap (prev_image, prev_size);
+        }
+
+      return ret;
+    }
+  }
+
+  return 0;
+}
index cef6647..830432c 100644 (file)
@@ -54,6 +54,9 @@ extern int elf_w (get_proc_name_in_image) (unw_addr_space_t as,
                                            unw_word_t ip,
                                            char *buf, size_t buf_len, unw_word_t *offp);
 
+extern Elf_W (Shdr)* elf_w (find_section) (struct elf_image *ei, const char* secname);
+extern int elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local);
+
 static inline int
 elf_w (valid_object) (struct elf_image *ei)
 {
diff --git a/src/hppa/Gapply_reg_state.c b/src/hppa/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index 71186e0..8a6cb8b 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index ce7a950..e10efcf 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index 549366a..02dfa30 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   /* struct cursor *c = (struct cursor *) cursor; */
index 89ad51c..461e4b9 100644 (file)
@@ -32,13 +32,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 static inline void *
 uc_addr (ucontext_t *uc, int reg)
@@ -179,7 +179,7 @@ HIDDEN void
 hppa_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.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
index 0ad2f88..1fdc771 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 {
   return -UNW_EINVAL;
@@ -36,8 +36,8 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+static int
+unw_init_local_common (unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -48,7 +48,30 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 
   c->dwarf.as = unw_local_addr_space;
   c->dwarf.as_arg = uc;
-  return common_init (c, 1);
+  return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
 }
 
 #endif /* !UNW_REMOTE_ONLY */
index a4160fd..71096ce 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index 00e40c6..addb551 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
 #ifdef __linux__ 
@@ -37,7 +37,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   int ret;
 
   as = c->dwarf.as;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   arg = c->dwarf.as_arg;
 
   /* Check if IP points at sigreturn() sequence.  On Linux, this normally is:
diff --git a/src/hppa/Greg_states_iterate.c b/src/hppa/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index f6bc023..6c11f14 100644 (file)
@@ -121,7 +121,7 @@ establish_machine_state (struct cursor *c)
   return 0;
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 078ff43..4fc8a87 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "offsets.h"
 
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -60,7 +60,6 @@ unw_step (unw_cursor_t *cursor)
 
           c->sigcontext_format = HPPA_SCF_LINUX_RT_SIGFRAME;
           c->sigcontext_addr = sc_addr;
-          c->dwarf.ret_addr_column = UNW_HPPA_RP;
 
           if ((ret = dwarf_get (&c->dwarf, iaoq_loc, &ip)) < 0)
             {
diff --git a/src/hppa/Lapply_reg_state.c b/src/hppa/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/hppa/Lreg_states_iterate.c b/src/hppa/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index 06dfae7..5698a58 100644 (file)
@@ -40,7 +40,7 @@ static const char *regname[] =
     "cfa"
   };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
diff --git a/src/ia64/Gapply_reg_state.c b/src/ia64/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..b45d1b5
--- /dev/null
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  // Needs dwarf support on ia64
+  // return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+  return -UNW_EINVAL;
+}
index 20cf5d8..7ad29cb 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index 6b4722d..3ec82b9 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index fc37ad9..34efe99 100644 (file)
@@ -30,7 +30,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "offsets.h"
 #include "regs.h"
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   struct cursor *c = (struct cursor *) cursor;
index 7b64f0c..b09a2ad 100644 (file)
@@ -33,13 +33,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 #ifdef HAVE_SYS_UC_ACCESS_H
 
@@ -361,7 +361,7 @@ ia64_local_addr_space_init (void)
 #elif defined(__hpux)
   local_addr_space.abi = ABI_HPUX;
 #endif
-  local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+  local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   local_addr_space.acc.find_proc_info = tdep_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;
index 8c727e1..8fe1c67 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
 {
   return -UNW_EINVAL;
@@ -76,7 +76,7 @@ get_initial_stack_pointers (struct cursor *c, unw_context_t *uc,
   return 0;
 }
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
 {
   struct cursor *c = (struct cursor *) cursor;
index e26a4e4..b570c7e 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index 0b7e19c..e268a06 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
diff --git a/src/ia64/Greg_states_iterate.c b/src/ia64/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..3570740
--- /dev/null
@@ -0,0 +1,39 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  // Needs dwarf support on ia64
+  // return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+  return -UNW_EINVAL;
+}
index aa395b6..68fe8a6 100644 (file)
@@ -259,7 +259,7 @@ remote_install_cursor (struct cursor *c)
 
 #endif /* !UNW_LOCAL_ONLY */
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index e96e89e..526aeaf 100644 (file)
@@ -45,7 +45,7 @@ enum ia64_script_insn_opcode
     IA64_INSN_MOVE_SCRATCH_NO_NAT /* like above, but clear NaT info */
   };
 
-#ifdef HAVE___THREAD
+#if defined(HAVE___THREAD) && HAVE___THREAD
 static __thread struct ia64_script_cache ia64_per_thread_cache =
   {
 #ifdef HAVE_ATOMIC_OPS_H
@@ -105,7 +105,7 @@ get_script_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
   if (!spin_trylock_irqsave (&cache->busy, *saved_maskp))
     return NULL;
 #else
-# ifdef HAVE___THREAD
+# if defined(HAVE___THREAD) && HAVE___THREAD
   if (as->caching_policy == UNW_CACHE_PER_THREAD)
     cache = &ia64_per_thread_cache;
 # endif
index 0191f64..df4ecb8 100644 (file)
@@ -342,7 +342,7 @@ update_frame_state (struct cursor *c)
 }
 
 
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 6959cae..f5e8f2d 100644 (file)
@@ -68,7 +68,7 @@ is_local_addr_space (unw_addr_space_t as)
 static inline int
 read_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, void *arg)
 {
-  unw_accessors_t *a = unw_get_accessors (as);
+  unw_accessors_t *a = unw_get_accessors_int (as);
 
   return (*a->access_mem) (as, addr, valp, 0, arg);
 }
@@ -87,7 +87,7 @@ remote_lookup (unw_addr_space_t as,
                struct ia64_table_entry *e, void *arg)
 {
   unw_word_t e_addr = 0, start_offset, end_offset, info_offset;
-  unw_accessors_t *a = unw_get_accessors (as);
+  unw_accessors_t *a = unw_get_accessors_int (as);
   unsigned long lo, hi, mid;
   int ret;
 
@@ -136,7 +136,7 @@ tdep_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
     }
 }
 
-PROTECTED unw_word_t
+unw_word_t
 _Uia64_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg)
 {
   unw_word_t hdr_addr, info_addr, hdr, directives, pers, cookie, off;
@@ -165,7 +165,7 @@ _Uia64_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg)
 
     case UNW_INFO_FORMAT_REMOTE_TABLE:
       {
-        unw_accessors_t *a = unw_get_accessors (as);
+        unw_accessors_t *a = unw_get_accessors_int (as);
         unw_word_t e_addr = di->u.rti.table_data;
 
         table_size = di->u.rti.table_len * sizeof (unw_word_t);
@@ -247,7 +247,7 @@ lookup (struct ia64_table_entry *table, size_t table_size, unw_word_t rel_ip)
   return e;
 }
 
-PROTECTED int
+int
 unw_search_ia64_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)
@@ -440,7 +440,7 @@ get_kernel_table (unw_dyn_info_t *di)
 #  ifndef UNW_LOCAL_ONLY
 
 /* This is exported for the benefit of libunwind-ptrace.a.  */
-PROTECTED int
+int
 _Uia64_get_kernel_table (unw_dyn_info_t *di)
 {
   int ret;
diff --git a/src/ia64/Lapply_reg_state.c b/src/ia64/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/ia64/Lreg_states_iterate.c b/src/ia64/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index 8753e52..3636df8 100644 (file)
@@ -179,7 +179,7 @@ purpose.  */
 
 #define NREGS   ((int) (sizeof (regname_str) - 1) / regname_len)
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < NREGS)
index 719c051..504558e 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED void
+void
 unw_destroy_addr_space (unw_addr_space_t as)
 {
 #ifndef UNW_LOCAL_ONLY
index c8ae7a0..5f7682e 100644 (file)
@@ -49,6 +49,7 @@ unwi_extract_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip,
 
     case UNW_INFO_FORMAT_TABLE:
     case UNW_INFO_FORMAT_REMOTE_TABLE:
+    case UNW_INFO_FORMAT_ARM_EXIDX:
     case UNW_INFO_FORMAT_IP_OFFSET:
 #ifdef tdep_search_unwind_table
       /* call platform-specific search routine: */
index 1f029b4..40a5ad8 100644 (file)
@@ -205,7 +205,7 @@ unwi_dyn_remote_find_proc_info (unw_addr_space_t as, unw_word_t ip,
                                 unw_proc_info_t *pi,
                                 int need_unwind_info, void *arg)
 {
-  unw_accessors_t *a = unw_get_accessors (as);
+  unw_accessors_t *a = unw_get_accessors_int (as);
   unw_word_t dyn_list_addr, addr, next_addr, gen1, gen2, start_ip, end_ip;
   unw_dyn_info_t *di = NULL;
   int ret;
@@ -311,7 +311,7 @@ unwi_dyn_validate_cache (unw_addr_space_t as, void *arg)
        in the cache.  */
     return 0;
 
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   addr = as->dyn_info_list_addr;
 
   if (fetchw (as, a, &addr, &gen, arg) < 0)
index 548c763..31a6fba 100644 (file)
@@ -25,7 +25,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED unw_accessors_t *
+HIDDEN ALIAS(unw_get_accessors) unw_accessors_t *
+unw_get_accessors_int (unw_addr_space_t as);
+
+unw_accessors_t *
 unw_get_accessors (unw_addr_space_t as)
 {
   if (!tdep_init_done)
index f2f7405..f32b128 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_get_fpreg (unw_cursor_t *cursor, int regnum, unw_fpreg_t *valp)
 {
   struct cursor *c = (struct cursor *) cursor;
index c39312d..2697ff8 100644 (file)
@@ -25,11 +25,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info_by_ip (unw_addr_space_t as, unw_word_t ip,
                          unw_proc_info_t *pi, void *as_arg)
 {
-  unw_accessors_t *a = unw_get_accessors (as);
+  unw_accessors_t *a = unw_get_accessors_int (as);
   int ret;
 
   ret = unwi_find_dynamic_proc_info (as, ip, pi, 0, as_arg);
index 5376f82..840d900 100644 (file)
@@ -49,7 +49,7 @@ static inline int
 get_proc_name (unw_addr_space_t as, unw_word_t ip,
                char *buf, size_t buf_len, unw_word_t *offp, void *arg)
 {
-  unw_accessors_t *a = unw_get_accessors (as);
+  unw_accessors_t *a = unw_get_accessors_int (as);
   unw_proc_info_t pi;
   int ret;
 
@@ -95,7 +95,7 @@ get_proc_name (unw_addr_space_t as, unw_word_t ip,
   return -UNW_ENOINFO;
 }
 
-PROTECTED int
+int
 unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len,
                    unw_word_t *offp)
 {
@@ -104,11 +104,15 @@ unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len,
   int error;
 
   ip = tdep_get_ip (c);
+#if !defined(__ia64__)
   if (c->dwarf.use_prev_instr)
     --ip;
+#endif
   error = get_proc_name (tdep_get_as (c), ip, buf, buf_len, offp,
                          tdep_get_as_arg (c));
+#if !defined(__ia64__)
   if (c->dwarf.use_prev_instr && offp != NULL && error == 0)
     *offp += 1;
+#endif
   return error;
 }
index 7c0a5a9..9fc725c 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_get_reg (unw_cursor_t *cursor, int regnum, unw_word_t *valp)
 {
   struct cursor *c = (struct cursor *) cursor;
diff --git a/src/mi/Gset_cache_size.c b/src/mi/Gset_cache_size.c
new file mode 100644 (file)
index 0000000..07b282e
--- /dev/null
@@ -0,0 +1,72 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2014
+        Contributed by Milian Wolff <address@hidden>
+                   and Dave Watson <dade.watson@gmail.com>
+
+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_i.h"
+
+int
+unw_set_cache_size (unw_addr_space_t as, size_t size, int flag)
+{
+  size_t power = 1;
+  unsigned short log_size = 0;
+
+  if (!tdep_init_done)
+    tdep_init ();
+
+  if (flag != 0)
+    return -1;
+
+  /* Currently not supported for per-thread cache due to memory leak */
+  /* A pthread-key destructor would work, but is not signal safe */
+#if defined(HAVE___THREAD) && HAVE___THREAD
+  return -1;
+#endif
+
+  /* Round up to next power of two, slowly but portably */
+  while(power < size)
+    {
+      power *= 2;
+      log_size++;
+      /* Largest size currently supported by rs_cache */
+      if (log_size >= 15)
+        break;
+    }
+
+#if !defined(__ia64__)
+  if (log_size == as->global_cache.log_size)
+    return 0;   /* no change */
+
+  as->global_cache.log_size = log_size;
+#endif
+
+  /* Ensure caches are empty (and initialized).  */
+  unw_flush_cache (as, 0, 0);
+#ifdef __ia64__
+  return 0;
+#else
+  /* Synchronously purge cache, to ensure memory is allocated */
+  return dwarf_flush_rs_cache(&as->global_cache);
+#endif
+}
index 45ba100..aa3d237 100644 (file)
@@ -25,13 +25,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_set_caching_policy (unw_addr_space_t as, unw_caching_policy_t policy)
 {
   if (!tdep_init_done)
     tdep_init ();
 
-#ifndef HAVE___THREAD
+#if !(defined(HAVE___THREAD) && HAVE___THREAD)
   if (policy == UNW_CACHE_PER_THREAD)
     policy = UNW_CACHE_GLOBAL;
 #endif
index 4f2fa7b..8c37afd 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_set_fpreg (unw_cursor_t *cursor, int regnum, unw_fpreg_t val)
 {
   struct cursor *c = (struct cursor *) cursor;
index c9b6e6a..b1b1770 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_set_reg (unw_cursor_t *cursor, int regnum, unw_word_t valp)
 {
   struct cursor *c = (struct cursor *) cursor;
diff --git a/src/mi/Ldyn-remote.c b/src/mi/Ldyn-remote.c
new file mode 100644 (file)
index 0000000..260722a
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gdyn-remote.c"
+#endif
diff --git a/src/mi/Lset_cache_size.c b/src/mi/Lset_cache_size.c
new file mode 100644 (file)
index 0000000..670f64d
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gset_cache_size.c"
+#endif
index 1a0790d..1c7c550 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
 
-PROTECTED unw_word_t
+unw_word_t
 _U_dyn_info_list_addr (void)
 {
   return (unw_word_t) (uintptr_t) &_U_dyn_info_list;
index 513d135..cbd93e1 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED void
+void
 unw_flush_cache (unw_addr_space_t as, unw_word_t lo, unw_word_t hi)
 {
 #if !UNW_TARGET_IA64
index 057027e..60a48c5 100644 (file)
@@ -32,7 +32,7 @@ static const char rcsid[] UNUSED =
 
 #if UNW_DEBUG
 
-/* Must not be declared HIDDEN/PROTECTED because libunwind.so and
+/* Must not be declared HIDDEN because libunwind.so and
    libunwind-PLATFORM.so will both define their own copies of this
    variable and we want to use only one or the other when both
    libraries are loaded.  */
diff --git a/src/mips/Gapply_reg_state.c b/src/mips/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index 371841d..493d03d 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index 973ddd9..7b84be8 100644 (file)
@@ -24,7 +24,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index d6075b7..c21f9b0 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 /* FIXME for MIPS.  */
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   struct cursor *c = (struct cursor *) cursor;
index 8290c40..3df170c 100644 (file)
@@ -30,13 +30,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+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).  */
@@ -59,7 +59,7 @@ tdep_uc_addr (ucontext_t *uc, int reg)
 {
   char *addr = uc_addr (uc, reg);
 
-  if (reg >= UNW_MIPS_R0 && reg <= UNW_MIPS_R31
+  if (((reg >= UNW_MIPS_R0 && reg <= UNW_MIPS_R31) || reg == UNW_MIPS_PC)
       && tdep_big_endian (unw_local_addr_space)
       && unw_local_addr_space->abi == UNW_MIPS_ABI_O32)
     addr += 4;
@@ -195,7 +195,7 @@ mips_local_addr_space_init (void)
 # error Unsupported ABI
 #endif
   local_addr_space.addr_size = sizeof (void *);
-  local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+  local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
index e5e1c5a..f3153b5 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 {
   return -UNW_EINVAL;
@@ -35,8 +35,8 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+static int
+unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -47,7 +47,30 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 
   c->dwarf.as = unw_local_addr_space;
   c->dwarf.as_arg = uc;
-  return common_init (c, 1);
+  return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local(unw_cursor_t *cursor, ucontext_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
 }
 
 #endif /* !UNW_REMOTE_ONLY */
index f284e99..9b8ba5b 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index 2c9627f..c0e3b98 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include <stdio.h>
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -37,7 +37,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   int ret;
 
   as = c->dwarf.as;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   arg = c->dwarf.as_arg;
 
   ip = c->dwarf.ip;
diff --git a/src/mips/Greg_states_iterate.c b/src/mips/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index 2697776..9519402 100644 (file)
@@ -70,6 +70,8 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
       break;
 
     case UNW_MIPS_PC:
+      if (write)
+       c->dwarf.ip = *valp;            /* update the IP cache */
       loc = c->dwarf.loc[reg];
       break;
 
index b822e24..cb70abc 100644 (file)
@@ -38,7 +38,7 @@ mips_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
 
 #endif /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   return -UNW_EINVAL;
index 0a0b9c2..937136a 100644 (file)
@@ -26,11 +26,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "offsets.h"
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
+static int
+mips_handle_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
-  unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
+  unw_word_t sc_addr, sp_addr = c->dwarf.cfa;
   unw_word_t ra, fp;
   int ret;
 
@@ -110,13 +110,13 @@ unw_handle_signal_frame (unw_cursor_t *cursor)
   return 1;
 }
 
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
   int ret;
 
-  ret = unw_handle_signal_frame (cursor);
+  ret = mips_handle_signal_frame (cursor);
   if (ret < 0)
     /* Not a signal frame, try DWARF-based unwinding. */
     ret = dwarf_step (&c->dwarf);
diff --git a/src/mips/Lapply_reg_state.c b/src/mips/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/mips/Lreg_states_iterate.c b/src/mips/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index 74c3ab9..30c193a 100644 (file)
@@ -48,7 +48,6 @@ common_init (struct cursor *c, unsigned use_prev_instr)
   /* FIXME: Initialisation for other registers.  */
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = 0;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
index 3acc696..a92dd5e 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 /* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful
    on MIPS.  */
 
-PROTECTED int
+int
 unw_is_fpreg (int regnum)
 {
   /* FIXME: Support FP.  */
index a4a6334..b137b97 100644 (file)
@@ -36,7 +36,7 @@ static const char *regname[] =
     "$24",  "$25",  "$26", "$27",  "$28",  "$29",  "$30",  "$31",
   };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
index 1aa1e07..753e819 100644 (file)
@@ -56,7 +56,7 @@ get_pid_by_tid(int tid)
   size_t len, len1;
   char *buf;
   struct kinfo_proc *kv;
-  int i, pid;
+  unsigned i, pid;
 
   len = 0;
   mib[0] = CTL_KERN;
@@ -88,7 +88,7 @@ get_pid_by_tid(int tid)
   return (pid);
 }
 
-PROTECTED int
+int
 tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
                     unsigned long *segbase, unsigned long *mapoff, char *path, size_t pathlen)
 {
@@ -143,3 +143,24 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
   free_mem(buf, len1);
   return (ret);
 }
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+  int mib[4], error;
+  size_t len;
+
+  len = 0;
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_PROC;
+  mib[2] = KERN_PROC_PATHNAME;
+  mib[3] = getpid();
+
+  error = sysctl(mib, 4, path, &len, NULL, 0);
+  if (error == -1)
+         path[0] = 0;
+}
+
+#endif
index 2ee6fa7..48bfb05 100644 (file)
@@ -65,3 +65,14 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
 
   return elf_map_image (ei, path);
 }
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+  path[0] = 0; /* XXX */
+}
+
+#endif
+
index 1cc9ba5..8a00669 100644 (file)
@@ -29,7 +29,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "libunwind_i.h"
 #include "os-linux.h"
 
-PROTECTED int
+int
 tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
                     unsigned long *segbase, unsigned long *mapoff,
                     char *path, size_t pathlen)
@@ -61,3 +61,13 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
   maps_close (&mi);
   return rc;
 }
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+  strcpy(path, "/proc/self/exe");
+}
+
+#endif /* !UNW_REMOTE_ONLY */
index 97bc766..4a76c7c 100644 (file)
@@ -53,7 +53,7 @@ static int callback(const struct dl_phdr_info *info, size_t size, void *data)
   return 0;
 }
 
-PROTECTED int
+int
 tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
                     unsigned long *segbase, unsigned long *mapoff,
                     char *path, size_t pathlen)
@@ -105,3 +105,13 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
 
   return ret;
 }
+
+#ifndef UNW_REMOTE_ONLY
+
+void
+tdep_get_exe_image_path (char *path)
+{
+  path[0] = 0; /* XXX */
+}
+
+#endif
diff --git a/src/ppc/Gapply_reg_state.c b/src/ppc/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index 29f1db5..7dfb6d4 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include <libunwind_i.h>
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index c5beb81..5343fa4 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include <libunwind_i.h>
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   /* XXX: empty stub.  */
index 4ca2b25..366cf5b 100644 (file)
@@ -34,7 +34,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 {
   /* XXX: empty stub.  */
@@ -43,8 +43,8 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+static int
+unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -56,10 +56,33 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
   c->dwarf.as = unw_local_addr_space;
   c->dwarf.as_arg = uc;
   #ifdef UNW_TARGET_PPC64
-    return common_init_ppc64 (c, 1);
+    return common_init_ppc64 (c, use_prev_instr);
   #else
-    return common_init_ppc32 (c, 1);
+    return common_init_ppc32 (c, use_prev_instr);
   #endif
 }
 
+int
+unw_init_local(unw_cursor_t *cursor, ucontext_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
+}
+
 #endif /* !UNW_REMOTE_ONLY */
index 4ee5402..ed85be8 100644 (file)
@@ -33,7 +33,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "../ppc32/init.h"
 #endif
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index e8b6917..6184dd5 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include <libunwind_i.h>
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t * cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -56,7 +56,7 @@ unw_is_signal_frame (unw_cursor_t * cursor)
      consecutive 32-bit words, so the second 8-byte word needs to be
      shifted right by 32 bits (think big-endian) */
 
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
       || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
     return 0;
diff --git a/src/ppc/Greg_states_iterate.c b/src/ppc/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
diff --git a/src/ppc/Lapply_reg_state.c b/src/ppc/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/ppc/Lreg_states_iterate.c b/src/ppc/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
diff --git a/src/ppc32/Gapply_reg_state.c b/src/ppc32/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index f5055ec..aaa68bb 100644 (file)
@@ -29,7 +29,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include <libunwind_i.h>
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index f2e6e82..ba30244 100644 (file)
@@ -34,13 +34,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 static void *
 uc_addr (ucontext_t *uc, int reg)
@@ -201,7 +201,7 @@ HIDDEN void
 ppc32_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.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
diff --git a/src/ppc32/Greg_states_iterate.c b/src/ppc32/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index 955d061..c0f9583 100644 (file)
@@ -61,7 +61,7 @@ establish_machine_state (struct cursor *c)
   return 0;
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 8506a61..478d3a6 100644 (file)
@@ -49,7 +49,7 @@ typedef struct
 } stack_frame_t;
 
 
-PROTECTED int
+int
 unw_step (unw_cursor_t * cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -79,7 +79,7 @@ unw_step (unw_cursor_t * cursor)
 
   if (unlikely (ret < 0))
     {
-      if (likely (!unw_is_signal_frame (cursor)))
+      if (likely (unw_is_signal_frame (cursor) <= 0))
         {
           /* DWARF unwinding failed.  As of 09/26/2006, gcc in 64-bit mode
              produces the mandatory level of traceback record in the code, but
diff --git a/src/ppc32/Lapply_reg_state.c b/src/ppc32/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/ppc32/Lreg_states_iterate.c b/src/ppc32/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index e8bb3ba..87a69b1 100644 (file)
@@ -61,7 +61,6 @@ common_init_ppc32 (struct cursor *c, unsigned use_prev_instr)
   c->sigcontext_addr = 0;
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = 0;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
index cccc511..646ff23 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_is_fpreg (int regnum)
 {
   return (regnum >= UNW_PPC32_F0 && regnum <= UNW_PPC32_F31);
index 79ba88a..459b83a 100644 (file)
@@ -102,7 +102,7 @@ static const char *regname[] =
     [UNW_PPC32_F31]="FPR31"
 };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
diff --git a/src/ppc32/setcontext.S b/src/ppc32/setcontext.S
new file mode 100644 (file)
index 0000000..b54378a
--- /dev/null
@@ -0,0 +1,9 @@
+       .global _UI_setcontext
+
+_UI_setcontext:
+       retq
+
+#ifdef __linux__
+        /* We do not need executable stack.  */
+        .section        .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/ppc64/Gapply_reg_state.c b/src/ppc64/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index 686653a..bd48555 100644 (file)
@@ -29,7 +29,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include <libunwind_i.h>
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index 0740961..4c88cd6 100644 (file)
@@ -34,13 +34,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 static void *
 uc_addr (ucontext_t *uc, int reg)
@@ -169,13 +169,11 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
   ucontext_t *uc = arg;
   unw_fpreg_t *addr;
 
-  if ((reg - UNW_PPC64_F0) < 0)
+  /* Allow only 32 fregs and 32 vregs */
+  if (!(((unsigned) (reg - UNW_PPC64_F0) < 32)
+       ||((unsigned) (reg - UNW_PPC64_V0) < 32)))
     goto badreg;
 
-  if ((unsigned) (reg - UNW_PPC64_V0) >= 32)
-    goto badreg;
-
-
   addr = uc_addr (uc, reg);
   if (!addr)
     goto badreg;
@@ -216,7 +214,7 @@ ppc64_local_addr_space_init (void)
 #else
   local_addr_space.abi = UNW_PPC64_ABI_ELFv1;
 #endif
-  local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+  local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
diff --git a/src/ppc64/Greg_states_iterate.c b/src/ppc64/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index 3f850e9..0d832d0 100644 (file)
@@ -95,7 +95,7 @@ establish_machine_state (struct cursor *c)
   return 0;
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 318beee..f44e959 100644 (file)
@@ -51,7 +51,7 @@ typedef struct
 } stack_frame_t;
 
 
-PROTECTED int
+int
 unw_step (unw_cursor_t * cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -74,7 +74,7 @@ unw_step (unw_cursor_t * cursor)
 
   if (unlikely (ret < 0))
     {
-      if (likely (!unw_is_signal_frame (cursor)))
+      if (likely (unw_is_signal_frame (cursor) <= 0))
         {
           /* DWARF unwinding failed.  As of 09/26/2006, gcc in 64-bit mode
              produces the mandatory level of traceback record in the code, but
@@ -448,7 +448,7 @@ unw_step (unw_cursor_t * cursor)
   {
     unw_word_t ip = c->dwarf.ip;
     unw_addr_space_t as = c->dwarf.as;
-    unw_accessors_t *a = unw_get_accessors (as);
+    unw_accessors_t *a = unw_get_accessors_int (as);
     void *arg = c->dwarf.as_arg;
     uint32_t toc_save = (as->abi == UNW_PPC64_ABI_ELFv2)? 24 : 40;
     int32_t inst;
diff --git a/src/ppc64/Lapply_reg_state.c b/src/ppc64/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/ppc64/Lreg_states_iterate.c b/src/ppc64/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index 13abb7d..80a58fa 100644 (file)
@@ -36,7 +36,7 @@ tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
       unw_accessors_t *a;
       int ret;
 
-      a = unw_get_accessors (as);
+      a = unw_get_accessors_int (as);
       /* Entry-point is stored in the 1st word of the function descriptor.
          In case that changes in the future, we'd have to update the line
          below and read the word at addr + offset: */
index 22376e7..9b81393 100644 (file)
@@ -71,7 +71,6 @@ common_init_ppc64 (struct cursor *c, unsigned use_prev_instr)
   c->sigcontext_addr = 0;
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = 0;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
index b34bf87..653964a 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_is_fpreg (int regnum)
 {
   return (regnum >= UNW_PPC64_F0 && regnum <= UNW_PPC64_F31);
index 3e3a141..58c6fa6 100644 (file)
@@ -154,7 +154,7 @@ static const char *regname[] =
 
    };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
index e90ec47..2b92462 100644 (file)
@@ -75,6 +75,18 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
   pid_t pid = ui->pid;
   fpregset_t fpreg;
 
+#if defined(__amd64__)
+  if (1) /* XXXKIB */
+    return -UNW_EBADREG;
+#elif defined(__i386__)
+  if ((unsigned) reg < UNW_X86_ST0 || (unsigned) reg > UNW_X86_ST7)
+    return -UNW_EBADREG;
+#elif defined(__arm__)
+  if ((unsigned) reg < UNW_ARM_F0 || (unsigned) reg > UNW_ARM_F7)
+    return -UNW_EBADREG;
+#else
+#error Fix me
+#endif
   if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset))
     return -UNW_EBADREG;
 
@@ -85,6 +97,8 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
           memcpy(&fpreg.fpr_xacc[reg], val, sizeof(unw_fpreg_t));
 #elif defined(__i386__)
           memcpy(&fpreg.fpr_acc[reg], val, sizeof(unw_fpreg_t));
+#elif defined(__arm__)
+          memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t));
 #else
 #error Fix me
 #endif
@@ -95,6 +109,8 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
           memcpy(val, &fpreg.fpr_xacc[reg], sizeof(unw_fpreg_t));
 #elif defined(__i386__)
           memcpy(val, &fpreg.fpr_acc[reg], sizeof(unw_fpreg_t));
+#elif defined(__arm__)
+          memcpy(val, &fpreg.fpr[reg], sizeof(unw_fpreg_t));
 #else
 #error Fix me
 #endif
index ab93ce3..79bde25 100644 (file)
@@ -32,33 +32,66 @@ _UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
                  int write, void *arg)
 {
   struct UPT_info *ui = arg;
+  int    i, end;
+  unw_word_t tmp_val;
+
   if (!ui)
         return -UNW_EINVAL;
 
   pid_t pid = ui->pid;
 
-  errno = 0;
-  if (write)
+  // Some 32-bit archs have to define a 64-bit unw_word_t.
+  // Callers of this function therefore expect a 64-bit
+  // return value, but ptrace only returns a 32-bit value
+  // in such cases.
+  if (sizeof(long) == 4 && sizeof(unw_word_t) == 8)
+    end = 2;
+  else
+    end = 1;
+
+  for (i = 0; i < end; i++)
     {
-      Debug (16, "mem[%lx] <- %lx\n", (long) addr, (long) *val);
+      unw_word_t tmp_addr = i == 0 ? addr : addr + 4;
+
+      errno = 0;
+      if (write)
+        {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+          tmp_val = i == 0 ? *val : *val >> 32;
+#else
+          tmp_val = i == 0 && end == 2 ? *val >> 32 : *val;
+#endif
+
+          Debug (16, "mem[%lx] <- %lx\n", (long) tmp_addr, (long) tmp_val);
 #ifdef HAVE_TTRACE
-#       warning No support for ttrace() yet.
+#         warning No support for ttrace() yet.
 #else
-      ptrace (PTRACE_POKEDATA, pid, addr, *val);
-      if (errno)
-        return -UNW_EINVAL;
+          ptrace (PTRACE_POKEDATA, pid, tmp_addr, tmp_val);
+          if (errno)
+            return -UNW_EINVAL;
 #endif
-    }
-  else
-    {
+        }
+      else
+        {
 #ifdef HAVE_TTRACE
-#       warning No support for ttrace() yet.
+#         warning No support for ttrace() yet.
 #else
-      *val = ptrace (PTRACE_PEEKDATA, pid, addr, 0);
-      if (errno)
-        return -UNW_EINVAL;
+          tmp_val = (unsigned long) ptrace (PTRACE_PEEKDATA, pid, tmp_addr, 0);
+
+          if (i == 0)
+              *val = 0;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+          *val |= tmp_val << (i * 32);
+#else
+          *val |= i == 0 && end == 2 ? tmp_val << 32 : tmp_val;
+#endif
+
+          if (errno)
+            return -UNW_EINVAL;
 #endif
-      Debug (16, "mem[%lx] -> %lx\n", (long) addr, (long) *val);
+          Debug (16, "mem[%lx] -> %lx\n", (long) tmp_addr, (long) tmp_val);
+        }
     }
   return 0;
 }
index ae71608..ce25c78 100644 (file)
@@ -34,7 +34,50 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 # include "tdep-ia64/rse.h"
 #endif
 
-#if HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE
+#if HAVE_DECL_PTRACE_SETREGSET
+#include <sys/uio.h>
+int
+_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
+                 int write, void *arg)
+{
+  struct UPT_info *ui = arg;
+  pid_t pid = ui->pid;
+  gregset_t regs;
+  char *r;
+  struct iovec loc;
+
+#if UNW_DEBUG
+  Debug(16, "using getregset: reg: %s [%u], val: %lx, write: %u\n", 
+       unw_regname(reg), (unsigned) reg, (long) val, write);
+
+  if (write)
+    Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val);
+#endif
+  if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset))
+    {
+      errno = EINVAL;
+      goto badreg;
+    }
+
+  loc.iov_base = &regs;
+  loc.iov_len = sizeof(regs);
+
+  r = (char *)&regs + _UPT_reg_offset[reg];
+  if (ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS, &loc) == -1)
+    goto badreg;
+  if (write) {
+    memcpy(r, val, sizeof(unw_word_t));
+    if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &loc) == -1)
+      goto badreg;
+  } else
+    memcpy(val, r, sizeof(unw_word_t));
+  return 0;
+
+badreg:
+  Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno));
+  return -UNW_EBADREG;
+}
+#elif HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE
 int
 _UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
                  int write, void *arg)
index 3190e78..4724360 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "_UPT_internal.h"
 
-PROTECTED unw_accessors_t _UPT_accessors =
+unw_accessors_t _UPT_accessors =
   {
     .find_proc_info             = _UPT_find_proc_info,
     .put_unwind_info            = _UPT_put_unwind_info,
index d2a37ea..b3209f4 100644 (file)
@@ -131,15 +131,15 @@ _UPT_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
     ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache,
                                     pi, need_unwind_info, arg);
 
+  if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1)
+    ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi,
+                                    need_unwind_info, arg);
+
 #if UNW_TARGET_ARM
   if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1)
     ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi,
                                     need_unwind_info, arg);
 #endif
 
-  if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1)
-    ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi,
-                                    need_unwind_info, arg);
-
   return ret;
 }
index 68461a2..c82d1c9 100644 (file)
@@ -484,6 +484,7 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] =
 #endif
 
 #elif defined(UNW_TARGET_ARM)
+#if defined(__linux__) || defined(__FreeBSD__)
     [UNW_ARM_R0]       = 0x00,
     [UNW_ARM_R1]       = 0x04,
     [UNW_ARM_R2]       = 0x08,
@@ -500,7 +501,43 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] =
     [UNW_ARM_R13]      = 0x34,
     [UNW_ARM_R14]      = 0x38,
     [UNW_ARM_R15]      = 0x3c,
+#else
+#error Fix me
+#endif
 #elif defined(UNW_TARGET_MIPS)
+    [UNW_MIPS_R0]  =  0,
+    [UNW_MIPS_R1]  =  1,
+    [UNW_MIPS_R2]  =  2,
+    [UNW_MIPS_R3]  =  3,
+    [UNW_MIPS_R4]  =  4,
+    [UNW_MIPS_R5]  =  5,
+    [UNW_MIPS_R6]  =  6,
+    [UNW_MIPS_R7]  =  7,
+    [UNW_MIPS_R8]  =  8,
+    [UNW_MIPS_R9]  =  9,
+    [UNW_MIPS_R10] = 10,
+    [UNW_MIPS_R11] = 11,
+    [UNW_MIPS_R12] = 12,
+    [UNW_MIPS_R13] = 13,
+    [UNW_MIPS_R14] = 14,
+    [UNW_MIPS_R15] = 15,
+    [UNW_MIPS_R16] = 16,
+    [UNW_MIPS_R17] = 17,
+    [UNW_MIPS_R18] = 18,
+    [UNW_MIPS_R19] = 19,
+    [UNW_MIPS_R20] = 20,
+    [UNW_MIPS_R21] = 21,
+    [UNW_MIPS_R22] = 22,
+    [UNW_MIPS_R23] = 23,
+    [UNW_MIPS_R24] = 24,
+    [UNW_MIPS_R25] = 25,
+    [UNW_MIPS_R26] = 26,
+    [UNW_MIPS_R27] = 27,
+    [UNW_MIPS_R28] = 28,
+    [UNW_MIPS_R29] = 29,
+    [UNW_MIPS_R30] = 30,
+    [UNW_MIPS_R31] = 31,
+    [UNW_MIPS_PC]  = 64,
 #elif defined(UNW_TARGET_SH)
 #elif defined(UNW_TARGET_AARCH64)
     [UNW_AARCH64_X0]       = 0x00,
diff --git a/src/sh/Gapply_reg_state.c b/src/sh/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index 1907d04..6ca3a38 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index de9199f..c363d24 100644 (file)
@@ -24,7 +24,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index 7690a80..24d9f63 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   struct cursor *c = (struct cursor *) cursor;
index b380db1..52988a7 100644 (file)
@@ -31,13 +31,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 static inline void *
 uc_addr (ucontext_t *uc, int reg)
@@ -171,7 +171,7 @@ HIDDEN void
 sh_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.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
index e1cc30c..99ddb36 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
 {
   return -UNW_EINVAL;
@@ -36,8 +36,8 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+static int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -49,7 +49,30 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
   c->dwarf.as = unw_local_addr_space;
   c->dwarf.as_arg = uc;
 
-  return common_init (c, 1);
+  return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
 }
 
 #endif /* !UNW_REMOTE_ONLY */
index f284e99..9b8ba5b 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index 9719f8e..4481fe1 100644 (file)
@@ -63,7 +63,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
   3e:   09 00           nop
 */
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
 #ifdef __linux__
@@ -75,7 +75,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   int ret;
 
   as = c->dwarf.as;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   arg = c->dwarf.as_arg;
 
   ip = c->dwarf.ip;
diff --git a/src/sh/Greg_states_iterate.c b/src/sh/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index fb4ca74..7d8e8e9 100644 (file)
@@ -33,6 +33,9 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
 
   switch (reg)
     {
+    case UNW_SH_PC:
+      if (write)
+        c->dwarf.ip = *valp;            /* update the IP cache */
     case UNW_SH_R0:
     case UNW_SH_R1:
     case UNW_SH_R2:
@@ -48,7 +51,6 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
     case UNW_SH_R12:
     case UNW_SH_R13:
     case UNW_SH_R14:
-    case UNW_SH_PC:
     case UNW_SH_PR:
       loc = c->dwarf.loc[reg];
       break;
index b14e419..a263c92 100644 (file)
@@ -143,7 +143,7 @@ establish_machine_state (struct cursor *c)
     }
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 9bbb5ff..60d7ec2 100644 (file)
@@ -27,8 +27,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "offsets.h"
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
+static int
+sh_handle_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
   int ret;
@@ -94,7 +94,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor)
   return 1;
 }
 
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -102,8 +102,8 @@ unw_step (unw_cursor_t *cursor)
 
   Debug (1, "(cursor=%p)\n", c);
 
-  if (unw_is_signal_frame (cursor))
-    return unw_handle_signal_frame (cursor);
+  if (unw_is_signal_frame (cursor) > 0)
+    return sh_handle_signal_frame (cursor);
 
   ret = dwarf_step (&c->dwarf);
 
diff --git a/src/sh/Lapply_reg_state.c b/src/sh/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/sh/Lreg_states_iterate.c b/src/sh/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index a180258..36713fe 100644 (file)
@@ -62,7 +62,6 @@ common_init (struct cursor *c, unsigned use_prev_instr)
   c->sigcontext_pc = 0;
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = 0;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
index c351f81..de09340 100644 (file)
@@ -24,7 +24,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_is_fpreg (int regnum)
 {
   /* FIXME: Support FP.  */
index dcab240..b52925b 100644 (file)
@@ -46,7 +46,7 @@ static const char *const regname[] =
     [UNW_SH_PR]  = "pr",
   };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname) && regname[reg] != NULL)
diff --git a/src/tilegx/Gapply_reg_state.c b/src/tilegx/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index a2821a3..39acdc2 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index f82700d..3a158da 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index ec474e1..fcf0697 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   struct cursor *c = (struct cursor *) cursor;
index df3ffca..7564a55 100644 (file)
@@ -31,13 +31,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+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).  */
@@ -152,7 +152,7 @@ tilegx_local_addr_space_init (void)
 
   local_addr_space.abi = UNW_TILEGX_ABI_N64;
   local_addr_space.addr_size = sizeof (void *);
-  local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+  local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
index f75c98f..31a716d 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 {
   return -UNW_EINVAL;
@@ -36,8 +36,8 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+static int
+unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -51,7 +51,30 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
   c->dwarf.as = unw_local_addr_space;
 
   c->dwarf.as_arg = uc;
-  return common_init (c, 1);
+  return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
 }
 
 #endif /* !UNW_REMOTE_ONLY */
index c554100..2a31b18 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index 96bd34a..5452c2c 100644 (file)
@@ -40,7 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
     ((unsigned long)TREG_SYSCALL_NR << 31) )
 #define  SWINT1      0x286b180051485000ULL
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor*) cursor;
@@ -51,7 +51,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   int ret;
 
   as = c->dwarf.as;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   arg = c->dwarf.as_arg;
 
   ip = c->dwarf.ip;
@@ -75,8 +75,8 @@ unw_is_signal_frame (unw_cursor_t *cursor)
 }
 
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
+HIDDEN int
+tilegx_handle_signal_frame (unw_cursor_t *cursor)
 {
   int i;
   struct cursor *c = (struct cursor *) cursor;
diff --git a/src/tilegx/Greg_states_iterate.c b/src/tilegx/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index 53e7bf4..565c6f4 100644 (file)
@@ -52,7 +52,17 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
     }
   
   if (write)
-    return dwarf_put (&c->dwarf, loc, *valp);
+    {
+      if (ci->dwarf.use_prev_instr == 0) {
+       if (reg == UNW_TILEGX_PC)
+         c->dwarf.ip = *valp;            /* update the IP cache */
+       }
+      else {
+       if (reg == UNW_TILEGX_R55)
+         c->dwarf.ip = *valp;            /* update the IP cache */
+      }
+      return dwarf_put (&c->dwarf, loc, *valp);
+    }
   else
     return dwarf_get (&c->dwarf, loc, valp);
 }
index f532fd8..ece443a 100644 (file)
@@ -72,7 +72,7 @@ establish_machine_state (struct cursor *c)
     }
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 0d8f8af..c748dbc 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "offsets.h"
 
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -36,8 +36,8 @@ unw_step (unw_cursor_t *cursor)
          c, c->dwarf.ip, c->dwarf.cfa);
 
   /* Special handling the singal frame. */
-  if (unw_is_signal_frame (cursor))
-    return unw_handle_signal_frame (cursor);
+  if (unw_is_signal_frame (cursor) > 0)
+    return tilegx_handle_signal_frame (cursor);
 
   /* Try DWARF-based unwinding... */
   ret = dwarf_step (&c->dwarf);
diff --git a/src/tilegx/Lapply_reg_state.c b/src/tilegx/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/tilegx/Lreg_states_iterate.c b/src/tilegx/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index e75e590..0e0f7fd 100644 (file)
@@ -52,7 +52,6 @@ common_init (struct cursor *c, unsigned use_prev_instr)
     return ret;
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = 0;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
index 118e055..d6d5896 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 /* TILEGX has no FP. */
 
-PROTECTED int
+int
 unw_is_fpreg (int regnum)
 {
   return 0;
index fd73804..0ce47b9 100644 (file)
@@ -45,7 +45,7 @@ static const char *regname[] =
     "pc",  "cfa"
   };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
index 50f1fb6..0b14df4 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED _Unwind_Reason_Code
+_Unwind_Reason_Code
 _Unwind_Backtrace (_Unwind_Trace_Fn trace, void *trace_parameter)
 {
   struct _Unwind_Context context;
index 79be65e..ad38eaf 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED void
+void
 _Unwind_DeleteException (struct _Unwind_Exception *exception_object)
 {
   _Unwind_Exception_Cleanup_Fn cleanup = exception_object->exception_cleanup;
index b9873da..4f10666 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED void *
+void *
 _Unwind_FindEnclosingFunction (void *ip)
 {
   unw_proc_info_t pi;
index da8a60e..905b31c 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED _Unwind_Reason_Code
+_Unwind_Reason_Code
 _Unwind_ForcedUnwind (struct _Unwind_Exception *exception_object,
                       _Unwind_Stop_Fn stop, void *stop_parameter)
 {
index 253fde0..d1bc84e 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetBSP (struct _Unwind_Context *context)
 {
 #ifdef UNW_TARGET_IA64
index 7975b1d..5ca6390 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetCFA (struct _Unwind_Context *context)
 {
   unw_word_t val;
index 9bdd4cb..8e6914f 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetDataRelBase (struct _Unwind_Context *context)
 {
   unw_proc_info_t pi;
index b7ab05c..fa70943 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetGR (struct _Unwind_Context *context, int index)
 {
   unw_word_t val;
index e93853d..e9fc494 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetIP (struct _Unwind_Context *context)
 {
   unw_word_t val;
index 9105396..e8ee7fd 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 /* gcc/unwind-dw2.c: Retrieve the return address and flag whether that IP is
    before or after first not yet fully executed instruction.  */
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
 {
   unw_word_t val;
index df52c92..e7ca9b4 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
 {
   unw_proc_info_t pi;
index f0da344..f499581 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetRegionStart (struct _Unwind_Context *context)
 {
   unw_proc_info_t pi;
index d0826e7..ce65ae9 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED unsigned long
+unsigned long
 _Unwind_GetTextRelBase (struct _Unwind_Context *context)
 {
   return 0;
index cdf134a..3c3ca19 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED _Unwind_Reason_Code
+_Unwind_Reason_Code
 _Unwind_RaiseException (struct _Unwind_Exception *exception_object)
 {
   uint64_t exception_class = exception_object->exception_class;
index dd0a44b..e23d6be 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED void
+void
 _Unwind_Resume (struct _Unwind_Exception *exception_object)
 {
   struct _Unwind_Context context;
index d60e038..9c76443 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED _Unwind_Reason_Code
+_Unwind_Reason_Code
 _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exception_object)
 {
   struct _Unwind_Context context;
index 143b354..ae77a8e 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "dwarf_i.h"
 #endif
 
-PROTECTED void
+void
 _Unwind_SetGR (struct _Unwind_Context *context, int index,
                unsigned long new_value)
 {
index c55ab97..fccc2f0 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind-internal.h"
 
-PROTECTED void
+void
 _Unwind_SetIP (struct _Unwind_Context *context, unsigned long new_value)
 {
   unw_set_reg (&context->cursor, UNW_REG_IP, new_value);
diff --git a/src/x86/Gapply_reg_state.c b/src/x86/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index 45fec6d..a7e41a5 100644 (file)
@@ -31,7 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
 #endif
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index 45b4cd5..4dc2cff 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index d440f9e..e459382 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   struct cursor *c = (struct cursor *) cursor;
index b05a08e..f6b8dc2 100644 (file)
@@ -36,13 +36,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifdef UNW_REMOTE_ONLY
 
 /* unw_local_addr_space is a NULL pointer in this case.  */
-PROTECTED unw_addr_space_t unw_local_addr_space;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 # ifdef UNW_LOCAL_ONLY
 
@@ -228,7 +228,7 @@ HIDDEN void
 x86_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.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
index 02fb994..bff0687 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 {
   return -UNW_EINVAL;
@@ -36,8 +36,8 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+static int
+unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -50,7 +50,30 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
   c->dwarf.as_arg = c;
   c->uc = uc;
   c->validate = 0;
-  return common_init (c, 1);
+  return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
 }
 
 #endif /* !UNW_REMOTE_ONLY */
index 16b6395..7c15096 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index cf05f07..7dd0140 100644 (file)
@@ -35,7 +35,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "offsets.h"
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -46,7 +46,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   int ret;
 
   as = c->dwarf.as;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   arg = c->dwarf.as_arg;
 
   /* Check if EIP points at sigreturn() sequence.  It can be:
@@ -101,8 +101,8 @@ XXX
   return (ret);
 }
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
+HIDDEN int
+x86_handle_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
   int ret;
index 17aebc2..fb9a5e3 100644 (file)
@@ -26,7 +26,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "offsets.h"
 
-PROTECTED int
+#include <sys/syscall.h>
+
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -37,7 +39,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   int ret;
 
   as = c->dwarf.as;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   arg = c->dwarf.as_arg;
 
   /* Check if EIP points at sigreturn() sequence.  On Linux, this is:
@@ -52,7 +54,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
     __restore_rt:
        0xb8 0xad 0x00 0x00 0x00        movl 0xad,%eax
        0xcd 0x80                       int 0x80
-       0x00                            
+       0x00
 
      if SA_SIGINFO is specified.
   */
@@ -67,8 +69,8 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   return ret;
 }
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
+HIDDEN int
+x86_handle_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
   int ret;
@@ -296,7 +298,7 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
       struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
 
       Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc);
-      sigreturn (sc);
+      x86_sigreturn (sc);
     }
   else
     {
@@ -305,4 +307,25 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
     }
   return -UNW_EINVAL;
 }
+
+/* sigreturn() is a no-op on x86 glibc.  */
+HIDDEN void
+x86_sigreturn (unw_cursor_t *cursor)
+{
+  struct cursor *c = (struct cursor *) cursor;
+  struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+  mcontext_t *sc_mcontext = &((ucontext_t*)sc)->uc_mcontext;
+  /* Copy in saved uc - all preserved regs are at the start of sigcontext */
+  memcpy(sc_mcontext, &c->uc->uc_mcontext,
+         DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t));
+
+  Debug (8, "resuming at ip=%llx via sigreturn(%p)\n",
+             (unsigned long long) c->dwarf.ip, sc);
+  __asm__ __volatile__ ("mov %0, %%esp;"
+                        "mov %1, %%eax;"
+                        "syscall"
+                        :: "r"(sc), "i"(SYS_rt_sigreturn)
+                        : "memory");
+  abort();
+}
 #endif
diff --git a/src/x86/Greg_states_iterate.c b/src/x86/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index cb3fb31..5072c4b 100644 (file)
@@ -63,10 +63,19 @@ establish_machine_state (struct cursor *c)
             (*access_reg) (as, reg, &val, 1, arg);
         }
     }
+
+  if (c->dwarf.args_size)
+    {
+      if (tdep_access_reg (c, UNW_X86_ESP, &val, 0) >= 0)
+        {
+          val += c->dwarf.args_size;
+          (*access_reg) (as, UNW_X86_ESP, &val, 1, arg);
+        }
+    }
   return 0;
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index 10e2cbc..129b739 100644 (file)
@@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "offsets.h"
 
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -55,9 +55,9 @@ unw_step (unw_cursor_t *cursor)
 
       Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
 
-      if (unw_is_signal_frame (cursor))
+      if (unw_is_signal_frame (cursor) > 0)
         {
-          ret = unw_handle_signal_frame(cursor);
+          ret = x86_handle_signal_frame(cursor);
           if (ret < 0)
             {
               Debug (2, "returning 0\n");
@@ -90,7 +90,6 @@ unw_step (unw_cursor_t *cursor)
           c->dwarf.loc[EIP] = eip_loc;
           c->dwarf.use_prev_instr = 1;
         }
-      c->dwarf.ret_addr_column = EIP;
 
       if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP]))
         {
diff --git a/src/x86/Lapply_reg_state.c b/src/x86/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/x86/Lreg_states_iterate.c b/src/x86/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index 027aedc..b0db8d3 100644 (file)
@@ -58,7 +58,6 @@ common_init (struct cursor *c, unsigned use_prev_instr)
   c->sigcontext_addr = 0;
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = 0;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
index addf9bc..a3a98ac 100644 (file)
@@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_is_fpreg (int regnum)
 {
   return ((regnum >= UNW_X86_ST0 && regnum <= UNW_X86_ST7)
index 2228510..11f6228 100644 (file)
@@ -17,7 +17,7 @@ static const char *regname[] =
     "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
   };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
index cd52824..caa7e02 100644 (file)
@@ -52,6 +52,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #define x86_scratch_loc                 UNW_OBJ(scratch_loc)
 #define x86_get_scratch_loc             UNW_OBJ(get_scratch_loc)
 #define x86_r_uc_addr                   UNW_OBJ(r_uc_addr)
+#define x86_sigreturn                   UNW_OBJ(sigreturn)
 
 extern void x86_local_addr_space_init (void);
 extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
@@ -60,4 +61,8 @@ extern dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg);
 extern dwarf_loc_t x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg);
 extern void *x86_r_uc_addr (ucontext_t *uc, int reg);
 
+extern void x86_sigreturn (unw_cursor_t *cursor);
+#define x86_handle_signal_frame UNW_OBJ(handle_signal_frame)
+extern int x86_handle_signal_frame(unw_cursor_t *cursor);
+
 #endif /* unwind_i_h */
diff --git a/src/x86_64/Gapply_reg_state.c b/src/x86_64/Gapply_reg_state.c
new file mode 100644 (file)
index 0000000..82f056d
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_apply_reg_state (unw_cursor_t *cursor,
+                    void *reg_states_data)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
+}
index 38ee5af..9b2db98 100644 (file)
@@ -34,7 +34,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
 #endif
 
-PROTECTED unw_addr_space_t
+unw_addr_space_t
 unw_create_addr_space (unw_accessors_t *a, int byte_order)
 {
 #ifdef UNW_LOCAL_ONLY
index 8def62d..50de1e4 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
 {
   struct cursor *c = (struct cursor *) cursor;
index b48fa91..0057c62 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
 {
   struct cursor *c = (struct cursor *) cursor;
index 6e9d4fe..2a84a1e 100644 (file)
@@ -30,22 +30,24 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include <config.h>
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <sys/syscall.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;
+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;
+unw_addr_space_t unw_local_addr_space = &local_addr_space;
 
 HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
 
@@ -71,17 +73,79 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
 #define PAGE_SIZE 4096
 #define PAGE_START(a)   ((a) & ~(PAGE_SIZE-1))
 
+static int mem_validate_pipe[2] = {-1, -1};
+
+static inline void
+open_pipe (void)
+{
+  /* ignore errors for closing invalid fd's */
+  close (mem_validate_pipe[0]);
+  close (mem_validate_pipe[1]);
+
+  pipe2 (mem_validate_pipe, O_CLOEXEC | O_NONBLOCK);
+}
+
+ALWAYS_INLINE
+static int
+write_validate (void *addr)
+{
+  int ret = -1;
+  ssize_t bytes = 0;
+
+  do
+    {
+      char buf;
+      bytes = read (mem_validate_pipe[0], &buf, 1);
+    }
+  while ( errno == EINTR );
+
+  int valid_read = (bytes > 0 || errno == EAGAIN || errno == EWOULDBLOCK);
+  if (!valid_read)
+    {
+      // re-open closed pipe
+      open_pipe ();
+    }
+
+  do
+    {
+      /* use syscall insteadof write() so that ASAN does not complain */
+      ret = syscall (SYS_write, mem_validate_pipe[1], addr, 1);
+    }
+  while ( errno == EINTR );
+
+  return ret;
+}
+
 static int (*mem_validate_func) (void *addr, size_t len);
 static int msync_validate (void *addr, size_t len)
 {
-  return msync (addr, len, MS_ASYNC);
+  if (msync (addr, len, MS_ASYNC) != 0)
+    {
+      return -1;
+    }
+
+  return write_validate (addr);
 }
 
 #ifdef HAVE_MINCORE
 static int mincore_validate (void *addr, size_t len)
 {
   unsigned char mvec[2]; /* Unaligned access may cross page boundary */
-  return mincore (addr, len, mvec);
+  size_t i;
+
+  /* mincore could fail with EAGAIN but we conservatively return -1
+     instead of looping. */
+  if (mincore (addr, len, mvec) != 0)
+    {
+      return -1;
+    }
+
+  for (i = 0; i < (len + PAGE_SIZE - 1) / PAGE_SIZE; i++)
+    {
+      if (!(mvec[i] & 1)) return -1;
+    }
+
+  return write_validate (addr);
 }
 #endif
 
@@ -92,9 +156,16 @@ static int mincore_validate (void *addr, size_t len)
 HIDDEN void
 tdep_init_mem_validate (void)
 {
+  open_pipe ();
+
 #ifdef HAVE_MINCORE
   unsigned char present = 1;
-  if (mincore (&present, 1, &present) == 0)
+  unw_word_t addr = PAGE_START((unw_word_t)&present);
+  unsigned char mvec[1];
+  int ret;
+  while ((ret = mincore ((void*)addr, PAGE_SIZE, mvec)) == -1 &&
+         errno == EAGAIN) {}
+  if (ret == 0 && (mvec[0] & 1))
     {
       Debug(1, "using mincore to validate memory\n");
       mem_validate_func = mincore_validate;
@@ -253,7 +324,7 @@ HIDDEN void
 x86_64_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.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
   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;
index 0799389..5eaead0 100644 (file)
@@ -30,7 +30,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #ifdef UNW_REMOTE_ONLY
 
-PROTECTED int
+int
 unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 {
   return -UNW_EINVAL;
@@ -38,8 +38,8 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
 
 #else /* !UNW_REMOTE_ONLY */
 
-PROTECTED int
-unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+static int
+unw_init_local_common (unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr)
 {
   struct cursor *c = (struct cursor *) cursor;
 
@@ -52,7 +52,30 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
   c->dwarf.as_arg = c;
   c->uc = uc;
   c->validate = 0;
-  return common_init (c, 1);
+  return common_init (c, use_prev_instr);
+}
+
+int
+unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+{
+  return unw_init_local_common(cursor, uc, 1);
+}
+
+int
+unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
+{
+  if (!flag)
+    {
+      return unw_init_local_common(cursor, uc, 1);
+    }
+  else if (flag == UNW_INIT_SIGNAL_FRAME)
+    {
+      return unw_init_local_common(cursor, uc, 0);
+    }
+  else
+    {
+      return -UNW_EINVAL;
+    }
 }
 
 #endif /* !UNW_REMOTE_ONLY */
index f3b7bb9..efd61d6 100644 (file)
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "init.h"
 #include "unwind_i.h"
 
-PROTECTED int
+int
 unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
 {
 #ifdef UNW_LOCAL_ONLY
index e7e8da1..883025c 100644 (file)
@@ -33,7 +33,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "unwind_i.h"
 #include "ucontext_i.h"
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
   /* XXXKIB */
@@ -45,7 +45,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
   int ret;
 
   as = c->dwarf.as;
-  a = unw_get_accessors (as);
+  a = unw_get_accessors_int (as);
   arg = c->dwarf.as_arg;
 
   /* Check if RIP points at sigreturn sequence.
@@ -87,8 +87,8 @@ eb fd                   jmp     0b
   return (X86_64_SCF_NONE);
 }
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
+HIDDEN int
+x86_64_handle_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
   unw_word_t ucontext;
@@ -192,6 +192,24 @@ x86_64_sigreturn (unw_cursor_t *cursor)
   ucontext_t *uc = (ucontext_t *)(c->sigcontext_addr +
     offsetof(struct sigframe, sf_uc));
 
+  uc->uc_mcontext.mc_r8 = c->uc->uc_mcontext.mc_r8;
+  uc->uc_mcontext.mc_r9 = c->uc->uc_mcontext.mc_r9;
+  uc->uc_mcontext.mc_r10 = c->uc->uc_mcontext.mc_r10;
+  uc->uc_mcontext.mc_r11 = c->uc->uc_mcontext.mc_r11;
+  uc->uc_mcontext.mc_r12 = c->uc->uc_mcontext.mc_r12;
+  uc->uc_mcontext.mc_r13 = c->uc->uc_mcontext.mc_r13;
+  uc->uc_mcontext.mc_r14 = c->uc->uc_mcontext.mc_r14;
+  uc->uc_mcontext.mc_r15 = c->uc->uc_mcontext.mc_r15;
+  uc->uc_mcontext.mc_rdi = c->uc->uc_mcontext.mc_rdi;
+  uc->uc_mcontext.mc_rsi = c->uc->uc_mcontext.mc_rsi;
+  uc->uc_mcontext.mc_rbp = c->uc->uc_mcontext.mc_rbp;
+  uc->uc_mcontext.mc_rbx = c->uc->uc_mcontext.mc_rbx;
+  uc->uc_mcontext.mc_rdx = c->uc->uc_mcontext.mc_rdx;
+  uc->uc_mcontext.mc_rax = c->uc->uc_mcontext.mc_rax;
+  uc->uc_mcontext.mc_rcx = c->uc->uc_mcontext.mc_rcx;
+  uc->uc_mcontext.mc_rsp = c->uc->uc_mcontext.mc_rsp;
+  uc->uc_mcontext.mc_rip = c->uc->uc_mcontext.mc_rip;
+
   Debug (8, "resuming at ip=%llx via sigreturn(%p)\n",
              (unsigned long long) c->dwarf.ip, uc);
   sigreturn(uc);
index 9e1acfc..bd14234 100644 (file)
@@ -47,21 +47,21 @@ tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info)
         dw->ip, dw->cfa, c->sigcontext_format);
 }
 
-HIDDEN void
-tdep_cache_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
+HIDDEN int
+tdep_cache_frame (struct dwarf_cursor *dw)
 {
   struct cursor *c = (struct cursor *) dw;
-  rs->signal_frame = c->sigcontext_format;
 
   Debug(5, "cache frame ip=0x%lx cfa=0x%lx format=%d\n",
         dw->ip, dw->cfa, c->sigcontext_format);
+  return c->sigcontext_format;
 }
 
 HIDDEN void
-tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
+tdep_reuse_frame (struct dwarf_cursor *dw, int frame)
 {
   struct cursor *c = (struct cursor *) dw;
-  c->sigcontext_format = rs->signal_frame;
+  c->sigcontext_format = frame;
   if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME)
   {
     c->frame_info.frame_type = UNW_X86_64_FRAME_SIGRETURN;
@@ -69,8 +69,6 @@ tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
     c->frame_info.cfa_reg_offset = 0;
     c->sigcontext_addr = dw->cfa;
   }
-  else
-    c->sigcontext_addr = 0;
 
   Debug(5, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx offset=%+d\n",
         dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr,
@@ -78,15 +76,15 @@ tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
          ? c->frame_info.cfa_reg_offset : 0));
 }
 
-PROTECTED int
+int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
   return c->sigcontext_format != X86_64_SCF_NONE;
 }
 
-PROTECTED int
-unw_handle_signal_frame (unw_cursor_t *cursor)
+HIDDEN int
+x86_64_handle_signal_frame (unw_cursor_t *cursor)
 {
 #if UNW_DEBUG /* To silence compiler warnings */
   /* Should not get here because we now use kernel-provided dwarf
@@ -140,6 +138,10 @@ x86_64_sigreturn (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
   struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
+  mcontext_t *sc_mcontext = &((ucontext_t*)sc)->uc_mcontext;
+  /* Copy in saved uc - all preserved regs are at the start of sigcontext */
+  memcpy(sc_mcontext, &c->uc->uc_mcontext,
+         DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t));
 
   Debug (8, "resuming at ip=%llx via sigreturn(%p)\n",
              (unsigned long long) c->dwarf.ip, sc);
diff --git a/src/x86_64/Greg_states_iterate.c b/src/x86_64/Greg_states_iterate.c
new file mode 100644 (file)
index 0000000..a17dc1b
--- /dev/null
@@ -0,0 +1,37 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
+        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
+
+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"
+
+int
+unw_reg_states_iterate (unw_cursor_t *cursor,
+                       unw_reg_states_callback cb, void *token)
+{
+  struct cursor *c = (struct cursor *) cursor;
+
+  return dwarf_reg_states_iterate (&c->dwarf, cb, token);
+}
index 6880d94..944cdaa 100644 (file)
@@ -44,7 +44,7 @@ x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
      at least.  */
   dwarf_make_proc_info (&c->dwarf);
 
-  if (unlikely (c->sigcontext_format != X86_64_SCF_NONE))
+  if (unlikely (c->sigcontext_addr != X86_64_SCF_NONE))
     {
       x86_64_sigreturn(cursor);
       abort();
@@ -95,10 +95,19 @@ establish_machine_state (struct cursor *c)
             (*access_reg) (as, reg, &val, 1, arg);
         }
     }
+
+  if (c->dwarf.args_size)
+    {
+      if (tdep_access_reg (c, UNW_X86_64_RSP, &val, 0) >= 0)
+        {
+          val += c->dwarf.args_size;
+          (*access_reg) (as, UNW_X86_64_RSP, &val, 1, arg);
+        }
+    }
   return 0;
 }
 
-PROTECTED int
+int
 unw_resume (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
index dc6c7c8..2c7bc31 100644 (file)
@@ -34,12 +34,29 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
   Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
          " ra=0x%lx rbp [where=%d val=%ld @0x%lx] rsp [where=%d val=%ld @0x%lx]\n",
          d->ip, d->cfa, f->frame_type,
-         rs->reg[DWARF_CFA_REG_COLUMN].where,
-         rs->reg[DWARF_CFA_REG_COLUMN].val,
-         rs->reg[DWARF_CFA_OFF_COLUMN].val,
-         DWARF_GET_LOC(d->loc[d->ret_addr_column]),
-         rs->reg[RBP].where, rs->reg[RBP].val, DWARF_GET_LOC(d->loc[RBP]),
-         rs->reg[RSP].where, rs->reg[RSP].val, DWARF_GET_LOC(d->loc[RSP]));
+         rs->reg.where[DWARF_CFA_REG_COLUMN],
+         rs->reg.val[DWARF_CFA_REG_COLUMN],
+         rs->reg.val[DWARF_CFA_OFF_COLUMN],
+         DWARF_GET_LOC(d->loc[rs->ret_addr_column]),
+         rs->reg.where[RBP], rs->reg.val[RBP], DWARF_GET_LOC(d->loc[RBP]),
+         rs->reg.where[RSP], rs->reg.val[RSP], DWARF_GET_LOC(d->loc[RSP]));
+
+  if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR &&
+    rs->reg.where[RBP] == DWARF_WHERE_EXPR) {
+    /* Check for GCC generated alignment frame for rsp.  A simple
+     * def_cfa_expr that loads a constant offset from rbp, where the
+     * addres of the rip was pushed on the stack */
+    unw_word_t cfa_addr = rs->reg.val[DWARF_CFA_REG_COLUMN];
+    unw_word_t rbp_addr = rs->reg.val[RBP];
+    unw_word_t cfa_offset;
+
+    int ret = dwarf_stack_aligned(d, cfa_addr, rbp_addr, &cfa_offset);
+    if (ret) {
+      f->frame_type = UNW_X86_64_FRAME_ALIGNED;
+      f->cfa_reg_offset = cfa_offset;
+      f->cfa_reg_rsp = 0;
+    }
+  }
 
   /* A standard frame is defined as:
       - CFA is register-relative offset off RBP or RSP;
@@ -47,30 +64,30 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
       - RBP is unsaved or saved at CFA+offset, offset != -1;
       - RSP is unsaved or saved at CFA+offset, offset != -1.  */
   if (f->frame_type == UNW_X86_64_FRAME_OTHER
-      && (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
-      && (rs->reg[DWARF_CFA_REG_COLUMN].val == RBP
-          || rs->reg[DWARF_CFA_REG_COLUMN].val == RSP)
-      && labs((long) rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
-      && DWARF_GET_LOC(d->loc[d->ret_addr_column]) == d->cfa-8
-      && (rs->reg[RBP].where == DWARF_WHERE_UNDEF
-          || rs->reg[RBP].where == DWARF_WHERE_SAME
-          || (rs->reg[RBP].where == DWARF_WHERE_CFAREL
-              && labs((long) rs->reg[RBP].val) < (1 << 14)
-              && rs->reg[RBP].val+1 != 0))
-      && (rs->reg[RSP].where == DWARF_WHERE_UNDEF
-          || rs->reg[RSP].where == DWARF_WHERE_SAME
-          || (rs->reg[RSP].where == DWARF_WHERE_CFAREL
-              && labs((long) rs->reg[RSP].val) < (1 << 14)
-              && rs->reg[RSP].val+1 != 0)))
+      && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
+      && (rs->reg.val[DWARF_CFA_REG_COLUMN] == RBP
+          || rs->reg.val[DWARF_CFA_REG_COLUMN] == RSP)
+      && labs((long) rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 28)
+      && DWARF_GET_LOC(d->loc[rs->ret_addr_column]) == d->cfa-8
+      && (rs->reg.where[RBP] == DWARF_WHERE_UNDEF
+          || rs->reg.where[RBP] == DWARF_WHERE_SAME
+          || (rs->reg.where[RBP] == DWARF_WHERE_CFAREL
+              && labs((long) rs->reg.val[RBP]) < (1 << 14)
+              && rs->reg.val[RBP]+1 != 0))
+      && (rs->reg.where[RSP] == DWARF_WHERE_UNDEF
+          || rs->reg.where[RSP] == DWARF_WHERE_SAME
+          || (rs->reg.where[RSP] == DWARF_WHERE_CFAREL
+              && labs((long) rs->reg.val[RSP]) < (1 << 14)
+              && rs->reg.val[RSP]+1 != 0)))
   {
     /* Save information for a standard frame. */
     f->frame_type = UNW_X86_64_FRAME_STANDARD;
-    f->cfa_reg_rsp = (rs->reg[DWARF_CFA_REG_COLUMN].val == RSP);
-    f->cfa_reg_offset = rs->reg[DWARF_CFA_OFF_COLUMN].val;
-    if (rs->reg[RBP].where == DWARF_WHERE_CFAREL)
-      f->rbp_cfa_offset = rs->reg[RBP].val;
-    if (rs->reg[RSP].where == DWARF_WHERE_CFAREL)
-      f->rsp_cfa_offset = rs->reg[RSP].val;
+    f->cfa_reg_rsp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == RSP);
+    f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN];
+    if (rs->reg.where[RBP] == DWARF_WHERE_CFAREL)
+      f->rbp_cfa_offset = rs->reg.val[RBP];
+    if (rs->reg.where[RSP] == DWARF_WHERE_CFAREL)
+      f->rsp_cfa_offset = rs->reg.val[RSP];
     Debug (4, " standard frame\n");
   }
 
@@ -92,6 +109,10 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
     Debug (4, " sigreturn frame\n");
   }
 
+  else if (f->frame_type == UNW_X86_64_FRAME_ALIGNED) {
+    Debug (4, " aligned frame, offset %li\n", f->cfa_reg_offset);
+  }
+
   /* PLT and guessed RBP-walked frames are handled in unw_step(). */
   else
     Debug (4, " unusual frame\n");
index 84b3728..1049817 100644 (file)
@@ -39,7 +39,7 @@ is_plt_entry (struct dwarf_cursor *c)
   unw_accessors_t *a;
   int ret;
 
-  a = unw_get_accessors (c->as);
+  a = unw_get_accessors_int (c->as);
   if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0
       || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0)
     return 0;
@@ -52,7 +52,7 @@ is_plt_entry (struct dwarf_cursor *c)
   return ret;
 }
 
-PROTECTED int
+int
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
@@ -84,8 +84,7 @@ unw_step (unw_cursor_t *cursor)
     {
       /* x86_64 ABI specifies that end of call-chain is marked with a
          NULL RBP or undefined return address  */
-        if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])
-            || DWARF_IS_NULL_LOC(c->dwarf.loc[c->dwarf.ret_addr_column]))
+      if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
           {
             c->dwarf.ip = 0;
             ret = 0;
@@ -114,9 +113,9 @@ unw_step (unw_cursor_t *cursor)
 
       Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
 
-      if (unw_is_signal_frame (cursor))
+      if (unw_is_signal_frame (cursor) > 0)
         {
-          ret = unw_handle_signal_frame(cursor);
+          ret = x86_64_handle_signal_frame(cursor);
           if (ret < 0)
             {
               Debug (2, "returning 0\n");
@@ -198,8 +197,6 @@ unw_step (unw_cursor_t *cursor)
           c->dwarf.use_prev_instr = 1;
         }
 
-      c->dwarf.ret_addr_column = RIP;
-
       if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
         {
           ret = 0;
index 833d7a7..7412271 100644 (file)
@@ -506,6 +506,24 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
       d->use_prev_instr = 0;
       break;
 
+    case UNW_X86_64_FRAME_ALIGNED:
+      /* Address of RIP was pushed on the stack via a simple
+       * def_cfa_expr - result stack offset stored in cfa_reg_offset */
+      cfa = (f->cfa_reg_rsp ? rsp : rbp) + f->cfa_reg_offset;
+      ACCESS_MEM_FAST(ret, c->validate, d, cfa, cfa);
+      if (likely(ret >= 0))
+        ACCESS_MEM_FAST(ret, c->validate, d, cfa - 8, rip);
+      if (likely(ret >= 0))
+        ACCESS_MEM_FAST(ret, c->validate, d, rbp, rbp);
+
+      /* Don't bother reading RSP from DWARF, CFA becomes new RSP. */
+      rsp = cfa;
+
+      /* Next frame needs to back up for unwind info lookup. */
+      d->use_prev_instr = 1;
+
+      break;
+
     default:
       /* We cannot trace through this frame, give up and tell the
          caller we had to stop.  Data collected so far may still be
diff --git a/src/x86_64/Lapply_reg_state.c b/src/x86_64/Lapply_reg_state.c
new file mode 100644 (file)
index 0000000..7ebada4
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gapply_reg_state.c"
+#endif
diff --git a/src/x86_64/Lreg_states_iterate.c b/src/x86_64/Lreg_states_iterate.c
new file mode 100644 (file)
index 0000000..f1eb1e7
--- /dev/null
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Greg_states_iterate.c"
+#endif
index 442b2bf..a7a996f 100644 (file)
@@ -77,13 +77,13 @@ common_init (struct cursor *c, unsigned use_prev_instr)
   c->sigcontext_addr = 0;
 
   c->dwarf.args_size = 0;
-  c->dwarf.ret_addr_column = RIP;
   c->dwarf.stash_frames = 0;
   c->dwarf.use_prev_instr = use_prev_instr;
   c->dwarf.pi_valid = 0;
   c->dwarf.pi_is_dynamic = 0;
   c->dwarf.hint = 0;
   c->dwarf.prev_rs = 0;
+  c->dwarf.eh_valid_mask = 0;
 
   return 0;
 }
index 1188a61..5c03613 100644 (file)
@@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
-PROTECTED int
+int
 unw_is_fpreg (int regnum)
 {
 #if 0
index 6c0e2f3..77660af 100644 (file)
@@ -46,7 +46,7 @@ static const char *regname[] =
     "RIP",
    };
 
-PROTECTED const char *
+const char *
 unw_regname (unw_regnum_t reg)
 {
   if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
index 1af8b67..358217d 100644 (file)
@@ -25,19 +25,12 @@ 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_i.h"
-#if defined __linux__
-#include <asm/unistd.h>
-#define        SIG_SETMASK   2
-#define        SIGSET_BYTE_SIZE   (64/8)
-#elif defined __FreeBSD__
-#include <sys/syscall.h>
-#endif
 
 /*  int _Ux86_64_setcontext (const ucontext_t *ucp)
 
   Restores the machine context provided.
   Unlike the libc implementation, doesn't clobber %rax
-  
+
 */
        .global _Ux86_64_setcontext
        .type _Ux86_64_setcontext, @function
@@ -45,32 +38,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 _Ux86_64_setcontext:
 
 #if defined __linux__
-       /* restore signal mask
-           sigprocmask(SIG_SETMASK, ucp->uc_sigmask, NULL, sizeof(sigset_t)) */
-       push %rdi
-       mov $__NR_rt_sigprocmask, %rax
-       lea UC_SIGMASK(%rdi), %rsi
-       mov $SIG_SETMASK, %rdi
-       xor %rdx, %rdx
-       mov $SIGSET_BYTE_SIZE, %r10
-       syscall
-       pop %rdi
-
         /* restore fp state */
        mov    UC_MCONTEXT_FPREGS_PTR(%rdi),%r8
        fldenv (%r8)
        ldmxcsr FPREGS_OFFSET_MXCSR(%r8)
 #elif defined __FreeBSD__
-       /* restore signal mask */
-       pushq   %rdi
-       xorl    %edx,%edx
-       leaq    UC_SIGMASK(%rdi),%rsi
-       movl    $3,%edi/* SIG_SETMASK */
-       movl    $SYS_sigprocmask,%eax
-       movq    %rcx,%r10
-       syscall
-       popq    %rdi
-
        /* restore fp state */
        cmpq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi)
        jne 1f
index 4f81566..e95a60f 100644 (file)
@@ -87,5 +87,7 @@ extern dwarf_loc_t x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg);
 
 extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg);
 extern NORETURN void x86_64_sigreturn (unw_cursor_t *cursor);
+#define x86_64_handle_signal_frame UNW_OBJ(handle_signal_frame)
+extern int x86_64_handle_signal_frame(unw_cursor_t *cursor);
 
 #endif /* unwind_i_h */
index 2173406..e181918 100644 (file)
@@ -249,6 +249,8 @@ main (int argc, char **argv)
 
   measure_init ();
 
+  doit ("default         ");
+
   unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE);
   doit ("no cache        ");
 
index cc4fac6..4d24fa5 100644 (file)
@@ -235,6 +235,8 @@ main (int argc, char **argv)
 
   measure_init ();
 
+  doit ("default         ");
+
   unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE);
   doit ("no cache        ");
 
index 802dd08..beae2a3 100644 (file)
@@ -37,6 +37,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ucontext.h>
 #include <unistd.h>
 #include <libunwind.h>
 
index 147ecd0..18ec65d 100644 (file)
@@ -74,11 +74,19 @@ handler (int sig)
 #endif
 {
   unw_word_t ip;
-  sigset_t mask, oldmask;
+  sigset_t mask;
   unw_context_t uc;
   unw_cursor_t c;
   char foo;
   int ret;
+  // The test rely on SIGUSR2 mask to be cleared when the handler returns.
+  // For local context from the signal handler, there doesn't seem to be a way
+  // currently to set it so just clear the whole struct to make sure the signal mask is cleared.
+  // This should probably be fixed to avoid signal mask being set to random values
+  // by `unw_resume` if the context was not pre-zeroed.,
+  // Using the signal ucontext direction should also work automatically but currently doesn't
+  // on ARM/AArch64 (or any other archs that doesn't have a proper sigreturn implementation)
+  memset(&uc, 0x0, sizeof(uc));
 
 #if UNW_TARGET_IA64
   if (verbose)
@@ -95,17 +103,13 @@ handler (int sig)
 
       sigemptyset (&mask);
       sigaddset (&mask, SIGUSR2);
-      sigprocmask (SIG_BLOCK, &mask, &oldmask);
+      sigprocmask (SIG_BLOCK, &mask, NULL);
       kill (getpid (), SIGUSR2);       /* pend SIGUSR2 */
 
       signal (SIGUSR1, SIG_IGN);
 
       if ((ret = unw_getcontext (&uc)) < 0)
        panic ("unw_getcontext() failed: ret=%d\n", ret);
-#if UNW_TARGET_X86_64
-      /* unw_getcontext() doesn't save signal mask to avoid a syscall */
-      uc.uc_sigmask = oldmask; 
-#endif
       if ((ret = unw_init_local (&c, &uc)) < 0)
        panic ("unw_init_local() failed: ret=%d\n", ret);
 
index 194379a..fc1f646 100644 (file)
@@ -36,6 +36,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ucontext.h>
 #include <unistd.h>
 #include <libunwind.h>
 
@@ -212,7 +213,11 @@ sighandler (int signal, void *siginfo UNUSED, void *context)
       printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_rip);
 #endif
 #elif defined UNW_TARGET_ARM
+#if defined __linux__
       printf (" @ %lx", (unsigned long) uc->uc_mcontext.arm_pc);
+#elif defined __FreeBSD__
+      printf (" @ %lx", (unsigned long) uc->uc_mcontext.__gregs[_REG_PC]);
+#endif
 #endif
       printf ("\n");
     }
diff --git a/tests/Ltest-init-local-signal-lib.c b/tests/Ltest-init-local-signal-lib.c
new file mode 100644 (file)
index 0000000..7474f71
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+/* To prevent inlining and optimizing away */
+int foo(volatile int* f) {
+  return *f;
+}
diff --git a/tests/Ltest-init-local-signal.c b/tests/Ltest-init-local-signal.c
new file mode 100644 (file)
index 0000000..4bde218
--- /dev/null
@@ -0,0 +1,60 @@
+#include "libunwind.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <stdlib.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <assert.h>
+
+int stepper(unw_cursor_t* c) {
+  int steps = 0;
+  int ret = 1;
+  while (ret) {
+
+    ret = unw_step(c);
+    if (!ret) {
+      break;
+    }
+    steps++;
+  }
+  return steps;
+}
+
+/* Verify that we can step from both ucontext, and from getcontext()
+ * roughly the same.  This tests that the IP from ucontext is used
+ * correctly (see impl of unw_init_local2) */
+void handler(int num, siginfo_t* info, void* ucontext) {
+  unw_cursor_t c;
+  unw_context_t context;
+  unw_getcontext(&context);
+  int ret = unw_init_local2(&c, ucontext, UNW_INIT_SIGNAL_FRAME);
+  assert(!ret);
+  int ucontext_steps = stepper(&c);
+
+  ret = unw_init_local(&c, &context);
+  (void)ret;
+  assert(!ret);
+  int getcontext_steps = stepper(&c);
+  if (ucontext_steps == getcontext_steps - 2) {
+    exit(0);
+  }
+  printf("unw_getcontext steps was %i, ucontext steps was %i, should be %i\n",
+        getcontext_steps, ucontext_steps, getcontext_steps - 2);
+  exit(-1);
+}
+
+int foo(volatile int* f);
+
+int main(){
+  struct sigaction a;
+  memset(&a, 0, sizeof(struct sigaction));
+  a.sa_sigaction = &handler;
+  a.sa_flags = SA_SIGINFO;
+  sigaction(SIGSEGV, &a, NULL);
+
+  foo(NULL);
+  return 0;
+}
diff --git a/tests/Ltest-mem-validate.c b/tests/Ltest-mem-validate.c
new file mode 100644 (file)
index 0000000..1cacb9f
--- /dev/null
@@ -0,0 +1,143 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2003-2004 Hewlett-Packard Co
+       Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+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 "compiler.h"
+
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/resource.h>
+#include <sys/mman.h>
+
+#define panic(args...)                         \
+       { fprintf (stderr, args); exit (-1); }
+
+void * stack_start;
+
+#define PAGE_SIZE 4096
+
+void do_backtrace (void)
+{
+  void* buffer[1024];
+  int size = 1024;
+  mprotect((void*)((uintptr_t)stack_start & ~(PAGE_SIZE - 1)),
+           PAGE_SIZE, PROT_NONE);
+
+  unw_cursor_t cursor;
+  unw_word_t ip, sp;
+  unw_context_t uc;
+  int ret;
+  int steps = 0;
+
+  unw_getcontext (&uc);
+  if (unw_init_local (&cursor, &uc) < 0)
+    panic ("unw_init_local failed!\n");
+
+  do
+    {
+      unw_get_reg (&cursor, UNW_REG_IP, &ip);
+      unw_get_reg (&cursor, UNW_REG_SP, &sp);
+
+      ret = unw_step (&cursor);
+      if (ret < 0)
+       {
+         unw_get_reg (&cursor, UNW_REG_IP, &ip);
+       }
+      steps ++;
+    }
+  while (ret > 0);
+
+  if (steps < 5)
+    {
+      exit(-1);
+    }
+
+  mprotect((void*)((uintptr_t)stack_start & ~(PAGE_SIZE - 1)),
+           PAGE_SIZE, PROT_READ|PROT_WRITE);
+}
+
+void consume_and_run (int depth)
+{
+  unw_cursor_t cursor;
+  unw_context_t uc;
+  char string[1024];
+
+  sprintf (string, "hello %p %p\n", &cursor, &uc);
+  if (depth == 0) {
+    do_backtrace();
+  } else {
+    consume_and_run(depth - 1);
+  }
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+  int start;
+  unw_context_t uc;
+  unw_cursor_t cursor;
+
+  stack_start = &start;
+
+  // Initialize pipe mem validate check, opens file descriptors
+  unw_getcontext(&uc);
+  if (unw_init_local (&cursor, &uc) < 0)
+    panic ("unw_init_local failed!\n");
+
+  int i;
+  for (i = 3; i < 10; i++)
+    {
+
+      pid_t childpid = fork();
+      if (!childpid)
+        {
+          /* Close fds and make sure we still work */
+          int ret = close(i);
+        }
+
+      int status;
+      if (childpid)
+        {
+          wait(&status);
+          if (WIFEXITED(status))
+              return WEXITSTATUS(status);
+          else
+            return -1;
+        }
+      else
+        {
+          consume_and_run (10);
+
+          return 0;
+        }
+    }
+
+  return 0;
+}
index fe2dba8..4b0b9db 100644 (file)
@@ -7,24 +7,27 @@ EXTRA_DIST =  run-ia64-test-dyn1 run-ptrace-mapper run-ptrace-misc    \
 
 MAINTAINERCLEANFILES = Makefile.in
 
+noinst_PROGRAMS_arch =
+noinst_PROGRAMS_cdep =
 noinst_PROGRAMS_common =
+check_PROGRAMS_arch =
+check_PROGRAMS_cdep =
 check_PROGRAMS_common = test-proc-info test-static-link \
                        test-strerror
+check_SCRIPTS_arch =
+check_SCRIPTS_cdep =
 check_SCRIPTS_common = run-check-namespace
 
 if REMOTE_ONLY
- check_SCRIPTS_cdep =
- check_PROGRAMS_cdep =
- noinst_PROGRAMS_cdep = $(noinst_PROGRAMS_common)
 
 perf:
 
 else
  LIBUNWIND_local = $(top_builddir)/src/libunwind.la
 if ARCH_IA64
- noinst_PROGRAMS_arch = ia64-test-dyn1
- check_SCRIPTS_arch  run-ia64-test-dyn1
- check_PROGRAMS_arch = Gia64-test-stack Lia64-test-stack               \
+ noinst_PROGRAMS_arch += ia64-test-dyn1
+ check_SCRIPTS_arch += run-ia64-test-dyn1
+ check_PROGRAMS_arch +=        Gia64-test-stack Lia64-test-stack               \
                        Gia64-test-nat Lia64-test-nat                   \
                        Gia64-test-rbs Lia64-test-rbs                   \
                        Gia64-test-readonly Lia64-test-readonly         \
@@ -32,22 +35,22 @@ if ARCH_IA64
 else #!ARCH_IA64
 if ARCH_PPC64
 if USE_ALTIVEC
- noinst_PROGRAMS_arch = ppc64-test-altivec
+ noinst_PROGRAMS_arch += ppc64-test-altivec
 endif #USE_ALTIVEC
 endif #ARCH_PPC64
 endif #!ARCH_IA64
- check_SCRIPTS_cdep =
- check_PROGRAMS_cdep = Gtest-bt Ltest-bt Gtest-exc Ltest-exc            \
+ check_PROGRAMS_cdep +=        Gtest-bt Ltest-bt Gtest-exc Ltest-exc            \
                        Gtest-init Ltest-init                            \
                        Gtest-concurrent Ltest-concurrent                \
                        Gtest-resume-sig Ltest-resume-sig                \
                        Gtest-resume-sig-rt Ltest-resume-sig-rt          \
-                       Gtest-dyn1 Ltest-dyn1                            \
                        Gtest-trace Ltest-trace                          \
+                       Ltest-init-local-signal                          \
+                       Ltest-mem-validate                               \
                        test-async-sig test-flush-cache test-init-remote \
-                       test-mem Ltest-varargs Ltest-nomalloc    \
-                       Ltest-nocalloc Lrs-race
- noinst_PROGRAMS_cdep = forker Gperf-simple Lperf-simple \
+                       test-mem test-reg-state Ltest-varargs            \
+                       Ltest-nomalloc Ltest-nocalloc Lrs-race
+ noinst_PROGRAMS_cdep += forker Gperf-simple Lperf-simple \
                        Gperf-trace Lperf-trace
 
 if BUILD_PTRACE
@@ -96,8 +99,8 @@ check_SCRIPTS =       $(check_SCRIPTS_common) $(check_SCRIPTS_cdep) \
 TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
 XFAIL_TESTS =
 
-if !ARCH_IA64
-XFAIL_TESTS += Gtest-dyn1 Ltest-dyn1
+if ARCH_IA64
+ check_PROGRAMS_cdep += Gtest-dyn1 Ltest-dyn1
 endif
 
 # Use if arch defines but does not support PTRACE_SINGLESTEP
@@ -113,6 +116,13 @@ if ARCH_ARM
 XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP)
 endif
 
+# This is meant for multilib binaries, -m32.
+# ptrace gives EBADREG when testing,
+# but generally everything else works.
+if NO_PTRACE_TEST
+ XFAIL_TESTS += run-ptrace-mapper test-ptrace Ltest-init-local-signal
+endif
+
 noinst_PROGRAMS = $(noinst_PROGRAMS_common) $(noinst_PROGRAMS_cdep) \
        $(noinst_PROGRAMS_arch)
 
@@ -133,6 +143,8 @@ Gtest_init_SOURCES = Gtest-init.cxx
 Ltest_init_SOURCES = Ltest-init.cxx
 Ltest_cxx_exceptions_SOURCES = Ltest-cxx-exceptions.cxx
 
+Ltest_init_local_signal_SOURCES = Ltest-init-local-signal.c Ltest-init-local-signal-lib.c
+
 Gtest_dyn1_SOURCES = Gtest-dyn1.c flush-cache.S flush-cache.h
 Ltest_dyn1_SOURCES = Ltest-dyn1.c flush-cache.S flush-cache.h
 test_static_link_SOURCES = test-static-link-loc.c test-static-link-gen.c
@@ -145,6 +157,7 @@ Ltest_nomalloc_SOURCES = Ltest-nomalloc.c
 Ltest_nocalloc_SOURCES = Ltest-nocalloc.c
 Gtest_trace_SOURCES = Gtest-trace.c ident.c
 Ltest_trace_SOURCES = Ltest-trace.c ident.c
+Ltest_mem_validate_SOURCES = Ltest-mem-validate.c
 
 LIBUNWIND = $(top_builddir)/src/libunwind-$(arch).la
 LIBUNWIND_ptrace = $(top_builddir)/src/libunwind-ptrace.la
@@ -167,18 +180,20 @@ test_async_sig_LDADD = $(LIBUNWIND_local) -lpthread
 test_flush_cache_LDADD = $(LIBUNWIND_local)
 test_init_remote_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
 test_mem_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+test_reg_state_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
 test_ptrace_LDADD = $(LIBUNWIND_ptrace) $(LIBUNWIND)
 test_proc_info_LDADD = $(LIBUNWIND)
 test_static_link_LDADD = $(LIBUNWIND)
 test_strerror_LDADD = $(LIBUNWIND)
 Lrs_race_LDADD = $(LIBUNWIND_local) -lpthread
 Ltest_varargs_LDADD = $(LIBUNWIND_local)
+Ltest_init_local_signal_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
 
 Gtest_bt_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
 Gtest_concurrent_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) -lpthread
 Gtest_dyn1_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
 Gtest_exc_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
-Gtest_init_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
+Gtest_init_LDADD = $(LIBUNWIND) $(LIBUNWIND_local) @BACKTRACELIB@
 Gtest_resume_sig_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
 Gtest_resume_sig_rt_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
 Gperf_simple_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
@@ -197,12 +212,13 @@ Ltest_resume_sig_rt_LDADD = $(LIBUNWIND_local)
 Lperf_simple_LDADD = $(LIBUNWIND_local)
 Ltest_trace_LDADD = $(LIBUNWIND_local)
 Lperf_trace_LDADD = $(LIBUNWIND_local)
+Ltest_mem_validate_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
 
 test_setjmp_LDADD = $(LIBUNWIND_setjmp)
 ia64_test_setjmp_LDADD = $(LIBUNWIND_setjmp)
 
 if BUILD_COREDUMP
-test_coredump_unwind_LDADD = $(LIBUNWIND_coredump) $(LIBUNWIND)
+test_coredump_unwind_LDADD = $(LIBUNWIND_coredump) $(LIBUNWIND) @BACKTRACELIB@
 endif
 
 Gia64_test_nat_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
index 1ef74ab..6d00817 100644 (file)
@@ -88,6 +88,8 @@ filter_misc () {
 }
 
 check_local_unw_abi () {
+    match _UL${plat}_apply_reg_state
+    match _UL${plat}_reg_states_iterate
     match _UL${plat}_create_addr_space
     match _UL${plat}_destroy_addr_space
     match _UL${plat}_get_fpreg
@@ -97,12 +99,13 @@ check_local_unw_abi () {
     match _UL${plat}_get_reg
     match _UL${plat}_get_save_loc
     match _UL${plat}_init_local
+    match _UL${plat}_init_local2
     match _UL${plat}_init_remote
     match _UL${plat}_is_signal_frame
-    match _UL${plat}_handle_signal_frame
     match _UL${plat}_local_addr_space
     match _UL${plat}_resume
     match _UL${plat}_set_caching_policy
+    match _UL${plat}_set_cache_size
     match _UL${plat}_set_reg
     match _UL${plat}_set_fpreg
     match _UL${plat}_step
@@ -123,6 +126,7 @@ check_local_unw_abi () {
     case ${plat} in
        arm)
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_is_fpreg
            match _UL${plat}_search_unwind_table
            match _UL${plat}_dwarf_search_unwind_table
@@ -132,20 +136,24 @@ check_local_unw_abi () {
            match _UL${plat}_dwarf_search_unwind_table
            match _UL${plat}_dwarf_find_unwind_table
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_setcontext
            ;;
        ia64)
            match _UL${plat}_search_unwind_table
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            ;;
        x86)
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_is_fpreg
            match _UL${plat}_dwarf_search_unwind_table
            match _UL${plat}_dwarf_find_unwind_table
            ;;
        x86_64)
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_is_fpreg
            match _UL${plat}_dwarf_search_unwind_table
            match _UL${plat}_dwarf_find_unwind_table
@@ -154,6 +162,7 @@ check_local_unw_abi () {
        ppc*)
            match _U${plat}_get_func_addr
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_is_fpreg
            match _UL${plat}_dwarf_search_unwind_table
            match _UL${plat}_dwarf_find_unwind_table
@@ -164,7 +173,8 @@ check_local_unw_abi () {
            match _UL${plat}_dwarf_find_unwind_table
             match _UL${plat}_local_addr_space_init
             match _U${plat}_get_elf_image
-            match ${plat}_lock     
+           match _U${plat}_get_exe_image_path
+            match ${plat}_lock
             ;;
 
        *)
@@ -181,6 +191,8 @@ check_local_unw_abi () {
 }
 
 check_generic_unw_abi () {
+    match _U${plat}_apply_reg_state
+    match _U${plat}_reg_states_iterate
     match _U${plat}_create_addr_space
     match _U${plat}_destroy_addr_space
     match _U${plat}_flush_cache
@@ -192,13 +204,14 @@ check_generic_unw_abi () {
     match _U${plat}_get_reg
     match _U${plat}_get_save_loc
     match _U${plat}_init_local
+    match _U${plat}_init_local2
     match _U${plat}_init_remote
     match _U${plat}_is_signal_frame
-    match _U${plat}_handle_signal_frame
     match _U${plat}_local_addr_space
     match _U${plat}_regname
     match _U${plat}_resume
     match _U${plat}_set_caching_policy
+    match _U${plat}_set_cache_size
     match _U${plat}_set_fpreg
     match _U${plat}_set_reg
     match _U${plat}_step
@@ -208,6 +221,7 @@ check_generic_unw_abi () {
        arm)
            match _U${plat}_is_fpreg
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_search_unwind_table
            match _U${plat}_dwarf_search_unwind_table
            match _U${plat}_dwarf_find_unwind_table
@@ -216,12 +230,14 @@ check_generic_unw_abi () {
            match _U${plat}_dwarf_search_unwind_table
            match _U${plat}_dwarf_find_unwind_table
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            ;;
        ia64)
            match _U${plat}_search_unwind_table
            match _U${plat}_find_dyn_list
            if [ $plat = $build_plat ]; then
                match _U${plat}_get_elf_image
+               match _U${plat}_get_exe_image_path
                case $os in
                    linux*)
                        match _U${plat}_get_kernel_table
@@ -231,18 +247,21 @@ check_generic_unw_abi () {
            ;;
        x86)
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_is_fpreg
            match _U${plat}_dwarf_search_unwind_table
            match _U${plat}_dwarf_find_unwind_table
            ;;
        x86_64)
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_is_fpreg
            match _U${plat}_dwarf_search_unwind_table
            match _U${plat}_dwarf_find_unwind_table
            ;;
        ppc*)
            match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
            match _U${plat}_get_func_addr
            match _U${plat}_is_fpreg
            match _U${plat}_dwarf_search_unwind_table
@@ -252,6 +271,7 @@ check_generic_unw_abi () {
             match _U${plat}_dwarf_search_unwind_table
            match _U${plat}_dwarf_find_unwind_table
             match _U${plat}_get_elf_image
+           match _U${plat}_get_exe_image_path
             match _U${plat}_is_fpreg
             match _U${plat}_local_addr_space_init
             match ${plat}_lock
index 905f319..b47ae78 100644 (file)
@@ -39,6 +39,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
 # define MAP_ANONYMOUS MAP_ANON
 #endif
+#if !defined(MAP_NORESERVE)
+# define MAP_NORESERVE 0
+#endif
 
 int
 main (void)
@@ -52,7 +55,11 @@ main (void)
   for (n = 0; n < 30000; ++n)
     {
       if (mmap (NULL, 1, (n & 1) ? PROT_READ : PROT_WRITE,
-               MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+               MAP_PRIVATE | MAP_ANONYMOUS
+#ifdef MAP_NORESERVE
+               | MAP_NORESERVE
+#endif
+               ,
                -1, 0) == MAP_FAILED)
        {
          printf ("Failed after %ld successful maps\n", n - 1);
index 6b7f0c1..d0a315b 100755 (executable)
@@ -5,4 +5,4 @@
 # it is tested using the coredump accessors. For more info about MiniDebugInfo
 # see e.g. http://fedoraproject.org/wiki/Features/MiniDebugInfo
 
-./run-coredump-unwind -minidebuginfo
+${0%/*}/run-coredump-unwind -minidebuginfo
index 5254708..5349823 100644 (file)
@@ -137,7 +137,7 @@ static void verror_msg_helper(const char *s,
   if (flags & LOGMODE_STDIO)
     {
       fflush(stdout);
-      used += write(STDERR_FILENO, msg, used + msgeol_len);
+      write(STDERR_FILENO, msg, used + msgeol_len);
     }
   msg[used] = '\0'; /* remove msg_eol (usually "\n") */
   if (flags & LOGMODE_SYSLOG)
@@ -314,7 +314,7 @@ main(int argc UNUSED, char **argv)
   while (*argv)
     {
       char *colon;
-      long vaddr = strtol(*argv, &colon, 16);
+      unsigned long vaddr = strtoul(*argv, &colon, 16);
       if (*colon != ':')
         error_msg_and_die("Bad format: '%s'", *argv);
       if (_UCD_add_backing_file_at_vaddr(ui, vaddr, colon + 1) < 0)
index 592162c..1611cf4 100644 (file)
@@ -46,6 +46,7 @@ f257 (void)
     for (i = 0; i < n; ++i)
       printf ("[%d] ip=%p\n", i, buffer[i]);
 
+  unw_set_cache_size (unw_local_addr_space, 1023, 0);
   unw_flush_cache (unw_local_addr_space, 0, 0);
 
   if (verbose)
index a5b71dd..e7c7883 100644 (file)
@@ -182,6 +182,11 @@ main (int argc, char **argv)
 
       /* automated test case */
       argv = args;
+
+      /* Unless the args array is 'walked' the child
+         process is unable to access it and dies with a segfault */
+      fprintf(stderr, "Automated test (%s,%s,%s,%s)\n",
+              args[0],args[1],args[2],args[3]);
     }
   else if (argc > 1)
     while (argv[optind][0] == '-')
diff --git a/tests/test-reg-state.c b/tests/test-reg-state.c
new file mode 100644 (file)
index 0000000..ac713ea
--- /dev/null
@@ -0,0 +1,133 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2003-2004 Hewlett-Packard Co
+       Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Copyright (c) 2003 Hewlett-Packard Co.
+
+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 "compiler.h"
+
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/resource.h>
+
+#define panic(args...)                         \
+       { fprintf (stderr, args); exit (-1); }
+
+int verbose;
+
+struct cb_data
+{
+  unw_word_t ip;
+  void* reg_state;
+  size_t len;
+};
+
+static int
+dwarf_reg_states_callback(void *token,
+                         void *rs,
+                         size_t size,
+                         unw_word_t start_ip, unw_word_t end_ip)
+{
+  struct cb_data *data = token;
+  if (start_ip <= data->ip && data->ip < end_ip)
+    {
+      data->reg_state = mmap(NULL, size, PROT_READ | PROT_WRITE,
+                            MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      memcpy(data->reg_state, rs, size);
+      data->len = size;
+    }
+  return 0;
+}
+
+static void
+do_backtrace (void)
+{
+  unw_cursor_t cursor;
+  unw_word_t ip, sp;
+  unw_context_t uc;
+  int ret;
+
+  unw_getcontext (&uc);
+  if (unw_init_local (&cursor, &uc) < 0)
+    panic ("unw_init_local failed!\n");
+
+  do
+    {
+      unw_get_reg (&cursor, UNW_REG_IP, &ip);
+      unw_get_reg (&cursor, UNW_REG_SP, &sp);
+
+      if (verbose)
+       printf ("%016lx (sp=%016lx)\n", (long) ip, (long) sp);
+
+      struct cb_data data = {.ip = ip, .reg_state = NULL};
+      ret = unw_reg_states_iterate(&cursor, dwarf_reg_states_callback, &data);
+      if (ret > 0)
+       {
+         ret = unw_apply_reg_state (&cursor, data.reg_state);
+         munmap(data.reg_state, data.len);
+       }
+      if (ret < 0)
+       {
+         unw_get_reg (&cursor, UNW_REG_IP, &ip);
+         panic ("FAILURE: unw_step() returned %d for ip=%lx\n",
+                ret, (long) ip);
+       }
+    }
+  while (ret > 0);
+}
+
+int
+consume_some_stack_space (void)
+{
+  unw_cursor_t cursor;
+  unw_context_t uc;
+  char string[1024];
+
+  memset (&cursor, 0, sizeof (cursor));
+  memset (&uc, 0, sizeof (uc));
+  return sprintf (string, "hello %p %p\n", &cursor, &uc);
+}
+
+int
+main (int argc, char **argv UNUSED)
+{
+  struct rlimit rlim;
+
+  verbose = argc > 1;
+
+  if (consume_some_stack_space () > 9999)
+    exit (-1); /* can't happen, but don't let the compiler know... */
+
+  rlim.rlim_cur = 0;
+  rlim.rlim_max = RLIM_INFINITY;
+  setrlimit (RLIMIT_DATA, &rlim);
+
+  do_backtrace ();
+  return 0;
+}
index 3246416..d61e7a5 100644 (file)
@@ -43,6 +43,7 @@ static void *funcs[] =
     (void *) &unw_get_accessors,
     (void *) &unw_flush_cache,
     (void *) &unw_set_caching_policy,
+    (void *) &unw_set_cache_size,
     (void *) &unw_regname,
     (void *) &unw_get_proc_info,
     (void *) &unw_get_save_loc,
index 4e47e45..1c7aa03 100644 (file)
@@ -61,6 +61,7 @@ static void *funcs[] =
     (void *) &unw_get_accessors,
     (void *) &unw_flush_cache,
     (void *) &unw_set_caching_policy,
+    (void *) &unw_set_cache_size,
     (void *) &unw_regname,
     (void *) &unw_get_proc_info,
     (void *) &unw_get_save_loc,