contrib: Fixed unwind build under GCC 7. [#METR-21516]

See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81712 .
This commit is contained in:
Vladimir Chebotarev 2017-09-28 22:42:01 +03:00
parent 8f3a244d26
commit 07c964ef3b
92 changed files with 1805 additions and 636 deletions

View File

@ -45,7 +45,6 @@ src/dwarf/Lfde.c
src/dwarf/Lfind_proc_info-lsb.c src/dwarf/Lfind_proc_info-lsb.c
src/dwarf/Lparser.c src/dwarf/Lparser.c
src/dwarf/Lpe.c src/dwarf/Lpe.c
src/dwarf/Lstep.c
src/dwarf/global.c src/dwarf/global.c
src/elf64.c src/elf64.c
@ -53,9 +52,17 @@ src/os-linux.c
src/x86_64/Los-linux.c src/x86_64/Los-linux.c
) )
find_file (HAVE_ATOMIC_OPS_H "atomic_ops.h")
configure_file (config/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config/config.h)
configure_file (config/libunwind.h.in ${CMAKE_CURRENT_BINARY_DIR}/config/libunwind.h)
configure_file (config/libunwind-common.h.in ${CMAKE_CURRENT_BINARY_DIR}/config/libunwind-common.h)
configure_file (config/tdep/libunwind_i.h.in ${CMAKE_CURRENT_BINARY_DIR}/config/tdep/libunwind_i.h)
target_compile_definitions (unwind PRIVATE HAVE_CONFIG_H=1 _XOPEN_SOURCE _GNU_SOURCE) target_compile_definitions (unwind PRIVATE HAVE_CONFIG_H=1 _XOPEN_SOURCE _GNU_SOURCE)
target_compile_options (unwind PRIVATE -Wno-visibility -Wno-header-guard) target_compile_options (unwind PRIVATE -Wno-visibility -Wno-header-guard)
target_include_directories (unwind PUBLIC include) target_include_directories (unwind PUBLIC include)
target_include_directories (unwind PRIVATE include/tdep) target_include_directories (unwind PRIVATE include/tdep)
target_include_directories (unwind PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/config)
target_include_directories (unwind PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/config/tdep)
target_include_directories (unwind PRIVATE src) target_include_directories (unwind PRIVATE src)

View File

@ -1,2 +1,2 @@
Source: https://github.com/libunwind/libunwind Source: https://github.com/libunwind/libunwind
Revision: 2934cf40529e0261801a4142fabae449a65effd0 Revision: 60ddc67196eafb5cafd0d89e461c9d700a697d6d

View File

@ -17,7 +17,7 @@
/* #undef HAVE_ASM_PTRACE_OFFSETS_H */ /* #undef HAVE_ASM_PTRACE_OFFSETS_H */
/* Define to 1 if you have the <atomic_ops.h> header file. */ /* Define to 1 if you have the <atomic_ops.h> header file. */
/* #undef HAVE_ATOMIC_OPS_H */ #cmakedefine HAVE_ATOMIC_OPS_H
/* Define to 1 if you have the <byteswap.h> header file. */ /* Define to 1 if you have the <byteswap.h> header file. */
#define HAVE_BYTESWAP_H 1 #define HAVE_BYTESWAP_H 1
@ -34,6 +34,10 @@
you don't. */ you don't. */
#define HAVE_DECL_PTRACE_POKEUSER 1 #define HAVE_DECL_PTRACE_POKEUSER 1
/* Define to 1 if you have the declaration of `PTRACE_SETREGSET', and to 0 if
you don't. */
#define HAVE_DECL_PTRACE_SETREGSET 1
/* Define to 1 if you have the declaration of `PTRACE_SINGLESTEP', and to 0 if /* Define to 1 if you have the declaration of `PTRACE_SINGLESTEP', and to 0 if
you don't. */ you don't. */
#define HAVE_DECL_PTRACE_SINGLESTEP 1 #define HAVE_DECL_PTRACE_SINGLESTEP 1
@ -183,9 +187,10 @@
#define HAVE__BUILTIN___CLEAR_CACHE 1 #define HAVE__BUILTIN___CLEAR_CACHE 1
/* Define to 1 if __thread keyword is supported by the C compiler. */ /* Define to 1 if __thread keyword is supported by the C compiler. */
#define HAVE___THREAD 1 /* #undef HAVE___THREAD */
/* Define to the sub-directory where libtool stores uninstalled libraries. */ /* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/" #define LT_OBJDIR ".libs/"
/* Name of package */ /* Name of package */

View File

@ -86,6 +86,12 @@ typedef enum
} }
unw_caching_policy_t; 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; typedef int unw_regnum_t;
/* The unwind cursor starts at the youngest (most deeply nested) frame /* The unwind cursor starts at the youngest (most deeply nested) frame
@ -219,7 +225,7 @@ unw_save_loc_t;
#define unw_destroy_addr_space UNW_OBJ(destroy_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 UNW_ARCH_OBJ(get_accessors)
#define unw_init_local UNW_OBJ(init_local) #define unw_init_local UNW_OBJ(init_local)
#define unw_init_local_signal UNW_OBJ(init_local_signal) #define unw_init_local2 UNW_OBJ(init_local2)
#define unw_init_remote UNW_OBJ(init_remote) #define unw_init_remote UNW_OBJ(init_remote)
#define unw_step UNW_OBJ(step) #define unw_step UNW_OBJ(step)
#define unw_resume UNW_OBJ(resume) #define unw_resume UNW_OBJ(resume)
@ -250,7 +256,7 @@ extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
extern const char *unw_regname (unw_regnum_t); extern const char *unw_regname (unw_regnum_t);
extern int unw_init_local (unw_cursor_t *, unw_context_t *); extern int unw_init_local (unw_cursor_t *, unw_context_t *);
extern int unw_init_local_signal (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_init_remote (unw_cursor_t *, unw_addr_space_t, void *);
extern int unw_step (unw_cursor_t *); extern int unw_step (unw_cursor_t *);
extern int unw_resume (unw_cursor_t *); extern int unw_resume (unw_cursor_t *);

View File

@ -1,230 +0,0 @@
/* include/config.h.in. Generated from configure.ac by autoheader. */
/* Block signals before mutex operations */
#undef CONFIG_BLOCK_SIGNALS
/* Enable Debug Frame */
#undef CONFIG_DEBUG_FRAME
/* Support for Microsoft ABI extensions */
#undef CONFIG_MSABI_SUPPORT
/* Define to 1 if you want every memory access validated */
#undef CONSERVATIVE_CHECKS
/* Define to 1 if you have the <asm/ptrace_offsets.h> header file. */
#undef HAVE_ASM_PTRACE_OFFSETS_H
/* Define to 1 if you have the <atomic_ops.h> header file. */
#undef HAVE_ATOMIC_OPS_H
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
/* Define to 1 if you have the declaration of `PTRACE_CONT', and to 0 if you
don't. */
#undef HAVE_DECL_PTRACE_CONT
/* Define to 1 if you have the declaration of `PTRACE_POKEDATA', and to 0 if
you don't. */
#undef HAVE_DECL_PTRACE_POKEDATA
/* Define to 1 if you have the declaration of `PTRACE_POKEUSER', and to 0 if
you don't. */
#undef HAVE_DECL_PTRACE_POKEUSER
/* Define to 1 if you have the declaration of `PTRACE_SINGLESTEP', and to 0 if
you don't. */
#undef HAVE_DECL_PTRACE_SINGLESTEP
/* Define to 1 if you have the declaration of `PTRACE_SYSCALL', and to 0 if
you don't. */
#undef HAVE_DECL_PTRACE_SYSCALL
/* Define to 1 if you have the declaration of `PTRACE_TRACEME', and to 0 if
you don't. */
#undef HAVE_DECL_PTRACE_TRACEME
/* Define to 1 if you have the declaration of `PT_CONTINUE', and to 0 if you
don't. */
#undef HAVE_DECL_PT_CONTINUE
/* Define to 1 if you have the declaration of `PT_GETFPREGS', and to 0 if you
don't. */
#undef HAVE_DECL_PT_GETFPREGS
/* Define to 1 if you have the declaration of `PT_GETREGS', and to 0 if you
don't. */
#undef HAVE_DECL_PT_GETREGS
/* Define to 1 if you have the declaration of `PT_IO', and to 0 if you don't.
*/
#undef HAVE_DECL_PT_IO
/* Define to 1 if you have the declaration of `PT_STEP', and to 0 if you
don't. */
#undef HAVE_DECL_PT_STEP
/* Define to 1 if you have the declaration of `PT_SYSCALL', and to 0 if you
don't. */
#undef HAVE_DECL_PT_SYSCALL
/* Define to 1 if you have the declaration of `PT_TRACE_ME', and to 0 if you
don't. */
#undef HAVE_DECL_PT_TRACE_ME
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `dlmodinfo' function. */
#undef HAVE_DLMODINFO
/* Define to 1 if you have the `dl_iterate_phdr' function. */
#undef HAVE_DL_ITERATE_PHDR
/* Define to 1 if you have the `dl_phdr_removals_counter' function. */
#undef HAVE_DL_PHDR_REMOVALS_COUNTER
/* Define to 1 if you have the <elf.h> header file. */
#undef HAVE_ELF_H
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define to 1 if you have the <execinfo.h> header file. */
#undef HAVE_EXECINFO_H
/* Define to 1 if you have the `getunwind' function. */
#undef HAVE_GETUNWIND
/* Define to 1 if you have the <ia64intrin.h> header file. */
#undef HAVE_IA64INTRIN_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `uca' library (-luca). */
#undef HAVE_LIBUCA
/* Define to 1 if you have the <link.h> header file. */
#undef HAVE_LINK_H
/* Define if you have liblzma */
#undef HAVE_LZMA
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mincore' function. */
#undef HAVE_MINCORE
/* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if `dlpi_subs' is a member of `struct dl_phdr_info'. */
#undef HAVE_STRUCT_DL_PHDR_INFO_DLPI_SUBS
/* Define to 1 if the system has the type `struct elf_prstatus'. */
#undef HAVE_STRUCT_ELF_PRSTATUS
/* Define to 1 if the system has the type `struct prstatus'. */
#undef HAVE_STRUCT_PRSTATUS
/* Defined if __sync atomics are available */
#undef HAVE_SYNC_ATOMICS
/* Define to 1 if you have the <sys/elf.h> header file. */
#undef HAVE_SYS_ELF_H
/* Define to 1 if you have the <sys/endian.h> header file. */
#undef HAVE_SYS_ENDIAN_H
/* Define to 1 if you have the <sys/link.h> header file. */
#undef HAVE_SYS_LINK_H
/* Define to 1 if you have the <sys/procfs.h> header file. */
#undef HAVE_SYS_PROCFS_H
/* Define to 1 if you have the <sys/ptrace.h> header file. */
#undef HAVE_SYS_PTRACE_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uc_access.h> header file. */
#undef HAVE_SYS_UC_ACCESS_H
/* Define to 1 if you have the `ttrace' function. */
#undef HAVE_TTRACE
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Defined if __builtin_unreachable() is available */
#undef HAVE__BUILTIN_UNREACHABLE
/* Defined if __builtin___clear_cache() is available */
#undef HAVE__BUILTIN___CLEAR_CACHE
/* Define to 1 if __thread keyword is supported by the C compiler. */
#undef HAVE___THREAD
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `off_t', as computed by sizeof. */
#undef SIZEOF_OFF_T
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

View 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 */ #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 version;
unsigned char eh_frame_ptr_enc; unsigned char eh_frame_ptr_enc;
unsigned char fde_count_enc; unsigned char fde_count_enc;
unsigned char table_enc; unsigned char table_enc;
Elf_W (Addr) eh_frame;
/* The rest of the header is variable-length and consists of the /* The rest of the header is variable-length and consists of the
following members: following members:
encoded_t eh_frame_ptr;
encoded_t fde_count; encoded_t fde_count;
struct struct
{ {

View File

@ -37,13 +37,6 @@ struct elf_dyn_info;
# include "config.h" # include "config.h"
#endif #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 #ifndef UNW_REMOTE_ONLY
#if defined(HAVE_LINK_H) #if defined(HAVE_LINK_H)
#include <link.h> #include <link.h>

View File

@ -265,7 +265,7 @@ unw_tdep_context_t;
#ifndef __thumb__ #ifndef __thumb__
#define unw_tdep_getcontext(uc) (({ \ #define unw_tdep_getcontext(uc) (({ \
unw_tdep_context_t *unw_ctx = (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__ ( \ __asm__ __volatile__ ( \
"stmia %[base], {r0-r15}" \ "stmia %[base], {r0-r15}" \
: : [base] "r" (unw_base) : "memory"); \ : : [base] "r" (unw_base) : "memory"); \
@ -273,11 +273,12 @@ unw_tdep_context_t;
#else /* __thumb__ */ #else /* __thumb__ */
#define unw_tdep_getcontext(uc) (({ \ #define unw_tdep_getcontext(uc) (({ \
unw_tdep_context_t *unw_ctx = (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__ ( \ __asm__ __volatile__ ( \
".align 2\nbx pc\nnop\n.code 32\n" \ ".align 2\nbx pc\nnop\n.code 32\n" \
"stmia %[base], {r0-r15}\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"); \ : [base] "+r" (unw_base) : : "memory", "cc"); \
}), 0) }), 0)
#endif #endif

View File

@ -86,6 +86,12 @@ typedef enum
} }
unw_caching_policy_t; 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; typedef int unw_regnum_t;
/* The unwind cursor starts at the youngest (most deeply nested) frame /* The unwind cursor starts at the youngest (most deeply nested) frame
@ -219,7 +225,7 @@ unw_save_loc_t;
#define unw_destroy_addr_space UNW_OBJ(destroy_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 UNW_ARCH_OBJ(get_accessors)
#define unw_init_local UNW_OBJ(init_local) #define unw_init_local UNW_OBJ(init_local)
#define unw_init_local_signal UNW_OBJ(init_local_signal) #define unw_init_local2 UNW_OBJ(init_local2)
#define unw_init_remote UNW_OBJ(init_remote) #define unw_init_remote UNW_OBJ(init_remote)
#define unw_step UNW_OBJ(step) #define unw_step UNW_OBJ(step)
#define unw_resume UNW_OBJ(resume) #define unw_resume UNW_OBJ(resume)
@ -250,7 +256,7 @@ extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
extern const char *unw_regname (unw_regnum_t); extern const char *unw_regname (unw_regnum_t);
extern int unw_init_local (unw_cursor_t *, unw_context_t *); extern int unw_init_local (unw_cursor_t *, unw_context_t *);
extern int unw_init_local_signal (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_init_remote (unw_cursor_t *, unw_addr_space_t, void *);
extern int unw_step (unw_cursor_t *); extern int unw_step (unw_cursor_t *);
extern int unw_resume (unw_cursor_t *); extern int unw_resume (unw_cursor_t *);

View File

@ -37,11 +37,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "compiler.h" #include "compiler.h"
#ifdef HAVE___THREAD #if defined(HAVE___THREAD) && HAVE___THREAD
/* For now, turn off per-thread caching. It uses up too much TLS #define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_PER_THREAD
memory per thread even when the thread never uses libunwind at #else
all. */ #define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_GLOBAL
# undef HAVE___THREAD
#endif #endif
/* Platform-independent libunwind-internal declarations. */ /* Platform-independent libunwind-internal declarations. */
@ -69,6 +68,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
# include <endian.h> # include <endian.h>
#elif defined(HAVE_SYS_ENDIAN_H) #elif defined(HAVE_SYS_ENDIAN_H)
# include <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 #else
# define __LITTLE_ENDIAN 1234 # define __LITTLE_ENDIAN 1234
# define __BIG_ENDIAN 4321 # define __BIG_ENDIAN 4321

View File

@ -1 +0,0 @@
timestamp for include/config.h

View File

@ -38,6 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
typedef enum 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_STANDARD = -2, /* regular r7, sp +/- offset */
UNW_ARM_FRAME_SIGRETURN = -1, /* special sigreturn frame */ UNW_ARM_FRAME_SIGRETURN = -1, /* special sigreturn frame */
UNW_ARM_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */ UNW_ARM_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
@ -48,7 +49,7 @@ unw_tdep_frame_type_t;
typedef struct typedef struct
{ {
uint32_t virtual_address; 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 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_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 */ 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_SIGFRAME, /* non-RT signal frame, kernel >=2.6.18 */
ARM_SCF_LINUX_RT_SIGFRAME, /* 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_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; sigcontext_format;
unw_word_t sigcontext_addr; unw_word_t sigcontext_addr;

View File

@ -36,10 +36,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "mempool.h" #include "mempool.h"
#include "dwarf.h" #include "dwarf.h"
#ifdef HAVE___THREAD
# undef HAVE___THREAD
#endif
typedef struct typedef struct
{ {
/* no Tilegx-specific fast trace */ /* no Tilegx-specific fast trace */

View File

@ -5,7 +5,7 @@
#if defined __aarch64__ #if defined __aarch64__
# include "tdep-aarch64/jmpbuf.h" # include "tdep-aarch64/jmpbuf.h"
#if defined __arm__ #elif defined __arm__
# include "tdep-arm/jmpbuf.h" # include "tdep-arm/jmpbuf.h"
#elif defined __hppa__ #elif defined __hppa__
# include "tdep-hppa/jmpbuf.h" # include "tdep-hppa/jmpbuf.h"

View File

@ -0,0 +1,749 @@
SOVERSION=8:1:0 # See comments at end of file.
SETJMP_SO_VERSION=0:0:0
COREDUMP_SO_VERSION=0:0:0
#
# Don't link with start-files since we don't use any constructors/destructors:
#
COMMON_SO_LDFLAGS = $(LDFLAGS_NOSTARTFILES)
lib_LIBRARIES =
lib_LTLIBRARIES =
if !REMOTE_ONLY
lib_LTLIBRARIES += libunwind.la
if BUILD_PTRACE
lib_LTLIBRARIES += libunwind-ptrace.la
endif
if BUILD_COREDUMP
lib_LTLIBRARIES += libunwind-coredump.la
endif
endif
noinst_HEADERS =
noinst_LTLIBRARIES =
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libunwind-generic.pc
if !REMOTE_ONLY
pkgconfig_DATA += unwind/libunwind.pc
endif
if BUILD_PTRACE
pkgconfig_DATA += ptrace/libunwind-ptrace.pc
endif
if BUILD_SETJMP
pkgconfig_DATA += setjmp/libunwind-setjmp.pc
endif
if BUILD_COREDUMP
pkgconfig_DATA += coredump/libunwind-coredump.pc
endif
### libunwind-ptrace:
libunwind_ptrace_la_SOURCES = \
ptrace/_UPT_elf.c \
ptrace/_UPT_accessors.c ptrace/_UPT_access_fpreg.c \
ptrace/_UPT_access_mem.c ptrace/_UPT_access_reg.c \
ptrace/_UPT_create.c ptrace/_UPT_destroy.c \
ptrace/_UPT_find_proc_info.c ptrace/_UPT_get_dyn_info_list_addr.c \
ptrace/_UPT_put_unwind_info.c ptrace/_UPT_get_proc_name.c \
ptrace/_UPT_reg_offset.c ptrace/_UPT_resume.c
noinst_HEADERS += ptrace/_UPT_internal.h
### libunwind-coredump:
libunwind_coredump_la_SOURCES = \
coredump/_UCD_accessors.c \
coredump/_UCD_create.c \
coredump/_UCD_destroy.c \
coredump/_UCD_access_mem.c \
coredump/_UCD_elf_map_image.c \
coredump/_UCD_find_proc_info.c \
coredump/_UCD_get_proc_name.c \
\
coredump/_UPT_elf.c \
coredump/_UPT_access_fpreg.c \
coredump/_UPT_get_dyn_info_list_addr.c \
coredump/_UPT_put_unwind_info.c \
coredump/_UPT_resume.c
libunwind_coredump_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \
-version-info $(COREDUMP_SO_VERSION)
libunwind_coredump_la_LIBADD = $(LIBLZMA)
noinst_HEADERS += coredump/_UCD_internal.h coredump/_UCD_lib.h
### libunwind-setjmp:
libunwind_setjmp_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \
-version-info $(SETJMP_SO_VERSION)
if USE_ELF32
LIBUNWIND_ELF = libunwind-elf32.la
endif
if USE_ELF64
LIBUNWIND_ELF = libunwind-elf64.la
endif
if USE_ELFXX
LIBUNWIND_ELF = libunwind-elfxx.la
endif
libunwind_setjmp_la_LIBADD = $(LIBUNWIND_ELF) \
libunwind-$(arch).la \
libunwind.la -lc
libunwind_setjmp_la_SOURCES = setjmp/longjmp.c \
setjmp/siglongjmp.c
noinst_HEADERS += setjmp/setjmp_i.h
### libunwind:
libunwind_la_LIBADD =
# List of arch-independent files needed by both local-only and generic
# libraries:
libunwind_la_SOURCES_common = \
$(libunwind_la_SOURCES_os) \
mi/init.c mi/flush_cache.c mi/mempool.c mi/strerror.c
# List of arch-independent files needed by generic library (libunwind-$ARCH):
libunwind_la_SOURCES_generic = \
mi/Gdyn-extract.c mi/Gdyn-remote.c mi/Gfind_dynamic_proc_info.c \
mi/Gget_accessors.c \
mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c \
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_cache_size.c
if SUPPORT_CXX_EXCEPTIONS
libunwind_la_SOURCES_local_unwind = \
unwind/Backtrace.c unwind/DeleteException.c \
unwind/FindEnclosingFunction.c unwind/ForcedUnwind.c \
unwind/GetBSP.c unwind/GetCFA.c unwind/GetDataRelBase.c \
unwind/GetGR.c unwind/GetIP.c unwind/GetLanguageSpecificData.c \
unwind/GetRegionStart.c unwind/GetTextRelBase.c \
unwind/RaiseException.c unwind/Resume.c \
unwind/Resume_or_Rethrow.c unwind/SetGR.c unwind/SetIP.c \
unwind/GetIPInfo.c
# _ReadULEB()/_ReadSLEB() are needed for Intel C++ 8.0 compatibility
libunwind_la_SOURCES_os_linux_local = mi/_ReadULEB.c mi/_ReadSLEB.c
endif
# List of arch-independent files needed by local-only library (libunwind):
libunwind_la_SOURCES_local_nounwind = \
$(libunwind_la_SOURCES_os_local) \
mi/backtrace.c \
mi/dyn-cancel.c mi/dyn-info-list.c mi/dyn-register.c \
mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c \
mi/Lget_accessors.c \
mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c \
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_cache_size.c
libunwind_la_SOURCES_local = \
$(libunwind_la_SOURCES_local_nounwind) \
$(libunwind_la_SOURCES_local_unwind)
noinst_HEADERS += os-linux.h
libunwind_la_SOURCES_os_linux = os-linux.c
libunwind_la_SOURCES_os_hpux = os-hpux.c
libunwind_la_SOURCES_os_freebsd = os-freebsd.c
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/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/Gfind_proc_info-lsb.c \
dwarf/Gfind_unwind_table.c
libunwind_dwarf_generic_la_LIBADD = libunwind-dwarf-common.la
if USE_DWARF
noinst_LTLIBRARIES += libunwind-dwarf-common.la libunwind-dwarf-generic.la
if !REMOTE_ONLY
noinst_LTLIBRARIES += libunwind-dwarf-local.la
endif
libunwind_la_LIBADD += libunwind-dwarf-local.la
endif
noinst_HEADERS += elf32.h elf64.h elfxx.h
libunwind_elf32_la_SOURCES = elf32.c
libunwind_elf64_la_SOURCES = elf64.c
libunwind_elfxx_la_SOURCES = elfxx.c
libunwind_elf32_la_LIBADD = $(LIBLZMA)
libunwind_elf64_la_LIBADD = $(LIBLZMA)
libunwind_elfxx_la_LIBADD = $(LIBLZMA)
noinst_LTLIBRARIES += $(LIBUNWIND_ELF)
libunwind_la_LIBADD += $(LIBUNWIND_ELF)
# The list of files that go into libunwind and libunwind-aarch64:
noinst_HEADERS += aarch64/init.h aarch64/offsets.h aarch64/unwind_i.h
libunwind_la_SOURCES_aarch64_common = $(libunwind_la_SOURCES_common) \
aarch64/is_fpreg.c aarch64/regname.c
# 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 \
aarch64/Lis_signal_frame.c aarch64/Lregs.c aarch64/Lresume.c \
aarch64/Lstash_frame.c aarch64/Lstep.c aarch64/Ltrace.c \
aarch64/getcontext.S
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 \
aarch64/Gis_signal_frame.c aarch64/Gregs.c aarch64/Gresume.c \
aarch64/Gstash_frame.c aarch64/Gstep.c aarch64/Gtrace.c
# The list of files that go into libunwind and libunwind-arm:
noinst_HEADERS += arm/init.h arm/offsets.h arm/unwind_i.h
libunwind_la_SOURCES_arm_common = $(libunwind_la_SOURCES_common) \
arm/is_fpreg.c arm/regname.c
# The list of files that go into libunwind:
libunwind_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common) \
$(libunwind_la_SOURCES_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/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/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:
noinst_HEADERS += ia64/init.h ia64/offsets.h ia64/regs.h \
ia64/ucontext_i.h ia64/unwind_decoder.h ia64/unwind_i.h
libunwind_la_SOURCES_ia64_common = $(libunwind_la_SOURCES_common) \
ia64/regname.c
# The list of files that go into libunwind:
libunwind_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common) \
$(libunwind_la_SOURCES_local) \
\
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 \
ia64/Lrbs.c ia64/Lregs.c ia64/Lresume.c ia64/Lscript.c ia64/Lstep.c \
ia64/Ltables.c ia64/Lfind_unwind_table.c
# 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 \
ia64/Grbs.c ia64/Gregs.c ia64/Gresume.c ia64/Gscript.c ia64/Gstep.c \
ia64/Gtables.c ia64/Gfind_unwind_table.c
# The list of files that go both into libunwind and libunwind-hppa:
noinst_HEADERS += hppa/init.h hppa/offsets.h hppa/unwind_i.h
libunwind_la_SOURCES_hppa_common = $(libunwind_la_SOURCES_common) \
hppa/regname.c
# The list of files that go into libunwind:
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 \
hppa/Lresume.c hppa/Lstep.c
# 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 mips/unwind_i.h
libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common) \
mips/is_fpreg.c mips/regname.c
# The list of files that go into libunwind:
libunwind_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common) \
$(libunwind_la_SOURCES_local) \
mips/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 tilegx/unwind_i.h
libunwind_la_SOURCES_tilegx_common = $(libunwind_la_SOURCES_common) \
tilegx/is_fpreg.c tilegx/regname.c
# The list of files that go into libunwind:
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
# The list of files that go both into libunwind and libunwind-x86:
noinst_HEADERS += x86/init.h x86/offsets.h x86/unwind_i.h
libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \
x86/is_fpreg.c x86/regname.c
# The list of files that go into libunwind:
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 \
x86/Lresume.c x86/Lstep.c
# The list of files that go into libunwind-x86:
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 \
x86/Gresume.c x86/Gstep.c
# The list of files that go both into libunwind and libunwind-x86_64:
noinst_HEADERS += x86_64/offsets.h \
x86_64/init.h x86_64/unwind_i.h x86_64/ucontext_i.h
libunwind_la_SOURCES_x86_64_common = $(libunwind_la_SOURCES_common) \
x86_64/is_fpreg.c x86_64/regname.c
# The list of files that go into libunwind:
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 \
x86_64/Lstash_frame.c x86_64/Lstep.c x86_64/Ltrace.c x86_64/getcontext.S
# The list of files that go into libunwind-x86_64:
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 \
x86_64/Gstash_frame.c x86_64/Gstep.c x86_64/Gtrace.c
# The list of local files that go to Power 64 and 32:
libunwind_la_SOURCES_ppc = \
ppc/Lget_proc_info.c ppc/Lget_save_loc.c ppc/Linit_local.c \
ppc/Linit_remote.c ppc/Lis_signal_frame.c
# The list of generic files that go to Power 64 and 32:
libunwind_ppc_la_SOURCES_ppc_generic = \
ppc/Gget_proc_info.c ppc/Gget_save_loc.c ppc/Ginit_local.c \
ppc/Ginit_remote.c ppc/Gis_signal_frame.c
# The list of files that go both into libunwind and libunwind-ppc32:
noinst_HEADERS += ppc32/init.h ppc32/unwind_i.h ppc32/ucontext_i.h
libunwind_la_SOURCES_ppc32_common = $(libunwind_la_SOURCES_common) \
ppc32/is_fpreg.c ppc32/regname.c ppc32/get_func_addr.c
# The list of files that go into libunwind:
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
# The list of files that go into libunwind-ppc32:
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
# The list of files that go both into libunwind and libunwind-ppc64:
noinst_HEADERS += ppc64/init.h ppc64/unwind_i.h ppc64/ucontext_i.h
libunwind_la_SOURCES_ppc64_common = $(libunwind_la_SOURCES_common) \
ppc64/is_fpreg.c ppc64/regname.c ppc64/get_func_addr.c
# The list of files that go into libunwind:
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
# The list of files that go into libunwind-ppc64:
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
# The list of files that go into libunwind and libunwind-sh:
noinst_HEADERS += sh/init.h sh/offsets.h sh/unwind_i.h
libunwind_la_SOURCES_sh_common = $(libunwind_la_SOURCES_common) \
sh/is_fpreg.c sh/regname.c
# 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
if REMOTE_ONLY
install-exec-hook:
# Nothing to do here....
else
#
# This is not ideal, but I know of no other way to install an
# alias for a library. For the shared version, we have to do
# a file check before creating the link, because it isn't going
# to be there if the user configured with --disable-shared.
#
install-exec-hook:
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; \
fi
endif
if OS_LINUX
libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux)
libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local)
libunwind_la_SOURCES_x86_os = x86/Gos-linux.c
libunwind_x86_la_SOURCES_os = x86/getcontext-linux.S
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_coredump_la_SOURCES += coredump/_UCD_access_reg_linux.c
endif
if OS_HPUX
libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_hpux)
libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_hpux_local)
endif
if OS_FREEBSD
libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd)
libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local)
libunwind_la_SOURCES_x86_os = x86/Gos-freebsd.c
libunwind_x86_la_SOURCES_os = x86/getcontext-freebsd.S
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
lib_LTLIBRARIES += libunwind-aarch64.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_aarch64)
libunwind_aarch64_la_SOURCES = $(libunwind_aarch64_la_SOURCES_aarch64)
libunwind_aarch64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_aarch64_la_LIBADD = libunwind-dwarf-generic.la
libunwind_aarch64_la_LIBADD += libunwind-elf64.la
if !REMOTE_ONLY
libunwind_aarch64_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += aarch64/siglongjmp.S
else
if ARCH_ARM
lib_LTLIBRARIES += libunwind-arm.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_arm)
libunwind_arm_la_SOURCES = $(libunwind_arm_la_SOURCES_arm)
libunwind_arm_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_arm_la_LIBADD = libunwind-dwarf-generic.la
libunwind_arm_la_LIBADD += libunwind-elf32.la
if !REMOTE_ONLY
libunwind_arm_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += arm/siglongjmp.S
else
if ARCH_IA64
BUILT_SOURCES = Gcursor_i.h Lcursor_i.h
mk_Gcursor_i.s: $(srcdir)/ia64/mk_Gcursor_i.c
$(COMPILE) -S "$(srcdir)/ia64/mk_Gcursor_i.c" -o mk_Gcursor_i.s
mk_Lcursor_i.s: $(srcdir)/ia64/mk_Lcursor_i.c
$(COMPILE) -S "$(srcdir)/ia64/mk_Lcursor_i.c" -o mk_Lcursor_i.s
Gcursor_i.h: mk_Gcursor_i.s
"$(srcdir)/ia64/mk_cursor_i" mk_Gcursor_i.s > Gcursor_i.h
Lcursor_i.h: mk_Lcursor_i.s
"$(srcdir)/ia64/mk_cursor_i" mk_Lcursor_i.s > Lcursor_i.h
lib_LTLIBRARIES += libunwind-ia64.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_ia64)
libunwind_ia64_la_SOURCES = $(libunwind_ia64_la_SOURCES_ia64)
libunwind_ia64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_ia64_la_LIBADD = libunwind-elf64.la
if !REMOTE_ONLY
libunwind_ia64_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += ia64/setjmp.S ia64/sigsetjmp.S \
ia64/longjmp.S ia64/siglongjmp.S
else
if ARCH_HPPA
lib_LTLIBRARIES += libunwind-hppa.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_hppa)
libunwind_hppa_la_SOURCES = $(libunwind_hppa_la_SOURCES_hppa)
libunwind_hppa_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_hppa_la_LIBADD = libunwind-dwarf-generic.la
libunwind_hppa_la_LIBADD += libunwind-elf32.la
if !REMOTE_ONLY
libunwind_hppa_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += hppa/siglongjmp.S
else
if ARCH_MIPS
lib_LTLIBRARIES += libunwind-mips.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_mips)
libunwind_mips_la_SOURCES = $(libunwind_mips_la_SOURCES_mips)
libunwind_mips_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_mips_la_LIBADD = libunwind-dwarf-generic.la
libunwind_mips_la_LIBADD += libunwind-elfxx.la
if !REMOTE_ONLY
libunwind_mips_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += mips/siglongjmp.S
else
if ARCH_TILEGX
lib_LTLIBRARIES += libunwind-tilegx.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_tilegx)
libunwind_tilegx_la_SOURCES = $(libunwind_tilegx_la_SOURCES_tilegx)
libunwind_tilegx_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_tilegx_la_LIBADD = libunwind-dwarf-generic.la
libunwind_tilegx_la_LIBADD += libunwind-elfxx.la
if !REMOTE_ONLY
libunwind_tilegx_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += tilegx/siglongjmp.S
else
if ARCH_X86
lib_LTLIBRARIES += libunwind-x86.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86) $(libunwind_x86_la_SOURCES_os)
libunwind_x86_la_SOURCES = $(libunwind_x86_la_SOURCES_x86)
libunwind_x86_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_x86_la_LIBADD = libunwind-dwarf-generic.la
libunwind_x86_la_LIBADD += libunwind-elf32.la
if !REMOTE_ONLY
libunwind_x86_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += x86/longjmp.S x86/siglongjmp.S
else
if ARCH_X86_64
lib_LTLIBRARIES += libunwind-x86_64.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86_64)
libunwind_x86_64_la_SOURCES = $(libunwind_x86_64_la_SOURCES_x86_64)
libunwind_x86_64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_x86_64_la_LIBADD = libunwind-dwarf-generic.la
libunwind_x86_64_la_LIBADD += libunwind-elf64.la
if !REMOTE_ONLY
libunwind_x86_64_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += x86_64/longjmp.S x86_64/siglongjmp.S
else
if ARCH_PPC32
lib_LTLIBRARIES += libunwind-ppc32.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_ppc32)
libunwind_ppc32_la_SOURCES = $(libunwind_ppc32_la_SOURCES_ppc32)
libunwind_ppc32_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_ppc32_la_LIBADD = libunwind-dwarf-generic.la
libunwind_ppc32_la_LIBADD += libunwind-elf32.la
if !REMOTE_ONLY
libunwind_ppc32_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += ppc/longjmp.S ppc/siglongjmp.S
else
if ARCH_PPC64
lib_LTLIBRARIES += libunwind-ppc64.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_ppc64)
libunwind_ppc64_la_SOURCES = $(libunwind_ppc64_la_SOURCES_ppc64)
libunwind_ppc64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_ppc64_la_LIBADD = libunwind-dwarf-generic.la
libunwind_ppc64_la_LIBADD += libunwind-elf64.la
if !REMOTE_ONLY
libunwind_ppc64_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += ppc/longjmp.S ppc/siglongjmp.S
else
if ARCH_SH
lib_LTLIBRARIES += libunwind-sh.la
libunwind_la_SOURCES = $(libunwind_la_SOURCES_sh)
libunwind_sh_la_SOURCES = $(libunwind_sh_la_SOURCES_sh)
libunwind_sh_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION)
libunwind_sh_la_LIBADD = libunwind-dwarf-generic.la
libunwind_sh_la_LIBADD += libunwind-elf32.la
if !REMOTE_ONLY
libunwind_sh_la_LIBADD += libunwind.la -lc
endif
libunwind_setjmp_la_SOURCES += sh/siglongjmp.S
endif # ARCH_SH
endif # ARCH_PPC64
endif # ARCH_PPC32
endif # ARCH_X86_64
endif # ARCH_X86
endif # ARCH_TILEGX
endif # ARCH_MIPS
endif # ARCH_HPPA
endif # ARCH_IA64
endif # ARCH_ARM
endif # ARCH_AARCH64
# libunwind-setjmp depends on libunwind-$(arch). Therefore must be added
# at the end.
if BUILD_SETJMP
lib_LTLIBRARIES += libunwind-setjmp.la
endif
#
# Don't link with standard libraries, because those may mention
# libunwind already.
#
libunwind_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -XCClinker -nostdlib \
$(LDFLAGS_STATIC_LIBCXA) -version-info $(SOVERSION)
libunwind_la_LIBADD += -lc $(LIBCRTS)
libunwind_la_LIBADD += $(LIBLZMA)
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/tdep-$(arch) -I.
AM_CCASFLAGS = $(AM_CPPFLAGS)
noinst_HEADERS += unwind/unwind-internal.h
EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \
$(libunwind_la_SOURCES_arm) \
$(libunwind_la_SOURCES_hppa) \
$(libunwind_la_SOURCES_ia64) \
$(libunwind_la_SOURCES_mips) \
$(libunwind_la_SOURCES_sh) \
$(libunwind_la_SOURCES_x86) \
$(libunwind_la_SOURCES_os_freebsd) \
$(libunwind_la_SOURCES_os_linux) \
$(libunwind_la_SOURCES_os_hpux) \
$(libunwind_la_SOURCES_os_qnx) \
$(libunwind_la_SOURCES_common) \
$(libunwind_la_SOURCES_local) \
$(libunwind_la_SOURCES_generic) \
$(libunwind_aarch64_la_SOURCES_aarch64) \
$(libunwind_arm_la_SOURCES_arm) \
$(libunwind_hppa_la_SOURCES_hppa) \
$(libunwind_ia64_la_SOURCES_ia64) \
$(libunwind_mips_la_SOURCES_mips) \
$(libunwind_sh_la_SOURCES_sh) \
$(libunwind_x86_la_SOURCES_x86) \
$(libunwind_x86_64_la_SOURCES_x86_64)
MAINTAINERCLEANFILES = Makefile.in
# The -version-info flag accepts an argument of the form
# `current[:revision[:age]]'. So, passing `-version-info 3:12:1' sets
# current to 3, revision to 12, and age to 1.
# If either revision or age are omitted, they default to 0. Also note
# that age must be less than or equal to the current interface number.
# Here are a set of rules to help you update your library version
# information:
# 1. Start with version information of `0:0:0' for each libtool
# library.
# 2. Update the version information only immediately before a public
# release of your software. More frequent updates are unnecessary,
# and only guarantee that the current interface number gets larger
# faster.
# 3. If the library source code has changed at all since the last
# update, then increment revision (`c:r:a' becomes `c:r+1:a').
# 4. If any interfaces have been added, removed, or changed since the
# last update, increment current, and set revision to 0.
# 5. If any interfaces have been added since the last public release,
# then increment age.
# 6. If any interfaces have been removed since the last public
# release, then set age to 0.

View File

@ -43,8 +43,10 @@ PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space;
static inline void * static inline void *
uc_addr (ucontext_t *uc, int reg) 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]; 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 else
return NULL; return NULL;
} }
@ -172,7 +174,7 @@ HIDDEN void
aarch64_local_addr_space_init (void) aarch64_local_addr_space_init (void)
{ {
memset (&local_addr_space, 0, sizeof (local_addr_space)); 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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -59,9 +59,20 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal (unw_cursor_t *cursor, unw_context_t *uc) unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -55,6 +55,9 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
loc = c->dwarf.loc[reg]; loc = c->dwarf.loc[reg];
break; break;
case UNW_AARCH64_X30:
if (write)
c->dwarf.ip = *valp; /* update the IP cache */
case UNW_AARCH64_X4: case UNW_AARCH64_X4:
case UNW_AARCH64_X5: case UNW_AARCH64_X5:
case UNW_AARCH64_X6: 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_X27:
case UNW_AARCH64_X28: case UNW_AARCH64_X28:
case UNW_AARCH64_X29: case UNW_AARCH64_X29:
case UNW_AARCH64_X30:
case UNW_AARCH64_PC: case UNW_AARCH64_PC:
case UNW_AARCH64_PSTATE: case UNW_AARCH64_PSTATE:
loc = c->dwarf.loc[reg]; 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, tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
int write) int write)
{ {
Debug (1, "bad register number %u\n", reg); dwarf_loc_t loc = c->dwarf.loc[reg];
return -UNW_EBADREG; if (write)
return dwarf_putfp (&c->dwarf, loc, *valp);
else
return dwarf_getfp (&c->dwarf, loc, valp);
} }

View 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 /* Since there are no signals involved here we restore EH and non scratch
registers only. */ registers only. */
unsigned long regs[15]; unsigned long regs[24];
regs[0] = uc->uc_mcontext.regs[0]; regs[0] = uc->uc_mcontext.regs[0];
regs[1] = uc->uc_mcontext.regs[1]; regs[1] = uc->uc_mcontext.regs[1];
regs[2] = uc->uc_mcontext.regs[2]; 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[11] = uc->uc_mcontext.regs[26];
regs[12] = uc->uc_mcontext.regs[27]; regs[12] = uc->uc_mcontext.regs[27];
regs[13] = uc->uc_mcontext.regs[28]; 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; unsigned long sp = uc->uc_mcontext.sp;
struct regs_overlay { 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 x23, x24, [x4,64]\n"
"ldp x25, x26, [x4,80]\n" "ldp x25, x26, [x4,80]\n"
"ldp x27, x28, [x4,96]\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" "mov sp, x5\n"
"ret \n" "ret \n"
: :
@ -147,7 +160,7 @@ establish_machine_state (struct cursor *c)
Debug (8, "copying out cursor state\n"); 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); Debug (16, "copying %s %d\n", unw_regname (reg), reg);
if (unw_is_fpreg (reg)) if (unw_is_fpreg (reg))

View File

@ -27,6 +27,30 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h" #include "unwind_i.h"
#include "offsets.h" #include "offsets.h"
/* 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 (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;
}
PROTECTED int PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor) unw_handle_signal_frame (unw_cursor_t *cursor)
{ {
@ -101,6 +125,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor)
dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);
c->dwarf.pi_valid = 0; c->dwarf.pi_valid = 0;
c->dwarf.use_prev_instr = 0;
return 1; return 1;
} }
@ -125,7 +150,40 @@ unw_step (unw_cursor_t *cursor)
return ret; return ret;
if (unlikely (ret < 0)) 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; return (c->dwarf.ip == 0) ? 0 : 1;
} }

View File

@ -59,4 +59,6 @@ extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
} while (0) } while (0)
#endif #endif
#define GET_FPCTX(uc) ((struct fpsimd_context *)(&uc->uc_mcontext.__reserved))
#endif /* unwind_i_h */ #endif /* unwind_i_h */

View File

@ -126,6 +126,11 @@ static int
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
void *arg) void *arg)
{ {
/* validate address */
const struct cursor *c = (const struct cursor *) arg;
if (c && validate_mem(addr))
return -1;
if (write) if (write)
{ {
Debug (16, "mem[%x] <- %x\n", addr, *val); 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 else
{ {
/* validate address */
const struct cursor *c = (const struct cursor *) arg;
if (c && validate_mem(addr))
return -1;
*val = *(unw_word_t *) addr; *val = *(unw_word_t *) addr;
Debug (16, "mem[%x] -> %x\n", addr, *val); Debug (16, "mem[%x] -> %x\n", addr, *val);
} }
@ -220,7 +220,7 @@ HIDDEN void
arm_local_addr_space_init (void) arm_local_addr_space_init (void)
{ {
memset (&local_addr_space, 0, sizeof (local_addr_space)); 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.find_proc_info = arm_find_proc_info;
local_addr_space.acc.put_unwind_info = arm_put_unwind_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; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -59,9 +59,20 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal (unw_cursor_t *cursor, unw_context_t *uc) unw_init_local2 (unw_cursor_t *cursor, unw_context_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -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
}

View File

@ -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"
PROTECTED int
unw_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. */
PROTECTED 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 (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;
}

View File

@ -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"
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;
}
#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. */
PROTECTED 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 (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;
}

View File

@ -1,8 +1,7 @@
/* libunwind - a platform-independent unwind library /* libunwind - a platform-independent unwind library
Copyright (C) 2006-2007 IBM Copyright (C) 2008 CodeSourcery
Contributed by Copyright 2011 Linaro Limited
Corey Ashford <cjashfor@us.ibm.com> Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
This file is part of libunwind. This file is part of libunwind.
@ -25,30 +24,25 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <stdlib.h> #include <stdio.h>
#include <signal.h>
#include "unwind_i.h"
#include "offsets.h"
#include <libunwind_i.h> PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
PROTECTED unw_addr_space_t
unw_create_addr_space (unw_accessors_t *a, int byte_order)
{ {
#ifdef UNW_LOCAL_ONLY return -UNW_EUNSPEC;
return NULL; }
PROTECTED int
unw_is_signal_frame (unw_cursor_t *cursor)
{
#if defined(__QNX__)
/* Not supported yet */
return 0;
#else #else
unw_addr_space_t as = malloc (sizeof (*as)); printf ("%s: implement me\n", __FUNCTION__);
return -UNW_ENOINFO;
if (!as)
return NULL;
memset (as, 0, sizeof (*as));
as->acc = *a;
/*
* Linux ppc64 supports only big-endian.
*/
if (byte_order != 0 && byte_order != __BIG_ENDIAN)
return NULL;
return as;
#endif #endif
} }

View File

@ -32,6 +32,9 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
switch (reg) switch (reg)
{ {
case UNW_ARM_R15:
if (write)
c->dwarf.ip = *valp; /* update the IP cache */
case UNW_ARM_R0: case UNW_ARM_R0:
case UNW_ARM_R1: case UNW_ARM_R1:
case UNW_ARM_R2: 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_R11:
case UNW_ARM_R12: case UNW_ARM_R12:
case UNW_ARM_R14: case UNW_ARM_R14:
case UNW_ARM_R15:
loc = c->dwarf.loc[reg - UNW_ARM_R0]; loc = c->dwarf.loc[reg - UNW_ARM_R0];
break; break;

View File

@ -45,8 +45,14 @@ arm_exidx_step (struct cursor *c)
/* mark PC unsaved */ /* mark PC unsaved */
c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC; c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC;
if ((ret = tdep_find_proc_info (&c->dwarf, c->dwarf.ip, 1)) < 0) /* check dynamic info first --- it overrides everything else */
return ret; ret = unwi_find_dynamic_proc_info (c->dwarf.as, c->dwarf.ip, &c->dwarf.pi, 1,
c->dwarf.as_arg);
if (ret == -UNW_ENOINFO)
{
if ((ret = tdep_find_proc_info (&c->dwarf, c->dwarf.ip, 1)) < 0)
return ret;
}
if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX) if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX)
return -UNW_ENOINFO; return -UNW_ENOINFO;
@ -73,99 +79,6 @@ arm_exidx_step (struct cursor *c)
return (c->dwarf.ip == 0) ? 0 : 1; 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 PROTECTED int
unw_step (unw_cursor_t *cursor) unw_step (unw_cursor_t *cursor)
{ {
@ -210,14 +123,18 @@ unw_step (unw_cursor_t *cursor)
/* Fall back on APCS frame parsing. /* Fall back on APCS frame parsing.
Note: This won't work in case the ARM EABI is used. */ Note: This won't work in case the ARM EABI is used. */
#ifdef __FreeBSD__
if (0)
#else
if (unlikely (ret < 0)) if (unlikely (ret < 0))
#endif
{ {
if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME)) if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME))
{ {
Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
ret = UNW_ESUCCESS; ret = UNW_ESUCCESS;
/* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */ /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */
unw_word_t instr, i; unw_word_t instr, i;
Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
dwarf_loc_t ip_loc, fp_loc; dwarf_loc_t ip_loc, fp_loc;
unw_word_t frame; unw_word_t frame;
/* Mark all registers unsaved, since we don't know where /* Mark all registers unsaved, since we don't know where
@ -260,7 +177,7 @@ unw_step (unw_cursor_t *cursor)
c->dwarf.loc[UNW_ARM_R12] = ip_loc; c->dwarf.loc[UNW_ARM_R12] = ip_loc;
c->dwarf.loc[UNW_ARM_R11] = fp_loc; c->dwarf.loc[UNW_ARM_R11] = fp_loc;
c->dwarf.pi_valid = 0; c->dwarf.pi_valid = 0;
Debug(15, "ip=%lx\n", c->dwarf.ip); Debug(15, "ip=%x\n", c->dwarf.ip);
} }
else else
{ {
@ -268,5 +185,5 @@ unw_step (unw_cursor_t *cursor)
} }
} }
} }
return ret == -UNW_ENOINFO ? 0 : 1; return ret == -UNW_ENOINFO ? 0 : ret;
} }

View File

@ -503,7 +503,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
case UNW_ARM_FRAME_SIGRETURN: case UNW_ARM_FRAME_SIGRETURN:
cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */ 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); ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc);
if (likely(ret >= 0)) if (likely(ret >= 0))
ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_R7_OFF, r7); 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. */ doesn't save the link register in the prologue, e.g. kill. */
if (likely(ret >= 0)) if (likely(ret >= 0))
ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_LR_OFF, lr); 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 /* Resume stack at signal restoration point. The stack is not
necessarily continuous here, especially with sigaltstack(). */ 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; d->use_prev_instr = 0;
break; break;
case UNW_ARM_FRAME_SYSCALL:
printf("XXX1\n");
break;
default: default:
/* We cannot trace through this frame, give up and tell the /* We cannot trace through this frame, give up and tell the
caller we had to stop. Data collected so far may still be caller we had to stop. Data collected so far may still be

View File

@ -1,5 +1,5 @@
#define UNW_LOCAL_ONLY #define UNW_LOCAL_ONLY
#include <libunwind.h> #include <libunwind.h>
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
#include "Gis_signal_frame.c" #include "Gos-freebsd.c"
#endif #endif

View File

@ -1,5 +1,5 @@
#define UNW_LOCAL_ONLY #define UNW_LOCAL_ONLY
#include <libunwind.h> #include <libunwind.h>
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
#include "Gstep.c" #include "Gos-linux.c"
#endif #endif

View File

@ -1,5 +1,5 @@
#define UNW_LOCAL_ONLY #define UNW_LOCAL_ONLY
#include <libunwind.h> #include <libunwind.h>
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
#include "Gcreate_addr_space.c" #include "Gos-freebsd.c"
#endif #endif

View File

@ -35,8 +35,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
_Uarm_getcontext: _Uarm_getcontext:
stmfd sp!, {r0, r1} stmfd sp!, {r0, r1}
@ store r0 @ store r0
#if defined(__linux__)
str r0, [r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF] str r0, [r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF]
add 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 @ store r1 to r12
stmib r0, {r1-r12} stmib r0, {r1-r12}
@ reconstruct r13 at call site, then store @ reconstruct r13 at call site, then store
@ -50,7 +57,7 @@ _Uarm_getcontext:
str r1, [r0, #15 * 4] str r1, [r0, #15 * 4]
ldmfd sp!, {r0, r1} ldmfd sp!, {r0, r1}
bx lr bx lr
#ifdef __linux__ #if defined(__linux__) || defined(__FreeBSD__)
/* We do not need executable stack. */ /* We do not need executable stack. */
.section .note.GNU-stack,"",%progbits .section .note.GNU-stack,"",%progbits
#endif #endif

View File

@ -34,3 +34,9 @@
#define LINUX_SC_PC_OFF 0x48 #define LINUX_SC_PC_OFF 0x48
#define LINUX_SC_CPSR_OFF 0x4C #define LINUX_SC_CPSR_OFF 0x4C
#define LINUX_SC_FAULTADDR_OFF 0x50 #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

View File

@ -76,7 +76,7 @@ _UCD_access_reg (unw_addr_space_t as,
default: default:
Debug(0, "bad regnum:%d\n", regnum); Debug(0, "bad regnum:%d\n", regnum);
return -UNW_EINVAL; return -UNW_EINVAL;
}; }
#elif defined(UNW_TARGET_X86_64) #elif defined(UNW_TARGET_X86_64)
switch (regnum) { switch (regnum) {
case UNW_X86_64_RAX: case UNW_X86_64_RAX:
@ -109,7 +109,26 @@ _UCD_access_reg (unw_addr_space_t as,
default: default:
Debug(0, "bad regnum:%d\n", regnum); Debug(0, "bad regnum:%d\n", regnum);
return -UNW_EINVAL; 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 #else
#error Port me #error Port me
#endif #endif

View File

@ -44,7 +44,9 @@ _UCD_destroy (struct UCD_info *ui)
close(phdr->backing_fd); close(phdr->backing_fd);
} }
free(ui->phdrs);
free(ui->note_phdr); free(ui->note_phdr);
free(ui->threads);
free(ui); free(ui);
} }

View File

@ -1,11 +0,0 @@
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libunwind-coredump
Description: libunwind coredump library
Version: 1.2
Requires: libunwind-generic libunwind
Libs: -L${libdir} -lunwind-coredump
Cflags: -I${includedir}

View File

@ -32,7 +32,7 @@ is_cie_id (unw_word_t val, int is_debug_frame)
0xffffffffffffffff (for 64-bit ELF). However, .eh_frame 0xffffffffffffffff (for 64-bit ELF). However, .eh_frame
uses 0. */ uses 0. */
if (is_debug_frame) if (is_debug_frame)
return (val == - (uint32_t) 1 || val == - (uint64_t) 1); return (val == (uint32_t)(-1) || val == (uint64_t)(-1));
else else
return (val == 0); return (val == 0);
} }

View File

@ -199,7 +199,7 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
name = (char*) dlname; name = (char*) dlname;
err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space); err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
if (!err) if (!err)
{ {
fdesc = malloc (sizeof (struct unw_debug_frame_list)); fdesc = malloc (sizeof (struct unw_debug_frame_list));
@ -210,10 +210,10 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
fdesc->debug_frame_size = bufsize; fdesc->debug_frame_size = bufsize;
fdesc->index = NULL; fdesc->index = NULL;
fdesc->next = as->debug_frames; fdesc->next = as->debug_frames;
as->debug_frames = fdesc; as->debug_frames = fdesc;
} }
return fdesc; return fdesc;
} }
@ -235,10 +235,10 @@ debug_frame_tab_append (struct debug_frame_tab *tab,
tab->size *= 2; tab->size *= 2;
tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size); tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size);
} }
tab->tab[length].fde_offset = fde_offset; tab->tab[length].fde_offset = fde_offset;
tab->tab[length].start_ip_offset = start_ip; tab->tab[length].start_ip_offset = start_ip;
tab->length = length + 1; tab->length = length + 1;
} }
@ -256,7 +256,7 @@ static int
debug_frame_tab_compare (const void *a, const void *b) debug_frame_tab_compare (const void *a, const void *b)
{ {
const struct table_entry *fa = a, *fb = b; const struct table_entry *fa = a, *fb = b;
if (fa->start_ip_offset > fb->start_ip_offset) if (fa->start_ip_offset > fb->start_ip_offset)
return 1; return 1;
else if (fa->start_ip_offset < fb->start_ip_offset) else if (fa->start_ip_offset < fb->start_ip_offset)
@ -522,7 +522,7 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
else if (phdr->p_type == PT_DYNAMIC) else if (phdr->p_type == PT_DYNAMIC)
p_dynamic = phdr; p_dynamic = phdr;
} }
if (!p_text) if (!p_text)
return 0; return 0;
@ -537,14 +537,14 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
eh_frame = dwarf_find_eh_frame_section (info); eh_frame = dwarf_find_eh_frame_section (info);
if (eh_frame) if (eh_frame)
{ {
unsigned char *p = (unsigned char *) &synth_eh_frame_hdr;
Debug (1, "using synthetic .eh_frame_hdr section for %s\n", Debug (1, "using synthetic .eh_frame_hdr section for %s\n",
info->dlpi_name); info->dlpi_name);
/* synth_eh_frame_hdr.version */ p[0] = DW_EH_VERSION; synth_eh_frame_hdr.version = DW_EH_VERSION;
/* synth_eh_frame_hdr.eh_frame_ptr_enc */ p[1] = DW_EH_PE_absptr | ((sizeof(Elf_W (Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); synth_eh_frame_hdr.eh_frame_ptr_enc = DW_EH_PE_absptr |
/* synth_eh_frame_hdr.fde_count_enc */ p[2] = DW_EH_PE_omit; ((sizeof(Elf_W (Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8);
/* synth_eh_frame_hdr.table_enc */ p[3] = DW_EH_PE_omit; synth_eh_frame_hdr.fde_count_enc = DW_EH_PE_omit;
*(Elf_W (Addr) *)(&p[4]) = eh_frame; synth_eh_frame_hdr.table_enc = DW_EH_PE_omit;
synth_eh_frame_hdr.eh_frame = eh_frame;
hdr = &synth_eh_frame_hdr; hdr = &synth_eh_frame_hdr;
} }
} }
@ -581,7 +581,7 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
} }
a = unw_get_accessors (unw_local_addr_space); a = unw_get_accessors (unw_local_addr_space);
addr = (unw_word_t) (uintptr_t) (hdr + 1); addr = (unw_word_t) (uintptr_t) (&hdr->eh_frame);
/* (Optionally) read eh_frame_ptr: */ /* (Optionally) read eh_frame_ptr: */
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
@ -618,12 +618,13 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
/* XXX we know how to build a local binary search table for /* XXX we know how to build a local binary search table for
.debug_frame, so we could do that here too. */ .debug_frame, so we could do that here too. */
cb_data->single_fde = 1;
found = linear_search (unw_local_addr_space, ip, found = linear_search (unw_local_addr_space, ip,
eh_frame_start, eh_frame_end, fde_count, eh_frame_start, eh_frame_end, fde_count,
pi, need_unwind_info, NULL); pi, need_unwind_info, NULL);
if (found != 1) if (found != 1)
found = 0; found = 0;
else
cb_data->single_fde = 1;
} }
else else
{ {

View File

@ -139,7 +139,7 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
} }
a = unw_get_accessors (unw_local_addr_space); a = unw_get_accessors (unw_local_addr_space);
addr = to_unw_word (hdr + 1); addr = to_unw_word (&hdr->eh_frame);
/* Fill in a dummy proc_info structure. We just need to fill in /* 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 enough to ensure that dwarf_read_encoded_pointer() can do it's

View File

@ -278,7 +278,7 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
ret = -UNW_ENOMEM; ret = -UNW_ENOMEM;
break; break;
} }
memcpy (&(*rs_stack)->state, &sr->rs_current, sizeof (sr->rs_current)) memcpy (&(*rs_stack)->state, &sr->rs_current, sizeof (sr->rs_current));
Debug (15, "CFA_remember_state\n"); Debug (15, "CFA_remember_state\n");
break; break;
@ -289,8 +289,10 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
ret = -UNW_EINVAL; ret = -UNW_EINVAL;
break; break;
} }
memcpy (&sr->rs_current, &(*rs_stack)->state, sizeof (sr->rs_current)); if (*ip < end_ip) {
pop_rstate_stack(rs_stack); memcpy (&sr->rs_current, &(*rs_stack)->state, sizeof (sr->rs_current));
pop_rstate_stack(rs_stack);
}
Debug (15, "CFA_restore_state\n"); Debug (15, "CFA_restore_state\n");
break; break;
@ -606,7 +608,17 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
if (caching == UNW_CACHE_NONE) if (caching == UNW_CACHE_NONE)
return NULL; 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)) if (likely (caching == UNW_CACHE_GLOBAL))
#endif
{ {
Debug (16, "acquiring lock\n"); Debug (16, "acquiring lock\n");
lock_acquire (&cache->lock, *saved_maskp); lock_acquire (&cache->lock, *saved_maskp);
@ -615,6 +627,8 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
|| !cache->hash) || !cache->hash)
{ {
/* 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) if (dwarf_flush_rs_cache (cache) < 0)
return NULL; return NULL;
cache->generation = as->cache_generation; cache->generation = as->cache_generation;
@ -679,7 +693,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
unsigned short head; unsigned short head;
head = cache->rr_head; head = cache->rr_head;
cache->rr_head = (head + 1) & (cache->log_size - 1); 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): */ /* remove the old rs from the hash table (if it's there): */
if (cache->links[head].ip) if (cache->links[head].ip)
@ -885,7 +899,7 @@ find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr)
int ret = 0; int ret = 0;
intrmask_t saved_mask; intrmask_t saved_mask;
if ((cache = get_rs_cache(c->as, &saved_mask)) && if ((cache = get_rs_cache(c->as, &saved_mask)) &&
(rs = rs_lookup(cache, c))) (rs = rs_lookup(cache, c)))
{ {
/* update hint; no locking needed: single-word writes are atomic */ /* update hint; no locking needed: single-word writes are atomic */
@ -951,7 +965,7 @@ dwarf_make_proc_info (struct dwarf_cursor *c)
needed for unw_resume */ needed for unw_resume */
dwarf_state_record_t sr; dwarf_state_record_t sr;
int ret; int ret;
/* Lookup it up the slow way... */ /* Lookup it up the slow way... */
ret = fetch_proc_info (c, c->ip, 0); ret = fetch_proc_info (c, c->ip, 0);
if (ret >= 0) if (ret >= 0)
@ -1018,11 +1032,11 @@ dwarf_reg_states_iterate(struct dwarf_cursor *c,
case UNW_INFO_FORMAT_REMOTE_TABLE: case UNW_INFO_FORMAT_REMOTE_TABLE:
ret = dwarf_reg_states_table_iterate(c, cb, token); ret = dwarf_reg_states_table_iterate(c, cb, token);
break; break;
case UNW_INFO_FORMAT_DYNAMIC: case UNW_INFO_FORMAT_DYNAMIC:
ret = dwarf_reg_states_dynamic_iterate (c, cb, token); ret = dwarf_reg_states_dynamic_iterate (c, cb, token);
break; break;
default: default:
Debug (1, "Unexpected unwind-info format %d\n", c->pi.format); Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
ret = -UNW_EINVAL; ret = -UNW_EINVAL;

View File

@ -386,6 +386,8 @@ elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local)
{ {
int ret; int ret;
Elf_W (Shdr) *shdr; Elf_W (Shdr) *shdr;
Elf_W (Ehdr) *prev_image = ei->image;
off_t prev_size = ei->size;
if (!ei->image) if (!ei->image)
{ {
@ -420,7 +422,6 @@ elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local)
if (memchr (linkbuf, 0, shdr->sh_size) == NULL) if (memchr (linkbuf, 0, shdr->sh_size) == NULL)
return 0; return 0;
munmap (ei->image, ei->size);
ei->image = NULL; ei->image = NULL;
Debug(1, "Found debuglink section, following %s\n", linkbuf); Debug(1, "Found debuglink section, following %s\n", linkbuf);
@ -456,6 +457,19 @@ elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local)
ret = elf_w (load_debuglink) (newname, ei, -1); 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 ret;
} }
} }

View File

@ -179,7 +179,7 @@ HIDDEN void
hppa_local_addr_space_init (void) hppa_local_addr_space_init (void)
{ {
memset (&local_addr_space, 0, sizeof (local_addr_space)); 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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -58,9 +58,20 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal (unw_cursor_t *cursor, ucontext_t *uc) unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -33,5 +33,7 @@ unw_apply_reg_state (unw_cursor_t *cursor,
{ {
struct cursor *c = (struct cursor *) cursor; struct cursor *c = (struct cursor *) cursor;
return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); // Needs dwarf support on ia64
// return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
return -UNW_EINVAL;
} }

View File

@ -361,7 +361,7 @@ ia64_local_addr_space_init (void)
#elif defined(__hpux) #elif defined(__hpux)
local_addr_space.abi = ABI_HPUX; local_addr_space.abi = ABI_HPUX;
#endif #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.find_proc_info = tdep_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -33,5 +33,7 @@ unw_reg_states_iterate (unw_cursor_t *cursor,
{ {
struct cursor *c = (struct cursor *) cursor; struct cursor *c = (struct cursor *) cursor;
return dwarf_reg_states_iterate (&c->dwarf, cb, token); // Needs dwarf support on ia64
// return dwarf_reg_states_iterate (&c->dwarf, cb, token);
return -UNW_EINVAL;
} }

View File

@ -45,7 +45,7 @@ enum ia64_script_insn_opcode
IA64_INSN_MOVE_SCRATCH_NO_NAT /* like above, but clear NaT info */ 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 = static __thread struct ia64_script_cache ia64_per_thread_cache =
{ {
#ifdef HAVE_ATOMIC_OPS_H #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)) if (!spin_trylock_irqsave (&cache->busy, *saved_maskp))
return NULL; return NULL;
#else #else
# ifdef HAVE___THREAD # if defined(HAVE___THREAD) && HAVE___THREAD
if (as->caching_policy == UNW_CACHE_PER_THREAD) if (as->caching_policy == UNW_CACHE_PER_THREAD)
cache = &ia64_per_thread_cache; cache = &ia64_per_thread_cache;
# endif # endif

View File

@ -1,11 +0,0 @@
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libunwind-generic
Description: libunwind generic library
Version: 1.2
Requires: libunwind
Libs: -L${libdir} -lunwind-generic
Cflags: -I${includedir}

View 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_TABLE:
case UNW_INFO_FORMAT_REMOTE_TABLE: case UNW_INFO_FORMAT_REMOTE_TABLE:
case UNW_INFO_FORMAT_ARM_EXIDX:
case UNW_INFO_FORMAT_IP_OFFSET: case UNW_INFO_FORMAT_IP_OFFSET:
#ifdef tdep_search_unwind_table #ifdef tdep_search_unwind_table
/* call platform-specific search routine: */ /* call platform-specific search routine: */

View File

@ -104,11 +104,15 @@ unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len,
int error; int error;
ip = tdep_get_ip (c); ip = tdep_get_ip (c);
#if !defined(__ia64__)
if (c->dwarf.use_prev_instr) if (c->dwarf.use_prev_instr)
--ip; --ip;
#endif
error = get_proc_name (tdep_get_as (c), ip, buf, buf_len, offp, error = get_proc_name (tdep_get_as (c), ip, buf, buf_len, offp,
tdep_get_as_arg (c)); tdep_get_as_arg (c));
#if !defined(__ia64__)
if (c->dwarf.use_prev_instr && offp != NULL && error == 0) if (c->dwarf.use_prev_instr && offp != NULL && error == 0)
*offp += 1; *offp += 1;
#endif
return error; return error;
} }

View File

@ -38,6 +38,12 @@ unw_set_cache_size (unw_addr_space_t as, size_t size, int flag)
if (flag != 0) if (flag != 0)
return -1; 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 */ /* Round up to next power of two, slowly but portably */
while(power < size) while(power < size)
{ {
@ -48,10 +54,12 @@ unw_set_cache_size (unw_addr_space_t as, size_t size, int flag)
break; break;
} }
#if !defined(__ia64__)
if (log_size == as->global_cache.log_size) if (log_size == as->global_cache.log_size)
return 0; /* no change */ return 0; /* no change */
as->global_cache.log_size = log_size; as->global_cache.log_size = log_size;
#endif
/* Ensure caches are empty (and initialized). */ /* Ensure caches are empty (and initialized). */
unw_flush_cache (as, 0, 0); unw_flush_cache (as, 0, 0);

View File

@ -31,7 +31,7 @@ unw_set_caching_policy (unw_addr_space_t as, unw_caching_policy_t policy)
if (!tdep_init_done) if (!tdep_init_done)
tdep_init (); tdep_init ();
#ifndef HAVE___THREAD #if !(defined(HAVE___THREAD) && HAVE___THREAD)
if (policy == UNW_CACHE_PER_THREAD) if (policy == UNW_CACHE_PER_THREAD)
policy = UNW_CACHE_GLOBAL; policy = UNW_CACHE_GLOBAL;
#endif #endif

View File

@ -195,7 +195,7 @@ mips_local_addr_space_init (void)
# error Unsupported ABI # error Unsupported ABI
#endif #endif
local_addr_space.addr_size = sizeof (void *); 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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -57,9 +57,20 @@ unw_init_local(unw_cursor_t *cursor, ucontext_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal(unw_cursor_t *cursor, ucontext_t *uc) unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -70,6 +70,8 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
break; break;
case UNW_MIPS_PC: case UNW_MIPS_PC:
if (write)
c->dwarf.ip = *valp; /* update the IP cache */
loc = c->dwarf.loc[reg]; loc = c->dwarf.loc[reg];
break; break;

View File

@ -56,7 +56,7 @@ get_pid_by_tid(int tid)
size_t len, len1; size_t len, len1;
char *buf; char *buf;
struct kinfo_proc *kv; struct kinfo_proc *kv;
int i, pid; unsigned i, pid;
len = 0; len = 0;
mib[0] = CTL_KERN; mib[0] = CTL_KERN;

View File

@ -69,9 +69,20 @@ unw_init_local(unw_cursor_t *cursor, ucontext_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal(unw_cursor_t *cursor, ucontext_t *uc) unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -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"
PROTECTED 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);
}

View File

@ -201,7 +201,7 @@ HIDDEN void
ppc32_local_addr_space_init (void) ppc32_local_addr_space_init (void)
{ {
memset (&local_addr_space, 0, sizeof (local_addr_space)); 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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -1,6 +1,8 @@
/* libunwind - a platform-independent unwind library /* 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> 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. This file is part of libunwind.
@ -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 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "dwarf.h" #include "unwind_i.h"
#include "libunwind_i.h"
HIDDEN int PROTECTED int
dwarf_step (struct dwarf_cursor *c) unw_reg_states_iterate (unw_cursor_t *cursor,
unw_reg_states_callback cb, void *token)
{ {
int ret; struct cursor *c = (struct cursor *) cursor;
if ((ret = dwarf_find_save_locs (c)) >= 0) { return dwarf_reg_states_iterate (&c->dwarf, cb, token);
c->pi_valid = 0;
ret = (c->ip == 0) ? 0 : 1;
}
Debug (15, "returning %d\n", ret);
return ret;
} }

View File

@ -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

View File

@ -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

View File

@ -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"
PROTECTED 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);
}

View File

@ -214,7 +214,7 @@ ppc64_local_addr_space_init (void)
#else #else
local_addr_space.abi = UNW_PPC64_ABI_ELFv1; local_addr_space.abi = UNW_PPC64_ABI_ELFv1;
#endif #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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -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"
PROTECTED 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);
}

View File

@ -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

View File

@ -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

View 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; pid_t pid = ui->pid;
fpregset_t fpreg; 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)) if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset))
return -UNW_EBADREG; 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)); memcpy(&fpreg.fpr_xacc[reg], val, sizeof(unw_fpreg_t));
#elif defined(__i386__) #elif defined(__i386__)
memcpy(&fpreg.fpr_acc[reg], val, sizeof(unw_fpreg_t)); memcpy(&fpreg.fpr_acc[reg], val, sizeof(unw_fpreg_t));
#elif defined(__arm__)
memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t));
#else #else
#error Fix me #error Fix me
#endif #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)); memcpy(val, &fpreg.fpr_xacc[reg], sizeof(unw_fpreg_t));
#elif defined(__i386__) #elif defined(__i386__)
memcpy(val, &fpreg.fpr_acc[reg], sizeof(unw_fpreg_t)); memcpy(val, &fpreg.fpr_acc[reg], sizeof(unw_fpreg_t));
#elif defined(__arm__)
memcpy(val, &fpreg.fpr[reg], sizeof(unw_fpreg_t));
#else #else
#error Fix me #error Fix me
#endif #endif

View File

@ -34,7 +34,50 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
# include "tdep-ia64/rse.h" # include "tdep-ia64/rse.h"
#endif #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 int
_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, _UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
int write, void *arg) int write, void *arg)

View File

@ -484,6 +484,7 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] =
#endif #endif
#elif defined(UNW_TARGET_ARM) #elif defined(UNW_TARGET_ARM)
#if defined(__linux__) || defined(__FreeBSD__)
[UNW_ARM_R0] = 0x00, [UNW_ARM_R0] = 0x00,
[UNW_ARM_R1] = 0x04, [UNW_ARM_R1] = 0x04,
[UNW_ARM_R2] = 0x08, [UNW_ARM_R2] = 0x08,
@ -500,6 +501,9 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] =
[UNW_ARM_R13] = 0x34, [UNW_ARM_R13] = 0x34,
[UNW_ARM_R14] = 0x38, [UNW_ARM_R14] = 0x38,
[UNW_ARM_R15] = 0x3c, [UNW_ARM_R15] = 0x3c,
#else
#error Fix me
#endif
#elif defined(UNW_TARGET_MIPS) #elif defined(UNW_TARGET_MIPS)
[UNW_MIPS_R0] = 0, [UNW_MIPS_R0] = 0,
[UNW_MIPS_R1] = 1, [UNW_MIPS_R1] = 1,

View File

@ -1,11 +0,0 @@
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libunwind-ptrace
Description: libunwind ptrace library
Version: 1.2
Requires: libunwind-generic libunwind
Libs: -L${libdir} -lunwind-ptrace
Cflags: -I${includedir}

View File

@ -1,11 +0,0 @@
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libunwind-setjmp
Description: libunwind setjmp library
Version: 1.2
Requires: libunwind
Libs: -L${libdir} -lunwind-setjmp
Cflags: -I${includedir}

View File

@ -171,7 +171,7 @@ HIDDEN void
sh_local_addr_space_init (void) sh_local_addr_space_init (void)
{ {
memset (&local_addr_space, 0, sizeof (local_addr_space)); 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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -59,9 +59,20 @@ unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal (unw_cursor_t *cursor, unw_context_t *uc) unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -33,6 +33,9 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
switch (reg) switch (reg)
{ {
case UNW_SH_PC:
if (write)
c->dwarf.ip = *valp; /* update the IP cache */
case UNW_SH_R0: case UNW_SH_R0:
case UNW_SH_R1: case UNW_SH_R1:
case UNW_SH_R2: 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_R12:
case UNW_SH_R13: case UNW_SH_R13:
case UNW_SH_R14: case UNW_SH_R14:
case UNW_SH_PC:
case UNW_SH_PR: case UNW_SH_PR:
loc = c->dwarf.loc[reg]; loc = c->dwarf.loc[reg];
break; break;

View File

@ -152,7 +152,7 @@ tilegx_local_addr_space_init (void)
local_addr_space.abi = UNW_TILEGX_ABI_N64; local_addr_space.abi = UNW_TILEGX_ABI_N64;
local_addr_space.addr_size = sizeof (void *); 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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -61,9 +61,20 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal (unw_cursor_t *cursor, ucontext_t *uc) unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -52,7 +52,17 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
} }
if (write) 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 else
return dwarf_get (&c->dwarf, loc, valp); return dwarf_get (&c->dwarf, loc, valp);
} }

View File

@ -1,11 +0,0 @@
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libunwind
Description: libunwind base library
Version: 1.2
Libs: -L${libdir} -lunwind
Libs.private: -llzma
Cflags: -I${includedir}

View File

@ -228,7 +228,7 @@ HIDDEN void
x86_local_addr_space_init (void) x86_local_addr_space_init (void)
{ {
memset (&local_addr_space, 0, sizeof (local_addr_space)); 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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -60,9 +60,20 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal (unw_cursor_t *cursor, ucontext_t *uc) unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -52,7 +52,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
__restore_rt: __restore_rt:
0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
0xcd 0x80 int 0x80 0xcd 0x80 int 0x80
0x00 0x00
if SA_SIGINFO is specified. if SA_SIGINFO is specified.
*/ */
@ -296,7 +296,7 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc);
sigreturn (sc); x86_sigreturn (sc);
} }
else else
{ {
@ -305,4 +305,25 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
} }
return -UNW_EINVAL; 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 = &((struct ucontext*)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 #endif

View 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_scratch_loc UNW_OBJ(scratch_loc)
#define x86_get_scratch_loc UNW_OBJ(get_scratch_loc) #define x86_get_scratch_loc UNW_OBJ(get_scratch_loc)
#define x86_r_uc_addr UNW_OBJ(r_uc_addr) #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 void x86_local_addr_space_init (void);
extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
@ -60,4 +61,6 @@ 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 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_r_uc_addr (ucontext_t *uc, int reg);
extern void x86_sigreturn (unw_cursor_t *cursor);
#endif /* unwind_i_h */ #endif /* unwind_i_h */

View File

@ -72,10 +72,57 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1)) #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
{
ret = write (mem_validate_pipe[1], addr, 1);
}
while ( errno == EINTR );
return ret;
}
static int (*mem_validate_func) (void *addr, size_t len); static int (*mem_validate_func) (void *addr, size_t len);
static int msync_validate (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 #ifdef HAVE_MINCORE
@ -96,7 +143,7 @@ static int mincore_validate (void *addr, size_t len)
if (!(mvec[i] & 1)) return -1; if (!(mvec[i] & 1)) return -1;
} }
return 0; return write_validate (addr);
} }
#endif #endif
@ -107,6 +154,8 @@ static int mincore_validate (void *addr, size_t len)
HIDDEN void HIDDEN void
tdep_init_mem_validate (void) tdep_init_mem_validate (void)
{ {
open_pipe ();
#ifdef HAVE_MINCORE #ifdef HAVE_MINCORE
unsigned char present = 1; unsigned char present = 1;
unw_word_t addr = PAGE_START((unw_word_t)&present); unw_word_t addr = PAGE_START((unw_word_t)&present);
@ -273,7 +322,7 @@ HIDDEN void
x86_64_local_addr_space_init (void) x86_64_local_addr_space_init (void)
{ {
memset (&local_addr_space, 0, sizeof (local_addr_space)); 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.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;

View File

@ -62,9 +62,20 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
} }
PROTECTED int PROTECTED int
unw_init_local_signal (unw_cursor_t *cursor, ucontext_t *uc) unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
{ {
return unw_init_local_common(cursor, uc, 0); 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 */ #endif /* !UNW_REMOTE_ONLY */

View File

@ -138,7 +138,7 @@ x86_64_sigreturn (unw_cursor_t *cursor)
{ {
struct cursor *c = (struct cursor *) cursor; struct cursor *c = (struct cursor *) cursor;
struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
mcontext_t *sc_mcontext = &((struct ucontext*)sc)->uc_mcontext; mcontext_t *sc_mcontext = &((ucontext_t*)sc)->uc_mcontext;
/* Copy in saved uc - all preserved regs are at the start of sigcontext */ /* Copy in saved uc - all preserved regs are at the start of sigcontext */
memcpy(sc_mcontext, &c->uc->uc_mcontext, memcpy(sc_mcontext, &c->uc->uc_mcontext,
DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t)); DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t));

View File

@ -83,6 +83,7 @@ common_init (struct cursor *c, unsigned use_prev_instr)
c->dwarf.pi_is_dynamic = 0; c->dwarf.pi_is_dynamic = 0;
c->dwarf.hint = 0; c->dwarf.hint = 0;
c->dwarf.prev_rs = 0; c->dwarf.prev_rs = 0;
c->dwarf.eh_valid_mask = 0;
return 0; return 0;
} }

View File

@ -192,7 +192,7 @@ size_t backtraceLibUnwind(void ** out_frames, size_t max_frames, ucontext_t & co
unw_cursor_t cursor; unw_cursor_t cursor;
if (unw_init_local_signal(&cursor, &context) < 0) if (unw_init_local2(&cursor, &context, UNW_INIT_SIGNAL_FRAME) < 0)
return 0; return 0;
size_t i = 0; size_t i = 0;