mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
switch to llvm libunwind
This commit is contained in:
parent
6e3f7f62eb
commit
10942b2ef1
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -79,3 +79,6 @@
|
||||
[submodule "contrib/hyperscan"]
|
||||
path = contrib/hyperscan
|
||||
url = https://github.com/ClickHouse-Extras/hyperscan.git
|
||||
[submodule "contrib/libunwind"]
|
||||
path = contrib/libunwind
|
||||
url = https://github.com/llvm-mirror/libunwind.git
|
||||
|
1
contrib/libunwind
vendored
Submodule
1
contrib/libunwind
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 255dc597a525e374917609c0d794cf4ee6e2a69b
|
@ -1 +0,0 @@
|
||||
David Mosberger <dmosberger@gmail.org>
|
@ -1,122 +0,0 @@
|
||||
enable_language(ASM)
|
||||
|
||||
if (ARCH_PPC64LE)
|
||||
add_library(unwind
|
||||
src/mi/init.c
|
||||
src/mi/flush_cache.c
|
||||
src/mi/mempool.c
|
||||
src/mi/strerror.c
|
||||
src/mi/_ReadULEB.c
|
||||
src/mi/_ReadSLEB.c
|
||||
src/mi/backtrace.c
|
||||
src/mi/dyn-cancel.c
|
||||
src/mi/dyn-info-list.c
|
||||
src/mi/dyn-register.c
|
||||
src/mi/Ldyn-extract.c
|
||||
src/mi/Lfind_dynamic_proc_info.c
|
||||
src/mi/Lget_accessors.c
|
||||
src/mi/Lget_proc_info_by_ip.c
|
||||
src/mi/Lget_proc_name.c
|
||||
src/mi/Lput_dynamic_unwind_info.c
|
||||
src/mi/Ldestroy_addr_space.c
|
||||
src/mi/Lget_reg.c
|
||||
src/mi/Lset_reg.c
|
||||
src/mi/Lget_fpreg.c
|
||||
src/mi/Lset_fpreg.c
|
||||
src/mi/Lset_caching_policy.c
|
||||
src/dwarf/Lexpr.c
|
||||
src/dwarf/Lfde.c
|
||||
src/dwarf/Lfind_proc_info-lsb.c
|
||||
src/dwarf/Lparser.c
|
||||
src/dwarf/Lpe.c
|
||||
src/dwarf/global.c
|
||||
src/elf64.c
|
||||
src/os-linux.c
|
||||
|
||||
src/ppc64/is_fpreg.c
|
||||
src/ppc64/regname.c
|
||||
src/ppc64/get_func_addr.c
|
||||
src/ppc/Linit_local.c
|
||||
src/ppc/Linit_remote.c
|
||||
src/ppc/Lis_signal_frame.c
|
||||
src/ppc/longjmp.S
|
||||
src/ppc/Lreg_states_iterate.c
|
||||
src/ppc/siglongjmp.S
|
||||
src/ppc64/setcontext.S
|
||||
src/ppc64/Lcreate_addr_space.c
|
||||
src/ppc64/Lglobal.c
|
||||
src/ppc64/Linit.c
|
||||
src/ppc64/Lreg_states_iterate.c
|
||||
src/ppc64/Lregs.c
|
||||
src/ppc64/Lresume.c
|
||||
src/ppc64/Lstep.c
|
||||
src/ppc64/regname.c
|
||||
src/ppc64/setcontext.S
|
||||
)
|
||||
else ()
|
||||
add_library(unwind
|
||||
src/mi/init.c
|
||||
src/mi/flush_cache.c
|
||||
src/mi/mempool.c
|
||||
src/mi/strerror.c
|
||||
src/mi/_ReadULEB.c
|
||||
src/mi/_ReadSLEB.c
|
||||
src/mi/backtrace.c
|
||||
src/mi/dyn-cancel.c
|
||||
src/mi/dyn-info-list.c
|
||||
src/mi/dyn-register.c
|
||||
src/mi/Ldyn-extract.c
|
||||
src/mi/Lfind_dynamic_proc_info.c
|
||||
src/mi/Lget_accessors.c
|
||||
src/mi/Lget_proc_info_by_ip.c
|
||||
src/mi/Lget_proc_name.c
|
||||
src/mi/Lput_dynamic_unwind_info.c
|
||||
src/mi/Ldestroy_addr_space.c
|
||||
src/mi/Lget_reg.c
|
||||
src/mi/Lset_reg.c
|
||||
src/mi/Lget_fpreg.c
|
||||
src/mi/Lset_fpreg.c
|
||||
src/mi/Lset_caching_policy.c
|
||||
src/dwarf/Lexpr.c
|
||||
src/dwarf/Lfde.c
|
||||
src/dwarf/Lfind_proc_info-lsb.c
|
||||
src/dwarf/Lparser.c
|
||||
src/dwarf/Lpe.c
|
||||
src/dwarf/global.c
|
||||
src/elf64.c
|
||||
src/os-linux.c
|
||||
|
||||
src/x86_64/is_fpreg.c
|
||||
src/x86_64/regname.c
|
||||
src/x86_64/setcontext.S
|
||||
src/x86_64/Lcreate_addr_space.c
|
||||
src/x86_64/Lget_save_loc.c
|
||||
src/x86_64/Lglobal.c
|
||||
src/x86_64/Linit.c
|
||||
src/x86_64/Linit_local.c
|
||||
src/x86_64/Linit_remote.c
|
||||
src/x86_64/Lget_proc_info.c
|
||||
src/x86_64/Lregs.c
|
||||
src/x86_64/Lresume.c
|
||||
src/x86_64/Lstash_frame.c
|
||||
src/x86_64/Lstep.c
|
||||
src/x86_64/Ltrace.c
|
||||
src/x86_64/getcontext.S
|
||||
src/x86_64/Los-linux.c
|
||||
)
|
||||
endif()
|
||||
|
||||
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_options (unwind PRIVATE -Wno-visibility -Wno-header-guard)
|
||||
|
||||
target_include_directories (unwind PUBLIC include)
|
||||
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)
|
@ -1,20 +0,0 @@
|
||||
Copyright (c) 2002 Hewlett-Packard Co.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,2 +0,0 @@
|
||||
Source: https://github.com/libunwind/libunwind
|
||||
Revision: 60ddc67196eafb5cafd0d89e461c9d700a697d6d
|
@ -1,236 +0,0 @@
|
||||
/* include/config.h. Generated from config.h.in by configure. */
|
||||
/* include/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Block signals before mutex operations */
|
||||
#define 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 */
|
||||
#define CONSERVATIVE_CHECKS 1
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine HAVE_ATOMIC_OPS_H
|
||||
|
||||
/* Define to 1 if you have the <byteswap.h> header file. */
|
||||
#define HAVE_BYTESWAP_H 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PTRACE_CONT', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_PTRACE_CONT 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PTRACE_POKEDATA', and to 0 if
|
||||
you don't. */
|
||||
#define HAVE_DECL_PTRACE_POKEDATA 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PTRACE_POKEUSER', and to 0 if
|
||||
you don't. */
|
||||
#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
|
||||
you don't. */
|
||||
#define HAVE_DECL_PTRACE_SINGLESTEP 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PTRACE_SYSCALL', and to 0 if
|
||||
you don't. */
|
||||
#define HAVE_DECL_PTRACE_SYSCALL 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PTRACE_TRACEME', and to 0 if
|
||||
you don't. */
|
||||
#define HAVE_DECL_PTRACE_TRACEME 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PT_CONTINUE', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_PT_CONTINUE 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PT_GETFPREGS', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_PT_GETFPREGS 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PT_GETREGS', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_PT_GETREGS 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PT_IO', and to 0 if you don't.
|
||||
*/
|
||||
#define HAVE_DECL_PT_IO 0
|
||||
|
||||
/* Define to 1 if you have the declaration of `PT_STEP', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_PT_STEP 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PT_SYSCALL', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_PT_SYSCALL 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `PT_TRACE_ME', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_PT_TRACE_ME 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the `dlmodinfo' function. */
|
||||
/* #undef HAVE_DLMODINFO */
|
||||
|
||||
/* Define to 1 if you have the `dl_iterate_phdr' function. */
|
||||
#define HAVE_DL_ITERATE_PHDR 1
|
||||
|
||||
/* 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. */
|
||||
#define HAVE_ELF_H 1
|
||||
|
||||
/* Define to 1 if you have the <endian.h> header file. */
|
||||
#define HAVE_ENDIAN_H 1
|
||||
|
||||
/* Define to 1 if you have the <execinfo.h> header file. */
|
||||
#define HAVE_EXECINFO_H 1
|
||||
|
||||
/* 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. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `uca' library (-luca). */
|
||||
/* #undef HAVE_LIBUCA */
|
||||
|
||||
/* Define to 1 if you have the <link.h> header file. */
|
||||
#define HAVE_LINK_H 1
|
||||
|
||||
/* Define if you have liblzma */
|
||||
/* #undef HAVE_LZMA */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `mincore' function. */
|
||||
#define HAVE_MINCORE 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if `dlpi_subs' is a member of `struct dl_phdr_info'. */
|
||||
#define HAVE_STRUCT_DL_PHDR_INFO_DLPI_SUBS 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct elf_prstatus'. */
|
||||
#define HAVE_STRUCT_ELF_PRSTATUS 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct prstatus'. */
|
||||
/* #undef HAVE_STRUCT_PRSTATUS */
|
||||
|
||||
/* Defined if __sync atomics are available */
|
||||
#define HAVE_SYNC_ATOMICS 1
|
||||
|
||||
/* 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. */
|
||||
#define HAVE_SYS_PROCFS_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/ptrace.h> header file. */
|
||||
#define HAVE_SYS_PTRACE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* 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. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Defined if __builtin_unreachable() is available */
|
||||
#define HAVE__BUILTIN_UNREACHABLE 1
|
||||
|
||||
/* Defined if __builtin___clear_cache() is available */
|
||||
#define HAVE__BUILTIN___CLEAR_CACHE 1
|
||||
|
||||
/* Define to 1 if __thread keyword is supported by the C compiler. */
|
||||
/* #undef HAVE___THREAD */
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libunwind"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "libunwind-devel@nongnu.org"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "libunwind"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "libunwind 1.2"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "libunwind"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.2"
|
||||
|
||||
/* The size of `off_t', as computed by sizeof. */
|
||||
#define SIZEOF_OFF_T 8
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.2"
|
||||
|
||||
/* 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 */
|
@ -1,279 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#define UNW_VERSION_MAJOR 1
|
||||
#define UNW_VERSION_MINOR 2
|
||||
#define UNW_VERSION_EXTRA
|
||||
|
||||
#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min))
|
||||
#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR)
|
||||
|
||||
#define UNW_PASTE2(x,y) x##y
|
||||
#define UNW_PASTE(x,y) UNW_PASTE2(x,y)
|
||||
#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn)
|
||||
#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_)
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
/* Error codes. The unwind routines return the *negated* values of
|
||||
these error codes on error and a non-negative value on success. */
|
||||
typedef enum
|
||||
{
|
||||
UNW_ESUCCESS = 0, /* no error */
|
||||
UNW_EUNSPEC, /* unspecified (general) error */
|
||||
UNW_ENOMEM, /* out of memory */
|
||||
UNW_EBADREG, /* bad register number */
|
||||
UNW_EREADONLYREG, /* attempt to write read-only register */
|
||||
UNW_ESTOPUNWIND, /* stop unwinding */
|
||||
UNW_EINVALIDIP, /* invalid IP */
|
||||
UNW_EBADFRAME, /* bad frame */
|
||||
UNW_EINVAL, /* unsupported operation or bad value */
|
||||
UNW_EBADVERSION, /* unwind info has unsupported version */
|
||||
UNW_ENOINFO /* no unwind info found */
|
||||
}
|
||||
unw_error_t;
|
||||
|
||||
/* The following enum defines the indices for a couple of
|
||||
(pseudo-)registers which have the same meaning across all
|
||||
platforms. (RO) means read-only. (RW) means read-write. General
|
||||
registers (aka "integer registers") are expected to start with
|
||||
index 0. The number of such registers is architecture-dependent.
|
||||
The remaining indices can be used as an architecture sees fit. The
|
||||
last valid register index is given by UNW_REG_LAST. */
|
||||
typedef enum
|
||||
{
|
||||
UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */
|
||||
UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */
|
||||
UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */
|
||||
UNW_REG_LAST = UNW_TDEP_LAST_REG
|
||||
}
|
||||
unw_frame_regnum_t;
|
||||
|
||||
/* Number of exception-handler argument registers: */
|
||||
#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_CACHE_NONE, /* no caching */
|
||||
UNW_CACHE_GLOBAL, /* shared global cache */
|
||||
UNW_CACHE_PER_THREAD /* per-thread caching */
|
||||
}
|
||||
unw_caching_policy_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_INIT_SIGNAL_FRAME = 1, /* We know this is a signal frame */
|
||||
}
|
||||
unw_init_local2_flags_t;
|
||||
|
||||
typedef int unw_regnum_t;
|
||||
|
||||
/* The unwind cursor starts at the youngest (most deeply nested) frame
|
||||
and is used to track the frame state as the unwinder steps from
|
||||
frame to frame. It is safe to make (shallow) copies of variables
|
||||
of this type. */
|
||||
typedef struct unw_cursor
|
||||
{
|
||||
unw_word_t opaque[UNW_TDEP_CURSOR_LEN];
|
||||
}
|
||||
unw_cursor_t;
|
||||
|
||||
/* This type encapsulates the entire (preserved) machine-state. */
|
||||
typedef unw_tdep_context_t unw_context_t;
|
||||
|
||||
/* unw_getcontext() fills the unw_context_t pointed to by UC with the
|
||||
machine state as it exists at the call-site. For implementation
|
||||
reasons, this needs to be a target-dependent macro. It's easiest
|
||||
to think of unw_getcontext() as being identical to getcontext(). */
|
||||
#define unw_getcontext(uc) unw_tdep_getcontext(uc)
|
||||
|
||||
/* Return 1 if register number R is a floating-point register, zero
|
||||
otherwise.
|
||||
This routine is signal-safe. */
|
||||
#define unw_is_fpreg(r) unw_tdep_is_fpreg(r)
|
||||
|
||||
typedef unw_tdep_fpreg_t unw_fpreg_t;
|
||||
|
||||
typedef struct unw_addr_space *unw_addr_space_t;
|
||||
|
||||
/* Each target may define it's own set of flags, but bits 0-15 are
|
||||
reserved for general libunwind-use. */
|
||||
#define UNW_PI_FLAG_FIRST_TDEP_BIT 16
|
||||
/* The information comes from a .debug_frame section. */
|
||||
#define UNW_PI_FLAG_DEBUG_FRAME 32
|
||||
|
||||
typedef struct unw_proc_info
|
||||
{
|
||||
unw_word_t start_ip; /* first IP covered by this procedure */
|
||||
unw_word_t end_ip; /* first IP NOT covered by this procedure */
|
||||
#if defined(NEED_LAST_IP)
|
||||
unw_word_t last_ip; /* first IP that could begin another procedure */
|
||||
#endif
|
||||
unw_word_t lsda; /* address of lang.-spec. data area (if any) */
|
||||
unw_word_t handler; /* optional personality routine */
|
||||
unw_word_t gp; /* global-pointer value for this procedure */
|
||||
unw_word_t flags; /* misc. flags */
|
||||
|
||||
int format; /* unwind-info format (arch-specific) */
|
||||
int unwind_info_size; /* size of the information (if applicable) */
|
||||
void *unwind_info; /* unwind-info (arch-specific) */
|
||||
unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */
|
||||
}
|
||||
unw_proc_info_t;
|
||||
|
||||
typedef int (*unw_reg_states_callback)(void *token,
|
||||
void *reg_states_data,
|
||||
size_t reg_states_data_size,
|
||||
unw_word_t start_ip, unw_word_t end_ip);
|
||||
|
||||
/* These are backend callback routines that provide access to the
|
||||
state of a "remote" process. This can be used, for example, to
|
||||
unwind another process through the ptrace() interface. */
|
||||
typedef struct unw_accessors
|
||||
{
|
||||
/* Look up the unwind info associated with instruction-pointer IP.
|
||||
On success, the routine fills in the PROC_INFO structure. */
|
||||
int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *,
|
||||
int, void *);
|
||||
|
||||
/* Release any resources (e.g., memory) that were allocated for
|
||||
the unwind info returned in by a previous call to
|
||||
find_proc_info() with NEED_UNWIND_INFO set to 1. */
|
||||
void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *);
|
||||
|
||||
/* Return the list-head of the dynamically registered unwind
|
||||
info. */
|
||||
int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *);
|
||||
|
||||
/* Access aligned word at address ADDR. The value is returned
|
||||
according to the endianness of the host (e.g., if the host is
|
||||
little-endian and the target is big-endian, access_mem() needs
|
||||
to byte-swap the value before returning it). */
|
||||
int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int,
|
||||
void *);
|
||||
|
||||
/* Access register number REG at address ADDR. */
|
||||
int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int,
|
||||
void *);
|
||||
|
||||
/* Access register number REG at address ADDR. */
|
||||
int (*access_fpreg) (unw_addr_space_t, unw_regnum_t,
|
||||
unw_fpreg_t *, int, void *);
|
||||
|
||||
int (*resume) (unw_addr_space_t, unw_cursor_t *, void *);
|
||||
|
||||
/* Optional call back to obtain the name of a (static) procedure.
|
||||
Dynamically generated procedures are handled automatically by
|
||||
libunwind. This callback is optional and may be set to
|
||||
NULL. */
|
||||
int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t,
|
||||
unw_word_t *, void *);
|
||||
}
|
||||
unw_accessors_t;
|
||||
|
||||
typedef enum unw_save_loc_type
|
||||
{
|
||||
UNW_SLT_NONE, /* register is not saved ("not an l-value") */
|
||||
UNW_SLT_MEMORY, /* register has been saved in memory */
|
||||
UNW_SLT_REG /* register has been saved in (another) register */
|
||||
}
|
||||
unw_save_loc_type_t;
|
||||
|
||||
typedef struct unw_save_loc
|
||||
{
|
||||
unw_save_loc_type_t type;
|
||||
union
|
||||
{
|
||||
unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */
|
||||
unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */
|
||||
}
|
||||
u;
|
||||
unw_tdep_save_loc_t extra; /* target-dependent additional information */
|
||||
}
|
||||
unw_save_loc_t;
|
||||
|
||||
/* These routines work both for local and remote unwinding. */
|
||||
|
||||
#define unw_local_addr_space UNW_OBJ(local_addr_space)
|
||||
#define unw_create_addr_space UNW_OBJ(create_addr_space)
|
||||
#define unw_destroy_addr_space UNW_OBJ(destroy_addr_space)
|
||||
#define unw_get_accessors UNW_ARCH_OBJ(get_accessors)
|
||||
#define unw_init_local UNW_OBJ(init_local)
|
||||
#define unw_init_local2 UNW_OBJ(init_local2)
|
||||
#define unw_init_remote UNW_OBJ(init_remote)
|
||||
#define unw_step UNW_OBJ(step)
|
||||
#define unw_resume UNW_OBJ(resume)
|
||||
#define unw_get_proc_info UNW_OBJ(get_proc_info)
|
||||
#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip)
|
||||
#define unw_reg_states_iterate UNW_OBJ(reg_states_iterate)
|
||||
#define unw_apply_reg_state UNW_OBJ(apply_reg_state)
|
||||
#define unw_get_reg UNW_OBJ(get_reg)
|
||||
#define unw_set_reg UNW_OBJ(set_reg)
|
||||
#define unw_get_fpreg UNW_OBJ(get_fpreg)
|
||||
#define unw_set_fpreg UNW_OBJ(set_fpreg)
|
||||
#define unw_get_save_loc UNW_OBJ(get_save_loc)
|
||||
#define unw_is_signal_frame UNW_OBJ(is_signal_frame)
|
||||
#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame)
|
||||
#define unw_get_proc_name UNW_OBJ(get_proc_name)
|
||||
#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
|
||||
#define unw_set_cache_size UNW_OBJ(set_cache_size)
|
||||
#define unw_regname UNW_ARCH_OBJ(regname)
|
||||
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
|
||||
#define unw_strerror UNW_ARCH_OBJ(strerror)
|
||||
|
||||
extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int);
|
||||
extern void unw_destroy_addr_space (unw_addr_space_t);
|
||||
extern unw_accessors_t *unw_get_accessors (unw_addr_space_t);
|
||||
extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t);
|
||||
extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t);
|
||||
extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
|
||||
extern const char *unw_regname (unw_regnum_t);
|
||||
|
||||
extern int unw_init_local (unw_cursor_t *, unw_context_t *);
|
||||
extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int);
|
||||
extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *);
|
||||
extern int unw_step (unw_cursor_t *);
|
||||
extern int unw_resume (unw_cursor_t *);
|
||||
extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *);
|
||||
extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t,
|
||||
unw_proc_info_t *, void *);
|
||||
extern int unw_reg_states_iterate (unw_cursor_t *, unw_reg_states_callback, void *);
|
||||
extern int unw_apply_reg_state (unw_cursor_t *, void *);
|
||||
extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *);
|
||||
extern int unw_set_reg (unw_cursor_t *, int, unw_word_t);
|
||||
extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *);
|
||||
extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t);
|
||||
extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *);
|
||||
extern int unw_is_signal_frame (unw_cursor_t *);
|
||||
extern int unw_handle_signal_frame (unw_cursor_t *);
|
||||
extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *);
|
||||
extern const char *unw_strerror (int);
|
||||
extern int unw_backtrace (void **, int);
|
||||
|
||||
extern unw_addr_space_t unw_local_addr_space;
|
@ -1,36 +0,0 @@
|
||||
/* Provide a real file - not a symlink - as it would cause multiarch conflicts
|
||||
when multiple different arch releases are installed simultaneously. */
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
#if defined __aarch64__
|
||||
#include "libunwind-aarch64.h"
|
||||
#elif defined __arm__
|
||||
# include "libunwind-arm.h"
|
||||
#elif defined __hppa__
|
||||
# include "libunwind-hppa.h"
|
||||
#elif defined __ia64__
|
||||
# include "libunwind-ia64.h"
|
||||
#elif defined __mips__
|
||||
# include "libunwind-mips.h"
|
||||
#elif defined __powerpc__ && !defined __powerpc64__
|
||||
# include "libunwind-ppc32.h"
|
||||
#elif defined __powerpc64__
|
||||
# include "libunwind-ppc64.h"
|
||||
#elif defined __sh__
|
||||
# include "libunwind-sh.h"
|
||||
#elif defined __i386__
|
||||
# include "libunwind-x86.h"
|
||||
#elif defined __x86_64__
|
||||
# include "libunwind-x86_64.h"
|
||||
#elif defined __tilegx__
|
||||
# include "libunwind-tilegx.h"
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
|
||||
#else /* UNW_REMOTE_ONLY */
|
||||
|
||||
# include "libunwind-x86_64.h"
|
||||
|
||||
#endif /* UNW_REMOTE_ONLY */
|
@ -1,37 +0,0 @@
|
||||
/* Provide a real file - not a symlink - as it would cause multiarch conflicts
|
||||
when multiple different arch releases are installed simultaneously. */
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
#if defined __aarch64__
|
||||
# include "tdep-aarch64/libunwind_i.h"
|
||||
#elif defined __arm__
|
||||
# include "tdep-arm/libunwind_i.h"
|
||||
#elif defined __hppa__
|
||||
# include "tdep-hppa/libunwind_i.h"
|
||||
#elif defined __ia64__
|
||||
# include "tdep-ia64/libunwind_i.h"
|
||||
#elif defined __mips__
|
||||
# include "tdep-mips/libunwind_i.h"
|
||||
#elif defined __powerpc__ && !defined __powerpc64__
|
||||
# include "tdep-ppc32/libunwind_i.h"
|
||||
#elif defined __powerpc64__
|
||||
# include "tdep-ppc64/libunwind_i.h"
|
||||
#elif defined __sh__
|
||||
# include "tdep-sh/libunwind_i.h"
|
||||
#elif defined __i386__
|
||||
# include "tdep-x86/libunwind_i.h"
|
||||
#elif defined __x86_64__
|
||||
# include "tdep-x86_64/libunwind_i.h"
|
||||
#elif defined __tilegx__
|
||||
# include "tdep-tilegx/libunwind_i.h"
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
|
||||
|
||||
#else /* UNW_REMOTE_ONLY */
|
||||
|
||||
# include "tdep-x86_64/libunwind_i.h"
|
||||
|
||||
#endif /* UNW_REMOTE_ONLY */
|
@ -1,74 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2005 Hewlett-Packard Co
|
||||
Copyright (C) 2007 David Mosberger-Tang
|
||||
Contributed by David Mosberger-Tang <dmosberger@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. */
|
||||
|
||||
/* Compiler specific useful bits that are used in libunwind, and also in the
|
||||
* tests. */
|
||||
|
||||
#ifndef COMPILER_H
|
||||
#define COMPILER_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define ALIGNED(x) __attribute__((aligned(x)))
|
||||
# define CONST_ATTR __attribute__((__const__))
|
||||
# define UNUSED __attribute__((unused))
|
||||
# define NOINLINE __attribute__((noinline))
|
||||
# define NORETURN __attribute__((noreturn))
|
||||
# define ALIAS(name) __attribute__((alias (#name)))
|
||||
# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
|
||||
# define ALWAYS_INLINE inline __attribute__((always_inline))
|
||||
# define HIDDEN __attribute__((visibility ("hidden")))
|
||||
# define PROTECTED __attribute__((visibility ("protected")))
|
||||
# else
|
||||
# define ALWAYS_INLINE
|
||||
# define HIDDEN
|
||||
# define PROTECTED
|
||||
# endif
|
||||
# define WEAK __attribute__((weak))
|
||||
# if (__GNUC__ >= 3)
|
||||
# define likely(x) __builtin_expect ((x), 1)
|
||||
# define unlikely(x) __builtin_expect ((x), 0)
|
||||
# else
|
||||
# define likely(x) (x)
|
||||
# define unlikely(x) (x)
|
||||
# endif
|
||||
#else
|
||||
# define ALIGNED(x)
|
||||
# define ALWAYS_INLINE
|
||||
# define CONST_ATTR
|
||||
# define UNUSED
|
||||
# define NOINLINE
|
||||
# define NORETURN
|
||||
# define ALIAS(name)
|
||||
# define HIDDEN
|
||||
# define PROTECTED
|
||||
# define WEAK
|
||||
# define likely(x) (x)
|
||||
# define unlikely(x) (x)
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
|
||||
#endif /* COMPILER_H */
|
@ -1,128 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef dwarf_eh_h
|
||||
#define dwarf_eh_h
|
||||
|
||||
#include "dwarf.h"
|
||||
|
||||
/* This header file defines the format of a DWARF exception-header
|
||||
section (.eh_frame_hdr, pointed to by program-header
|
||||
PT_GNU_EH_FRAME). The exception-header is self-describing in the
|
||||
sense that the format of the addresses contained in it is expressed
|
||||
as a one-byte type-descriptor called a "pointer-encoding" (PE).
|
||||
|
||||
The exception header encodes the address of the .eh_frame section
|
||||
and optionally contains a binary search table for the
|
||||
Frame Descriptor Entries (FDEs) in the .eh_frame. The contents of
|
||||
.eh_frame has the format described by the DWARF v3 standard
|
||||
(http://www.eagercon.com/dwarf/dwarf3std.htm), except that code
|
||||
addresses may be encoded in different ways. Also, .eh_frame has
|
||||
augmentations that allow encoding a language-specific data-area
|
||||
(LSDA) pointer and a pointer to a personality-routine.
|
||||
|
||||
Details:
|
||||
|
||||
The Common Information Entry (CIE) associated with an FDE may
|
||||
contain an augmentation string. Each character in this string has
|
||||
a specific meaning and either one or two associated operands. The
|
||||
operands are stored in an augmentation body which appears right
|
||||
after the "return_address_register" member and before the
|
||||
"initial_instructions" member. The operands appear in the order
|
||||
in which the characters appear in the string. For example, if the
|
||||
augmentation string is "zL", the operand for 'z' would be first in
|
||||
the augmentation body and the operand for 'L' would be second.
|
||||
The following characters are supported for the CIE augmentation
|
||||
string:
|
||||
|
||||
'z': The operand for this character is a uleb128 value that gives the
|
||||
length of the CIE augmentation body, not counting the length
|
||||
of the uleb128 operand itself. If present, this code must
|
||||
appear as the first character in the augmentation body.
|
||||
|
||||
'L': Indicates that the FDE's augmentation body contains an LSDA
|
||||
pointer. The operand for this character is a single byte
|
||||
that specifies the pointer-encoding (PE) that is used for
|
||||
the LSDA pointer.
|
||||
|
||||
'R': Indicates that the code-pointers (FDE members
|
||||
"initial_location" and "address_range" and the operand for
|
||||
DW_CFA_set_loc) in the FDE have a non-default encoding. The
|
||||
operand for this character is a single byte that specifies
|
||||
the pointer-encoding (PE) that is used for the
|
||||
code-pointers. Note: the "address_range" member is always
|
||||
encoded as an absolute value. Apart from that, the specified
|
||||
FDE pointer-encoding applies.
|
||||
|
||||
'P': Indicates the presence of a personality routine (handler).
|
||||
The first operand for this character specifies the
|
||||
pointer-encoding (PE) that is used for the second operand,
|
||||
which specifies the address of the personality routine.
|
||||
|
||||
If the augmentation string contains any other characters, the
|
||||
remainder of the augmentation string should be ignored.
|
||||
Furthermore, if the size of the augmentation body is unknown
|
||||
(i.e., 'z' is not the first character of the augmentation string),
|
||||
then the entire CIE as well all associated FDEs must be ignored.
|
||||
|
||||
A Frame Descriptor Entries (FDE) may contain an augmentation body
|
||||
which, if present, appears right after the "address_range" member
|
||||
and before the "instructions" member. The contents of this body
|
||||
is implicitly defined by the augmentation string of the associated
|
||||
CIE. The meaning of the characters in the CIE's augmentation
|
||||
string as far as FDEs are concerned is as follows:
|
||||
|
||||
'z': The first operand in the FDE's augmentation body specifies
|
||||
the total length of the augmentation body as a uleb128 (not
|
||||
counting the length of the uleb128 operand itself).
|
||||
|
||||
'L': The operand for this character is an LSDA pointer, encoded
|
||||
in the format specified by the corresponding operand in the
|
||||
CIE's augmentation body.
|
||||
|
||||
*/
|
||||
|
||||
#define DW_EH_VERSION 1 /* The version we're implementing */
|
||||
|
||||
struct __attribute__((packed)) dwarf_eh_frame_hdr
|
||||
{
|
||||
unsigned char version;
|
||||
unsigned char eh_frame_ptr_enc;
|
||||
unsigned char fde_count_enc;
|
||||
unsigned char table_enc;
|
||||
Elf_W (Addr) eh_frame;
|
||||
/* The rest of the header is variable-length and consists of the
|
||||
following members:
|
||||
|
||||
encoded_t fde_count;
|
||||
struct
|
||||
{
|
||||
encoded_t start_ip; // first address covered by this FDE
|
||||
encoded_t fde_addr; // address of the FDE
|
||||
}
|
||||
binary_search_table[fde_count]; */
|
||||
};
|
||||
|
||||
#endif /* dwarf_eh_h */
|
@ -1,448 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef dwarf_h
|
||||
#define dwarf_h
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
struct dwarf_cursor; /* forward-declaration */
|
||||
struct elf_dyn_info;
|
||||
|
||||
#include "dwarf-config.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
#if defined(HAVE_LINK_H)
|
||||
#include <link.h>
|
||||
#elif defined(HAVE_SYS_LINK_H)
|
||||
#include <sys/link.h>
|
||||
#else
|
||||
#error Could not find <link.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* DWARF expression opcodes. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DW_OP_addr = 0x03,
|
||||
DW_OP_deref = 0x06,
|
||||
DW_OP_const1u = 0x08,
|
||||
DW_OP_const1s = 0x09,
|
||||
DW_OP_const2u = 0x0a,
|
||||
DW_OP_const2s = 0x0b,
|
||||
DW_OP_const4u = 0x0c,
|
||||
DW_OP_const4s = 0x0d,
|
||||
DW_OP_const8u = 0x0e,
|
||||
DW_OP_const8s = 0x0f,
|
||||
DW_OP_constu = 0x10,
|
||||
DW_OP_consts = 0x11,
|
||||
DW_OP_dup = 0x12,
|
||||
DW_OP_drop = 0x13,
|
||||
DW_OP_over = 0x14,
|
||||
DW_OP_pick = 0x15,
|
||||
DW_OP_swap = 0x16,
|
||||
DW_OP_rot = 0x17,
|
||||
DW_OP_xderef = 0x18,
|
||||
DW_OP_abs = 0x19,
|
||||
DW_OP_and = 0x1a,
|
||||
DW_OP_div = 0x1b,
|
||||
DW_OP_minus = 0x1c,
|
||||
DW_OP_mod = 0x1d,
|
||||
DW_OP_mul = 0x1e,
|
||||
DW_OP_neg = 0x1f,
|
||||
DW_OP_not = 0x20,
|
||||
DW_OP_or = 0x21,
|
||||
DW_OP_plus = 0x22,
|
||||
DW_OP_plus_uconst = 0x23,
|
||||
DW_OP_shl = 0x24,
|
||||
DW_OP_shr = 0x25,
|
||||
DW_OP_shra = 0x26,
|
||||
DW_OP_xor = 0x27,
|
||||
DW_OP_skip = 0x2f,
|
||||
DW_OP_bra = 0x28,
|
||||
DW_OP_eq = 0x29,
|
||||
DW_OP_ge = 0x2a,
|
||||
DW_OP_gt = 0x2b,
|
||||
DW_OP_le = 0x2c,
|
||||
DW_OP_lt = 0x2d,
|
||||
DW_OP_ne = 0x2e,
|
||||
DW_OP_lit0 = 0x30,
|
||||
DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5,
|
||||
DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, DW_OP_lit9, DW_OP_lit10,
|
||||
DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15,
|
||||
DW_OP_lit16, DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20,
|
||||
DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25,
|
||||
DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30,
|
||||
DW_OP_lit31,
|
||||
DW_OP_reg0 = 0x50,
|
||||
DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5,
|
||||
DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, DW_OP_reg9, DW_OP_reg10,
|
||||
DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15,
|
||||
DW_OP_reg16, DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20,
|
||||
DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25,
|
||||
DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30,
|
||||
DW_OP_reg31,
|
||||
DW_OP_breg0 = 0x70,
|
||||
DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5,
|
||||
DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, DW_OP_breg9, DW_OP_breg10,
|
||||
DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15,
|
||||
DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20,
|
||||
DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25,
|
||||
DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30,
|
||||
DW_OP_breg31,
|
||||
DW_OP_regx = 0x90,
|
||||
DW_OP_fbreg = 0x91,
|
||||
DW_OP_bregx = 0x92,
|
||||
DW_OP_piece = 0x93,
|
||||
DW_OP_deref_size = 0x94,
|
||||
DW_OP_xderef_size = 0x95,
|
||||
DW_OP_nop = 0x96,
|
||||
DW_OP_push_object_address = 0x97,
|
||||
DW_OP_call2 = 0x98,
|
||||
DW_OP_call4 = 0x99,
|
||||
DW_OP_call_ref = 0x9a,
|
||||
DW_OP_lo_user = 0xe0,
|
||||
DW_OP_hi_user = 0xff
|
||||
}
|
||||
dwarf_expr_op_t;
|
||||
|
||||
#define DWARF_CIE_VERSION 3 /* GCC emits version 1??? */
|
||||
|
||||
#define DWARF_CFA_OPCODE_MASK 0xc0
|
||||
#define DWARF_CFA_OPERAND_MASK 0x3f
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DW_CFA_advance_loc = 0x40,
|
||||
DW_CFA_offset = 0x80,
|
||||
DW_CFA_restore = 0xc0,
|
||||
DW_CFA_nop = 0x00,
|
||||
DW_CFA_set_loc = 0x01,
|
||||
DW_CFA_advance_loc1 = 0x02,
|
||||
DW_CFA_advance_loc2 = 0x03,
|
||||
DW_CFA_advance_loc4 = 0x04,
|
||||
DW_CFA_offset_extended = 0x05,
|
||||
DW_CFA_restore_extended = 0x06,
|
||||
DW_CFA_undefined = 0x07,
|
||||
DW_CFA_same_value = 0x08,
|
||||
DW_CFA_register = 0x09,
|
||||
DW_CFA_remember_state = 0x0a,
|
||||
DW_CFA_restore_state = 0x0b,
|
||||
DW_CFA_def_cfa = 0x0c,
|
||||
DW_CFA_def_cfa_register = 0x0d,
|
||||
DW_CFA_def_cfa_offset = 0x0e,
|
||||
DW_CFA_def_cfa_expression = 0x0f,
|
||||
DW_CFA_expression = 0x10,
|
||||
DW_CFA_offset_extended_sf = 0x11,
|
||||
DW_CFA_def_cfa_sf = 0x12,
|
||||
DW_CFA_def_cfa_offset_sf = 0x13,
|
||||
DW_CFA_val_expression = 0x16,
|
||||
DW_CFA_lo_user = 0x1c,
|
||||
DW_CFA_MIPS_advance_loc8 = 0x1d,
|
||||
DW_CFA_GNU_window_save = 0x2d,
|
||||
DW_CFA_GNU_args_size = 0x2e,
|
||||
DW_CFA_GNU_negative_offset_extended = 0x2f,
|
||||
DW_CFA_hi_user = 0x3c
|
||||
}
|
||||
dwarf_cfa_t;
|
||||
|
||||
/* DWARF Pointer-Encoding (PEs).
|
||||
|
||||
Pointer-Encodings were invented for the GCC exception-handling
|
||||
support for C++, but they represent a rather generic way of
|
||||
describing the format in which an address/pointer is stored and
|
||||
hence we include the definitions here, in the main dwarf.h file.
|
||||
The Pointer-Encoding format is partially documented in Linux Base
|
||||
Spec v1.3 (http://www.linuxbase.org/spec/). The rest is reverse
|
||||
engineered from GCC.
|
||||
|
||||
*/
|
||||
#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
|
||||
#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
|
||||
/* Flag bit. If set, the resulting pointer is the address of the word
|
||||
that contains the final address. */
|
||||
#define DW_EH_PE_indirect 0x80
|
||||
|
||||
/* Pointer-encoding formats: */
|
||||
#define DW_EH_PE_omit 0xff
|
||||
#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
|
||||
#define DW_EH_PE_uleb128 0x01 /* unsigned LE base-128 value */
|
||||
#define DW_EH_PE_udata2 0x02 /* unsigned 16-bit value */
|
||||
#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
|
||||
#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
|
||||
#define DW_EH_PE_sleb128 0x09 /* signed LE base-128 value */
|
||||
#define DW_EH_PE_sdata2 0x0a /* signed 16-bit value */
|
||||
#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
|
||||
#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
|
||||
|
||||
/* Pointer-encoding application: */
|
||||
#define DW_EH_PE_absptr 0x00 /* absolute value */
|
||||
#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
|
||||
#define DW_EH_PE_textrel 0x20 /* text-relative (GCC-specific???) */
|
||||
#define DW_EH_PE_datarel 0x30 /* data-relative */
|
||||
/* The following are not documented by LSB v1.3, yet they are used by
|
||||
GCC, presumably they aren't documented by LSB since they aren't
|
||||
used on Linux: */
|
||||
#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
|
||||
#define DW_EH_PE_aligned 0x50 /* aligned pointer */
|
||||
|
||||
extern struct mempool dwarf_reg_state_pool;
|
||||
extern struct mempool dwarf_cie_info_pool;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DWARF_WHERE_UNDEF, /* register isn't saved at all */
|
||||
DWARF_WHERE_SAME, /* register has same value as in prev. frame */
|
||||
DWARF_WHERE_CFAREL, /* register saved at CFA-relative address */
|
||||
DWARF_WHERE_REG, /* register saved in another register */
|
||||
DWARF_WHERE_EXPR, /* register saved */
|
||||
DWARF_WHERE_VAL_EXPR, /* register has computed value */
|
||||
}
|
||||
dwarf_where_t;
|
||||
|
||||
/* For uniformity, we'd like to treat the CFA save-location like any
|
||||
other register save-location, but this doesn't quite work, because
|
||||
the CFA can be expressed as a (REGISTER,OFFSET) pair. To handle
|
||||
this, we use two dwarf_save_loc structures to describe the CFA.
|
||||
The first one (CFA_REG_COLUMN), tells us where the CFA is saved.
|
||||
In the case of DWARF_WHERE_EXPR, the CFA is defined by a DWARF
|
||||
location expression whose address is given by member "val". In the
|
||||
case of DWARF_WHERE_REG, member "val" gives the number of the
|
||||
base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives
|
||||
the offset value. */
|
||||
#define DWARF_CFA_REG_COLUMN DWARF_NUM_PRESERVED_REGS
|
||||
#define DWARF_CFA_OFF_COLUMN (DWARF_NUM_PRESERVED_REGS + 1)
|
||||
|
||||
typedef struct dwarf_reg_only_state
|
||||
{
|
||||
char where[DWARF_NUM_PRESERVED_REGS + 2]; /* how is the register saved? */
|
||||
unw_word_t val[DWARF_NUM_PRESERVED_REGS + 2]; /* where it's saved */
|
||||
}
|
||||
dwarf_reg_only_state_t;
|
||||
|
||||
typedef struct dwarf_reg_state
|
||||
{
|
||||
unw_word_t ret_addr_column; /* which column in rule table represents return address */
|
||||
dwarf_reg_only_state_t reg;
|
||||
}
|
||||
dwarf_reg_state_t;
|
||||
|
||||
typedef struct dwarf_stackable_reg_state
|
||||
{
|
||||
struct dwarf_stackable_reg_state *next; /* for rs_stack */
|
||||
dwarf_reg_only_state_t state;
|
||||
}
|
||||
dwarf_stackable_reg_state_t;
|
||||
|
||||
typedef struct dwarf_reg_cache_entry
|
||||
{
|
||||
unw_word_t ip; /* ip this rs is for */
|
||||
unsigned short coll_chain; /* used for hash collisions */
|
||||
unsigned short hint; /* hint for next rs to try (or -1) */
|
||||
unsigned short valid : 1; /* optional machine-dependent signal info */
|
||||
unsigned short signal_frame : 1; /* optional machine-dependent signal info */
|
||||
}
|
||||
dwarf_reg_cache_entry_t;
|
||||
|
||||
typedef struct dwarf_cie_info
|
||||
{
|
||||
unw_word_t cie_instr_start; /* start addr. of CIE "initial_instructions" */
|
||||
unw_word_t cie_instr_end; /* end addr. of CIE "initial_instructions" */
|
||||
unw_word_t fde_instr_start; /* start addr. of FDE "instructions" */
|
||||
unw_word_t fde_instr_end; /* end addr. of FDE "instructions" */
|
||||
unw_word_t code_align; /* code-alignment factor */
|
||||
unw_word_t data_align; /* data-alignment factor */
|
||||
unw_word_t ret_addr_column; /* column of return-address register */
|
||||
unw_word_t handler; /* address of personality-routine */
|
||||
uint16_t abi;
|
||||
uint16_t tag;
|
||||
uint8_t fde_encoding;
|
||||
uint8_t lsda_encoding;
|
||||
unsigned int sized_augmentation : 1;
|
||||
unsigned int have_abi_marker : 1;
|
||||
unsigned int signal_frame : 1;
|
||||
}
|
||||
dwarf_cie_info_t;
|
||||
|
||||
typedef struct dwarf_state_record
|
||||
{
|
||||
unsigned char fde_encoding;
|
||||
unw_word_t args_size;
|
||||
|
||||
dwarf_reg_state_t rs_initial; /* reg-state after CIE instructions */
|
||||
dwarf_reg_state_t rs_current; /* current reg-state */
|
||||
}
|
||||
dwarf_state_record_t;
|
||||
|
||||
typedef struct dwarf_cursor
|
||||
{
|
||||
void *as_arg; /* argument to address-space callbacks */
|
||||
unw_addr_space_t as; /* reference to per-address-space info */
|
||||
|
||||
unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */
|
||||
unw_word_t ip; /* instruction pointer */
|
||||
unw_word_t args_size; /* size of arguments */
|
||||
unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS];
|
||||
unsigned int eh_valid_mask;
|
||||
|
||||
dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS];
|
||||
|
||||
unsigned int stash_frames :1; /* stash frames for fast lookup */
|
||||
unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */
|
||||
unsigned int pi_valid :1; /* is proc_info valid? */
|
||||
unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
|
||||
unw_proc_info_t pi; /* info about current procedure */
|
||||
|
||||
short hint; /* faster lookup of the rs cache */
|
||||
short prev_rs;
|
||||
}
|
||||
dwarf_cursor_t;
|
||||
|
||||
#define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE 7
|
||||
#define DWARF_DEFAULT_UNW_CACHE_SIZE (1 << DWARF_DEFAULT_LOG_UNW_CACHE_SIZE)
|
||||
|
||||
#define DWARF_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1)
|
||||
#define DWARF_DEFAULT_UNW_HASH_SIZE (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE)
|
||||
|
||||
typedef unsigned char unw_hash_index_t;
|
||||
|
||||
struct dwarf_rs_cache
|
||||
{
|
||||
pthread_mutex_t lock;
|
||||
unsigned short rr_head; /* index of least-recently allocated rs */
|
||||
|
||||
unsigned short log_size;
|
||||
unsigned short prev_log_size;
|
||||
|
||||
/* hash table that maps instruction pointer to rs index: */
|
||||
unsigned short *hash;
|
||||
|
||||
uint32_t generation; /* generation number */
|
||||
|
||||
/* rs cache: */
|
||||
dwarf_reg_state_t *buckets;
|
||||
dwarf_reg_cache_entry_t *links;
|
||||
|
||||
/* default memory, loaded in BSS segment */
|
||||
unsigned short default_hash[DWARF_DEFAULT_UNW_HASH_SIZE];
|
||||
dwarf_reg_state_t default_buckets[DWARF_DEFAULT_UNW_CACHE_SIZE];
|
||||
dwarf_reg_cache_entry_t default_links[DWARF_DEFAULT_UNW_CACHE_SIZE];
|
||||
};
|
||||
|
||||
/* A list of descriptors for loaded .debug_frame sections. */
|
||||
|
||||
struct unw_debug_frame_list
|
||||
{
|
||||
/* The start (inclusive) and end (exclusive) of the described region. */
|
||||
unw_word_t start;
|
||||
unw_word_t end;
|
||||
/* The debug frame itself. */
|
||||
char *debug_frame;
|
||||
size_t debug_frame_size;
|
||||
/* Index (for binary search). */
|
||||
struct table_entry *index;
|
||||
size_t index_size;
|
||||
/* Pointer to next descriptor. */
|
||||
struct unw_debug_frame_list *next;
|
||||
};
|
||||
|
||||
/* Convenience macros: */
|
||||
#define dwarf_init UNW_ARCH_OBJ (dwarf_init)
|
||||
#define dwarf_callback UNW_OBJ (dwarf_callback)
|
||||
#define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info)
|
||||
#define dwarf_find_debug_frame UNW_OBJ (dwarf_find_debug_frame)
|
||||
#define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table)
|
||||
#define dwarf_find_unwind_table UNW_OBJ (dwarf_find_unwind_table)
|
||||
#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
|
||||
#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
|
||||
#define dwarf_eval_expr UNW_OBJ (dwarf_eval_expr)
|
||||
#define dwarf_stack_aligned UNW_OBJ (dwarf_stack_aligned)
|
||||
#define dwarf_extract_proc_info_from_fde \
|
||||
UNW_OBJ (dwarf_extract_proc_info_from_fde)
|
||||
#define dwarf_find_save_locs UNW_OBJ (dwarf_find_save_locs)
|
||||
#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
|
||||
#define dwarf_apply_reg_state UNW_OBJ (dwarf_apply_reg_state)
|
||||
#define dwarf_reg_states_iterate UNW_OBJ (dwarf_reg_states_iterate)
|
||||
#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
|
||||
#define dwarf_step UNW_OBJ (dwarf_step)
|
||||
#define dwarf_flush_rs_cache UNW_OBJ (dwarf_flush_rs_cache)
|
||||
|
||||
extern int dwarf_init (void);
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
extern int dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr);
|
||||
extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
||||
extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
|
||||
unw_word_t ip, unw_word_t segbase,
|
||||
const char* obj_name, unw_word_t start,
|
||||
unw_word_t end);
|
||||
extern int dwarf_search_unwind_table (unw_addr_space_t as,
|
||||
unw_word_t ip,
|
||||
unw_dyn_info_t *di,
|
||||
unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
||||
char *path, unw_word_t segbase, unw_word_t mapoff,
|
||||
unw_word_t ip);
|
||||
extern void dwarf_put_unwind_info (unw_addr_space_t as,
|
||||
unw_proc_info_t *pi, void *arg);
|
||||
extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
|
||||
unw_word_t len, unw_word_t *valp,
|
||||
int *is_register);
|
||||
extern int
|
||||
dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr,
|
||||
unw_word_t rbp_addr, unw_word_t *offset);
|
||||
|
||||
extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
|
||||
unw_accessors_t *a,
|
||||
unw_word_t *fde_addr,
|
||||
unw_proc_info_t *pi,
|
||||
unw_word_t base,
|
||||
int need_unwind_info,
|
||||
int is_debug_frame,
|
||||
void *arg);
|
||||
extern int dwarf_find_save_locs (struct dwarf_cursor *c);
|
||||
extern int dwarf_make_proc_info (struct dwarf_cursor *c);
|
||||
extern int dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs);
|
||||
extern int dwarf_reg_states_iterate (struct dwarf_cursor *c, unw_reg_states_callback cb, void *token);
|
||||
extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
|
||||
unw_accessors_t *a,
|
||||
unw_word_t *addr,
|
||||
unsigned char encoding,
|
||||
const unw_proc_info_t *pi,
|
||||
unw_word_t *valp, void *arg);
|
||||
extern int dwarf_step (struct dwarf_cursor *c);
|
||||
extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache);
|
||||
|
||||
#endif /* dwarf_h */
|
@ -1,490 +0,0 @@
|
||||
#ifndef DWARF_I_H
|
||||
#define DWARF_I_H
|
||||
|
||||
/* This file contains definitions that cannot be used in code outside
|
||||
of libunwind. In particular, most inline functions are here
|
||||
because otherwise they'd generate unresolved references when the
|
||||
files are compiled with inlining disabled. */
|
||||
|
||||
#include "dwarf.h"
|
||||
#include "libunwind_i.h"
|
||||
|
||||
/* Unless we are told otherwise, assume that a "machine address" is
|
||||
the size of an unw_word_t. */
|
||||
#ifndef dwarf_addr_size
|
||||
# define dwarf_addr_size(as) (sizeof (unw_word_t))
|
||||
#endif
|
||||
|
||||
#ifndef dwarf_to_unw_regnum
|
||||
# define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map)
|
||||
extern const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH];
|
||||
/* REG is evaluated multiple times; it better be side-effects free! */
|
||||
# define dwarf_to_unw_regnum(reg) \
|
||||
(((reg) < DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0)
|
||||
#endif
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
|
||||
/* In the local-only case, we can let the compiler directly access
|
||||
memory and don't need to worry about differing byte-order. */
|
||||
|
||||
typedef union __attribute__ ((packed))
|
||||
{
|
||||
int8_t s8;
|
||||
int16_t s16;
|
||||
int32_t s32;
|
||||
int64_t s64;
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
void *ptr;
|
||||
}
|
||||
dwarf_misaligned_value_t;
|
||||
|
||||
static inline int
|
||||
dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
int8_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->s8;
|
||||
*addr += sizeof (mvp->s8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
int16_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->s16;
|
||||
*addr += sizeof (mvp->s16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
int32_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->s32;
|
||||
*addr += sizeof (mvp->s32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
int64_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->s64;
|
||||
*addr += sizeof (mvp->s64);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
uint8_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->u8;
|
||||
*addr += sizeof (mvp->u8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
uint16_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->u16;
|
||||
*addr += sizeof (mvp->u16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
uint32_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->u32;
|
||||
*addr += sizeof (mvp->u32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
uint64_t *val, void *arg)
|
||||
{
|
||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||
|
||||
*val = mvp->u64;
|
||||
*addr += sizeof (mvp->u64);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
|
||||
static inline int
|
||||
dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
uint8_t *valp, void *arg)
|
||||
{
|
||||
unw_word_t val, aligned_addr = *addr & -sizeof (unw_word_t);
|
||||
unw_word_t off = *addr - aligned_addr;
|
||||
int ret;
|
||||
|
||||
*addr += 1;
|
||||
ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
val >>= 8*off;
|
||||
#else
|
||||
val >>= 8*(sizeof (unw_word_t) - 1 - off);
|
||||
#endif
|
||||
*valp = (uint8_t) val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
uint16_t *val, void *arg)
|
||||
{
|
||||
uint8_t v0, v1;
|
||||
int ret;
|
||||
|
||||
if ((ret = dwarf_readu8 (as, a, addr, &v0, arg)) < 0
|
||||
|| (ret = dwarf_readu8 (as, a, addr, &v1, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
if (tdep_big_endian (as))
|
||||
*val = (uint16_t) v0 << 8 | v1;
|
||||
else
|
||||
*val = (uint16_t) v1 << 8 | v0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
uint32_t *val, void *arg)
|
||||
{
|
||||
uint16_t v0, v1;
|
||||
int ret;
|
||||
|
||||
if ((ret = dwarf_readu16 (as, a, addr, &v0, arg)) < 0
|
||||
|| (ret = dwarf_readu16 (as, a, addr, &v1, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
if (tdep_big_endian (as))
|
||||
*val = (uint32_t) v0 << 16 | v1;
|
||||
else
|
||||
*val = (uint32_t) v1 << 16 | v0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
uint64_t *val, void *arg)
|
||||
{
|
||||
uint32_t v0, v1;
|
||||
int ret;
|
||||
|
||||
if ((ret = dwarf_readu32 (as, a, addr, &v0, arg)) < 0
|
||||
|| (ret = dwarf_readu32 (as, a, addr, &v1, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
if (tdep_big_endian (as))
|
||||
*val = (uint64_t) v0 << 32 | v1;
|
||||
else
|
||||
*val = (uint64_t) v1 << 32 | v0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
int8_t *val, void *arg)
|
||||
{
|
||||
uint8_t uval;
|
||||
int ret;
|
||||
|
||||
if ((ret = dwarf_readu8 (as, a, addr, &uval, arg)) < 0)
|
||||
return ret;
|
||||
*val = (int8_t) uval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
int16_t *val, void *arg)
|
||||
{
|
||||
uint16_t uval;
|
||||
int ret;
|
||||
|
||||
if ((ret = dwarf_readu16 (as, a, addr, &uval, arg)) < 0)
|
||||
return ret;
|
||||
*val = (int16_t) uval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
int32_t *val, void *arg)
|
||||
{
|
||||
uint32_t uval;
|
||||
int ret;
|
||||
|
||||
if ((ret = dwarf_readu32 (as, a, addr, &uval, arg)) < 0)
|
||||
return ret;
|
||||
*val = (int32_t) uval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
int64_t *val, void *arg)
|
||||
{
|
||||
uint64_t uval;
|
||||
int ret;
|
||||
|
||||
if ((ret = dwarf_readu64 (as, a, addr, &uval, arg)) < 0)
|
||||
return ret;
|
||||
*val = (int64_t) uval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
static inline int
|
||||
dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
unw_word_t *val, void *arg)
|
||||
{
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
int ret;
|
||||
|
||||
switch (dwarf_addr_size (as))
|
||||
{
|
||||
case 4:
|
||||
ret = dwarf_readu32 (as, a, addr, &u32, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = u32;
|
||||
return ret;
|
||||
|
||||
case 8:
|
||||
ret = dwarf_readu64 (as, a, addr, &u64, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = u64;
|
||||
return ret;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Read an unsigned "little-endian base 128" value. See Chapter 7.6
|
||||
of DWARF spec v3. */
|
||||
|
||||
static inline int
|
||||
dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
unw_word_t *valp, void *arg)
|
||||
{
|
||||
unw_word_t val = 0, shift = 0;
|
||||
unsigned char byte;
|
||||
int ret;
|
||||
|
||||
do
|
||||
{
|
||||
if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
val |= ((unw_word_t) byte & 0x7f) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
while (byte & 0x80);
|
||||
|
||||
*valp = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read a signed "little-endian base 128" value. See Chapter 7.6 of
|
||||
DWARF spec v3. */
|
||||
|
||||
static inline int
|
||||
dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
unw_word_t *valp, void *arg)
|
||||
{
|
||||
unw_word_t val = 0, shift = 0;
|
||||
unsigned char byte;
|
||||
int ret;
|
||||
|
||||
do
|
||||
{
|
||||
if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
|
||||
return ret;
|
||||
|
||||
val |= ((unw_word_t) byte & 0x7f) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
while (byte & 0x80);
|
||||
|
||||
if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0)
|
||||
/* sign-extend negative value */
|
||||
val |= ((unw_word_t) -1) << shift;
|
||||
|
||||
*valp = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE int
|
||||
dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, unsigned char encoding,
|
||||
const unw_proc_info_t *pi,
|
||||
unw_word_t *valp, void *arg)
|
||||
{
|
||||
unw_word_t val, initial_addr = *addr;
|
||||
uint16_t uval16;
|
||||
uint32_t uval32;
|
||||
uint64_t uval64;
|
||||
int16_t sval16 = 0;
|
||||
int32_t sval32 = 0;
|
||||
int64_t sval64 = 0;
|
||||
int ret;
|
||||
|
||||
/* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal
|
||||
format/application encoding. Handle them first. */
|
||||
if (encoding == DW_EH_PE_omit)
|
||||
{
|
||||
*valp = 0;
|
||||
return 0;
|
||||
}
|
||||
else if (encoding == DW_EH_PE_aligned)
|
||||
{
|
||||
int size = dwarf_addr_size (as);
|
||||
*addr = (initial_addr + size - 1) & -size;
|
||||
return dwarf_readw (as, a, addr, valp, arg);
|
||||
}
|
||||
|
||||
switch (encoding & DW_EH_PE_FORMAT_MASK)
|
||||
{
|
||||
case DW_EH_PE_ptr:
|
||||
if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_uleb128:
|
||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_udata2:
|
||||
if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0)
|
||||
return ret;
|
||||
val = uval16;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_udata4:
|
||||
if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0)
|
||||
return ret;
|
||||
val = uval32;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_udata8:
|
||||
if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0)
|
||||
return ret;
|
||||
val = uval64;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_sleb128:
|
||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_sdata2:
|
||||
if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0)
|
||||
return ret;
|
||||
val = sval16;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_sdata4:
|
||||
if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0)
|
||||
return ret;
|
||||
val = sval32;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_sdata8:
|
||||
if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0)
|
||||
return ret;
|
||||
val = sval64;
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug (1, "unexpected encoding format 0x%x\n",
|
||||
encoding & DW_EH_PE_FORMAT_MASK);
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
|
||||
if (val == 0)
|
||||
{
|
||||
/* 0 is a special value and always absolute. */
|
||||
*valp = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (encoding & DW_EH_PE_APPL_MASK)
|
||||
{
|
||||
case DW_EH_PE_absptr:
|
||||
break;
|
||||
|
||||
case DW_EH_PE_pcrel:
|
||||
val += initial_addr;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_datarel:
|
||||
/* XXX For now, assume that data-relative addresses are relative
|
||||
to the global pointer. */
|
||||
val += pi->gp;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_funcrel:
|
||||
val += pi->start_ip;
|
||||
break;
|
||||
|
||||
case DW_EH_PE_textrel:
|
||||
/* XXX For now we don't support text-rel values. If there is a
|
||||
platform which needs this, we probably would have to add a
|
||||
"segbase" member to unw_proc_info_t. */
|
||||
default:
|
||||
Debug (1, "unexpected application type 0x%x\n",
|
||||
encoding & DW_EH_PE_APPL_MASK);
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
|
||||
/* Trim off any extra bits. Assume that sign extension isn't
|
||||
required; the only place it is needed is MIPS kernel space
|
||||
addresses. */
|
||||
if (sizeof (val) > dwarf_addr_size (as))
|
||||
{
|
||||
assert (dwarf_addr_size (as) == 4);
|
||||
val = (uint32_t) val;
|
||||
}
|
||||
|
||||
if (encoding & DW_EH_PE_indirect)
|
||||
{
|
||||
unw_word_t indirect_addr = val;
|
||||
|
||||
if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
*valp = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* DWARF_I_H */
|
@ -1,210 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
Copyright (C) 2013 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. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define UNW_TARGET aarch64
|
||||
#define UNW_TARGET_AARCH64 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
|
||||
#define UNW_TDEP_CURSOR_LEN 512
|
||||
|
||||
typedef uint64_t unw_word_t;
|
||||
typedef int64_t unw_sword_t;
|
||||
|
||||
typedef long double unw_tdep_fpreg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no aarch64-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* 64-bit general registers. */
|
||||
UNW_AARCH64_X0,
|
||||
UNW_AARCH64_X1,
|
||||
UNW_AARCH64_X2,
|
||||
UNW_AARCH64_X3,
|
||||
UNW_AARCH64_X4,
|
||||
UNW_AARCH64_X5,
|
||||
UNW_AARCH64_X6,
|
||||
UNW_AARCH64_X7,
|
||||
UNW_AARCH64_X8,
|
||||
|
||||
/* Temporary registers. */
|
||||
UNW_AARCH64_X9,
|
||||
UNW_AARCH64_X10,
|
||||
UNW_AARCH64_X11,
|
||||
UNW_AARCH64_X12,
|
||||
UNW_AARCH64_X13,
|
||||
UNW_AARCH64_X14,
|
||||
UNW_AARCH64_X15,
|
||||
|
||||
/* Intra-procedure-call temporary registers. */
|
||||
UNW_AARCH64_X16,
|
||||
UNW_AARCH64_X17,
|
||||
|
||||
/* Callee-saved registers. */
|
||||
UNW_AARCH64_X18,
|
||||
UNW_AARCH64_X19,
|
||||
UNW_AARCH64_X20,
|
||||
UNW_AARCH64_X21,
|
||||
UNW_AARCH64_X22,
|
||||
UNW_AARCH64_X23,
|
||||
UNW_AARCH64_X24,
|
||||
UNW_AARCH64_X25,
|
||||
UNW_AARCH64_X26,
|
||||
UNW_AARCH64_X27,
|
||||
UNW_AARCH64_X28,
|
||||
|
||||
/* 64-bit frame pointer. */
|
||||
UNW_AARCH64_X29,
|
||||
|
||||
/* 64-bit link register. */
|
||||
UNW_AARCH64_X30,
|
||||
|
||||
/* 64-bit stack pointer. */
|
||||
UNW_AARCH64_SP = 31,
|
||||
UNW_AARCH64_PC,
|
||||
UNW_AARCH64_PSTATE,
|
||||
|
||||
/* 128-bit FP/Advanced SIMD registers. */
|
||||
UNW_AARCH64_V0 = 64,
|
||||
UNW_AARCH64_V1,
|
||||
UNW_AARCH64_V2,
|
||||
UNW_AARCH64_V3,
|
||||
UNW_AARCH64_V4,
|
||||
UNW_AARCH64_V5,
|
||||
UNW_AARCH64_V6,
|
||||
UNW_AARCH64_V7,
|
||||
UNW_AARCH64_V8,
|
||||
UNW_AARCH64_V9,
|
||||
UNW_AARCH64_V10,
|
||||
UNW_AARCH64_V11,
|
||||
UNW_AARCH64_V12,
|
||||
UNW_AARCH64_V13,
|
||||
UNW_AARCH64_V14,
|
||||
UNW_AARCH64_V15,
|
||||
UNW_AARCH64_V16,
|
||||
UNW_AARCH64_V17,
|
||||
UNW_AARCH64_V18,
|
||||
UNW_AARCH64_V19,
|
||||
UNW_AARCH64_V20,
|
||||
UNW_AARCH64_V21,
|
||||
UNW_AARCH64_V22,
|
||||
UNW_AARCH64_V23,
|
||||
UNW_AARCH64_V24,
|
||||
UNW_AARCH64_V25,
|
||||
UNW_AARCH64_V26,
|
||||
UNW_AARCH64_V27,
|
||||
UNW_AARCH64_V28,
|
||||
UNW_AARCH64_V29,
|
||||
UNW_AARCH64_V30,
|
||||
UNW_AARCH64_V31,
|
||||
|
||||
UNW_AARCH64_FPSR,
|
||||
UNW_AARCH64_FPCR,
|
||||
|
||||
/* For AArch64, the CFA is the value of SP (x31) at the call site of the
|
||||
previous frame. */
|
||||
UNW_AARCH64_CFA = UNW_AARCH64_SP,
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_AARCH64_FPCR,
|
||||
|
||||
UNW_TDEP_IP = UNW_AARCH64_X30,
|
||||
UNW_TDEP_SP = UNW_AARCH64_SP,
|
||||
UNW_TDEP_EH = UNW_AARCH64_X0,
|
||||
|
||||
}
|
||||
aarch64_regnum_t;
|
||||
|
||||
/* Use R0 through R3 to pass exception handling information. */
|
||||
#define UNW_TDEP_NUM_EH_REGS 4
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
|
||||
/* On AArch64, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
#define unw_tdep_getcontext(uc) (({ \
|
||||
unw_tdep_context_t *unw_ctx = (uc); \
|
||||
register uint64_t *unw_base asm ("x0") = (uint64_t*) unw_ctx->uc_mcontext.regs; \
|
||||
__asm__ __volatile__ ( \
|
||||
"stp x0, x1, [%[base], #0]\n" \
|
||||
"stp x2, x3, [%[base], #16]\n" \
|
||||
"stp x4, x5, [%[base], #32]\n" \
|
||||
"stp x6, x7, [%[base], #48]\n" \
|
||||
"stp x8, x9, [%[base], #64]\n" \
|
||||
"stp x10, x11, [%[base], #80]\n" \
|
||||
"stp x12, x13, [%[base], #96]\n" \
|
||||
"stp x14, x13, [%[base], #112]\n" \
|
||||
"stp x16, x17, [%[base], #128]\n" \
|
||||
"stp x18, x19, [%[base], #144]\n" \
|
||||
"stp x20, x21, [%[base], #160]\n" \
|
||||
"stp x22, x23, [%[base], #176]\n" \
|
||||
"stp x24, x25, [%[base], #192]\n" \
|
||||
"stp x26, x27, [%[base], #208]\n" \
|
||||
"stp x28, x29, [%[base], #224]\n" \
|
||||
"str x30, [%[base], #240]\n" \
|
||||
"mov x1, sp\n" \
|
||||
"stp x1, x30, [%[base], #248]\n" \
|
||||
: [base] "+r" (unw_base) : : "x1", "memory"); \
|
||||
}), 0)
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,303 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define UNW_TARGET arm
|
||||
#define UNW_TARGET_ARM 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
|
||||
/* FIXME for ARM. Too big? What do other things use for similar tasks? */
|
||||
#define UNW_TDEP_CURSOR_LEN 4096
|
||||
|
||||
typedef uint32_t unw_word_t;
|
||||
typedef int32_t unw_sword_t;
|
||||
|
||||
typedef long double unw_tdep_fpreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_ARM_R0,
|
||||
UNW_ARM_R1,
|
||||
UNW_ARM_R2,
|
||||
UNW_ARM_R3,
|
||||
UNW_ARM_R4,
|
||||
UNW_ARM_R5,
|
||||
UNW_ARM_R6,
|
||||
UNW_ARM_R7,
|
||||
UNW_ARM_R8,
|
||||
UNW_ARM_R9,
|
||||
UNW_ARM_R10,
|
||||
UNW_ARM_R11,
|
||||
UNW_ARM_R12,
|
||||
UNW_ARM_R13,
|
||||
UNW_ARM_R14,
|
||||
UNW_ARM_R15,
|
||||
|
||||
/* VFPv2 s0-s31 (obsolescent numberings). */
|
||||
UNW_ARM_S0 = 64,
|
||||
UNW_ARM_S1,
|
||||
UNW_ARM_S2,
|
||||
UNW_ARM_S3,
|
||||
UNW_ARM_S4,
|
||||
UNW_ARM_S5,
|
||||
UNW_ARM_S6,
|
||||
UNW_ARM_S7,
|
||||
UNW_ARM_S8,
|
||||
UNW_ARM_S9,
|
||||
UNW_ARM_S10,
|
||||
UNW_ARM_S11,
|
||||
UNW_ARM_S12,
|
||||
UNW_ARM_S13,
|
||||
UNW_ARM_S14,
|
||||
UNW_ARM_S15,
|
||||
UNW_ARM_S16,
|
||||
UNW_ARM_S17,
|
||||
UNW_ARM_S18,
|
||||
UNW_ARM_S19,
|
||||
UNW_ARM_S20,
|
||||
UNW_ARM_S21,
|
||||
UNW_ARM_S22,
|
||||
UNW_ARM_S23,
|
||||
UNW_ARM_S24,
|
||||
UNW_ARM_S25,
|
||||
UNW_ARM_S26,
|
||||
UNW_ARM_S27,
|
||||
UNW_ARM_S28,
|
||||
UNW_ARM_S29,
|
||||
UNW_ARM_S30,
|
||||
UNW_ARM_S31,
|
||||
|
||||
/* FPA register numberings. */
|
||||
UNW_ARM_F0 = 96,
|
||||
UNW_ARM_F1,
|
||||
UNW_ARM_F2,
|
||||
UNW_ARM_F3,
|
||||
UNW_ARM_F4,
|
||||
UNW_ARM_F5,
|
||||
UNW_ARM_F6,
|
||||
UNW_ARM_F7,
|
||||
|
||||
/* iWMMXt GR register numberings. */
|
||||
UNW_ARM_wCGR0 = 104,
|
||||
UNW_ARM_wCGR1,
|
||||
UNW_ARM_wCGR2,
|
||||
UNW_ARM_wCGR3,
|
||||
UNW_ARM_wCGR4,
|
||||
UNW_ARM_wCGR5,
|
||||
UNW_ARM_wCGR6,
|
||||
UNW_ARM_wCGR7,
|
||||
|
||||
/* iWMMXt register numberings. */
|
||||
UNW_ARM_wR0 = 112,
|
||||
UNW_ARM_wR1,
|
||||
UNW_ARM_wR2,
|
||||
UNW_ARM_wR3,
|
||||
UNW_ARM_wR4,
|
||||
UNW_ARM_wR5,
|
||||
UNW_ARM_wR6,
|
||||
UNW_ARM_wR7,
|
||||
UNW_ARM_wR8,
|
||||
UNW_ARM_wR9,
|
||||
UNW_ARM_wR10,
|
||||
UNW_ARM_wR11,
|
||||
UNW_ARM_wR12,
|
||||
UNW_ARM_wR13,
|
||||
UNW_ARM_wR14,
|
||||
UNW_ARM_wR15,
|
||||
|
||||
/* Two-byte encodings from here on. */
|
||||
|
||||
/* SPSR. */
|
||||
UNW_ARM_SPSR = 128,
|
||||
UNW_ARM_SPSR_FIQ,
|
||||
UNW_ARM_SPSR_IRQ,
|
||||
UNW_ARM_SPSR_ABT,
|
||||
UNW_ARM_SPSR_UND,
|
||||
UNW_ARM_SPSR_SVC,
|
||||
|
||||
/* User mode registers. */
|
||||
UNW_ARM_R8_USR = 144,
|
||||
UNW_ARM_R9_USR,
|
||||
UNW_ARM_R10_USR,
|
||||
UNW_ARM_R11_USR,
|
||||
UNW_ARM_R12_USR,
|
||||
UNW_ARM_R13_USR,
|
||||
UNW_ARM_R14_USR,
|
||||
|
||||
/* FIQ registers. */
|
||||
UNW_ARM_R8_FIQ = 151,
|
||||
UNW_ARM_R9_FIQ,
|
||||
UNW_ARM_R10_FIQ,
|
||||
UNW_ARM_R11_FIQ,
|
||||
UNW_ARM_R12_FIQ,
|
||||
UNW_ARM_R13_FIQ,
|
||||
UNW_ARM_R14_FIQ,
|
||||
|
||||
/* IRQ registers. */
|
||||
UNW_ARM_R13_IRQ = 158,
|
||||
UNW_ARM_R14_IRQ,
|
||||
|
||||
/* ABT registers. */
|
||||
UNW_ARM_R13_ABT = 160,
|
||||
UNW_ARM_R14_ABT,
|
||||
|
||||
/* UND registers. */
|
||||
UNW_ARM_R13_UND = 162,
|
||||
UNW_ARM_R14_UND,
|
||||
|
||||
/* SVC registers. */
|
||||
UNW_ARM_R13_SVC = 164,
|
||||
UNW_ARM_R14_SVC,
|
||||
|
||||
/* iWMMXt control registers. */
|
||||
UNW_ARM_wC0 = 192,
|
||||
UNW_ARM_wC1,
|
||||
UNW_ARM_wC2,
|
||||
UNW_ARM_wC3,
|
||||
UNW_ARM_wC4,
|
||||
UNW_ARM_wC5,
|
||||
UNW_ARM_wC6,
|
||||
UNW_ARM_wC7,
|
||||
|
||||
/* VFPv3/Neon 64-bit registers. */
|
||||
UNW_ARM_D0 = 256,
|
||||
UNW_ARM_D1,
|
||||
UNW_ARM_D2,
|
||||
UNW_ARM_D3,
|
||||
UNW_ARM_D4,
|
||||
UNW_ARM_D5,
|
||||
UNW_ARM_D6,
|
||||
UNW_ARM_D7,
|
||||
UNW_ARM_D8,
|
||||
UNW_ARM_D9,
|
||||
UNW_ARM_D10,
|
||||
UNW_ARM_D11,
|
||||
UNW_ARM_D12,
|
||||
UNW_ARM_D13,
|
||||
UNW_ARM_D14,
|
||||
UNW_ARM_D15,
|
||||
UNW_ARM_D16,
|
||||
UNW_ARM_D17,
|
||||
UNW_ARM_D18,
|
||||
UNW_ARM_D19,
|
||||
UNW_ARM_D20,
|
||||
UNW_ARM_D21,
|
||||
UNW_ARM_D22,
|
||||
UNW_ARM_D23,
|
||||
UNW_ARM_D24,
|
||||
UNW_ARM_D25,
|
||||
UNW_ARM_D26,
|
||||
UNW_ARM_D27,
|
||||
UNW_ARM_D28,
|
||||
UNW_ARM_D29,
|
||||
UNW_ARM_D30,
|
||||
UNW_ARM_D31,
|
||||
|
||||
/* For ARM, the CFA is the value of SP (r13) at the call site in the
|
||||
previous frame. */
|
||||
UNW_ARM_CFA,
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_ARM_D31,
|
||||
|
||||
UNW_TDEP_IP = UNW_ARM_R14, /* A little white lie. */
|
||||
UNW_TDEP_SP = UNW_ARM_R13,
|
||||
UNW_TDEP_EH = UNW_ARM_R0 /* FIXME. */
|
||||
}
|
||||
arm_regnum_t;
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for ARM. */
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
/* On ARM, we define our own unw_tdep_context instead of using ucontext_t.
|
||||
This allows us to support systems that don't support getcontext and
|
||||
therefore do not define ucontext_t. */
|
||||
typedef struct unw_tdep_context
|
||||
{
|
||||
unsigned long regs[16];
|
||||
}
|
||||
unw_tdep_context_t;
|
||||
|
||||
/* There is no getcontext() on ARM. Use a stub version which only saves GP
|
||||
registers. FIXME: Not ideal, may not be sufficient for all libunwind
|
||||
use cases. Stores pc+8, which is only approximately correct, really. */
|
||||
#ifndef __thumb__
|
||||
#define unw_tdep_getcontext(uc) (({ \
|
||||
unw_tdep_context_t *unw_ctx = (uc); \
|
||||
register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs; \
|
||||
__asm__ __volatile__ ( \
|
||||
"stmia %[base], {r0-r15}" \
|
||||
: : [base] "r" (unw_base) : "memory"); \
|
||||
}), 0)
|
||||
#else /* __thumb__ */
|
||||
#define unw_tdep_getcontext(uc) (({ \
|
||||
unw_tdep_context_t *unw_ctx = (uc); \
|
||||
register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs; \
|
||||
__asm__ __volatile__ ( \
|
||||
".align 2\nbx pc\nnop\n.code 32\n" \
|
||||
"stmia %[base], {r0-r15}\n" \
|
||||
"orr %[base], pc, #1\nbx %[base]\n" \
|
||||
".code 16\n" \
|
||||
: [base] "+r" (unw_base) : : "memory", "cc"); \
|
||||
}), 0)
|
||||
#endif
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no arm-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,279 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#define UNW_VERSION_MAJOR @PKG_MAJOR@
|
||||
#define UNW_VERSION_MINOR @PKG_MINOR@
|
||||
#define UNW_VERSION_EXTRA @PKG_EXTRA@
|
||||
|
||||
#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min))
|
||||
#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR)
|
||||
|
||||
#define UNW_PASTE2(x,y) x##y
|
||||
#define UNW_PASTE(x,y) UNW_PASTE2(x,y)
|
||||
#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn)
|
||||
#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_)
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
/* Error codes. The unwind routines return the *negated* values of
|
||||
these error codes on error and a non-negative value on success. */
|
||||
typedef enum
|
||||
{
|
||||
UNW_ESUCCESS = 0, /* no error */
|
||||
UNW_EUNSPEC, /* unspecified (general) error */
|
||||
UNW_ENOMEM, /* out of memory */
|
||||
UNW_EBADREG, /* bad register number */
|
||||
UNW_EREADONLYREG, /* attempt to write read-only register */
|
||||
UNW_ESTOPUNWIND, /* stop unwinding */
|
||||
UNW_EINVALIDIP, /* invalid IP */
|
||||
UNW_EBADFRAME, /* bad frame */
|
||||
UNW_EINVAL, /* unsupported operation or bad value */
|
||||
UNW_EBADVERSION, /* unwind info has unsupported version */
|
||||
UNW_ENOINFO /* no unwind info found */
|
||||
}
|
||||
unw_error_t;
|
||||
|
||||
/* The following enum defines the indices for a couple of
|
||||
(pseudo-)registers which have the same meaning across all
|
||||
platforms. (RO) means read-only. (RW) means read-write. General
|
||||
registers (aka "integer registers") are expected to start with
|
||||
index 0. The number of such registers is architecture-dependent.
|
||||
The remaining indices can be used as an architecture sees fit. The
|
||||
last valid register index is given by UNW_REG_LAST. */
|
||||
typedef enum
|
||||
{
|
||||
UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */
|
||||
UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */
|
||||
UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */
|
||||
UNW_REG_LAST = UNW_TDEP_LAST_REG
|
||||
}
|
||||
unw_frame_regnum_t;
|
||||
|
||||
/* Number of exception-handler argument registers: */
|
||||
#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_CACHE_NONE, /* no caching */
|
||||
UNW_CACHE_GLOBAL, /* shared global cache */
|
||||
UNW_CACHE_PER_THREAD /* per-thread caching */
|
||||
}
|
||||
unw_caching_policy_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_INIT_SIGNAL_FRAME = 1, /* We know this is a signal frame */
|
||||
}
|
||||
unw_init_local2_flags_t;
|
||||
|
||||
typedef int unw_regnum_t;
|
||||
|
||||
/* The unwind cursor starts at the youngest (most deeply nested) frame
|
||||
and is used to track the frame state as the unwinder steps from
|
||||
frame to frame. It is safe to make (shallow) copies of variables
|
||||
of this type. */
|
||||
typedef struct unw_cursor
|
||||
{
|
||||
unw_word_t opaque[UNW_TDEP_CURSOR_LEN];
|
||||
}
|
||||
unw_cursor_t;
|
||||
|
||||
/* This type encapsulates the entire (preserved) machine-state. */
|
||||
typedef unw_tdep_context_t unw_context_t;
|
||||
|
||||
/* unw_getcontext() fills the unw_context_t pointed to by UC with the
|
||||
machine state as it exists at the call-site. For implementation
|
||||
reasons, this needs to be a target-dependent macro. It's easiest
|
||||
to think of unw_getcontext() as being identical to getcontext(). */
|
||||
#define unw_getcontext(uc) unw_tdep_getcontext(uc)
|
||||
|
||||
/* Return 1 if register number R is a floating-point register, zero
|
||||
otherwise.
|
||||
This routine is signal-safe. */
|
||||
#define unw_is_fpreg(r) unw_tdep_is_fpreg(r)
|
||||
|
||||
typedef unw_tdep_fpreg_t unw_fpreg_t;
|
||||
|
||||
typedef struct unw_addr_space *unw_addr_space_t;
|
||||
|
||||
/* Each target may define it's own set of flags, but bits 0-15 are
|
||||
reserved for general libunwind-use. */
|
||||
#define UNW_PI_FLAG_FIRST_TDEP_BIT 16
|
||||
/* The information comes from a .debug_frame section. */
|
||||
#define UNW_PI_FLAG_DEBUG_FRAME 32
|
||||
|
||||
typedef struct unw_proc_info
|
||||
{
|
||||
unw_word_t start_ip; /* first IP covered by this procedure */
|
||||
unw_word_t end_ip; /* first IP NOT covered by this procedure */
|
||||
#if defined(NEED_LAST_IP)
|
||||
unw_word_t last_ip; /* first IP that could begin another procedure */
|
||||
#endif
|
||||
unw_word_t lsda; /* address of lang.-spec. data area (if any) */
|
||||
unw_word_t handler; /* optional personality routine */
|
||||
unw_word_t gp; /* global-pointer value for this procedure */
|
||||
unw_word_t flags; /* misc. flags */
|
||||
|
||||
int format; /* unwind-info format (arch-specific) */
|
||||
int unwind_info_size; /* size of the information (if applicable) */
|
||||
void *unwind_info; /* unwind-info (arch-specific) */
|
||||
unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */
|
||||
}
|
||||
unw_proc_info_t;
|
||||
|
||||
typedef int (*unw_reg_states_callback)(void *token,
|
||||
void *reg_states_data,
|
||||
size_t reg_states_data_size,
|
||||
unw_word_t start_ip, unw_word_t end_ip);
|
||||
|
||||
/* These are backend callback routines that provide access to the
|
||||
state of a "remote" process. This can be used, for example, to
|
||||
unwind another process through the ptrace() interface. */
|
||||
typedef struct unw_accessors
|
||||
{
|
||||
/* Look up the unwind info associated with instruction-pointer IP.
|
||||
On success, the routine fills in the PROC_INFO structure. */
|
||||
int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *,
|
||||
int, void *);
|
||||
|
||||
/* Release any resources (e.g., memory) that were allocated for
|
||||
the unwind info returned in by a previous call to
|
||||
find_proc_info() with NEED_UNWIND_INFO set to 1. */
|
||||
void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *);
|
||||
|
||||
/* Return the list-head of the dynamically registered unwind
|
||||
info. */
|
||||
int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *);
|
||||
|
||||
/* Access aligned word at address ADDR. The value is returned
|
||||
according to the endianness of the host (e.g., if the host is
|
||||
little-endian and the target is big-endian, access_mem() needs
|
||||
to byte-swap the value before returning it). */
|
||||
int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int,
|
||||
void *);
|
||||
|
||||
/* Access register number REG at address ADDR. */
|
||||
int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int,
|
||||
void *);
|
||||
|
||||
/* Access register number REG at address ADDR. */
|
||||
int (*access_fpreg) (unw_addr_space_t, unw_regnum_t,
|
||||
unw_fpreg_t *, int, void *);
|
||||
|
||||
int (*resume) (unw_addr_space_t, unw_cursor_t *, void *);
|
||||
|
||||
/* Optional call back to obtain the name of a (static) procedure.
|
||||
Dynamically generated procedures are handled automatically by
|
||||
libunwind. This callback is optional and may be set to
|
||||
NULL. */
|
||||
int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t,
|
||||
unw_word_t *, void *);
|
||||
}
|
||||
unw_accessors_t;
|
||||
|
||||
typedef enum unw_save_loc_type
|
||||
{
|
||||
UNW_SLT_NONE, /* register is not saved ("not an l-value") */
|
||||
UNW_SLT_MEMORY, /* register has been saved in memory */
|
||||
UNW_SLT_REG /* register has been saved in (another) register */
|
||||
}
|
||||
unw_save_loc_type_t;
|
||||
|
||||
typedef struct unw_save_loc
|
||||
{
|
||||
unw_save_loc_type_t type;
|
||||
union
|
||||
{
|
||||
unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */
|
||||
unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */
|
||||
}
|
||||
u;
|
||||
unw_tdep_save_loc_t extra; /* target-dependent additional information */
|
||||
}
|
||||
unw_save_loc_t;
|
||||
|
||||
/* These routines work both for local and remote unwinding. */
|
||||
|
||||
#define unw_local_addr_space UNW_OBJ(local_addr_space)
|
||||
#define unw_create_addr_space UNW_OBJ(create_addr_space)
|
||||
#define unw_destroy_addr_space UNW_OBJ(destroy_addr_space)
|
||||
#define unw_get_accessors UNW_ARCH_OBJ(get_accessors)
|
||||
#define unw_init_local UNW_OBJ(init_local)
|
||||
#define unw_init_local2 UNW_OBJ(init_local2)
|
||||
#define unw_init_remote UNW_OBJ(init_remote)
|
||||
#define unw_step UNW_OBJ(step)
|
||||
#define unw_resume UNW_OBJ(resume)
|
||||
#define unw_get_proc_info UNW_OBJ(get_proc_info)
|
||||
#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip)
|
||||
#define unw_reg_states_iterate UNW_OBJ(reg_states_iterate)
|
||||
#define unw_apply_reg_state UNW_OBJ(apply_reg_state)
|
||||
#define unw_get_reg UNW_OBJ(get_reg)
|
||||
#define unw_set_reg UNW_OBJ(set_reg)
|
||||
#define unw_get_fpreg UNW_OBJ(get_fpreg)
|
||||
#define unw_set_fpreg UNW_OBJ(set_fpreg)
|
||||
#define unw_get_save_loc UNW_OBJ(get_save_loc)
|
||||
#define unw_is_signal_frame UNW_OBJ(is_signal_frame)
|
||||
#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame)
|
||||
#define unw_get_proc_name UNW_OBJ(get_proc_name)
|
||||
#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
|
||||
#define unw_set_cache_size UNW_OBJ(set_cache_size)
|
||||
#define unw_regname UNW_ARCH_OBJ(regname)
|
||||
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
|
||||
#define unw_strerror UNW_ARCH_OBJ(strerror)
|
||||
|
||||
extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int);
|
||||
extern void unw_destroy_addr_space (unw_addr_space_t);
|
||||
extern unw_accessors_t *unw_get_accessors (unw_addr_space_t);
|
||||
extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t);
|
||||
extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t);
|
||||
extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
|
||||
extern const char *unw_regname (unw_regnum_t);
|
||||
|
||||
extern int unw_init_local (unw_cursor_t *, unw_context_t *);
|
||||
extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int);
|
||||
extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *);
|
||||
extern int unw_step (unw_cursor_t *);
|
||||
extern int unw_resume (unw_cursor_t *);
|
||||
extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *);
|
||||
extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t,
|
||||
unw_proc_info_t *, void *);
|
||||
extern int unw_reg_states_iterate (unw_cursor_t *, unw_reg_states_callback, void *);
|
||||
extern int unw_apply_reg_state (unw_cursor_t *, void *);
|
||||
extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *);
|
||||
extern int unw_set_reg (unw_cursor_t *, int, unw_word_t);
|
||||
extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *);
|
||||
extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t);
|
||||
extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *);
|
||||
extern int unw_is_signal_frame (unw_cursor_t *);
|
||||
extern int unw_handle_signal_frame (unw_cursor_t *);
|
||||
extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *);
|
||||
extern const char *unw_strerror (int);
|
||||
extern int unw_backtrace (void **, int);
|
||||
|
||||
extern unw_addr_space_t unw_local_addr_space;
|
@ -1,73 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef libunwind_coredump_h
|
||||
#define libunwind_coredump_h
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Helper routines which make it easy to use libunwind on a coredump.
|
||||
They're available only if UNW_REMOTE_ONLY is _not_ defined and they
|
||||
aren't really part of the libunwind API. They are implemented in a
|
||||
archive library called libunwind-coredump.a. */
|
||||
|
||||
struct UCD_info;
|
||||
|
||||
extern struct UCD_info *_UCD_create(const char *filename);
|
||||
extern void _UCD_destroy(struct UCD_info *);
|
||||
|
||||
extern int _UCD_get_num_threads(struct UCD_info *);
|
||||
extern void _UCD_select_thread(struct UCD_info *, int);
|
||||
extern pid_t _UCD_get_pid(struct UCD_info *);
|
||||
extern int _UCD_get_cursig(struct UCD_info *);
|
||||
extern int _UCD_add_backing_file_at_segment(struct UCD_info *, int phdr_no, const char *filename);
|
||||
extern int _UCD_add_backing_file_at_vaddr(struct UCD_info *,
|
||||
unsigned long vaddr,
|
||||
const char *filename);
|
||||
|
||||
extern int _UCD_find_proc_info (unw_addr_space_t, unw_word_t,
|
||||
unw_proc_info_t *, int, void *);
|
||||
extern void _UCD_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
|
||||
extern int _UCD_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
|
||||
void *);
|
||||
extern int _UCD_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
|
||||
void *);
|
||||
extern int _UCD_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
|
||||
int, void *);
|
||||
extern int _UCD_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
|
||||
int, void *);
|
||||
extern int _UCD_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
|
||||
unw_word_t *, void *);
|
||||
extern int _UCD_resume (unw_addr_space_t, unw_cursor_t *, void *);
|
||||
extern unw_accessors_t _UCD_accessors;
|
||||
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* libunwind_coredump_h */
|
@ -1,214 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002-2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
/* This file defines the runtime-support routines for dynamically
|
||||
generated code. Even though it is implemented as part of libunwind,
|
||||
it is logically separate from the interface to perform the actual
|
||||
unwinding. In particular, this interface is always used in the
|
||||
context of the unwind target, whereas the rest of the unwind API is
|
||||
used in context of the process that is doing the unwind (which may be
|
||||
a debugger running on another machine, for example).
|
||||
|
||||
Note that the data-structures declared here server a dual purpose:
|
||||
when a program registers a dynamically generated procedure, it uses
|
||||
these structures directly. On the other hand, with remote-unwinding,
|
||||
the data-structures are read from the remote process's memory and
|
||||
translated into internalized versions. To facilitate remote-access,
|
||||
the following rules should be followed in declaring these structures:
|
||||
|
||||
(1) Declare a member as a pointer only if the the information the
|
||||
member points to needs to be internalized as well (e.g., a
|
||||
string representing a procedure name should be declared as
|
||||
"const char *", but the instruction pointer should be declared
|
||||
as unw_word_t).
|
||||
|
||||
(2) Provide sufficient padding to ensure that no implicit padding
|
||||
will be needed on any of the supported target architectures. For
|
||||
the time being, padding data structures with the assumption that
|
||||
sizeof (unw_word_t) == 8 should be sufficient. (Note: it's not
|
||||
impossible to internalize structures with internal padding, but
|
||||
it does make the process a bit harder).
|
||||
|
||||
(3) Don't declare members that contain bitfields or floating-point
|
||||
values.
|
||||
|
||||
(4) Don't declare members with enumeration types. Declare them as
|
||||
int32_t instead. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_DYN_STOP = 0, /* end-of-unwind-info marker */
|
||||
UNW_DYN_SAVE_REG, /* save register to another register */
|
||||
UNW_DYN_SPILL_FP_REL, /* frame-pointer-relative register spill */
|
||||
UNW_DYN_SPILL_SP_REL, /* stack-pointer-relative register spill */
|
||||
UNW_DYN_ADD, /* add constant value to a register */
|
||||
UNW_DYN_POP_FRAMES, /* drop one or more stack frames */
|
||||
UNW_DYN_LABEL_STATE, /* name the current state */
|
||||
UNW_DYN_COPY_STATE, /* set the region's entry-state */
|
||||
UNW_DYN_ALIAS /* get unwind info from an alias */
|
||||
}
|
||||
unw_dyn_operation_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */
|
||||
UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */
|
||||
UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */
|
||||
UNW_INFO_FORMAT_ARM_EXIDX, /* ARM specific unwind info */
|
||||
UNW_INFO_FORMAT_IP_OFFSET, /* Like UNW_INFO_FORMAT_REMOTE_TABLE, but
|
||||
table entries are considered
|
||||
relative to di->start_ip, rather
|
||||
than di->segbase */
|
||||
}
|
||||
unw_dyn_info_format_t;
|
||||
|
||||
typedef struct unw_dyn_op
|
||||
{
|
||||
int8_t tag; /* what operation? */
|
||||
int8_t qp; /* qualifying predicate register */
|
||||
int16_t reg; /* what register */
|
||||
int32_t when; /* when does it take effect? */
|
||||
unw_word_t val; /* auxiliary value */
|
||||
}
|
||||
unw_dyn_op_t;
|
||||
|
||||
typedef struct unw_dyn_region_info
|
||||
{
|
||||
struct unw_dyn_region_info *next; /* linked list of regions */
|
||||
int32_t insn_count; /* region length (# of instructions) */
|
||||
uint32_t op_count; /* length of op-array */
|
||||
unw_dyn_op_t op[1]; /* variable-length op-array */
|
||||
}
|
||||
unw_dyn_region_info_t;
|
||||
|
||||
typedef struct unw_dyn_proc_info
|
||||
{
|
||||
unw_word_t name_ptr; /* address of human-readable procedure name */
|
||||
unw_word_t handler; /* address of personality routine */
|
||||
uint32_t flags;
|
||||
int32_t pad0;
|
||||
unw_dyn_region_info_t *regions;
|
||||
}
|
||||
unw_dyn_proc_info_t;
|
||||
|
||||
typedef struct unw_dyn_table_info
|
||||
{
|
||||
unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
|
||||
unw_word_t segbase; /* segment base */
|
||||
unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
|
||||
unw_word_t *table_data;
|
||||
}
|
||||
unw_dyn_table_info_t;
|
||||
|
||||
typedef struct unw_dyn_remote_table_info
|
||||
{
|
||||
unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
|
||||
unw_word_t segbase; /* segment base */
|
||||
unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
|
||||
unw_word_t table_data;
|
||||
}
|
||||
unw_dyn_remote_table_info_t;
|
||||
|
||||
typedef struct unw_dyn_info
|
||||
{
|
||||
/* doubly-linked list of dyn-info structures: */
|
||||
struct unw_dyn_info *next;
|
||||
struct unw_dyn_info *prev;
|
||||
unw_word_t start_ip; /* first IP covered by this entry */
|
||||
unw_word_t end_ip; /* first IP NOT covered by this entry */
|
||||
unw_word_t gp; /* global-pointer in effect for this entry */
|
||||
int32_t format; /* real type: unw_dyn_info_format_t */
|
||||
int32_t pad;
|
||||
union
|
||||
{
|
||||
unw_dyn_proc_info_t pi;
|
||||
unw_dyn_table_info_t ti;
|
||||
unw_dyn_remote_table_info_t rti;
|
||||
}
|
||||
u;
|
||||
}
|
||||
unw_dyn_info_t;
|
||||
|
||||
typedef struct unw_dyn_info_list
|
||||
{
|
||||
uint32_t version;
|
||||
uint32_t generation;
|
||||
unw_dyn_info_t *first;
|
||||
}
|
||||
unw_dyn_info_list_t;
|
||||
|
||||
/* Return the size (in bytes) of an unw_dyn_region_info_t structure that can
|
||||
hold OP_COUNT ops. */
|
||||
#define _U_dyn_region_info_size(op_count) \
|
||||
((char *) (((unw_dyn_region_info_t *) NULL)->op + (op_count)) \
|
||||
- (char *) NULL)
|
||||
|
||||
/* Register the unwind info for a single procedure.
|
||||
This routine is NOT signal-safe. */
|
||||
extern void _U_dyn_register (unw_dyn_info_t *);
|
||||
|
||||
/* Cancel the unwind info for a single procedure.
|
||||
This routine is NOT signal-safe. */
|
||||
extern void _U_dyn_cancel (unw_dyn_info_t *);
|
||||
|
||||
|
||||
/* Convenience routines. */
|
||||
|
||||
#define _U_dyn_op(_tag, _qp, _when, _reg, _val) \
|
||||
((unw_dyn_op_t) { (_tag), (_qp), (_reg), (_when), (_val) })
|
||||
|
||||
#define _U_dyn_op_save_reg(op, qp, when, reg, dst) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_SAVE_REG, (qp), (when), (reg), (dst)))
|
||||
|
||||
#define _U_dyn_op_spill_fp_rel(op, qp, when, reg, offset) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (qp), (when), (reg), \
|
||||
(offset)))
|
||||
|
||||
#define _U_dyn_op_spill_sp_rel(op, qp, when, reg, offset) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_SPILL_SP_REL, (qp), (when), (reg), \
|
||||
(offset)))
|
||||
|
||||
#define _U_dyn_op_add(op, qp, when, reg, value) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_ADD, (qp), (when), (reg), (value)))
|
||||
|
||||
#define _U_dyn_op_pop_frames(op, qp, when, num_frames) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_POP_FRAMES, (qp), (when), 0, (num_frames)))
|
||||
|
||||
#define _U_dyn_op_label_state(op, label) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, _U_QP_TRUE, -1, 0, (label)))
|
||||
|
||||
#define _U_dyn_op_copy_state(op, label) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, _U_QP_TRUE, -1, 0, (label)))
|
||||
|
||||
#define _U_dyn_op_alias(op, qp, when, addr) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr)))
|
||||
|
||||
#define _U_dyn_op_stop(op) \
|
||||
(*(op) = _U_dyn_op (UNW_DYN_STOP, _U_QP_TRUE, -1, 0, 0))
|
||||
|
||||
/* The target-dependent qualifying predicate which is always TRUE. On
|
||||
IA-64, that's p0 (0), on non-predicated architectures, the value is
|
||||
ignored. */
|
||||
#define _U_QP_TRUE _U_TDEP_QP_TRUE
|
@ -1,125 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003-2004 Hewlett-Packard Co
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define UNW_TARGET hppa
|
||||
#define UNW_TARGET_HPPA 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
#define UNW_TDEP_CURSOR_LEN 511
|
||||
|
||||
typedef uint32_t unw_word_t;
|
||||
typedef int32_t unw_sword_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct { unw_word_t bits[2]; } raw;
|
||||
double val;
|
||||
}
|
||||
unw_tdep_fpreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Note: general registers are expected to start with index 0.
|
||||
This convention facilitates architecture-independent
|
||||
implementation of the C++ exception handling ABI. See
|
||||
_Unwind_SetGR() and _Unwind_GetGR() for details. */
|
||||
UNW_HPPA_GR = 0,
|
||||
UNW_HPPA_RP = 2, /* return pointer */
|
||||
UNW_HPPA_FP = 3, /* frame pointer */
|
||||
UNW_HPPA_SP = UNW_HPPA_GR + 30,
|
||||
|
||||
UNW_HPPA_FR = UNW_HPPA_GR + 32,
|
||||
|
||||
UNW_HPPA_IP = UNW_HPPA_FR + 32, /* instruction pointer */
|
||||
|
||||
/* other "preserved" registers (fpsr etc.)... */
|
||||
|
||||
/* PA-RISC has 4 exception-argument registers but they're not
|
||||
contiguous. To deal with this, we define 4 pseudo
|
||||
exception-handling registers which we then alias to the actual
|
||||
physical register. */
|
||||
|
||||
UNW_HPPA_EH0 = UNW_HPPA_IP + 1, /* alias for UNW_HPPA_GR + 20 */
|
||||
UNW_HPPA_EH1 = UNW_HPPA_EH0 + 1, /* alias for UNW_HPPA_GR + 21 */
|
||||
UNW_HPPA_EH2 = UNW_HPPA_EH1 + 1, /* alias for UNW_HPPA_GR + 22 */
|
||||
UNW_HPPA_EH3 = UNW_HPPA_EH2 + 1, /* alias for UNW_HPPA_GR + 31 */
|
||||
|
||||
/* frame info (read-only) */
|
||||
UNW_HPPA_CFA,
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_HPPA_IP,
|
||||
|
||||
UNW_TDEP_IP = UNW_HPPA_IP,
|
||||
UNW_TDEP_SP = UNW_HPPA_SP,
|
||||
UNW_TDEP_EH = UNW_HPPA_EH0
|
||||
}
|
||||
hppa_regnum_t;
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 4
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
/* On PA-RISC, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_HPPA_FR) < 32)
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no PA-RISC-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
|
||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,194 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef ia64
|
||||
/* This works around a bug in Intel's ECC v7.0 which defines "ia64"
|
||||
as "1". */
|
||||
# undef ia64
|
||||
#endif
|
||||
|
||||
#ifdef __hpux
|
||||
/* On HP-UX, there is no hope of supporting UNW_LOCAL_ONLY, because
|
||||
it's impossible to obtain the address of the members in the
|
||||
sigcontext structure. */
|
||||
# undef UNW_LOCAL_ONLY
|
||||
# define UNW_GENERIC_ONLY
|
||||
#endif
|
||||
|
||||
#define UNW_TARGET ia64
|
||||
#define UNW_TARGET_IA64 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
#define UNW_TDEP_CURSOR_LEN 511
|
||||
|
||||
/* If this bit is it indicates that the procedure saved all of ar.bsp,
|
||||
ar.bspstore, and ar.rnat. If, additionally, ar.bsp != saved ar.bsp,
|
||||
then this procedure has performed a register-backing-store switch. */
|
||||
#define UNW_PI_FLAG_IA64_RBS_SWITCH_BIT (UNW_PI_FLAG_FIRST_TDEP_BIT + 0)
|
||||
|
||||
#define UNW_PI_FLAG_IA64_RBS_SWITCH (1 << UNW_PI_FLAG_IA64_RBS_SWITCH_BIT)
|
||||
|
||||
typedef uint64_t unw_word_t;
|
||||
typedef int64_t unw_sword_t;
|
||||
|
||||
/* On IA-64, we want to access the contents of floating-point
|
||||
registers as a pair of "words", but to ensure 16-byte alignment, we
|
||||
make it a union that contains a "long double". This will do the
|
||||
Right Thing on all known IA-64 platforms, including HP-UX. */
|
||||
typedef union
|
||||
{
|
||||
struct { unw_word_t bits[2]; } raw;
|
||||
long double dummy; /* dummy to force 16-byte alignment */
|
||||
}
|
||||
unw_tdep_fpreg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ia64-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Note: general registers are excepted to start with index 0.
|
||||
This convention facilitates architecture-independent
|
||||
implementation of the C++ exception handling ABI. See
|
||||
_Unwind_SetGR() and _Unwind_GetGR() for details. */
|
||||
UNW_IA64_GR = 0, /* general registers (r0..r127) */
|
||||
UNW_IA64_GP = UNW_IA64_GR + 1,
|
||||
UNW_IA64_TP = UNW_IA64_GR + 13,
|
||||
|
||||
UNW_IA64_NAT = UNW_IA64_GR + 128, /* NaT registers (nat0..nat127) */
|
||||
|
||||
UNW_IA64_FR = UNW_IA64_NAT + 128, /* fp registers (f0..f127) */
|
||||
|
||||
UNW_IA64_AR = UNW_IA64_FR + 128, /* application registers (ar0..r127) */
|
||||
UNW_IA64_AR_RSC = UNW_IA64_AR + 16,
|
||||
UNW_IA64_AR_BSP = UNW_IA64_AR + 17,
|
||||
UNW_IA64_AR_BSPSTORE = UNW_IA64_AR + 18,
|
||||
UNW_IA64_AR_RNAT = UNW_IA64_AR + 19,
|
||||
UNW_IA64_AR_CSD = UNW_IA64_AR + 25,
|
||||
UNW_IA64_AR_26 = UNW_IA64_AR + 26,
|
||||
UNW_IA64_AR_SSD = UNW_IA64_AR_26,
|
||||
UNW_IA64_AR_CCV = UNW_IA64_AR + 32,
|
||||
UNW_IA64_AR_UNAT = UNW_IA64_AR + 36,
|
||||
UNW_IA64_AR_FPSR = UNW_IA64_AR + 40,
|
||||
UNW_IA64_AR_PFS = UNW_IA64_AR + 64,
|
||||
UNW_IA64_AR_LC = UNW_IA64_AR + 65,
|
||||
UNW_IA64_AR_EC = UNW_IA64_AR + 66,
|
||||
|
||||
UNW_IA64_BR = UNW_IA64_AR + 128, /* branch registers (b0..p7) */
|
||||
UNW_IA64_RP = UNW_IA64_BR + 0, /* return pointer (rp) */
|
||||
UNW_IA64_PR = UNW_IA64_BR + 8, /* predicate registers (p0..p63) */
|
||||
UNW_IA64_CFM,
|
||||
|
||||
/* frame info: */
|
||||
UNW_IA64_BSP,
|
||||
UNW_IA64_IP,
|
||||
UNW_IA64_SP,
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_IA64_SP,
|
||||
|
||||
UNW_TDEP_IP = UNW_IA64_IP,
|
||||
UNW_TDEP_SP = UNW_IA64_SP,
|
||||
UNW_TDEP_EH = UNW_IA64_GR + 15
|
||||
}
|
||||
ia64_regnum_t;
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 4 /* r15-r18 are exception args */
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. On IA-64,
|
||||
we use this to provide the bit number in which a NaT bit gets
|
||||
saved. */
|
||||
uint8_t nat_bitnr;
|
||||
|
||||
/* Padding reserved for future use. */
|
||||
uint8_t reserved[7];
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
/* On IA-64, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_IA64_FR) < 128)
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#ifdef __hpux
|
||||
/* In theory, we could use _Uia64_getcontext() on HP-UX as well, but
|
||||
the benefit of doing so would be marginal given that it can't
|
||||
support UNW_LOCAL_ONLY. */
|
||||
# define unw_tdep_getcontext getcontext
|
||||
#else
|
||||
# define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
|
||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||
#endif
|
||||
|
||||
/* This is a helper routine to search an ia64 unwind table. If the
|
||||
address-space argument AS points to something other than the local
|
||||
address-space, the memory for the unwind-info will be allocated
|
||||
with malloc(), and should be free()d during the put_unwind_info()
|
||||
callback. This routine is signal-safe for the local-address-space
|
||||
case ONLY. */
|
||||
#define unw_search_ia64_unwind_table UNW_OBJ(search_unwind_table)
|
||||
extern int unw_search_ia64_unwind_table (unw_addr_space_t, unw_word_t,
|
||||
unw_dyn_info_t *, unw_proc_info_t *,
|
||||
int, void *);
|
||||
|
||||
/* This is a helper routine which the get_dyn_info_list_addr()
|
||||
callback can use to locate the special dynamic-info list entry in
|
||||
an IA-64 unwind table. If the entry exists in the table, the
|
||||
list-address is returned. In all other cases, 0 is returned. */
|
||||
extern unw_word_t _Uia64_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *,
|
||||
void *);
|
||||
|
||||
/* This is a helper routine to obtain the kernel-unwind info. It is
|
||||
signal-safe. */
|
||||
extern int _Uia64_get_kernel_table (unw_dyn_info_t *);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,160 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#ifdef mips
|
||||
# undef mips
|
||||
#endif
|
||||
|
||||
#define UNW_TARGET mips
|
||||
#define UNW_TARGET_MIPS 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
|
||||
/* FIXME for MIPS. Too big? What do other things use for similar tasks? */
|
||||
#define UNW_TDEP_CURSOR_LEN 4096
|
||||
|
||||
/* The size of a "word" varies on MIPS. This type is used for memory
|
||||
addresses and register values, which are 32-bit wide for O32 and N32
|
||||
ABIs, and 64-bit wide for N64 ABI. */
|
||||
#if _MIPS_SIM == _ABI64
|
||||
typedef uint64_t unw_word_t;
|
||||
#else
|
||||
typedef uint32_t unw_word_t;
|
||||
#endif
|
||||
typedef int32_t unw_sword_t;
|
||||
|
||||
/* FIXME: MIPS ABIs. */
|
||||
typedef long double unw_tdep_fpreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_MIPS_R0,
|
||||
UNW_MIPS_R1,
|
||||
UNW_MIPS_R2,
|
||||
UNW_MIPS_R3,
|
||||
UNW_MIPS_R4,
|
||||
UNW_MIPS_R5,
|
||||
UNW_MIPS_R6,
|
||||
UNW_MIPS_R7,
|
||||
UNW_MIPS_R8,
|
||||
UNW_MIPS_R9,
|
||||
UNW_MIPS_R10,
|
||||
UNW_MIPS_R11,
|
||||
UNW_MIPS_R12,
|
||||
UNW_MIPS_R13,
|
||||
UNW_MIPS_R14,
|
||||
UNW_MIPS_R15,
|
||||
UNW_MIPS_R16,
|
||||
UNW_MIPS_R17,
|
||||
UNW_MIPS_R18,
|
||||
UNW_MIPS_R19,
|
||||
UNW_MIPS_R20,
|
||||
UNW_MIPS_R21,
|
||||
UNW_MIPS_R22,
|
||||
UNW_MIPS_R23,
|
||||
UNW_MIPS_R24,
|
||||
UNW_MIPS_R25,
|
||||
UNW_MIPS_R26,
|
||||
UNW_MIPS_R27,
|
||||
UNW_MIPS_R28,
|
||||
UNW_MIPS_R29,
|
||||
UNW_MIPS_R30,
|
||||
UNW_MIPS_R31,
|
||||
|
||||
UNW_MIPS_PC = 34,
|
||||
|
||||
/* FIXME: Other registers! */
|
||||
|
||||
/* For MIPS, the CFA is the value of SP (r29) at the call site in the
|
||||
previous frame. */
|
||||
UNW_MIPS_CFA,
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_MIPS_PC,
|
||||
|
||||
UNW_TDEP_IP = UNW_MIPS_R31,
|
||||
UNW_TDEP_SP = UNW_MIPS_R29,
|
||||
UNW_TDEP_EH = UNW_MIPS_R0 /* FIXME. */
|
||||
}
|
||||
mips_regnum_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_MIPS_ABI_O32,
|
||||
UNW_MIPS_ABI_N32,
|
||||
UNW_MIPS_ABI_N64
|
||||
}
|
||||
mips_abi_t;
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for MIPS. */
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
/* On x86, we can directly use ucontext_t as the unwind context. FIXME for
|
||||
MIPS. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no mips-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
/* There is no getcontext() on MIPS. Use a stub version which only saves GP
|
||||
registers. FIXME: Not ideal, may not be sufficient for all libunwind
|
||||
use cases. */
|
||||
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
||||
extern int unw_tdep_getcontext (ucontext_t *uc);
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,207 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2006-2007 IBM
|
||||
Contributed by
|
||||
Corey Ashford <cjashfor@us.ibm.com>
|
||||
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
|
||||
|
||||
Copied from libunwind-x86_64.h, modified slightly for building
|
||||
frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
|
||||
Will be replaced when libunwind is ready on ppc64 platform.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define UNW_TARGET ppc32
|
||||
#define UNW_TARGET_PPC32 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/*
|
||||
* This needs to be big enough to accommodate "struct cursor", while
|
||||
* leaving some slack for future expansion. Changing this value will
|
||||
* require recompiling all users of this library. Stack allocation is
|
||||
* relatively cheap and unwind-state copying is relatively rare, so we want
|
||||
* to err on making it rather too big than too small.
|
||||
*
|
||||
* To simplify this whole process, we are at least initially taking the
|
||||
* tack that UNW_PPC32_* map straight across to the .eh_frame column register
|
||||
* numbers. These register numbers come from gcc's source in
|
||||
* gcc/config/rs6000/rs6000.h
|
||||
*
|
||||
* UNW_TDEP_CURSOR_LEN is in terms of unw_word_t size. Since we have 115
|
||||
* elements in the loc array, each sized 2 * unw_word_t, plus the rest of
|
||||
* the cursor struct, this puts us at about 2 * 115 + 40 = 270. Let's
|
||||
* round that up to 280.
|
||||
*/
|
||||
|
||||
#define UNW_TDEP_CURSOR_LEN 280
|
||||
|
||||
#if __WORDSIZE==32
|
||||
typedef uint32_t unw_word_t;
|
||||
typedef int32_t unw_sword_t;
|
||||
#else
|
||||
typedef uint64_t unw_word_t;
|
||||
typedef int64_t unw_sword_t;
|
||||
#endif
|
||||
|
||||
typedef long double unw_tdep_fpreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_PPC32_R0,
|
||||
UNW_PPC32_R1, /* called STACK_POINTER in gcc */
|
||||
UNW_PPC32_R2,
|
||||
UNW_PPC32_R3,
|
||||
UNW_PPC32_R4,
|
||||
UNW_PPC32_R5,
|
||||
UNW_PPC32_R6,
|
||||
UNW_PPC32_R7,
|
||||
UNW_PPC32_R8,
|
||||
UNW_PPC32_R9,
|
||||
UNW_PPC32_R10,
|
||||
UNW_PPC32_R11, /* called STATIC_CHAIN in gcc */
|
||||
UNW_PPC32_R12,
|
||||
UNW_PPC32_R13,
|
||||
UNW_PPC32_R14,
|
||||
UNW_PPC32_R15,
|
||||
UNW_PPC32_R16,
|
||||
UNW_PPC32_R17,
|
||||
UNW_PPC32_R18,
|
||||
UNW_PPC32_R19,
|
||||
UNW_PPC32_R20,
|
||||
UNW_PPC32_R21,
|
||||
UNW_PPC32_R22,
|
||||
UNW_PPC32_R23,
|
||||
UNW_PPC32_R24,
|
||||
UNW_PPC32_R25,
|
||||
UNW_PPC32_R26,
|
||||
UNW_PPC32_R27,
|
||||
UNW_PPC32_R28,
|
||||
UNW_PPC32_R29,
|
||||
UNW_PPC32_R30,
|
||||
UNW_PPC32_R31, /* called HARD_FRAME_POINTER in gcc */
|
||||
|
||||
/* Count Register */
|
||||
UNW_PPC32_CTR = 32,
|
||||
/* Fixed-Point Status and Control Register */
|
||||
UNW_PPC32_XER = 33,
|
||||
/* Condition Register */
|
||||
UNW_PPC32_CCR = 34,
|
||||
/* Machine State Register */
|
||||
//UNW_PPC32_MSR = 35,
|
||||
/* MQ or SPR0, not part of generic Power, part of MPC601 */
|
||||
//UNW_PPC32_MQ = 36,
|
||||
/* Link Register */
|
||||
UNW_PPC32_LR = 36,
|
||||
/* Floating Pointer Status and Control Register */
|
||||
UNW_PPC32_FPSCR = 37,
|
||||
|
||||
UNW_PPC32_F0 = 48,
|
||||
UNW_PPC32_F1,
|
||||
UNW_PPC32_F2,
|
||||
UNW_PPC32_F3,
|
||||
UNW_PPC32_F4,
|
||||
UNW_PPC32_F5,
|
||||
UNW_PPC32_F6,
|
||||
UNW_PPC32_F7,
|
||||
UNW_PPC32_F8,
|
||||
UNW_PPC32_F9,
|
||||
UNW_PPC32_F10,
|
||||
UNW_PPC32_F11,
|
||||
UNW_PPC32_F12,
|
||||
UNW_PPC32_F13,
|
||||
UNW_PPC32_F14,
|
||||
UNW_PPC32_F15,
|
||||
UNW_PPC32_F16,
|
||||
UNW_PPC32_F17,
|
||||
UNW_PPC32_F18,
|
||||
UNW_PPC32_F19,
|
||||
UNW_PPC32_F20,
|
||||
UNW_PPC32_F21,
|
||||
UNW_PPC32_F22,
|
||||
UNW_PPC32_F23,
|
||||
UNW_PPC32_F24,
|
||||
UNW_PPC32_F25,
|
||||
UNW_PPC32_F26,
|
||||
UNW_PPC32_F27,
|
||||
UNW_PPC32_F28,
|
||||
UNW_PPC32_F29,
|
||||
UNW_PPC32_F30,
|
||||
UNW_PPC32_F31,
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_PPC32_F31,
|
||||
|
||||
UNW_TDEP_IP = UNW_PPC32_LR,
|
||||
UNW_TDEP_SP = UNW_PPC32_R1,
|
||||
UNW_TDEP_EH = UNW_PPC32_R12
|
||||
}
|
||||
ppc32_regnum_t;
|
||||
|
||||
/*
|
||||
* According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for
|
||||
* passing parameters to exception handlers.
|
||||
*/
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 4
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
/* On ppc, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
/* XXX this is not ideal: an application should not be prevented from
|
||||
using the "getcontext" name just because it's using libunwind. We
|
||||
can't just use __getcontext() either, because that isn't exported
|
||||
by glibc... */
|
||||
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ppc32-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,271 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2006-2007 IBM
|
||||
Contributed by
|
||||
Corey Ashford <cjashfor@us.ibm.com>
|
||||
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
|
||||
|
||||
Copied from libunwind-x86_64.h, modified slightly for building
|
||||
frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
|
||||
Will be replaced when libunwind is ready on ppc64 platform.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define UNW_TARGET ppc64
|
||||
#define UNW_TARGET_PPC64 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/*
|
||||
* This needs to be big enough to accommodate "struct cursor", while
|
||||
* leaving some slack for future expansion. Changing this value will
|
||||
* require recompiling all users of this library. Stack allocation is
|
||||
* relatively cheap and unwind-state copying is relatively rare, so we want
|
||||
* to err on making it rather too big than too small.
|
||||
*
|
||||
* To simplify this whole process, we are at least initially taking the
|
||||
* tack that UNW_PPC64_* map straight across to the .eh_frame column register
|
||||
* numbers. These register numbers come from gcc's source in
|
||||
* gcc/config/rs6000/rs6000.h
|
||||
*
|
||||
* UNW_TDEP_CURSOR_LEN is in terms of unw_word_t size. Since we have 115
|
||||
* elements in the loc array, each sized 2 * unw_word_t, plus the rest of
|
||||
* the cursor struct, this puts us at about 2 * 115 + 40 = 270. Let's
|
||||
* round that up to 280.
|
||||
*/
|
||||
|
||||
#define UNW_TDEP_CURSOR_LEN 280
|
||||
|
||||
#if __WORDSIZE==32
|
||||
typedef uint32_t unw_word_t;
|
||||
typedef int32_t unw_sword_t;
|
||||
#else
|
||||
typedef uint64_t unw_word_t;
|
||||
typedef int64_t unw_sword_t;
|
||||
#endif
|
||||
|
||||
typedef long double unw_tdep_fpreg_t;
|
||||
|
||||
/*
|
||||
* Vector register (in PowerPC64 used for AltiVec registers)
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t halves[2];
|
||||
} unw_tdep_vreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_PPC64_R0,
|
||||
UNW_PPC64_R1, /* called STACK_POINTER in gcc */
|
||||
UNW_PPC64_R2,
|
||||
UNW_PPC64_R3,
|
||||
UNW_PPC64_R4,
|
||||
UNW_PPC64_R5,
|
||||
UNW_PPC64_R6,
|
||||
UNW_PPC64_R7,
|
||||
UNW_PPC64_R8,
|
||||
UNW_PPC64_R9,
|
||||
UNW_PPC64_R10,
|
||||
UNW_PPC64_R11, /* called STATIC_CHAIN in gcc */
|
||||
UNW_PPC64_R12,
|
||||
UNW_PPC64_R13,
|
||||
UNW_PPC64_R14,
|
||||
UNW_PPC64_R15,
|
||||
UNW_PPC64_R16,
|
||||
UNW_PPC64_R17,
|
||||
UNW_PPC64_R18,
|
||||
UNW_PPC64_R19,
|
||||
UNW_PPC64_R20,
|
||||
UNW_PPC64_R21,
|
||||
UNW_PPC64_R22,
|
||||
UNW_PPC64_R23,
|
||||
UNW_PPC64_R24,
|
||||
UNW_PPC64_R25,
|
||||
UNW_PPC64_R26,
|
||||
UNW_PPC64_R27,
|
||||
UNW_PPC64_R28,
|
||||
UNW_PPC64_R29,
|
||||
UNW_PPC64_R30,
|
||||
UNW_PPC64_R31, /* called HARD_FRAME_POINTER in gcc */
|
||||
|
||||
UNW_PPC64_F0 = 32,
|
||||
UNW_PPC64_F1,
|
||||
UNW_PPC64_F2,
|
||||
UNW_PPC64_F3,
|
||||
UNW_PPC64_F4,
|
||||
UNW_PPC64_F5,
|
||||
UNW_PPC64_F6,
|
||||
UNW_PPC64_F7,
|
||||
UNW_PPC64_F8,
|
||||
UNW_PPC64_F9,
|
||||
UNW_PPC64_F10,
|
||||
UNW_PPC64_F11,
|
||||
UNW_PPC64_F12,
|
||||
UNW_PPC64_F13,
|
||||
UNW_PPC64_F14,
|
||||
UNW_PPC64_F15,
|
||||
UNW_PPC64_F16,
|
||||
UNW_PPC64_F17,
|
||||
UNW_PPC64_F18,
|
||||
UNW_PPC64_F19,
|
||||
UNW_PPC64_F20,
|
||||
UNW_PPC64_F21,
|
||||
UNW_PPC64_F22,
|
||||
UNW_PPC64_F23,
|
||||
UNW_PPC64_F24,
|
||||
UNW_PPC64_F25,
|
||||
UNW_PPC64_F26,
|
||||
UNW_PPC64_F27,
|
||||
UNW_PPC64_F28,
|
||||
UNW_PPC64_F29,
|
||||
UNW_PPC64_F30,
|
||||
UNW_PPC64_F31,
|
||||
/* Note that there doesn't appear to be an .eh_frame register column
|
||||
for the FPSCR register. I don't know why this is. Since .eh_frame
|
||||
info is what this implementation uses for unwinding, we have no way
|
||||
to unwind this register, and so we will not expose an FPSCR register
|
||||
number in the libunwind API.
|
||||
*/
|
||||
|
||||
UNW_PPC64_LR = 65,
|
||||
UNW_PPC64_CTR = 66,
|
||||
UNW_PPC64_ARG_POINTER = 67,
|
||||
|
||||
UNW_PPC64_CR0 = 68,
|
||||
UNW_PPC64_CR1,
|
||||
UNW_PPC64_CR2,
|
||||
UNW_PPC64_CR3,
|
||||
UNW_PPC64_CR4,
|
||||
/* CR5 .. CR7 are currently unused */
|
||||
UNW_PPC64_CR5,
|
||||
UNW_PPC64_CR6,
|
||||
UNW_PPC64_CR7,
|
||||
|
||||
UNW_PPC64_XER = 76,
|
||||
|
||||
UNW_PPC64_V0 = 77,
|
||||
UNW_PPC64_V1,
|
||||
UNW_PPC64_V2,
|
||||
UNW_PPC64_V3,
|
||||
UNW_PPC64_V4,
|
||||
UNW_PPC64_V5,
|
||||
UNW_PPC64_V6,
|
||||
UNW_PPC64_V7,
|
||||
UNW_PPC64_V8,
|
||||
UNW_PPC64_V9,
|
||||
UNW_PPC64_V10,
|
||||
UNW_PPC64_V11,
|
||||
UNW_PPC64_V12,
|
||||
UNW_PPC64_V13,
|
||||
UNW_PPC64_V14,
|
||||
UNW_PPC64_V15,
|
||||
UNW_PPC64_V16,
|
||||
UNW_PPC64_V17,
|
||||
UNW_PPC64_V18,
|
||||
UNW_PPC64_V19,
|
||||
UNW_PPC64_V20,
|
||||
UNW_PPC64_V21,
|
||||
UNW_PPC64_V22,
|
||||
UNW_PPC64_V23,
|
||||
UNW_PPC64_V24,
|
||||
UNW_PPC64_V25,
|
||||
UNW_PPC64_V26,
|
||||
UNW_PPC64_V27,
|
||||
UNW_PPC64_V28,
|
||||
UNW_PPC64_V29,
|
||||
UNW_PPC64_V30,
|
||||
UNW_PPC64_V31,
|
||||
|
||||
UNW_PPC64_VRSAVE = 109,
|
||||
UNW_PPC64_VSCR = 110,
|
||||
UNW_PPC64_SPE_ACC = 111,
|
||||
UNW_PPC64_SPEFSCR = 112,
|
||||
|
||||
/* frame info (read-only) */
|
||||
UNW_PPC64_FRAME_POINTER,
|
||||
UNW_PPC64_NIP,
|
||||
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_PPC64_NIP,
|
||||
|
||||
UNW_TDEP_IP = UNW_PPC64_NIP,
|
||||
UNW_TDEP_SP = UNW_PPC64_R1,
|
||||
UNW_TDEP_EH = UNW_PPC64_R12
|
||||
}
|
||||
ppc64_regnum_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_PPC64_ABI_ELFv1,
|
||||
UNW_PPC64_ABI_ELFv2
|
||||
}
|
||||
ppc64_abi_t;
|
||||
|
||||
/*
|
||||
* According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for
|
||||
* passing parameters to exception handlers.
|
||||
*/
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 4
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
/* On ppc64, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
/* XXX this is not ideal: an application should not be prevented from
|
||||
using the "getcontext" name just because it's using libunwind. We
|
||||
can't just use __getcontext() either, because that isn't exported
|
||||
by glibc... */
|
||||
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ppc64-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,63 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef libunwind_ptrace_h
|
||||
#define libunwind_ptrace_h
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Helper routines which make it easy to use libunwind via ptrace().
|
||||
They're available only if UNW_REMOTE_ONLY is _not_ defined and they
|
||||
aren't really part of the libunwind API. They are implemented in a
|
||||
archive library called libunwind-ptrace.a. */
|
||||
|
||||
extern void *_UPT_create (pid_t);
|
||||
extern void _UPT_destroy (void *);
|
||||
extern int _UPT_find_proc_info (unw_addr_space_t, unw_word_t,
|
||||
unw_proc_info_t *, int, void *);
|
||||
extern void _UPT_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
|
||||
extern int _UPT_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
|
||||
void *);
|
||||
extern int _UPT_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
|
||||
void *);
|
||||
extern int _UPT_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
|
||||
int, void *);
|
||||
extern int _UPT_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
|
||||
int, void *);
|
||||
extern int _UPT_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
|
||||
unw_word_t *, void *);
|
||||
extern int _UPT_resume (unw_addr_space_t, unw_cursor_t *, void *);
|
||||
extern unw_accessors_t _UPT_accessors;
|
||||
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* libunwind_ptrace_h */
|
@ -1,114 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
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. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define UNW_TARGET sh
|
||||
#define UNW_TARGET_SH 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
|
||||
#define UNW_TDEP_CURSOR_LEN 4096
|
||||
|
||||
typedef uint32_t unw_word_t;
|
||||
typedef int32_t unw_sword_t;
|
||||
|
||||
typedef long double unw_tdep_fpreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_SH_R0,
|
||||
UNW_SH_R1,
|
||||
UNW_SH_R2,
|
||||
UNW_SH_R3,
|
||||
UNW_SH_R4,
|
||||
UNW_SH_R5,
|
||||
UNW_SH_R6,
|
||||
UNW_SH_R7,
|
||||
UNW_SH_R8,
|
||||
UNW_SH_R9,
|
||||
UNW_SH_R10,
|
||||
UNW_SH_R11,
|
||||
UNW_SH_R12,
|
||||
UNW_SH_R13,
|
||||
UNW_SH_R14,
|
||||
UNW_SH_R15,
|
||||
|
||||
UNW_SH_PC,
|
||||
UNW_SH_PR,
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_SH_PR,
|
||||
|
||||
UNW_TDEP_IP = UNW_SH_PR,
|
||||
UNW_TDEP_SP = UNW_SH_R15,
|
||||
UNW_TDEP_EH = UNW_SH_R0
|
||||
}
|
||||
sh_regnum_t;
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 2
|
||||
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no sh-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,161 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2014 Tilera Corp.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define UNW_TARGET tilegx
|
||||
#define UNW_TARGET_TILEGX 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
|
||||
#define UNW_TDEP_CURSOR_LEN 4096
|
||||
|
||||
/* The size of a "word" varies on TILEGX. This type is used for memory
|
||||
addresses and register values. */
|
||||
typedef uint64_t unw_word_t;
|
||||
typedef int64_t unw_sword_t;
|
||||
|
||||
typedef long double unw_tdep_fpreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_TILEGX_R0,
|
||||
UNW_TILEGX_R1,
|
||||
UNW_TILEGX_R2,
|
||||
UNW_TILEGX_R3,
|
||||
UNW_TILEGX_R4,
|
||||
UNW_TILEGX_R5,
|
||||
UNW_TILEGX_R6,
|
||||
UNW_TILEGX_R7,
|
||||
UNW_TILEGX_R8,
|
||||
UNW_TILEGX_R9,
|
||||
UNW_TILEGX_R10,
|
||||
UNW_TILEGX_R11,
|
||||
UNW_TILEGX_R12,
|
||||
UNW_TILEGX_R13,
|
||||
UNW_TILEGX_R14,
|
||||
UNW_TILEGX_R15,
|
||||
UNW_TILEGX_R16,
|
||||
UNW_TILEGX_R17,
|
||||
UNW_TILEGX_R18,
|
||||
UNW_TILEGX_R19,
|
||||
UNW_TILEGX_R20,
|
||||
UNW_TILEGX_R21,
|
||||
UNW_TILEGX_R22,
|
||||
UNW_TILEGX_R23,
|
||||
UNW_TILEGX_R24,
|
||||
UNW_TILEGX_R25,
|
||||
UNW_TILEGX_R26,
|
||||
UNW_TILEGX_R27,
|
||||
UNW_TILEGX_R28,
|
||||
UNW_TILEGX_R29,
|
||||
UNW_TILEGX_R30,
|
||||
UNW_TILEGX_R31,
|
||||
UNW_TILEGX_R32,
|
||||
UNW_TILEGX_R33,
|
||||
UNW_TILEGX_R34,
|
||||
UNW_TILEGX_R35,
|
||||
UNW_TILEGX_R36,
|
||||
UNW_TILEGX_R37,
|
||||
UNW_TILEGX_R38,
|
||||
UNW_TILEGX_R39,
|
||||
UNW_TILEGX_R40,
|
||||
UNW_TILEGX_R41,
|
||||
UNW_TILEGX_R42,
|
||||
UNW_TILEGX_R43,
|
||||
UNW_TILEGX_R44,
|
||||
UNW_TILEGX_R45,
|
||||
UNW_TILEGX_R46,
|
||||
UNW_TILEGX_R47,
|
||||
UNW_TILEGX_R48,
|
||||
UNW_TILEGX_R49,
|
||||
UNW_TILEGX_R50,
|
||||
UNW_TILEGX_R51,
|
||||
UNW_TILEGX_R52,
|
||||
UNW_TILEGX_R53,
|
||||
UNW_TILEGX_R54,
|
||||
UNW_TILEGX_R55,
|
||||
|
||||
/* FIXME: Other registers! */
|
||||
|
||||
UNW_TILEGX_PC,
|
||||
/* For TILEGX, the CFA is the value of SP (r54) at the call site in the
|
||||
previous frame. */
|
||||
UNW_TILEGX_CFA,
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_TILEGX_PC,
|
||||
|
||||
UNW_TDEP_IP = UNW_TILEGX_R55, /* R55 is link register for Tilegx */
|
||||
UNW_TDEP_SP = UNW_TILEGX_R54,
|
||||
UNW_TDEP_EH = UNW_TILEGX_R0 /* FIXME. */
|
||||
} tilegx_regnum_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_TILEGX_ABI_N64 = 2
|
||||
} tilegx_abi_t;
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for TILEGX. */
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
} unw_tdep_save_loc_t;
|
||||
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no tilegx-specific auxiliary proc-info */
|
||||
} unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_getcontext getcontext
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,187 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002-2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define UNW_TARGET x86
|
||||
#define UNW_TARGET_X86 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
#define UNW_TDEP_CURSOR_LEN 127
|
||||
|
||||
typedef uint32_t unw_word_t;
|
||||
typedef int32_t unw_sword_t;
|
||||
|
||||
typedef union {
|
||||
struct { uint8_t b[4]; } val32;
|
||||
struct { uint8_t b[10]; } val80;
|
||||
struct { uint8_t b[16]; } val128;
|
||||
} unw_tdep_fpreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Note: general registers are expected to start with index 0.
|
||||
This convention facilitates architecture-independent
|
||||
implementation of the C++ exception handling ABI. See
|
||||
_Unwind_SetGR() and _Unwind_GetGR() for details.
|
||||
|
||||
The described register usage convention is based on "System V
|
||||
Application Binary Interface, Intel386 Architecture Processor
|
||||
Supplement, Fourth Edition" at
|
||||
|
||||
http://www.linuxbase.org/spec/refspecs/elf/abi386-4.pdf
|
||||
|
||||
It would have been nice to use the same register numbering as
|
||||
DWARF, but that doesn't work because the libunwind requires
|
||||
that the exception argument registers be consecutive, which the
|
||||
wouldn't be with the DWARF numbering. */
|
||||
UNW_X86_EAX, /* scratch (exception argument 1) */
|
||||
UNW_X86_EDX, /* scratch (exception argument 2) */
|
||||
UNW_X86_ECX, /* scratch */
|
||||
UNW_X86_EBX, /* preserved */
|
||||
UNW_X86_ESI, /* preserved */
|
||||
UNW_X86_EDI, /* preserved */
|
||||
UNW_X86_EBP, /* (optional) frame-register */
|
||||
UNW_X86_ESP, /* (optional) frame-register */
|
||||
UNW_X86_EIP, /* frame-register */
|
||||
UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */
|
||||
UNW_X86_TRAPNO, /* scratch */
|
||||
|
||||
/* MMX/stacked-fp registers */
|
||||
UNW_X86_ST0, /* fp return value */
|
||||
UNW_X86_ST1, /* scratch */
|
||||
UNW_X86_ST2, /* scratch */
|
||||
UNW_X86_ST3, /* scratch */
|
||||
UNW_X86_ST4, /* scratch */
|
||||
UNW_X86_ST5, /* scratch */
|
||||
UNW_X86_ST6, /* scratch */
|
||||
UNW_X86_ST7, /* scratch */
|
||||
|
||||
UNW_X86_FCW, /* scratch */
|
||||
UNW_X86_FSW, /* scratch */
|
||||
UNW_X86_FTW, /* scratch */
|
||||
UNW_X86_FOP, /* scratch */
|
||||
UNW_X86_FCS, /* scratch */
|
||||
UNW_X86_FIP, /* scratch */
|
||||
UNW_X86_FEA, /* scratch */
|
||||
UNW_X86_FDS, /* scratch */
|
||||
|
||||
/* SSE registers */
|
||||
UNW_X86_XMM0_lo, /* scratch */
|
||||
UNW_X86_XMM0_hi, /* scratch */
|
||||
UNW_X86_XMM1_lo, /* scratch */
|
||||
UNW_X86_XMM1_hi, /* scratch */
|
||||
UNW_X86_XMM2_lo, /* scratch */
|
||||
UNW_X86_XMM2_hi, /* scratch */
|
||||
UNW_X86_XMM3_lo, /* scratch */
|
||||
UNW_X86_XMM3_hi, /* scratch */
|
||||
UNW_X86_XMM4_lo, /* scratch */
|
||||
UNW_X86_XMM4_hi, /* scratch */
|
||||
UNW_X86_XMM5_lo, /* scratch */
|
||||
UNW_X86_XMM5_hi, /* scratch */
|
||||
UNW_X86_XMM6_lo, /* scratch */
|
||||
UNW_X86_XMM6_hi, /* scratch */
|
||||
UNW_X86_XMM7_lo, /* scratch */
|
||||
UNW_X86_XMM7_hi, /* scratch */
|
||||
|
||||
UNW_X86_MXCSR, /* scratch */
|
||||
|
||||
/* segment registers */
|
||||
UNW_X86_GS, /* special */
|
||||
UNW_X86_FS, /* special */
|
||||
UNW_X86_ES, /* special */
|
||||
UNW_X86_DS, /* special */
|
||||
UNW_X86_SS, /* special */
|
||||
UNW_X86_CS, /* special */
|
||||
UNW_X86_TSS, /* special */
|
||||
UNW_X86_LDT, /* special */
|
||||
|
||||
/* frame info (read-only) */
|
||||
UNW_X86_CFA,
|
||||
|
||||
UNW_X86_XMM0, /* scratch */
|
||||
UNW_X86_XMM1, /* scratch */
|
||||
UNW_X86_XMM2, /* scratch */
|
||||
UNW_X86_XMM3, /* scratch */
|
||||
UNW_X86_XMM4, /* scratch */
|
||||
UNW_X86_XMM5, /* scratch */
|
||||
UNW_X86_XMM6, /* scratch */
|
||||
UNW_X86_XMM7, /* scratch */
|
||||
|
||||
UNW_TDEP_LAST_REG = UNW_X86_XMM7,
|
||||
|
||||
UNW_TDEP_IP = UNW_X86_EIP,
|
||||
UNW_TDEP_SP = UNW_X86_ESP,
|
||||
UNW_TDEP_EH = UNW_X86_EAX
|
||||
}
|
||||
x86_regnum_t;
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
/* On x86, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no x86-specific auxiliary proc-info */
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,141 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002-2004 Hewlett-Packard Co
|
||||
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. */
|
||||
|
||||
#ifndef LIBUNWIND_H
|
||||
#define LIBUNWIND_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define UNW_TARGET x86_64
|
||||
#define UNW_TARGET_X86_64 1
|
||||
|
||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||
|
||||
/* This needs to be big enough to accommodate "struct cursor", while
|
||||
leaving some slack for future expansion. Changing this value will
|
||||
require recompiling all users of this library. Stack allocation is
|
||||
relatively cheap and unwind-state copying is relatively rare, so we
|
||||
want to err on making it rather too big than too small. */
|
||||
#define UNW_TDEP_CURSOR_LEN 127
|
||||
|
||||
typedef uint64_t unw_word_t;
|
||||
typedef int64_t unw_sword_t;
|
||||
|
||||
typedef long double unw_tdep_fpreg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_X86_64_RAX,
|
||||
UNW_X86_64_RDX,
|
||||
UNW_X86_64_RCX,
|
||||
UNW_X86_64_RBX,
|
||||
UNW_X86_64_RSI,
|
||||
UNW_X86_64_RDI,
|
||||
UNW_X86_64_RBP,
|
||||
UNW_X86_64_RSP,
|
||||
UNW_X86_64_R8,
|
||||
UNW_X86_64_R9,
|
||||
UNW_X86_64_R10,
|
||||
UNW_X86_64_R11,
|
||||
UNW_X86_64_R12,
|
||||
UNW_X86_64_R13,
|
||||
UNW_X86_64_R14,
|
||||
UNW_X86_64_R15,
|
||||
UNW_X86_64_RIP,
|
||||
#ifdef CONFIG_MSABI_SUPPORT
|
||||
UNW_X86_64_XMM0,
|
||||
UNW_X86_64_XMM1,
|
||||
UNW_X86_64_XMM2,
|
||||
UNW_X86_64_XMM3,
|
||||
UNW_X86_64_XMM4,
|
||||
UNW_X86_64_XMM5,
|
||||
UNW_X86_64_XMM6,
|
||||
UNW_X86_64_XMM7,
|
||||
UNW_X86_64_XMM8,
|
||||
UNW_X86_64_XMM9,
|
||||
UNW_X86_64_XMM10,
|
||||
UNW_X86_64_XMM11,
|
||||
UNW_X86_64_XMM12,
|
||||
UNW_X86_64_XMM13,
|
||||
UNW_X86_64_XMM14,
|
||||
UNW_X86_64_XMM15,
|
||||
UNW_TDEP_LAST_REG = UNW_X86_64_XMM15,
|
||||
#else
|
||||
UNW_TDEP_LAST_REG = UNW_X86_64_RIP,
|
||||
#endif
|
||||
|
||||
/* XXX Add other regs here */
|
||||
|
||||
/* frame info (read-only) */
|
||||
UNW_X86_64_CFA,
|
||||
|
||||
UNW_TDEP_IP = UNW_X86_64_RIP,
|
||||
UNW_TDEP_SP = UNW_X86_64_RSP,
|
||||
UNW_TDEP_BP = UNW_X86_64_RBP,
|
||||
UNW_TDEP_EH = UNW_X86_64_RAX
|
||||
}
|
||||
x86_64_regnum_t;
|
||||
|
||||
#define UNW_TDEP_NUM_EH_REGS 2 /* XXX Not sure what this means */
|
||||
|
||||
typedef struct unw_tdep_save_loc
|
||||
{
|
||||
/* Additional target-dependent info on a save location. */
|
||||
char unused;
|
||||
}
|
||||
unw_tdep_save_loc_t;
|
||||
|
||||
/* On x86_64, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no x86-64-specific auxiliary proc-info */
|
||||
char unused;
|
||||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
|
||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNWIND_H */
|
@ -1,36 +0,0 @@
|
||||
/* Provide a real file - not a symlink - as it would cause multiarch conflicts
|
||||
when multiple different arch releases are installed simultaneously. */
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
#if defined __aarch64__
|
||||
#include "libunwind-aarch64.h"
|
||||
#elif defined __arm__
|
||||
# include "libunwind-arm.h"
|
||||
#elif defined __hppa__
|
||||
# include "libunwind-hppa.h"
|
||||
#elif defined __ia64__
|
||||
# include "libunwind-ia64.h"
|
||||
#elif defined __mips__
|
||||
# include "libunwind-mips.h"
|
||||
#elif defined __powerpc__ && !defined __powerpc64__
|
||||
# include "libunwind-ppc32.h"
|
||||
#elif defined __powerpc64__
|
||||
# include "libunwind-ppc64.h"
|
||||
#elif defined __sh__
|
||||
# include "libunwind-sh.h"
|
||||
#elif defined __i386__
|
||||
# include "libunwind-x86.h"
|
||||
#elif defined __x86_64__
|
||||
# include "libunwind-x86_64.h"
|
||||
#elif defined __tilegx__
|
||||
# include "libunwind-tilegx.h"
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
|
||||
#else /* UNW_REMOTE_ONLY */
|
||||
|
||||
# include "libunwind-@arch@.h"
|
||||
|
||||
#endif /* UNW_REMOTE_ONLY */
|
@ -1,365 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2005 Hewlett-Packard Co
|
||||
Copyright (C) 2007 David Mosberger-Tang
|
||||
Contributed by David Mosberger-Tang <dmosberger@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. */
|
||||
|
||||
/* This files contains libunwind-internal definitions which are
|
||||
subject to frequent change and are not to be exposed to
|
||||
libunwind-users. */
|
||||
|
||||
#ifndef libunwind_i_h
|
||||
#define libunwind_i_h
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
#if defined(HAVE___THREAD) && HAVE___THREAD
|
||||
#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_PER_THREAD
|
||||
#else
|
||||
#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_GLOBAL
|
||||
#endif
|
||||
|
||||
/* Platform-independent libunwind-internal declarations. */
|
||||
|
||||
#include <sys/types.h> /* HP-UX needs this before include of pthread.h */
|
||||
|
||||
#include <assert.h>
|
||||
#include <libunwind.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#if defined(HAVE_ELF_H)
|
||||
# include <elf.h>
|
||||
#elif defined(HAVE_SYS_ELF_H)
|
||||
# include <sys/elf.h>
|
||||
#else
|
||||
# error Could not locate <elf.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ENDIAN_H)
|
||||
# include <endian.h>
|
||||
#elif defined(HAVE_SYS_ENDIAN_H)
|
||||
# include <sys/endian.h>
|
||||
# if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
|
||||
# define __LITTLE_ENDIAN _LITTLE_ENDIAN
|
||||
# endif
|
||||
# if defined(_BIG_ENDIAN) && !defined(__BIG_ENDIAN)
|
||||
# define __BIG_ENDIAN _BIG_ENDIAN
|
||||
# endif
|
||||
# if defined(_BYTE_ORDER) && !defined(__BYTE_ORDER)
|
||||
# define __BYTE_ORDER _BYTE_ORDER
|
||||
# endif
|
||||
#else
|
||||
# define __LITTLE_ENDIAN 1234
|
||||
# define __BIG_ENDIAN 4321
|
||||
# if defined(__hpux)
|
||||
# define __BYTE_ORDER __BIG_ENDIAN
|
||||
# elif defined(__QNX__)
|
||||
# if defined(__BIGENDIAN__)
|
||||
# define __BYTE_ORDER __BIG_ENDIAN
|
||||
# elif defined(__LITTLEENDIAN__)
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
# else
|
||||
# error Host has unknown byte-order.
|
||||
# endif
|
||||
# else
|
||||
# error Host has unknown byte-order.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE__BUILTIN_UNREACHABLE)
|
||||
# define unreachable() __builtin_unreachable()
|
||||
#else
|
||||
# define unreachable() do { } while (1)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define UNW_DEBUG 1
|
||||
#else
|
||||
# define UNW_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* Make it easy to write thread-safe code which may or may not be
|
||||
linked against libpthread. The macros below can be used
|
||||
unconditionally and if -lpthread is around, they'll call the
|
||||
corresponding routines otherwise, they do nothing. */
|
||||
|
||||
#pragma weak pthread_mutex_init
|
||||
#pragma weak pthread_mutex_lock
|
||||
#pragma weak pthread_mutex_unlock
|
||||
|
||||
#define mutex_init(l) \
|
||||
(pthread_mutex_init != NULL ? pthread_mutex_init ((l), NULL) : 0)
|
||||
#define mutex_lock(l) \
|
||||
(pthread_mutex_lock != NULL ? pthread_mutex_lock (l) : 0)
|
||||
#define mutex_unlock(l) \
|
||||
(pthread_mutex_unlock != NULL ? pthread_mutex_unlock (l) : 0)
|
||||
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
# include <atomic_ops.h>
|
||||
static inline int
|
||||
cmpxchg_ptr (void *addr, void *old, void *new)
|
||||
{
|
||||
union
|
||||
{
|
||||
void *vp;
|
||||
AO_t *aop;
|
||||
}
|
||||
u;
|
||||
|
||||
u.vp = addr;
|
||||
return AO_compare_and_swap(u.aop, (AO_t) old, (AO_t) new);
|
||||
}
|
||||
# define fetch_and_add1(_ptr) AO_fetch_and_add1(_ptr)
|
||||
# define fetch_and_add(_ptr, value) AO_fetch_and_add(_ptr, value)
|
||||
/* GCC 3.2.0 on HP-UX crashes on cmpxchg_ptr() */
|
||||
# if !(defined(__hpux) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
|
||||
# define HAVE_CMPXCHG
|
||||
# endif
|
||||
# define HAVE_FETCH_AND_ADD
|
||||
#elif defined(HAVE_SYNC_ATOMICS) || defined(HAVE_IA64INTRIN_H)
|
||||
# ifdef HAVE_IA64INTRIN_H
|
||||
# include <ia64intrin.h>
|
||||
# endif
|
||||
static inline int
|
||||
cmpxchg_ptr (void *addr, void *old, void *new)
|
||||
{
|
||||
union
|
||||
{
|
||||
void *vp;
|
||||
long *vlp;
|
||||
}
|
||||
u;
|
||||
|
||||
u.vp = addr;
|
||||
return __sync_bool_compare_and_swap(u.vlp, (long) old, (long) new);
|
||||
}
|
||||
# define fetch_and_add1(_ptr) __sync_fetch_and_add(_ptr, 1)
|
||||
# define fetch_and_add(_ptr, value) __sync_fetch_and_add(_ptr, value)
|
||||
# define HAVE_CMPXCHG
|
||||
# define HAVE_FETCH_AND_ADD
|
||||
#endif
|
||||
#define atomic_read(ptr) (*(ptr))
|
||||
|
||||
#define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn))
|
||||
#define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn)
|
||||
|
||||
#define unwi_full_mask UNWI_ARCH_OBJ(full_mask)
|
||||
|
||||
/* Type of a mask that can be used to inhibit preemption. At the
|
||||
userlevel, preemption is caused by signals and hence sigset_t is
|
||||
appropriate. In constrast, the Linux kernel uses "unsigned long"
|
||||
to hold the processor "flags" instead. */
|
||||
typedef sigset_t intrmask_t;
|
||||
|
||||
extern intrmask_t unwi_full_mask;
|
||||
|
||||
/* Silence compiler warnings about variables which are used only if libunwind
|
||||
is configured in a certain way */
|
||||
static inline void mark_as_used(void *v UNUSED) {
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLOCK_SIGNALS)
|
||||
# define SIGPROCMASK(how, new_mask, old_mask) \
|
||||
sigprocmask((how), (new_mask), (old_mask))
|
||||
#else
|
||||
# define SIGPROCMASK(how, new_mask, old_mask) mark_as_used(old_mask)
|
||||
#endif
|
||||
|
||||
/* Prefer adaptive mutexes if available */
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
#define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
#else
|
||||
#define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
#endif
|
||||
|
||||
#define define_lock(name) \
|
||||
pthread_mutex_t name = UNW_PTHREAD_MUTEX_INITIALIZER
|
||||
#define lock_init(l) mutex_init (l)
|
||||
#define lock_acquire(l,m) \
|
||||
do { \
|
||||
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \
|
||||
mutex_lock (l); \
|
||||
} while (0)
|
||||
#define lock_release(l,m) \
|
||||
do { \
|
||||
mutex_unlock (l); \
|
||||
SIGPROCMASK (SIG_SETMASK, &(m), NULL); \
|
||||
} while (0)
|
||||
|
||||
#define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */
|
||||
|
||||
#ifndef MAP_ANONYMOUS
|
||||
# define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
#define GET_MEMORY(mem, size) \
|
||||
do { \
|
||||
/* Hopefully, mmap() goes straight through to a system call stub... */ \
|
||||
mem = mmap (NULL, size, PROT_READ | PROT_WRITE, \
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
|
||||
if (mem == MAP_FAILED) \
|
||||
mem = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define unwi_find_dynamic_proc_info UNWI_OBJ(find_dynamic_proc_info)
|
||||
#define unwi_extract_dynamic_proc_info UNWI_OBJ(extract_dynamic_proc_info)
|
||||
#define unwi_put_dynamic_unwind_info UNWI_OBJ(put_dynamic_unwind_info)
|
||||
#define unwi_dyn_remote_find_proc_info UNWI_OBJ(dyn_remote_find_proc_info)
|
||||
#define unwi_dyn_remote_put_unwind_info UNWI_OBJ(dyn_remote_put_unwind_info)
|
||||
#define unwi_dyn_validate_cache UNWI_OBJ(dyn_validate_cache)
|
||||
|
||||
extern int unwi_find_dynamic_proc_info (unw_addr_space_t as,
|
||||
unw_word_t ip,
|
||||
unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern int unwi_extract_dynamic_proc_info (unw_addr_space_t as,
|
||||
unw_word_t ip,
|
||||
unw_proc_info_t *pi,
|
||||
unw_dyn_info_t *di,
|
||||
int need_unwind_info,
|
||||
void *arg);
|
||||
extern void unwi_put_dynamic_unwind_info (unw_addr_space_t as,
|
||||
unw_proc_info_t *pi, void *arg);
|
||||
|
||||
/* These handle the remote (cross-address-space) case of accessing
|
||||
dynamic unwind info. */
|
||||
|
||||
extern int unwi_dyn_remote_find_proc_info (unw_addr_space_t as,
|
||||
unw_word_t ip,
|
||||
unw_proc_info_t *pi,
|
||||
int need_unwind_info,
|
||||
void *arg);
|
||||
extern void unwi_dyn_remote_put_unwind_info (unw_addr_space_t as,
|
||||
unw_proc_info_t *pi,
|
||||
void *arg);
|
||||
extern int unwi_dyn_validate_cache (unw_addr_space_t as, void *arg);
|
||||
|
||||
extern unw_dyn_info_list_t _U_dyn_info_list;
|
||||
extern pthread_mutex_t _U_dyn_info_list_lock;
|
||||
|
||||
#if UNW_DEBUG
|
||||
#define unwi_debug_level UNWI_ARCH_OBJ(debug_level)
|
||||
extern long unwi_debug_level;
|
||||
|
||||
# include <stdio.h>
|
||||
# define Debug(level,format...) \
|
||||
do { \
|
||||
if (unwi_debug_level >= level) \
|
||||
{ \
|
||||
int _n = level; \
|
||||
if (_n > 16) \
|
||||
_n = 16; \
|
||||
fprintf (stderr, "%*c>%s: ", _n, ' ', __FUNCTION__); \
|
||||
fprintf (stderr, format); \
|
||||
} \
|
||||
} while (0)
|
||||
# define Dprintf(format...) fprintf (stderr, format)
|
||||
#else
|
||||
# define Debug(level,format...)
|
||||
# define Dprintf(format...)
|
||||
#endif
|
||||
|
||||
static ALWAYS_INLINE int
|
||||
print_error (const char *string)
|
||||
{
|
||||
return write (2, string, strlen (string));
|
||||
}
|
||||
|
||||
#define mi_init UNWI_ARCH_OBJ(mi_init)
|
||||
|
||||
extern void mi_init (void); /* machine-independent initializations */
|
||||
extern unw_word_t _U_dyn_info_list_addr (void);
|
||||
|
||||
/* This is needed/used by ELF targets only. */
|
||||
|
||||
struct elf_image
|
||||
{
|
||||
void *image; /* pointer to mmap'd image */
|
||||
size_t size; /* (file-) size of the image */
|
||||
};
|
||||
|
||||
struct elf_dyn_info
|
||||
{
|
||||
struct elf_image ei;
|
||||
unw_dyn_info_t di_cache;
|
||||
unw_dyn_info_t di_debug; /* additional table info for .debug_frame */
|
||||
#if UNW_TARGET_IA64
|
||||
unw_dyn_info_t ktab;
|
||||
#endif
|
||||
#if UNW_TARGET_ARM
|
||||
unw_dyn_info_t di_arm; /* additional table info for .ARM.exidx */
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline void invalidate_edi (struct elf_dyn_info *edi)
|
||||
{
|
||||
if (edi->ei.image)
|
||||
munmap (edi->ei.image, edi->ei.size);
|
||||
memset (edi, 0, sizeof (*edi));
|
||||
edi->di_cache.format = -1;
|
||||
edi->di_debug.format = -1;
|
||||
#if UNW_TARGET_ARM
|
||||
edi->di_arm.format = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Provide a place holder for architecture to override for fast access
|
||||
to memory when known not to need to validate and know the access
|
||||
will be local to the process. A suitable override will improve
|
||||
unw_tdep_trace() performance in particular. */
|
||||
#define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \
|
||||
do { (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); } \
|
||||
while (0)
|
||||
|
||||
/* Define GNU and processor specific values for the Phdr p_type field in case
|
||||
they aren't defined by <elf.h>. */
|
||||
#ifndef PT_GNU_EH_FRAME
|
||||
# define PT_GNU_EH_FRAME 0x6474e550
|
||||
#endif /* !PT_GNU_EH_FRAME */
|
||||
#ifndef PT_ARM_EXIDX
|
||||
# define PT_ARM_EXIDX 0x70000001 /* ARM unwind segment */
|
||||
#endif /* !PT_ARM_EXIDX */
|
||||
|
||||
#include "tdep/libunwind_i.h"
|
||||
|
||||
#ifndef tdep_get_func_addr
|
||||
# define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0)
|
||||
#endif
|
||||
|
||||
#ifndef DWARF_VAL_LOC
|
||||
# define DWARF_IS_VAL_LOC(l) 0
|
||||
# define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC
|
||||
#endif
|
||||
|
||||
#define UNW_ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL))
|
||||
|
||||
#endif /* libunwind_i_h */
|
@ -1,89 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002-2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef mempool_h
|
||||
#define mempool_h
|
||||
|
||||
/* Memory pools provide simple memory management of fixed-size
|
||||
objects. Memory pools are used for two purposes:
|
||||
|
||||
o To ensure a stack can be unwound even when a process
|
||||
is out of memory.
|
||||
|
||||
o To ensure a stack can be unwound at any time in a
|
||||
multi-threaded process (e.g., even at a time when the normal
|
||||
malloc-lock is taken, possibly by the very thread that is
|
||||
being unwind).
|
||||
|
||||
|
||||
To achieve the second objective, memory pools allocate memory
|
||||
directly via mmap() system call (or an equivalent facility).
|
||||
|
||||
The first objective is accomplished by reserving memory ahead of
|
||||
time. Since the memory requirements of stack unwinding generally
|
||||
depends on the complexity of the procedures being unwind, there is
|
||||
no absolute guarantee that unwinding will always work, but in
|
||||
practice, this should not be a serious problem. */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "libunwind_i.h"
|
||||
|
||||
#define sos_alloc(s) UNWI_ARCH_OBJ(_sos_alloc)(s)
|
||||
#define mempool_init(p,s,r) UNWI_ARCH_OBJ(_mempool_init)(p,s,r)
|
||||
#define mempool_alloc(p) UNWI_ARCH_OBJ(_mempool_alloc)(p)
|
||||
#define mempool_free(p,o) UNWI_ARCH_OBJ(_mempool_free)(p,o)
|
||||
|
||||
/* The mempool structure should be treated as an opaque object. It's
|
||||
declared here only to enable static allocation of mempools. */
|
||||
struct mempool
|
||||
{
|
||||
pthread_mutex_t lock;
|
||||
size_t obj_size; /* object size (rounded up for alignment) */
|
||||
size_t chunk_size; /* allocation granularity */
|
||||
unsigned int reserve; /* minimum (desired) size of the free-list */
|
||||
unsigned int num_free; /* number of objects on the free-list */
|
||||
struct object
|
||||
{
|
||||
struct object *next;
|
||||
}
|
||||
*free_list;
|
||||
};
|
||||
|
||||
/* Emergency allocation for one-time stuff that doesn't fit the memory
|
||||
pool model. A limited amount of memory is available in this
|
||||
fashion and once allocated, there is no way to free it. */
|
||||
extern void *sos_alloc (size_t size);
|
||||
|
||||
/* Initialize POOL for an object size of OBJECT_SIZE bytes. RESERVE
|
||||
is the number of objects that should be reserved for use under
|
||||
tight memory situations. If it is zero, mempool attempts to pick a
|
||||
reasonable default value. */
|
||||
extern void mempool_init (struct mempool *pool,
|
||||
size_t obj_size, size_t reserve);
|
||||
extern void *mempool_alloc (struct mempool *pool);
|
||||
extern void mempool_free (struct mempool *pool, void *object);
|
||||
|
||||
#endif /* mempool_h */
|
@ -1,129 +0,0 @@
|
||||
#ifndef REMOTE_H
|
||||
#define REMOTE_H
|
||||
|
||||
/* Helper functions for accessing (remote) memory. These functions
|
||||
assume that all addresses are naturally aligned (e.g., 32-bit
|
||||
quantity is stored at a 32-bit-aligned address. */
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
|
||||
static inline int
|
||||
fetch8 (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, int8_t *valp, void *arg)
|
||||
{
|
||||
*valp = *(int8_t *) (uintptr_t) *addr;
|
||||
*addr += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
fetch16 (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, int16_t *valp, void *arg)
|
||||
{
|
||||
*valp = *(int16_t *) (uintptr_t) *addr;
|
||||
*addr += 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
fetch32 (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, int32_t *valp, void *arg)
|
||||
{
|
||||
*valp = *(int32_t *) (uintptr_t) *addr;
|
||||
*addr += 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
fetchw (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, unw_word_t *valp, void *arg)
|
||||
{
|
||||
*valp = *(unw_word_t *) (uintptr_t) *addr;
|
||||
*addr += sizeof (unw_word_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#define WSIZE (sizeof (unw_word_t))
|
||||
|
||||
static inline int
|
||||
fetch8 (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, int8_t *valp, void *arg)
|
||||
{
|
||||
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
||||
int ret;
|
||||
|
||||
*addr += 1;
|
||||
|
||||
ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
val >>= 8*off;
|
||||
#else
|
||||
val >>= 8*(WSIZE - 1 - off);
|
||||
#endif
|
||||
*valp = val & 0xff;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
fetch16 (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, int16_t *valp, void *arg)
|
||||
{
|
||||
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
||||
int ret;
|
||||
|
||||
if ((off & 0x1) != 0)
|
||||
return -UNW_EINVAL;
|
||||
|
||||
*addr += 2;
|
||||
|
||||
ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
val >>= 8*off;
|
||||
#else
|
||||
val >>= 8*(WSIZE - 2 - off);
|
||||
#endif
|
||||
*valp = val & 0xffff;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
fetch32 (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, int32_t *valp, void *arg)
|
||||
{
|
||||
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
||||
int ret;
|
||||
|
||||
if ((off & 0x3) != 0)
|
||||
return -UNW_EINVAL;
|
||||
|
||||
*addr += 4;
|
||||
|
||||
ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
val >>= 8*off;
|
||||
#else
|
||||
val >>= 8*(WSIZE - 4 - off);
|
||||
#endif
|
||||
*valp = val & 0xffffffff;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
fetchw (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t *addr, unw_word_t *valp, void *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (*a->access_mem) (as, *addr, valp, 0, arg);
|
||||
*addr += WSIZE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#endif /* REMOTE_H */
|
@ -1,52 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||
Copyright (C) 2013 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. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* This matches the value udes by GCC (see
|
||||
gcc/config/aarch64/aarch64.h:DWARF_FRAME_REGISTERS. */
|
||||
#define DWARF_NUM_PRESERVED_REGS 97
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) 0
|
||||
|
||||
#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_AARCH64_V31) ? (reg) : 0)
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,33 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2013 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. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
/* FIXME for AArch64 */
|
||||
|
||||
#define JB_SP 13
|
||||
#define JB_RP 14
|
||||
#define JB_MASK_SAVED 15
|
||||
#define JB_MASK 16
|
@ -1,320 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2005 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
Copyright (C) 2013 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. */
|
||||
|
||||
#ifndef AARCH64_LIBUNWIND_I_H
|
||||
#define AARCH64_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "elf64.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_AARCH64_FRAME_STANDARD = -2, /* regular fp, sp +/- offset */
|
||||
UNW_AARCH64_FRAME_SIGRETURN = -1, /* special sigreturn frame */
|
||||
UNW_AARCH64_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
|
||||
UNW_AARCH64_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
|
||||
}
|
||||
unw_tdep_frame_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t virtual_address;
|
||||
int64_t frame_type : 2; /* unw_tdep_frame_type_t classification */
|
||||
int64_t last_frame : 1; /* non-zero if last frame in chain */
|
||||
int64_t cfa_reg_sp : 1; /* cfa dwarf base register is sp vs. fp */
|
||||
int64_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
|
||||
int64_t fp_cfa_offset : 30; /* fp saved at this offset from cfa (-1 = not saved) */
|
||||
int64_t lr_cfa_offset : 30; /* lr saved at this offset from cfa (-1 = not saved) */
|
||||
int64_t sp_cfa_offset : 30; /* sp saved at this offset from cfa (-1 = not saved) */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
|
||||
typedef unw_word_t aarch64_loc_t;
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
|
||||
typedef struct aarch64_loc
|
||||
{
|
||||
unw_word_t w0, w1;
|
||||
}
|
||||
aarch64_loc_t;
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
int big_endian;
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
|
||||
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
||||
|
||||
enum
|
||||
{
|
||||
AARCH64_SCF_NONE,
|
||||
AARCH64_SCF_LINUX_RT_SIGFRAME,
|
||||
}
|
||||
sigcontext_format;
|
||||
unw_word_t sigcontext_addr;
|
||||
unw_word_t sigcontext_sp;
|
||||
unw_word_t sigcontext_pc;
|
||||
int validate;
|
||||
};
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
# define DWARF_IS_REG_LOC(l) 0
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
0, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||
c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
1, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
|
||||
|
||||
#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame UNW_OBJ(tdep_stash_frame)
|
||||
#define tdep_trace UNW_OBJ(tdep_trace)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
#define tdep_big_endian(as) ((as)->big_endian)
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t *valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t *valp, int write);
|
||||
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
||||
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
||||
struct dwarf_reg_state *rs);
|
||||
extern int tdep_getcontext_trace (unw_tdep_context_t *);
|
||||
|
||||
#endif /* AARCH64_LIBUNWIND_I_H */
|
@ -1,51 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
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. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
|
||||
explicitly defined. */
|
||||
#define DWARF_NUM_PRESERVED_REGS 128
|
||||
|
||||
#define dwarf_to_unw_regnum(reg) (((reg) < 16) ? (reg) : 0)
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) 0
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,55 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
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. */
|
||||
|
||||
#ifndef ARM_EX_TABLES_H
|
||||
#define ARM_EX_TABLES_H
|
||||
|
||||
typedef enum arm_exbuf_cmd {
|
||||
ARM_EXIDX_CMD_FINISH,
|
||||
ARM_EXIDX_CMD_DATA_PUSH,
|
||||
ARM_EXIDX_CMD_DATA_POP,
|
||||
ARM_EXIDX_CMD_REG_POP,
|
||||
ARM_EXIDX_CMD_REG_TO_SP,
|
||||
ARM_EXIDX_CMD_VFP_POP,
|
||||
ARM_EXIDX_CMD_WREG_POP,
|
||||
ARM_EXIDX_CMD_WCGR_POP,
|
||||
ARM_EXIDX_CMD_RESERVED,
|
||||
ARM_EXIDX_CMD_REFUSED,
|
||||
} arm_exbuf_cmd_t;
|
||||
|
||||
struct arm_exbuf_data
|
||||
{
|
||||
arm_exbuf_cmd_t cmd;
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
#define arm_exidx_extract UNW_OBJ(arm_exidx_extract)
|
||||
#define arm_exidx_decode UNW_OBJ(arm_exidx_decode)
|
||||
#define arm_exidx_apply_cmd UNW_OBJ(arm_exidx_apply_cmd)
|
||||
|
||||
int arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf);
|
||||
int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c);
|
||||
int arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c);
|
||||
|
||||
#endif // ARM_EX_TABLES_H
|
@ -1,32 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
/* FIXME for ARM! */
|
||||
|
||||
#define JB_SP 4
|
||||
#define JB_RP 5
|
||||
#define JB_MASK_SAVED 6
|
||||
#define JB_MASK 7
|
@ -1,326 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef ARM_LIBUNWIND_I_H
|
||||
#define ARM_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "elf32.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
#include "ex_tables.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_ARM_FRAME_SYSCALL = -3, /* r7 saved in r12, sp offset zero */
|
||||
UNW_ARM_FRAME_STANDARD = -2, /* regular r7, sp +/- offset */
|
||||
UNW_ARM_FRAME_SIGRETURN = -1, /* special sigreturn frame */
|
||||
UNW_ARM_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
|
||||
UNW_ARM_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
|
||||
}
|
||||
unw_tdep_frame_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t virtual_address;
|
||||
int32_t frame_type : 3; /* unw_tdep_frame_type_t classification */
|
||||
int32_t last_frame : 1; /* non-zero if last frame in chain */
|
||||
int32_t cfa_reg_sp : 1; /* cfa dwarf base register is sp vs. r7 */
|
||||
int32_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
|
||||
int32_t r7_cfa_offset : 30; /* r7 saved at this offset from cfa (-1 = not saved) */
|
||||
int32_t lr_cfa_offset : 30; /* lr saved at this offset from cfa (-1 = not saved) */
|
||||
int32_t sp_cfa_offset : 30; /* sp saved at this offset from cfa (-1 = not saved) */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
int big_endian;
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
|
||||
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
||||
|
||||
enum
|
||||
{
|
||||
ARM_SCF_NONE, /* no signal frame */
|
||||
ARM_SCF_LINUX_SIGFRAME, /* non-RT signal frame, kernel >=2.6.18 */
|
||||
ARM_SCF_LINUX_RT_SIGFRAME, /* RT signal frame, kernel >=2.6.18 */
|
||||
ARM_SCF_LINUX_OLD_SIGFRAME, /* non-RT signal frame, kernel < 2.6.18 */
|
||||
ARM_SCF_LINUX_OLD_RT_SIGFRAME, /* RT signal frame, kernel < 2.6.18 */
|
||||
ARM_SCF_FREEBSD_SIGFRAME, /* FreeBSD sigframe */
|
||||
ARM_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall stub */
|
||||
}
|
||||
sigcontext_format;
|
||||
unw_word_t sigcontext_addr;
|
||||
unw_word_t sigcontext_sp;
|
||||
unw_word_t sigcontext_pc;
|
||||
int validate;
|
||||
};
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
# define DWARF_IS_REG_LOC(l) 0
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
0, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||
c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
1, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
#define arm_find_proc_info UNW_OBJ(find_proc_info)
|
||||
#define arm_put_unwind_info UNW_OBJ(put_unwind_info)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table UNW_OBJ(search_unwind_table)
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame UNW_OBJ(tdep_stash_frame)
|
||||
#define tdep_trace UNW_OBJ(tdep_trace)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
arm_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
arm_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
#define tdep_big_endian(as) ((as)->big_endian)
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_proc_info_t *pi, int need_unwind_info,
|
||||
void *arg);
|
||||
extern void arm_put_unwind_info (unw_addr_space_t as,
|
||||
unw_proc_info_t *pi, void *arg);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t *valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t *valp, int write);
|
||||
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
||||
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
||||
struct dwarf_reg_state *rs);
|
||||
|
||||
/* unwinding method selection support */
|
||||
#define UNW_ARM_METHOD_ALL 0xFF
|
||||
#define UNW_ARM_METHOD_DWARF 0x01
|
||||
#define UNW_ARM_METHOD_FRAME 0x02
|
||||
#define UNW_ARM_METHOD_EXIDX 0x04
|
||||
|
||||
#define unwi_unwind_method UNW_OBJ(unwind_method)
|
||||
extern int unwi_unwind_method;
|
||||
|
||||
#define UNW_TRY_METHOD(x) (unwi_unwind_method & x)
|
||||
|
||||
#endif /* ARM_LIBUNWIND_I_H */
|
@ -1,54 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* See DWARF_FRAME_REGNUM() macro in gcc/config/pa/pa32-regs.h: */
|
||||
#define dwarf_to_unw_regnum(reg) \
|
||||
(((reg) < DWARF_NUM_PRESERVED_REGS) ? (reg) : 0)
|
||||
|
||||
/* This matches the value used by GCC (see
|
||||
gcc/config/pa/pa32-regs.h:FIRST_PSEUDO_REGISTER), which leaves
|
||||
plenty of room for expansion. */
|
||||
#define DWARF_NUM_PRESERVED_REGS 89
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) 1
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,33 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
#ifndef JB_SP
|
||||
# define JB_SP 19
|
||||
#endif
|
||||
#define JB_RP 20
|
||||
#define JB_MASK_SAVED 21
|
||||
#define JB_MASK 22
|
@ -1,279 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003-2005 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef HPPA_LIBUNWIND_I_H
|
||||
#define HPPA_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "elf32.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no hppa-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
|
||||
/* Format of sigcontext structure and address at which it is
|
||||
stored: */
|
||||
enum
|
||||
{
|
||||
HPPA_SCF_NONE, /* no signal frame encountered */
|
||||
HPPA_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
||||
}
|
||||
sigcontext_format;
|
||||
unw_word_t sigcontext_addr;
|
||||
};
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
# define DWARF_IS_REG_LOC(l) 0
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
0, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||
c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
1, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
#define tdep_big_endian(as) 1
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t *valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t *valp, int write);
|
||||
|
||||
#endif /* HPPA_LIBUNWIND_I_H */
|
@ -1,32 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP and BSP: */
|
||||
|
||||
#define JB_SP 0
|
||||
#define JB_RP 8
|
||||
#define JB_BSP 17
|
||||
#define JB_MASK_SAVED 70
|
||||
#define JB_MASK 71
|
@ -1,281 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2005 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef IA64_LIBUNWIND_I_H
|
||||
#define IA64_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include "elf64.h"
|
||||
#include "mempool.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ia64-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
enum ia64_pregnum
|
||||
{
|
||||
/* primary unat: */
|
||||
IA64_REG_PRI_UNAT_GR,
|
||||
IA64_REG_PRI_UNAT_MEM,
|
||||
|
||||
/* memory stack (order matters: see build_script() */
|
||||
IA64_REG_PSP, /* previous memory stack pointer */
|
||||
/* register stack */
|
||||
IA64_REG_BSP, /* register stack pointer */
|
||||
IA64_REG_BSPSTORE,
|
||||
IA64_REG_PFS, /* previous function state */
|
||||
IA64_REG_RNAT,
|
||||
/* instruction pointer: */
|
||||
IA64_REG_IP,
|
||||
|
||||
/* preserved registers: */
|
||||
IA64_REG_R4, IA64_REG_R5, IA64_REG_R6, IA64_REG_R7,
|
||||
IA64_REG_NAT4, IA64_REG_NAT5, IA64_REG_NAT6, IA64_REG_NAT7,
|
||||
IA64_REG_UNAT, IA64_REG_PR, IA64_REG_LC, IA64_REG_FPSR,
|
||||
IA64_REG_B1, IA64_REG_B2, IA64_REG_B3, IA64_REG_B4, IA64_REG_B5,
|
||||
IA64_REG_F2, IA64_REG_F3, IA64_REG_F4, IA64_REG_F5,
|
||||
IA64_REG_F16, IA64_REG_F17, IA64_REG_F18, IA64_REG_F19,
|
||||
IA64_REG_F20, IA64_REG_F21, IA64_REG_F22, IA64_REG_F23,
|
||||
IA64_REG_F24, IA64_REG_F25, IA64_REG_F26, IA64_REG_F27,
|
||||
IA64_REG_F28, IA64_REG_F29, IA64_REG_F30, IA64_REG_F31,
|
||||
IA64_NUM_PREGS
|
||||
};
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
|
||||
typedef unw_word_t ia64_loc_t;
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
|
||||
typedef struct ia64_loc
|
||||
{
|
||||
unw_word_t w0, w1;
|
||||
}
|
||||
ia64_loc_t;
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#include "script.h"
|
||||
|
||||
#define ABI_UNKNOWN 0
|
||||
#define ABI_LINUX 1
|
||||
#define ABI_HPUX 2
|
||||
#define ABI_FREEBSD 3
|
||||
#define ABI_OPENVMS 4
|
||||
#define ABI_NSK 5 /* Tandem/HP Non-Stop Kernel */
|
||||
#define ABI_WINDOWS 6
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
int big_endian;
|
||||
int abi; /* abi < 0 => unknown, 0 => SysV, 1 => HP-UX, 2 => Windows */
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation;
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
unsigned long long shared_object_removals;
|
||||
#endif
|
||||
|
||||
struct ia64_script_cache global_cache;
|
||||
};
|
||||
|
||||
/* Note: The ABI numbers in the ABI-markers (.unwabi directive) are
|
||||
not the same as the above ABI numbers. */
|
||||
#define ABI_MARKER_OLD_LINUX_SIGTRAMP ((0 << 8) | 's')
|
||||
#define ABI_MARKER_OLD_LINUX_INTERRUPT ((0 << 8) | 'i')
|
||||
#define ABI_MARKER_HP_UX_SIGTRAMP ((1 << 8) | 1)
|
||||
#define ABI_MARKER_LINUX_SIGTRAMP ((3 << 8) | 's')
|
||||
#define ABI_MARKER_LINUX_INTERRUPT ((3 << 8) | 'i')
|
||||
|
||||
struct cursor
|
||||
{
|
||||
void *as_arg; /* argument to address-space callbacks */
|
||||
unw_addr_space_t as; /* reference to per-address-space info */
|
||||
|
||||
/* IP, CFM, and predicate cache (these are always equal to the
|
||||
values stored in ip_loc, cfm_loc, and pr_loc,
|
||||
respectively). */
|
||||
unw_word_t ip; /* instruction pointer value */
|
||||
unw_word_t cfm; /* current frame mask */
|
||||
unw_word_t pr; /* current predicate values */
|
||||
|
||||
/* current frame info: */
|
||||
unw_word_t bsp; /* backing store pointer value */
|
||||
unw_word_t sp; /* stack pointer value */
|
||||
unw_word_t psp; /* previous sp value */
|
||||
ia64_loc_t cfm_loc; /* cfm save location (or NULL) */
|
||||
ia64_loc_t ec_loc; /* ar.ec save location (usually cfm_loc) */
|
||||
ia64_loc_t loc[IA64_NUM_PREGS];
|
||||
|
||||
unw_word_t eh_args[4]; /* exception handler arguments */
|
||||
unw_word_t sigcontext_addr; /* address of sigcontext or 0 */
|
||||
unw_word_t sigcontext_off; /* sigcontext-offset relative to signal sp */
|
||||
|
||||
short hint;
|
||||
short prev_script;
|
||||
|
||||
uint8_t nat_bitnr[4]; /* NaT bit numbers for r4-r7 */
|
||||
uint16_t abi_marker; /* abi_marker for current frame (if any) */
|
||||
uint16_t last_abi_marker; /* last abi_marker encountered so far */
|
||||
uint8_t eh_valid_mask;
|
||||
|
||||
unsigned int pi_valid :1; /* is proc_info valid? */
|
||||
unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
|
||||
unw_proc_info_t pi; /* info about current procedure */
|
||||
|
||||
/* In case of stack-discontiguities, such as those introduced by
|
||||
signal-delivery on an alternate signal-stack (see
|
||||
sigaltstack(2)), we use the following data-structure to keep
|
||||
track of the register-backing-store areas across on which the
|
||||
current frame may be backed up. Since there are at most 96
|
||||
stacked registers and since we only have to track the current
|
||||
frame and only areas that are not empty, this puts an upper
|
||||
limit on the # of backing-store areas we have to track.
|
||||
|
||||
Note that the rbs-area indexed by rbs_curr identifies the
|
||||
rbs-area that was in effect at the time AR.BSP had the value
|
||||
c->bsp. However, this rbs area may not actually contain the
|
||||
value in the register that c->bsp corresponds to because that
|
||||
register may not have gotten spilled until much later, when a
|
||||
possibly different rbs-area might have been in effect
|
||||
already. */
|
||||
uint8_t rbs_curr; /* index of curr. rbs-area (contains c->bsp) */
|
||||
uint8_t rbs_left_edge; /* index of inner-most valid rbs-area */
|
||||
struct rbs_area
|
||||
{
|
||||
unw_word_t end;
|
||||
unw_word_t size;
|
||||
ia64_loc_t rnat_loc;
|
||||
}
|
||||
rbs_area[96 + 2]; /* 96 stacked regs + 1 extra stack on each side... */
|
||||
};
|
||||
|
||||
struct ia64_global_unwind_state
|
||||
{
|
||||
pthread_mutex_t lock; /* global data lock */
|
||||
|
||||
volatile char init_done;
|
||||
|
||||
/* Table of registers that prologues can save (and order in which
|
||||
they're saved). */
|
||||
const unsigned char save_order[8];
|
||||
|
||||
/*
|
||||
* uc_addr() may return pointers to these variables. We need to
|
||||
* make sure they don't get written via ia64_put() or
|
||||
* ia64_putfp(). To make it possible to test for these variables
|
||||
* quickly, we collect them in a single sub-structure.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
unw_word_t r0; /* r0 is byte-order neutral */
|
||||
unw_fpreg_t f0; /* f0 is byte-order neutral */
|
||||
unw_fpreg_t f1_le, f1_be; /* f1 is byte-order dependent */
|
||||
}
|
||||
read_only;
|
||||
unw_fpreg_t nat_val_le, nat_val_be;
|
||||
unw_fpreg_t int_val_le, int_val_be;
|
||||
|
||||
struct mempool reg_state_pool;
|
||||
struct mempool labeled_state_pool;
|
||||
|
||||
# if UNW_DEBUG
|
||||
const char *preg_name[IA64_NUM_PREGS];
|
||||
# endif
|
||||
};
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done unw.init_done
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table unw_search_ia64_unwind_table
|
||||
#define tdep_find_unwind_table ia64_find_unwind_table
|
||||
#define tdep_find_proc_info UNW_OBJ(find_proc_info)
|
||||
#define tdep_uc_addr UNW_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
#define tdep_get_as(c) ((c)->as)
|
||||
#define tdep_get_as_arg(c) ((c)->as_arg)
|
||||
#define tdep_get_ip(c) ((c)->ip)
|
||||
#define tdep_big_endian(as) ((c)->as->big_endian != 0)
|
||||
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
# define tdep_put_unwind_info UNW_OBJ(put_unwind_info)
|
||||
#endif
|
||||
|
||||
/* This can't be an UNW_ARCH_OBJ() because we need separate
|
||||
unw.initialized flags for the local-only and generic versions of
|
||||
the library. Also, if we wanted to have a single, shared global
|
||||
data structure, we couldn't declare "unw" as HIDDEN/PROTECTED. */
|
||||
#define unw UNW_OBJ(data)
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_find_unwind_table (struct elf_dyn_info *edi,
|
||||
unw_addr_space_t as, char *path,
|
||||
unw_word_t segbase, unw_word_t mapoff,
|
||||
unw_word_t ip);
|
||||
extern int tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_proc_info_t *pi, int need_unwind_info,
|
||||
void *arg);
|
||||
extern void tdep_put_unwind_info (unw_addr_space_t as,
|
||||
unw_proc_info_t *pi, void *arg);
|
||||
extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum,
|
||||
uint8_t *nat_bitnr);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t *valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t *valp, int write);
|
||||
|
||||
extern struct ia64_global_unwind_state unw;
|
||||
|
||||
/* In user-level, we have no reasonable way of determining the base of
|
||||
an arbitrary backing-store. We default to half the
|
||||
address-space. */
|
||||
#define rbs_get_base(c,bspstore,rbs_basep) \
|
||||
(*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0)
|
||||
|
||||
#endif /* IA64_LIBUNWIND_I_H */
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 1998, 1999, 2002, 2003, 2005 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
*
|
||||
* Register stack engine related helper functions. This file may be
|
||||
* used in applications, so be careful about the name-space and give
|
||||
* some consideration to non-GNU C compilers (though __inline__ is
|
||||
* fine).
|
||||
*/
|
||||
#ifndef RSE_H
|
||||
#define RSE_H
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
static inline uint64_t
|
||||
rse_slot_num (uint64_t addr)
|
||||
{
|
||||
return (addr >> 3) & 0x3f;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if ADDR is the address of an RNAT slot.
|
||||
*/
|
||||
static inline uint64_t
|
||||
rse_is_rnat_slot (uint64_t addr)
|
||||
{
|
||||
return rse_slot_num (addr) == 0x3f;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the address of the RNAT slot that covers the slot at
|
||||
* address SLOT_ADDR.
|
||||
*/
|
||||
static inline uint64_t
|
||||
rse_rnat_addr (uint64_t slot_addr)
|
||||
{
|
||||
return slot_addr | (0x3f << 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the number of registers in the dirty partition starting at
|
||||
* BSPSTORE and ending at BSP. This isn't simply (BSP-BSPSTORE)/8
|
||||
* because every 64th slot stores ar.rnat.
|
||||
*/
|
||||
static inline uint64_t
|
||||
rse_num_regs (uint64_t bspstore, uint64_t bsp)
|
||||
{
|
||||
uint64_t slots = (bsp - bspstore) >> 3;
|
||||
|
||||
return slots - (rse_slot_num(bspstore) + slots)/0x40;
|
||||
}
|
||||
|
||||
/*
|
||||
* The inverse of the above: given bspstore and the number of
|
||||
* registers, calculate ar.bsp.
|
||||
*/
|
||||
static inline uint64_t
|
||||
rse_skip_regs (uint64_t addr, long num_regs)
|
||||
{
|
||||
long delta = rse_slot_num(addr) + num_regs;
|
||||
|
||||
if (num_regs < 0)
|
||||
delta -= 0x3e;
|
||||
return addr + ((num_regs + delta/0x3f) << 3);
|
||||
}
|
||||
|
||||
#endif /* RSE_H */
|
@ -1,85 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#define IA64_LOG_UNW_CACHE_SIZE 7
|
||||
#define IA64_UNW_CACHE_SIZE (1 << IA64_LOG_UNW_CACHE_SIZE)
|
||||
|
||||
#define IA64_LOG_UNW_HASH_SIZE (IA64_LOG_UNW_CACHE_SIZE + 1)
|
||||
#define IA64_UNW_HASH_SIZE (1 << IA64_LOG_UNW_HASH_SIZE)
|
||||
|
||||
typedef unsigned char unw_hash_index_t;
|
||||
|
||||
struct ia64_script_insn
|
||||
{
|
||||
unsigned int opc; /* see enum ia64_script_insn_opcode */
|
||||
unsigned int dst;
|
||||
unw_word_t val;
|
||||
};
|
||||
|
||||
/* Updating each preserved register may result in one script
|
||||
instruction each. At the end of the script, psp gets popped,
|
||||
accounting for one more instruction. */
|
||||
#define IA64_MAX_SCRIPT_LEN (IA64_NUM_PREGS + 1)
|
||||
|
||||
struct ia64_script
|
||||
{
|
||||
unw_word_t ip; /* ip this script is for */
|
||||
unw_word_t pr_mask; /* mask of predicates script depends on */
|
||||
unw_word_t pr_val; /* predicate values this script is for */
|
||||
unw_proc_info_t pi; /* info about underlying procedure */
|
||||
unsigned short lru_chain; /* used for least-recently-used chain */
|
||||
unsigned short coll_chain; /* used for hash collisions */
|
||||
unsigned short hint; /* hint for next script to try (or -1) */
|
||||
unsigned short count; /* number of instructions in script */
|
||||
unsigned short abi_marker;
|
||||
struct ia64_script_insn insn[IA64_MAX_SCRIPT_LEN];
|
||||
};
|
||||
|
||||
struct ia64_script_cache
|
||||
{
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_TS_t busy; /* is the script-cache busy? */
|
||||
#else
|
||||
pthread_mutex_t lock;
|
||||
#endif
|
||||
unsigned short lru_head; /* index of lead-recently used script */
|
||||
unsigned short lru_tail; /* index of most-recently used script */
|
||||
|
||||
/* hash table that maps instruction pointer to script index: */
|
||||
unsigned short hash[IA64_UNW_HASH_SIZE];
|
||||
|
||||
uint32_t generation; /* generation number */
|
||||
|
||||
/* script cache: */
|
||||
struct ia64_script buckets[IA64_UNW_CACHE_SIZE];
|
||||
};
|
||||
|
||||
#define ia64_cache_proc_info UNW_OBJ(cache_proc_info)
|
||||
#define ia64_get_cached_proc_info UNW_OBJ(get_cached_proc_info)
|
||||
|
||||
struct cursor; /* forward declaration */
|
||||
|
||||
extern int ia64_cache_proc_info (struct cursor *c);
|
||||
extern int ia64_get_cached_proc_info (struct cursor *c);
|
@ -1,54 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
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. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
|
||||
explicitly defined. */
|
||||
#define DWARF_NUM_PRESERVED_REGS 188
|
||||
|
||||
#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0)
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
||||
|
||||
/* Return the size of an address, for DWARF purposes. */
|
||||
#define dwarf_addr_size(addr_space) ((addr_space)->addr_size)
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,32 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
/* FIXME for MIPS! */
|
||||
|
||||
#define JB_SP 4
|
||||
#define JB_RP 5
|
||||
#define JB_MASK_SAVED 6
|
||||
#define JB_MASK 7
|
@ -1,331 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef MIPS_LIBUNWIND_I_H
|
||||
#define MIPS_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#if !defined(UNW_REMOTE_ONLY) && _MIPS_SIM == _ABI64
|
||||
# include "elf64.h"
|
||||
#else
|
||||
# include "elf32.h"
|
||||
#endif
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no mips-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
||||
int big_endian;
|
||||
mips_abi_t abi;
|
||||
unsigned int addr_size;
|
||||
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
#define tdep_big_endian(as) ((as)->big_endian)
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
unw_word_t sigcontext_addr;
|
||||
};
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
# if _MIPS_SIM == _ABIN32
|
||||
typedef long long mips_reg_t;
|
||||
# else
|
||||
typedef long mips_reg_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
# define DWARF_IS_REG_LOC(l) 0
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
|
||||
/* FIXME: Implement these for the MIPS FPU. */
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(mips_reg_t *) (intptr_t) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(mips_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
|
||||
static inline int
|
||||
read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val)
|
||||
{
|
||||
int offset = addr & 4;
|
||||
int ret;
|
||||
unw_word_t memval;
|
||||
|
||||
ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((offset != 0) == tdep_big_endian (c->as))
|
||||
*val = (int32_t) memval;
|
||||
else
|
||||
*val = (int32_t) (memval >> 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
write_s32 (struct dwarf_cursor *c, unw_word_t addr, const unw_word_t *val)
|
||||
{
|
||||
int offset = addr & 4;
|
||||
int ret;
|
||||
unw_word_t memval;
|
||||
|
||||
ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((offset != 0) == tdep_big_endian (c->as))
|
||||
memval = (memval & ~0xffffffffLL) | (uint32_t) *val;
|
||||
else
|
||||
memval = (memval & 0xffffffffLL) | (uint32_t) (*val << 32);
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 1, c->as_arg);
|
||||
}
|
||||
|
||||
/* FIXME: Implement these for the MIPS FPU. */
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
0, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||
c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
1, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
else if (c->as->abi == UNW_MIPS_ABI_O32)
|
||||
return read_s32 (c, DWARF_GET_LOC (loc), val);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else if (c->as->abi == UNW_MIPS_ABI_O32)
|
||||
return write_s32 (c, DWARF_GET_LOC (loc), &val);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t *valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t *valp, int write);
|
||||
|
||||
#endif /* MIPS_LIBUNWIND_I_H */
|
@ -1,56 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2006-2007 IBM
|
||||
Contributed by
|
||||
Corey Ashford <cjashfor@us.ibm.com>
|
||||
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
|
||||
|
||||
Copied from libunwind-x86_64.h, modified slightly for building
|
||||
frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
|
||||
Will be replaced when libunwind is ready on ppc64 platform.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */
|
||||
#define DWARF_NUM_PRESERVED_REGS 115
|
||||
|
||||
#define DWARF_REGNUM_MAP_LENGTH 115
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) 1
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,37 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2006-2007 IBM
|
||||
Contributed by
|
||||
Corey Ashford <cjashfor@us.ibm.com>
|
||||
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
|
||||
|
||||
Copied from libunwind-x86_64.h, modified slightly for building
|
||||
frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
|
||||
Will be replaced when libunwind is ready on ppc64 platform.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
#define JB_SP 6
|
||||
#define JB_RP 7
|
||||
#define JB_MASK_SAVED 8
|
||||
#define JB_MASK 9
|
@ -1,314 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2006-2007 IBM
|
||||
Contributed by
|
||||
Corey Ashford <cjashfor@us.ibm.com>
|
||||
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
|
||||
|
||||
Copied from libunwind-x86_64.h, modified slightly for building
|
||||
frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
|
||||
Will be replaced when libunwind is ready on ppc64 platform.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef PPC32_LIBUNWIND_I_H
|
||||
#define PPC32_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "elf32.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ppc32-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
int validate;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
|
||||
/* Format of sigcontext structure and address at which it is
|
||||
stored: */
|
||||
enum
|
||||
{
|
||||
PPC_SCF_NONE, /* no signal frame encountered */
|
||||
PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
||||
}
|
||||
sigcontext_format;
|
||||
unw_word_t sigcontext_addr;
|
||||
};
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
# define DWARF_IS_REG_LOC(l) 0
|
||||
# define DWARF_IS_FP_LOC(l) 0
|
||||
# define DWARF_IS_V_LOC(l) 0
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_LOC_TYPE_V (1 << 2)
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_V))
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
static inline int
|
||||
dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||
{
|
||||
unw_word_t *valp = (unw_word_t *) val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
assert (DWARF_IS_V_LOC (loc));
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
||||
0, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
unw_word_t *valp = (unw_word_t *) & val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
assert (DWARF_IS_V_LOC (loc));
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
||||
1, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||
{
|
||||
unw_word_t *valp = (unw_word_t *) val;
|
||||
unw_word_t addr;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
assert (DWARF_IS_FP_LOC (loc));
|
||||
assert (!DWARF_IS_V_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
|
||||
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
unw_word_t *valp = (unw_word_t *) & val;
|
||||
unw_word_t addr;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
assert (DWARF_IS_FP_LOC (loc));
|
||||
assert (!DWARF_IS_V_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
assert (!DWARF_IS_V_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
assert (!DWARF_IS_V_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
|
||||
int need_unwind_info);
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
#define tdep_big_endian(as) 1
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t * di,
|
||||
unw_proc_info_t * pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *tdep_uc_addr (ucontext_t * uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t * valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t * valp, int write);
|
||||
extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
|
||||
unw_word_t *entry_point);
|
||||
|
||||
#endif /* PPC64_LIBUNWIND_I_H */
|
@ -1,56 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2006-2007 IBM
|
||||
Contributed by
|
||||
Corey Ashford <cjashfor@us.ibm.com>
|
||||
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
|
||||
|
||||
Copied from libunwind-x86_64.h, modified slightly for building
|
||||
frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
|
||||
Will be replaced when libunwind is ready on ppc64 platform.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */
|
||||
#define DWARF_NUM_PRESERVED_REGS 115
|
||||
|
||||
#define DWARF_REGNUM_MAP_LENGTH 115
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,37 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2006-2007 IBM
|
||||
Contributed by
|
||||
Corey Ashford <cjashfor@us.ibm.com>
|
||||
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
|
||||
|
||||
Copied from libunwind-x86_64.h, modified slightly for building
|
||||
frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
|
||||
Will be replaced when libunwind is ready on ppc64 platform.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
#define JB_SP 6
|
||||
#define JB_RP 7
|
||||
#define JB_MASK_SAVED 8
|
||||
#define JB_MASK 9
|
@ -1,370 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2006-2007 IBM
|
||||
Contributed by
|
||||
Corey Ashford <cjashfor@us.ibm.com>
|
||||
Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
|
||||
|
||||
Copied from libunwind-x86_64.h, modified slightly for building
|
||||
frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
|
||||
Will be replaced when libunwind is ready on ppc64 platform.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef PPC64_LIBUNWIND_I_H
|
||||
#define PPC64_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
#include <libunwind-ppc64.h>
|
||||
|
||||
#include "elf64.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ppc64-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
int big_endian;
|
||||
ppc64_abi_t abi;
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
int validate;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
|
||||
/* Format of sigcontext structure and address at which it is
|
||||
stored: */
|
||||
enum
|
||||
{
|
||||
PPC_SCF_NONE, /* no signal frame encountered */
|
||||
PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
||||
}
|
||||
sigcontext_format;
|
||||
unw_word_t sigcontext_addr;
|
||||
};
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
# define DWARF_IS_REG_LOC(l) 0
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
|
||||
static inline int
|
||||
dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_LOC_TYPE_V (1 << 2)
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_V))
|
||||
|
||||
static inline int
|
||||
dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||
{
|
||||
unw_word_t *valp = (unw_word_t *) val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
assert (DWARF_IS_V_LOC (loc));
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
||||
0, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
unw_word_t *valp = (unw_word_t *) & val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
assert (DWARF_IS_V_LOC (loc));
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
||||
1, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||
{
|
||||
unw_word_t *valp = (unw_word_t *) val;
|
||||
unw_word_t addr;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
assert (DWARF_IS_FP_LOC (loc));
|
||||
assert (!DWARF_IS_V_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
|
||||
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
unw_word_t *valp = (unw_word_t *) & val;
|
||||
unw_word_t addr;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
assert (DWARF_IS_FP_LOC (loc));
|
||||
assert (!DWARF_IS_V_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
assert (!DWARF_IS_V_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
assert (!DWARF_IS_V_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
|
||||
int need_unwind_info);
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
#define tdep_big_endian(as) ((as)->big_endian)
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t * di,
|
||||
unw_proc_info_t * pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *tdep_uc_addr (ucontext_t * uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t * valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t * valp, int write);
|
||||
extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
|
||||
unw_word_t *entry_point);
|
||||
|
||||
#endif /* PPC64_LIBUNWIND_I_H */
|
@ -1,49 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
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. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
#define DWARF_NUM_PRESERVED_REGS 18
|
||||
|
||||
#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_SH_PR) ? (reg) : 0)
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,48 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
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. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
/* SH4 glibc jump buffer contents:
|
||||
* 0. r8
|
||||
* 1. r9
|
||||
* 2. r10
|
||||
* 3. r11
|
||||
* 4. r12
|
||||
* 5. r13
|
||||
* 6. r14
|
||||
* 7. r15
|
||||
* 8. pr/pc
|
||||
* 9. gbr
|
||||
* 10. fpscr
|
||||
* 11. fr12
|
||||
* 12. fr13
|
||||
* 13. fr14
|
||||
* 14. fr15
|
||||
*/
|
||||
|
||||
#define JB_SP 7
|
||||
#define JB_RP 8
|
||||
#define JB_MASK_SAVED 15
|
||||
#define JB_MASK 16
|
@ -1,280 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
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. */
|
||||
|
||||
#ifndef SH_LIBUNWIND_I_H
|
||||
#define SH_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "elf32.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no sh-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
int big_endian;
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
enum
|
||||
{
|
||||
SH_SCF_NONE, /* no signal frame */
|
||||
SH_SCF_LINUX_SIGFRAME, /* non-RT signal frame */
|
||||
SH_SCF_LINUX_RT_SIGFRAME, /* RT signal frame */
|
||||
}
|
||||
sigcontext_format;
|
||||
unw_word_t sigcontext_addr;
|
||||
unw_word_t sigcontext_sp;
|
||||
unw_word_t sigcontext_pc;
|
||||
};
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
# define DWARF_IS_REG_LOC(l) 0
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
0, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||
c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
1, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
#define tdep_big_endian(as) ((as)->big_endian)
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t *valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t *valp, int write);
|
||||
|
||||
#endif /* SH_LIBUNWIND_I_H */
|
@ -1,50 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2014 Tilera Corp.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
|
||||
explicitly defined. */
|
||||
#define DWARF_NUM_PRESERVED_REGS 188
|
||||
|
||||
#define DWARF_REGNUM_MAP_LENGTH (56 + 2)
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
} dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,33 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2014 Tilera Corp.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
/* FIXME for Tilegx! */
|
||||
|
||||
#define JB_SP 4
|
||||
#define JB_RP 5
|
||||
#define JB_MASK_SAVED 6
|
||||
#define JB_MASK 7
|
@ -1,263 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2014 Tilera Corp.
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef TILEGX_LIBUNWIND_I_H
|
||||
#define TILEGX_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
# include "elf64.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no Tilegx-specific fast trace */
|
||||
} unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
||||
int big_endian;
|
||||
tilegx_abi_t abi;
|
||||
unsigned int addr_size;
|
||||
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
#define tdep_big_endian(as) ((as)->big_endian)
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
unw_word_t sigcontext_addr;
|
||||
unw_word_t sigcontext_sp;
|
||||
unw_word_t sigcontext_pc;
|
||||
};
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
typedef long tilegx_reg_t;
|
||||
#endif
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
#define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
#define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
#define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
#define DWARF_IS_REG_LOC(l) 0
|
||||
#define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
#define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
#define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
|
||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||
|
||||
/* Tilegx has no FP. */
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
Debug (1, "Tielgx has no fp!\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
Debug (1, "Tielgx has no fp!\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
|
||||
*val = *(tilegx_reg_t *) (intptr_t) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
|
||||
*(tilegx_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
#define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
#define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
#define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
#define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
#define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
#define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
#define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
#define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
#define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
#define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
|
||||
/* TILEGX has no fp. */
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
Debug (1, "Tielgx has no fp!\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
Debug (1, "Tielgx has no fp!\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
#define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
#define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
#define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
#define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as,
|
||||
unw_word_t ip,
|
||||
unw_dyn_info_t *di,
|
||||
unw_proc_info_t *pi,
|
||||
int need_unwind_info,
|
||||
void *arg);
|
||||
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei,
|
||||
pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase,
|
||||
unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c,
|
||||
unw_regnum_t reg,
|
||||
unw_word_t *valp,
|
||||
int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c,
|
||||
unw_regnum_t reg,
|
||||
unw_fpreg_t *valp,
|
||||
int write);
|
||||
|
||||
#endif /* TILEGX_LIBUNWIND_I_H */
|
@ -1,52 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* This matches the value used by GCC (see
|
||||
gcc/config/i386.h:DWARF_FRAME_REGISTERS), which leaves plenty of
|
||||
room for expansion. */
|
||||
#define DWARF_NUM_PRESERVED_REGS 17
|
||||
|
||||
#define DWARF_REGNUM_MAP_LENGTH 19
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) 0
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||
#endif
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,42 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
#if defined __linux__
|
||||
|
||||
#define JB_SP 4
|
||||
#define JB_RP 5
|
||||
#define JB_MASK_SAVED 6
|
||||
#define JB_MASK 7
|
||||
|
||||
#elif defined __FreeBSD__
|
||||
|
||||
#define JB_SP 2
|
||||
#define JB_RP 0
|
||||
#define JB_MASK_SAVED 11
|
||||
#define JB_MASK 7
|
||||
|
||||
#endif
|
@ -1,293 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002-2005 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef X86_LIBUNWIND_I_H
|
||||
#define X86_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "elf32.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no x86-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
|
||||
/* Format of sigcontext structure and address at which it is
|
||||
stored: */
|
||||
enum
|
||||
{
|
||||
X86_SCF_NONE, /* no signal frame encountered */
|
||||
X86_SCF_LINUX_SIGFRAME, /* Linux x86 sigcontext */
|
||||
X86_SCF_LINUX_RT_SIGFRAME, /* POSIX ucontext_t */
|
||||
X86_SCF_FREEBSD_SIGFRAME, /* FreeBSD x86 sigcontext */
|
||||
X86_SCF_FREEBSD_SIGFRAME4, /* FreeBSD 4.x x86 sigcontext */
|
||||
X86_SCF_FREEBSD_OSIGFRAME, /* FreeBSD pre-4.x x86 sigcontext */
|
||||
X86_SCF_FREEBSD_SYSCALL, /* FreeBSD x86 syscall */
|
||||
}
|
||||
sigcontext_format;
|
||||
unw_word_t sigcontext_addr;
|
||||
int validate;
|
||||
ucontext_t *uc;
|
||||
};
|
||||
|
||||
static inline ucontext_t *
|
||||
dwarf_get_uc(const struct dwarf_cursor *cursor)
|
||||
{
|
||||
const struct cursor *c = (struct cursor *) cursor->as_arg;
|
||||
return c->uc;
|
||||
}
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||
# define DWARF_IS_REG_LOC(l) 0
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (!DWARF_GET_LOC (loc))
|
||||
return -1;
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
val, 0, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
0, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||
c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
char *valp = (char *) &val;
|
||||
unw_word_t addr;
|
||||
int ret;
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||
&val, 1, c->as_arg);
|
||||
|
||||
addr = DWARF_GET_LOC (loc);
|
||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||
1, c->as_arg)) < 0)
|
||||
return ret;
|
||||
|
||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
/* If a code-generator were to save a value of type unw_word_t in a
|
||||
floating-point register, we would have to support this case. I
|
||||
suppose it could happen with MMX registers, but does it really
|
||||
happen? */
|
||||
assert (!DWARF_IS_FP_LOC (loc));
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
#define tdep_getcontext_trace unw_getcontext
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
#define tdep_cache_frame(c) 0
|
||||
#define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
#define tdep_big_endian(as) 0
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t *valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t *valp, int write);
|
||||
|
||||
#endif /* X86_LIBUNWIND_I_H */
|
@ -1,57 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (c) 2003, 2005 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. */
|
||||
|
||||
/* copy of include/tdep-x86/dwarf-config.h, modified slightly for x86-64
|
||||
some consolidation is possible here */
|
||||
|
||||
#ifndef dwarf_config_h
|
||||
#define dwarf_config_h
|
||||
|
||||
/* XXX need to verify if this value is correct */
|
||||
#ifdef CONFIG_MSABI_SUPPORT
|
||||
#define DWARF_NUM_PRESERVED_REGS 33
|
||||
#else
|
||||
#define DWARF_NUM_PRESERVED_REGS 17
|
||||
#endif
|
||||
|
||||
#define DWARF_REGNUM_MAP_LENGTH DWARF_NUM_PRESERVED_REGS
|
||||
|
||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||
#define dwarf_is_big_endian(addr_space) 0
|
||||
|
||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||
unw_cursor_t. */
|
||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||
|
||||
typedef struct dwarf_loc
|
||||
{
|
||||
unw_word_t val;
|
||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||
}
|
||||
dwarf_loc_t;
|
||||
|
||||
#endif /* dwarf_config_h */
|
@ -1,43 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#if defined __linux__
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
#define JB_SP 6
|
||||
#define JB_RP 7
|
||||
#define JB_MASK_SAVED 8
|
||||
#define JB_MASK 9
|
||||
|
||||
#elif defined __FreeBSD__
|
||||
|
||||
#define JB_SP 2
|
||||
#define JB_RP 0
|
||||
/* Pretend the ip cannot be 0 and mask is always saved */
|
||||
#define JB_MASK_SAVED 0
|
||||
#define JB_MASK 9
|
||||
|
||||
#endif
|
@ -1,264 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002-2005 Hewlett-Packard Co
|
||||
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. */
|
||||
|
||||
#ifndef X86_64_LIBUNWIND_I_H
|
||||
#define X86_64_LIBUNWIND_I_H
|
||||
|
||||
/* Target-dependent definitions that are internal to libunwind but need
|
||||
to be shared with target-independent code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "elf64.h"
|
||||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_X86_64_FRAME_ALIGNED = -3, /* frame stack pointer aligned */
|
||||
UNW_X86_64_FRAME_STANDARD = -2, /* regular rbp, rsp +/- offset */
|
||||
UNW_X86_64_FRAME_SIGRETURN = -1, /* special sigreturn frame */
|
||||
UNW_X86_64_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
|
||||
UNW_X86_64_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
|
||||
}
|
||||
unw_tdep_frame_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t virtual_address;
|
||||
int64_t frame_type : 3; /* unw_tdep_frame_type_t classification */
|
||||
int64_t last_frame : 1; /* non-zero if last frame in chain */
|
||||
int64_t cfa_reg_rsp : 1; /* cfa dwarf base register is rsp vs. rbp */
|
||||
int64_t cfa_reg_offset : 29; /* cfa is at this offset from base register value */
|
||||
int64_t rbp_cfa_offset : 15; /* rbp saved at this offset from cfa (-1 = not saved) */
|
||||
int64_t rsp_cfa_offset : 15; /* rsp saved at this offset from cfa (-1 = not saved) */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
unw_caching_policy_t caching_policy;
|
||||
#ifdef HAVE_ATOMIC_OPS_H
|
||||
AO_t cache_generation;
|
||||
#else
|
||||
uint32_t cache_generation;
|
||||
#endif
|
||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
struct unw_debug_frame_list *debug_frames;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
struct dwarf_cursor dwarf; /* must be first */
|
||||
|
||||
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
||||
|
||||
/* Format of sigcontext structure and address at which it is
|
||||
stored: */
|
||||
enum
|
||||
{
|
||||
X86_64_SCF_NONE, /* no signal frame encountered */
|
||||
X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */
|
||||
X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD signal frame */
|
||||
X86_64_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall */
|
||||
}
|
||||
sigcontext_format;
|
||||
unw_word_t sigcontext_addr;
|
||||
int validate;
|
||||
ucontext_t *uc;
|
||||
};
|
||||
|
||||
static inline ucontext_t *
|
||||
dwarf_get_uc(const struct dwarf_cursor *cursor)
|
||||
{
|
||||
const struct cursor *c = (struct cursor *) cursor->as_arg;
|
||||
return c->uc;
|
||||
}
|
||||
|
||||
#define DWARF_GET_LOC(l) ((l).val)
|
||||
# define DWARF_LOC_TYPE_MEM (0 << 0)
|
||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||
# define DWARF_LOC_TYPE_VAL (1 << 2)
|
||||
|
||||
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
|
||||
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||
# define DWARF_IS_MEM_LOC(l) ((l).type == DWARF_LOC_TYPE_MEM)
|
||||
# define DWARF_IS_VAL_LOC(l) (((l).type & DWARF_LOC_TYPE_VAL) != 0)
|
||||
|
||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
|
||||
# define DWARF_VAL_LOC(c,v) DWARF_LOC ((v), DWARF_LOC_TYPE_VAL)
|
||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), DWARF_LOC_TYPE_MEM)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0))
|
||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||
x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0))
|
||||
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
|
||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||
# define DWARF_IS_NULL_LOC(l) \
|
||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||
| DWARF_LOC_TYPE_FP))
|
||||
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
|
||||
static inline int
|
||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
abort ();
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
abort ();
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||
{
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
if (DWARF_IS_MEM_LOC (loc))
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||
0, c->as_arg);
|
||||
assert(DWARF_IS_VAL_LOC (loc));
|
||||
*val = DWARF_GET_LOC (loc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||
{
|
||||
assert(!DWARF_IS_VAL_LOC (loc));
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
return -UNW_EBADREG;
|
||||
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
else
|
||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||
1, c->as_arg);
|
||||
}
|
||||
|
||||
#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
|
||||
#define tdep_init_done UNW_OBJ(init_done)
|
||||
#define tdep_init_mem_validate UNW_OBJ(init_mem_validate)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||
#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path)
|
||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||
#if __linux__
|
||||
# define tdep_fetch_frame UNW_OBJ(fetch_frame)
|
||||
# define tdep_cache_frame UNW_OBJ(cache_frame)
|
||||
# define tdep_reuse_frame UNW_OBJ(reuse_frame)
|
||||
#else
|
||||
# define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||
# define tdep_cache_frame(c) 0
|
||||
# define tdep_reuse_frame(c,frame) do {} while(0)
|
||||
#endif
|
||||
#define tdep_stash_frame UNW_OBJ(stash_frame)
|
||||
#define tdep_trace UNW_OBJ(tdep_trace)
|
||||
#define x86_64_r_uc_addr UNW_OBJ(r_uc_addr)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
dwarf_put_unwind_info((as), (pi), (arg))
|
||||
#else
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||
(c)->as_arg)
|
||||
# define tdep_put_unwind_info(as,pi,arg) \
|
||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||
#endif
|
||||
|
||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||
#define tdep_big_endian(as) 0
|
||||
|
||||
extern int tdep_init_done;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern void tdep_init_mem_validate (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg);
|
||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff,
|
||||
char *path, size_t pathlen);
|
||||
extern void tdep_get_exe_image_path (char *path);
|
||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_word_t *valp, int write);
|
||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||
unw_fpreg_t *valp, int write);
|
||||
#if __linux__
|
||||
extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip,
|
||||
int need_unwind_info);
|
||||
extern int tdep_cache_frame (struct dwarf_cursor *c);
|
||||
extern void tdep_reuse_frame (struct dwarf_cursor *c,
|
||||
int frame);
|
||||
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
||||
struct dwarf_reg_state *rs);
|
||||
#endif
|
||||
|
||||
extern int tdep_getcontext_trace (unw_tdep_context_t *);
|
||||
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
||||
|
||||
#endif /* X86_64_LIBUNWIND_I_H */
|
@ -1,28 +0,0 @@
|
||||
/* Provide a real file - not a symlink - as it would cause multiarch conflicts
|
||||
when multiple different arch releases are installed simultaneously. */
|
||||
|
||||
#if defined __aarch64__
|
||||
# include "tdep-aarch64/dwarf-config.h"
|
||||
#elif defined __arm__
|
||||
# include "tdep-arm/dwarf-config.h"
|
||||
#elif defined __hppa__
|
||||
# include "tdep-hppa/dwarf-config.h"
|
||||
#elif defined __ia64__
|
||||
# include "tdep-ia64/dwarf-config.h"
|
||||
#elif defined __mips__
|
||||
# include "tdep-mips/dwarf-config.h"
|
||||
#elif defined __powerpc__ && !defined __powerpc64__
|
||||
# include "tdep-ppc32/dwarf-config.h"
|
||||
#elif defined __powerpc64__
|
||||
# include "tdep-ppc64/dwarf-config.h"
|
||||
#elif defined __sh__
|
||||
# include "tdep-sh/dwarf-config.h"
|
||||
#elif defined __i386__
|
||||
# include "tdep-x86/dwarf-config.h"
|
||||
#elif defined __x86_64__ || defined __amd64__
|
||||
# include "tdep-x86_64/dwarf-config.h"
|
||||
#elif defined __tilegx__
|
||||
# include "tdep-tilegx/dwarf-config.h"
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
@ -1,30 +0,0 @@
|
||||
/* Provide a real file - not a symlink - as it would cause multiarch conflicts
|
||||
when multiple different arch releases are installed simultaneously. */
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
#if defined __aarch64__
|
||||
# include "tdep-aarch64/jmpbuf.h"
|
||||
#elif defined __arm__
|
||||
# include "tdep-arm/jmpbuf.h"
|
||||
#elif defined __hppa__
|
||||
# include "tdep-hppa/jmpbuf.h"
|
||||
#elif defined __ia64__
|
||||
# include "tdep-ia64/jmpbuf.h"
|
||||
#elif defined __mips__
|
||||
# include "tdep-mips/jmpbuf.h"
|
||||
#elif defined __powerpc__ && !defined __powerpc64__
|
||||
# include "tdep-ppc32/jmpbuf.h"
|
||||
#elif defined __powerpc64__
|
||||
# include "tdep-ppc64/jmpbuf.h"
|
||||
#elif defined __i386__
|
||||
# include "tdep-x86/jmpbuf.h"
|
||||
#elif defined __x86_64__
|
||||
# include "tdep-x86_64/jmpbuf.h"
|
||||
#elif defined __tilegx__
|
||||
# include "tdep-tilegx/jmpbuf.h"
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
@ -1,37 +0,0 @@
|
||||
/* Provide a real file - not a symlink - as it would cause multiarch conflicts
|
||||
when multiple different arch releases are installed simultaneously. */
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
#if defined __aarch64__
|
||||
# include "tdep-aarch64/libunwind_i.h"
|
||||
#elif defined __arm__
|
||||
# include "tdep-arm/libunwind_i.h"
|
||||
#elif defined __hppa__
|
||||
# include "tdep-hppa/libunwind_i.h"
|
||||
#elif defined __ia64__
|
||||
# include "tdep-ia64/libunwind_i.h"
|
||||
#elif defined __mips__
|
||||
# include "tdep-mips/libunwind_i.h"
|
||||
#elif defined __powerpc__ && !defined __powerpc64__
|
||||
# include "tdep-ppc32/libunwind_i.h"
|
||||
#elif defined __powerpc64__
|
||||
# include "tdep-ppc64/libunwind_i.h"
|
||||
#elif defined __sh__
|
||||
# include "tdep-sh/libunwind_i.h"
|
||||
#elif defined __i386__
|
||||
# include "tdep-x86/libunwind_i.h"
|
||||
#elif defined __x86_64__
|
||||
# include "tdep-x86_64/libunwind_i.h"
|
||||
#elif defined __tilegx__
|
||||
# include "tdep-tilegx/libunwind_i.h"
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
|
||||
|
||||
#else /* UNW_REMOTE_ONLY */
|
||||
|
||||
# include "tdep-@arch@/libunwind_i.h"
|
||||
|
||||
#endif /* UNW_REMOTE_ONLY */
|
@ -1,154 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
#ifndef _UNWIND_H
|
||||
#define _UNWIND_H
|
||||
|
||||
/* For uint64_t */
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Minimal interface as per C++ ABI draft standard:
|
||||
|
||||
http://www.codesourcery.com/cxx-abi/abi-eh.html */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
_URC_NO_REASON = 0,
|
||||
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
|
||||
_URC_FATAL_PHASE2_ERROR = 2,
|
||||
_URC_FATAL_PHASE1_ERROR = 3,
|
||||
_URC_NORMAL_STOP = 4,
|
||||
_URC_END_OF_STACK = 5,
|
||||
_URC_HANDLER_FOUND = 6,
|
||||
_URC_INSTALL_CONTEXT = 7,
|
||||
_URC_CONTINUE_UNWIND = 8
|
||||
}
|
||||
_Unwind_Reason_Code;
|
||||
|
||||
typedef int _Unwind_Action;
|
||||
|
||||
#define _UA_SEARCH_PHASE 1
|
||||
#define _UA_CLEANUP_PHASE 2
|
||||
#define _UA_HANDLER_FRAME 4
|
||||
#define _UA_FORCE_UNWIND 8
|
||||
|
||||
struct _Unwind_Context; /* opaque data-structure */
|
||||
struct _Unwind_Exception; /* forward-declaration */
|
||||
|
||||
typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
|
||||
struct _Unwind_Exception *);
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action,
|
||||
uint64_t,
|
||||
struct _Unwind_Exception *,
|
||||
struct _Unwind_Context *,
|
||||
void *);
|
||||
|
||||
/* The C++ ABI requires exception_class, private_1, and private_2 to
|
||||
be of type uint64 and the entire structure to be
|
||||
double-word-aligned. Please note that exception_class stays 64-bit
|
||||
even on 32-bit machines for gcc compatibility. */
|
||||
struct _Unwind_Exception
|
||||
{
|
||||
uint64_t exception_class;
|
||||
_Unwind_Exception_Cleanup_Fn exception_cleanup;
|
||||
unsigned long private_1;
|
||||
unsigned long private_2;
|
||||
} __attribute__((__aligned__));
|
||||
|
||||
extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *);
|
||||
extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *,
|
||||
_Unwind_Stop_Fn, void *);
|
||||
extern void _Unwind_Resume (struct _Unwind_Exception *);
|
||||
extern void _Unwind_DeleteException (struct _Unwind_Exception *);
|
||||
extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int);
|
||||
extern void _Unwind_SetGR (struct _Unwind_Context *, int, unsigned long);
|
||||
extern unsigned long _Unwind_GetIP (struct _Unwind_Context *);
|
||||
extern unsigned long _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
|
||||
extern void _Unwind_SetIP (struct _Unwind_Context *, unsigned long);
|
||||
extern unsigned long _Unwind_GetLanguageSpecificData (struct _Unwind_Context*);
|
||||
extern unsigned long _Unwind_GetRegionStart (struct _Unwind_Context *);
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
|
||||
/* Callback for _Unwind_Backtrace(). The backtrace stops immediately
|
||||
if the callback returns any value other than _URC_NO_REASON. */
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *,
|
||||
void *);
|
||||
|
||||
/* See http://gcc.gnu.org/ml/gcc-patches/2001-09/msg00082.html for why
|
||||
_UA_END_OF_STACK exists. */
|
||||
# define _UA_END_OF_STACK 16
|
||||
|
||||
/* If the unwind was initiated due to a forced unwind, resume that
|
||||
operation, else re-raise the exception. This is used by
|
||||
__cxa_rethrow(). */
|
||||
extern _Unwind_Reason_Code
|
||||
_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
|
||||
|
||||
/* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why
|
||||
_Unwind_GetBSP() exists. */
|
||||
extern unsigned long _Unwind_GetBSP (struct _Unwind_Context *);
|
||||
|
||||
/* Return the "canonical frame address" for the given context.
|
||||
This is used by NPTL... */
|
||||
extern unsigned long _Unwind_GetCFA (struct _Unwind_Context *);
|
||||
|
||||
/* Return the base-address for data references. */
|
||||
extern unsigned long _Unwind_GetDataRelBase (struct _Unwind_Context *);
|
||||
|
||||
/* Return the base-address for text references. */
|
||||
extern unsigned long _Unwind_GetTextRelBase (struct _Unwind_Context *);
|
||||
|
||||
/* Call _Unwind_Trace_Fn once for each stack-frame, without doing any
|
||||
cleanup. The first frame for which the callback is invoked is the
|
||||
one for the caller of _Unwind_Backtrace(). _Unwind_Backtrace()
|
||||
returns _URC_END_OF_STACK when the backtrace stopped due to
|
||||
reaching the end of the call-chain or _URC_FATAL_PHASE1_ERROR if it
|
||||
stops for any other reason. */
|
||||
extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *);
|
||||
|
||||
/* Find the start-address of the procedure containing the specified IP
|
||||
or NULL if it cannot be found (e.g., because the function has no
|
||||
unwind info). Note: there is not necessarily a one-to-one
|
||||
correspondence between source-level functions and procedures: some
|
||||
functions don't have unwind-info and others are split into multiple
|
||||
procedures. */
|
||||
extern void *_Unwind_FindEnclosingFunction (void *);
|
||||
|
||||
/* See also Linux Standard Base Spec:
|
||||
http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/libgcc-s.html */
|
||||
|
||||
#endif /* _GNU_SOURCE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _UNWIND_H */
|
@ -1,31 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2004 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.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. */
|
||||
|
||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||
|
||||
#define JB_SP 4
|
||||
#define JB_RP 5
|
||||
#define JB_MASK_SAVED 6
|
||||
#define JB_MASK 7
|
@ -1,749 +0,0 @@
|
||||
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.
|
@ -1,37 +0,0 @@
|
||||
/* 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);
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||
Copyright (C) 2013 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
PROTECTED unw_addr_space_t
|
||||
unw_create_addr_space (unw_accessors_t *a, int byte_order)
|
||||
{
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
return NULL;
|
||||
#else
|
||||
unw_addr_space_t as;
|
||||
|
||||
/* AArch64 supports little-endian and big-endian. */
|
||||
if (byte_order != 0 && byte_order != __LITTLE_ENDIAN
|
||||
&& byte_order != __BIG_ENDIAN)
|
||||
return NULL;
|
||||
|
||||
as = malloc (sizeof (*as));
|
||||
if (!as)
|
||||
return NULL;
|
||||
|
||||
memset (as, 0, sizeof (*as));
|
||||
|
||||
as->acc = *a;
|
||||
|
||||
/* Default to little-endian for AArch64. */
|
||||
if (byte_order == 0 || byte_order == __LITTLE_ENDIAN)
|
||||
as->big_endian = 0;
|
||||
else
|
||||
as->big_endian = 1;
|
||||
|
||||
return as;
|
||||
#endif
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
PROTECTED int
|
||||
unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
int ret;
|
||||
|
||||
ret = dwarf_make_proc_info (&c->dwarf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*pi = c->dwarf.pi;
|
||||
return 0;
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||
Copyright (C) 2013 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 "unwind_i.h"
|
||||
|
||||
PROTECTED int
|
||||
unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
dwarf_loc_t loc;
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case UNW_AARCH64_X0:
|
||||
case UNW_AARCH64_X1:
|
||||
case UNW_AARCH64_X2:
|
||||
case UNW_AARCH64_X3:
|
||||
case UNW_AARCH64_X4:
|
||||
case UNW_AARCH64_X5:
|
||||
case UNW_AARCH64_X6:
|
||||
case UNW_AARCH64_X7:
|
||||
case UNW_AARCH64_X8:
|
||||
case UNW_AARCH64_X9:
|
||||
case UNW_AARCH64_X10:
|
||||
case UNW_AARCH64_X11:
|
||||
case UNW_AARCH64_X12:
|
||||
case UNW_AARCH64_X13:
|
||||
case UNW_AARCH64_X14:
|
||||
case UNW_AARCH64_X15:
|
||||
case UNW_AARCH64_X16:
|
||||
case UNW_AARCH64_X17:
|
||||
case UNW_AARCH64_X18:
|
||||
case UNW_AARCH64_X19:
|
||||
case UNW_AARCH64_X20:
|
||||
case UNW_AARCH64_X21:
|
||||
case UNW_AARCH64_X22:
|
||||
case UNW_AARCH64_X23:
|
||||
case UNW_AARCH64_X24:
|
||||
case UNW_AARCH64_X25:
|
||||
case UNW_AARCH64_X26:
|
||||
case UNW_AARCH64_X27:
|
||||
case UNW_AARCH64_X28:
|
||||
case UNW_AARCH64_X29:
|
||||
case UNW_AARCH64_X30:
|
||||
case UNW_AARCH64_SP:
|
||||
case UNW_AARCH64_PC:
|
||||
case UNW_AARCH64_PSTATE:
|
||||
loc = c->dwarf.loc[reg];
|
||||
break;
|
||||
|
||||
default:
|
||||
loc = DWARF_NULL_LOC; /* default to "not saved" */
|
||||
break;
|
||||
}
|
||||
|
||||
memset (sloc, 0, sizeof (*sloc));
|
||||
|
||||
if (DWARF_IS_NULL_LOC (loc))
|
||||
{
|
||||
sloc->type = UNW_SLT_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(UNW_LOCAL_ONLY)
|
||||
if (DWARF_IS_REG_LOC (loc))
|
||||
{
|
||||
sloc->type = UNW_SLT_REG;
|
||||
sloc->u.regnum = DWARF_GET_LOC (loc);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sloc->type = UNW_SLT_MEMORY;
|
||||
sloc->u.addr = DWARF_GET_LOC (loc);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||
Copyright (C) 2013 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 "unwind_i.h"
|
||||
#include "dwarf_i.h"
|
||||
|
||||
HIDDEN define_lock (aarch64_lock);
|
||||
HIDDEN int tdep_init_done;
|
||||
|
||||
HIDDEN void
|
||||
tdep_init (void)
|
||||
{
|
||||
intrmask_t saved_mask;
|
||||
|
||||
sigfillset (&unwi_full_mask);
|
||||
|
||||
lock_acquire (&aarch64_lock, saved_mask);
|
||||
{
|
||||
if (tdep_init_done)
|
||||
/* another thread else beat us to it... */
|
||||
goto out;
|
||||
|
||||
mi_init ();
|
||||
|
||||
dwarf_init ();
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
aarch64_local_addr_space_init ();
|
||||
#endif
|
||||
tdep_init_done = 1; /* signal that we're initialized... */
|
||||
}
|
||||
out:
|
||||
lock_release (&aarch64_lock, saved_mask);
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||
Copyright (C) 2013 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
#ifdef UNW_REMOTE_ONLY
|
||||
|
||||
/* unw_local_addr_space is a NULL pointer in this case. */
|
||||
PROTECTED unw_addr_space_t unw_local_addr_space;
|
||||
|
||||
#else /* !UNW_REMOTE_ONLY */
|
||||
|
||||
static struct unw_addr_space local_addr_space;
|
||||
|
||||
PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space;
|
||||
|
||||
static inline void *
|
||||
uc_addr (ucontext_t *uc, int reg)
|
||||
{
|
||||
if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_V0)
|
||||
return &uc->uc_mcontext.regs[reg];
|
||||
else if (reg >= UNW_AARCH64_V0 && reg <= UNW_AARCH64_V31)
|
||||
return &GET_FPCTX(uc)->vregs[reg - UNW_AARCH64_V0];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
# ifdef UNW_LOCAL_ONLY
|
||||
|
||||
HIDDEN void *
|
||||
tdep_uc_addr (ucontext_t *uc, int reg)
|
||||
{
|
||||
return uc_addr (uc, reg);
|
||||
}
|
||||
|
||||
# endif /* UNW_LOCAL_ONLY */
|
||||
|
||||
HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
|
||||
|
||||
/* XXX fix me: there is currently no way to locate the dyn-info list
|
||||
by a remote unwinder. On ia64, this is done via a special
|
||||
unwind-table entry. Perhaps something similar can be done with
|
||||
DWARF2 unwind info. */
|
||||
|
||||
static void
|
||||
put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
|
||||
{
|
||||
/* it's a no-op */
|
||||
}
|
||||
|
||||
static int
|
||||
get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
||||
void *arg)
|
||||
{
|
||||
*dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
||||
void *arg)
|
||||
{
|
||||
if (write)
|
||||
{
|
||||
Debug (16, "mem[%lx] <- %lx\n", addr, *val);
|
||||
*(unw_word_t *) addr = *val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*val = *(unw_word_t *) addr;
|
||||
Debug (16, "mem[%lx] -> %lx\n", addr, *val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
||||
void *arg)
|
||||
{
|
||||
unw_word_t *addr;
|
||||
ucontext_t *uc = arg;
|
||||
|
||||
if (unw_is_fpreg (reg))
|
||||
goto badreg;
|
||||
|
||||
if (!(addr = uc_addr (uc, reg)))
|
||||
goto badreg;
|
||||
|
||||
if (write)
|
||||
{
|
||||
*(unw_word_t *) addr = *val;
|
||||
Debug (12, "%s <- %lx\n", unw_regname (reg), *val);
|
||||
}
|
||||
else
|
||||
{
|
||||
*val = *(unw_word_t *) addr;
|
||||
Debug (12, "%s -> %lx\n", unw_regname (reg), *val);
|
||||
}
|
||||
return 0;
|
||||
|
||||
badreg:
|
||||
Debug (1, "bad register number %u\n", reg);
|
||||
return -UNW_EBADREG;
|
||||
}
|
||||
|
||||
static int
|
||||
access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
||||
int write, void *arg)
|
||||
{
|
||||
ucontext_t *uc = arg;
|
||||
unw_fpreg_t *addr;
|
||||
|
||||
if (!unw_is_fpreg (reg))
|
||||
goto badreg;
|
||||
|
||||
if (!(addr = uc_addr (uc, reg)))
|
||||
goto badreg;
|
||||
|
||||
if (write)
|
||||
{
|
||||
Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
|
||||
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
||||
*(unw_fpreg_t *) addr = *val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*val = *(unw_fpreg_t *) addr;
|
||||
Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
|
||||
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
||||
}
|
||||
return 0;
|
||||
|
||||
badreg:
|
||||
Debug (1, "bad register number %u\n", reg);
|
||||
/* attempt to access a non-preserved register */
|
||||
return -UNW_EBADREG;
|
||||
}
|
||||
|
||||
static int
|
||||
get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
|
||||
char *buf, size_t buf_len, unw_word_t *offp,
|
||||
void *arg)
|
||||
{
|
||||
return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
|
||||
}
|
||||
|
||||
HIDDEN void
|
||||
aarch64_local_addr_space_init (void)
|
||||
{
|
||||
memset (&local_addr_space, 0, sizeof (local_addr_space));
|
||||
local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY;
|
||||
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
|
||||
local_addr_space.acc.put_unwind_info = put_unwind_info;
|
||||
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
|
||||
local_addr_space.acc.access_mem = access_mem;
|
||||
local_addr_space.acc.access_reg = access_reg;
|
||||
local_addr_space.acc.access_fpreg = access_fpreg;
|
||||
local_addr_space.acc.resume = aarch64_local_resume;
|
||||
local_addr_space.acc.get_proc_name = get_static_proc_name;
|
||||
local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
|
||||
unw_flush_cache (&local_addr_space, 0, 0);
|
||||
}
|
||||
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
@ -1,78 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2011-2013 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 "unwind_i.h"
|
||||
#include "init.h"
|
||||
|
||||
#ifdef UNW_REMOTE_ONLY
|
||||
|
||||
PROTECTED int
|
||||
unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
|
||||
{
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
|
||||
#else /* !UNW_REMOTE_ONLY */
|
||||
|
||||
static int
|
||||
unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
|
||||
if (!tdep_init_done)
|
||||
tdep_init ();
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
c->dwarf.as = unw_local_addr_space;
|
||||
c->dwarf.as_arg = uc;
|
||||
|
||||
return common_init (c, use_prev_instr);
|
||||
}
|
||||
|
||||
PROTECTED int
|
||||
unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
|
||||
{
|
||||
return unw_init_local_common(cursor, uc, 1);
|
||||
}
|
||||
|
||||
PROTECTED int
|
||||
unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag)
|
||||
{
|
||||
if (!flag)
|
||||
{
|
||||
return unw_init_local_common(cursor, uc, 1);
|
||||
}
|
||||
else if (flag == UNW_INIT_SIGNAL_FRAME)
|
||||
{
|
||||
return unw_init_local_common(cursor, uc, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
@ -1,45 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "init.h"
|
||||
#include "unwind_i.h"
|
||||
|
||||
PROTECTED int
|
||||
unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
|
||||
{
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
return -UNW_EINVAL;
|
||||
#else /* !UNW_LOCAL_ONLY */
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
|
||||
if (!tdep_init_done)
|
||||
tdep_init ();
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
c->dwarf.as = as;
|
||||
c->dwarf.as_arg = as_arg;
|
||||
return common_init (c, 0);
|
||||
#endif /* !UNW_LOCAL_ONLY */
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||
Copyright (C) 2013 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 "unwind_i.h"
|
||||
|
||||
/* The restorer stub will always have the form:
|
||||
|
||||
d2801168 movz x8, #0x8b
|
||||
d4000001 svc #0x0
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
ret = (*a->access_mem) (as, ip, &w0, 0, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* FIXME: distinguish 32bit insn vs 64bit registers. */
|
||||
if (w0 != 0xd4000001d2801168)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
#else
|
||||
return -UNW_ENOINFO;
|
||||
#endif
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* 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);
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||
Copyright (C) 2013 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 "unwind_i.h"
|
||||
|
||||
HIDDEN int
|
||||
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
|
||||
int write)
|
||||
{
|
||||
dwarf_loc_t loc = DWARF_NULL_LOC;
|
||||
unsigned int mask;
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case UNW_AARCH64_X0:
|
||||
case UNW_AARCH64_X1:
|
||||
case UNW_AARCH64_X2:
|
||||
case UNW_AARCH64_X3:
|
||||
mask = 1 << reg;
|
||||
if (write)
|
||||
{
|
||||
c->dwarf.eh_args[reg] = *valp;
|
||||
c->dwarf.eh_valid_mask |= mask;
|
||||
return 0;
|
||||
}
|
||||
else if ((c->dwarf.eh_valid_mask & mask) != 0)
|
||||
{
|
||||
*valp = c->dwarf.eh_args[reg];
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
loc = c->dwarf.loc[reg];
|
||||
break;
|
||||
|
||||
case UNW_AARCH64_X30:
|
||||
if (write)
|
||||
c->dwarf.ip = *valp; /* update the IP cache */
|
||||
case UNW_AARCH64_X4:
|
||||
case UNW_AARCH64_X5:
|
||||
case UNW_AARCH64_X6:
|
||||
case UNW_AARCH64_X7:
|
||||
case UNW_AARCH64_X8:
|
||||
case UNW_AARCH64_X9:
|
||||
case UNW_AARCH64_X10:
|
||||
case UNW_AARCH64_X11:
|
||||
case UNW_AARCH64_X12:
|
||||
case UNW_AARCH64_X13:
|
||||
case UNW_AARCH64_X14:
|
||||
case UNW_AARCH64_X15:
|
||||
case UNW_AARCH64_X16:
|
||||
case UNW_AARCH64_X17:
|
||||
case UNW_AARCH64_X18:
|
||||
case UNW_AARCH64_X19:
|
||||
case UNW_AARCH64_X20:
|
||||
case UNW_AARCH64_X21:
|
||||
case UNW_AARCH64_X22:
|
||||
case UNW_AARCH64_X23:
|
||||
case UNW_AARCH64_X24:
|
||||
case UNW_AARCH64_X25:
|
||||
case UNW_AARCH64_X26:
|
||||
case UNW_AARCH64_X27:
|
||||
case UNW_AARCH64_X28:
|
||||
case UNW_AARCH64_X29:
|
||||
case UNW_AARCH64_PC:
|
||||
case UNW_AARCH64_PSTATE:
|
||||
loc = c->dwarf.loc[reg];
|
||||
break;
|
||||
|
||||
case UNW_AARCH64_SP:
|
||||
if (write)
|
||||
return -UNW_EREADONLYREG;
|
||||
*valp = c->dwarf.cfa;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
Debug (1, "bad register number %u\n", reg);
|
||||
return -UNW_EBADREG;
|
||||
}
|
||||
|
||||
if (write)
|
||||
return dwarf_put (&c->dwarf, loc, *valp);
|
||||
else
|
||||
return dwarf_get (&c->dwarf, loc, valp);
|
||||
}
|
||||
|
||||
HIDDEN int
|
||||
tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
|
||||
int write)
|
||||
{
|
||||
dwarf_loc_t loc = c->dwarf.loc[reg];
|
||||
if (write)
|
||||
return dwarf_putfp (&c->dwarf, loc, *valp);
|
||||
else
|
||||
return dwarf_getfp (&c->dwarf, loc, valp);
|
||||
}
|
@ -1,198 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2011-2013 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 "unwind_i.h"
|
||||
#include "offsets.h"
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
HIDDEN inline int
|
||||
aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
|
||||
{
|
||||
#ifdef __linux__
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
unw_tdep_context_t *uc = c->dwarf.as_arg;
|
||||
|
||||
if (c->sigcontext_format == AARCH64_SCF_NONE)
|
||||
{
|
||||
/* Since there are no signals involved here we restore EH and non scratch
|
||||
registers only. */
|
||||
unsigned long regs[24];
|
||||
regs[0] = uc->uc_mcontext.regs[0];
|
||||
regs[1] = uc->uc_mcontext.regs[1];
|
||||
regs[2] = uc->uc_mcontext.regs[2];
|
||||
regs[3] = uc->uc_mcontext.regs[3];
|
||||
regs[4] = uc->uc_mcontext.regs[19];
|
||||
regs[5] = uc->uc_mcontext.regs[20];
|
||||
regs[6] = uc->uc_mcontext.regs[21];
|
||||
regs[7] = uc->uc_mcontext.regs[22];
|
||||
regs[8] = uc->uc_mcontext.regs[23];
|
||||
regs[9] = uc->uc_mcontext.regs[24];
|
||||
regs[10] = uc->uc_mcontext.regs[25];
|
||||
regs[11] = uc->uc_mcontext.regs[26];
|
||||
regs[12] = uc->uc_mcontext.regs[27];
|
||||
regs[13] = uc->uc_mcontext.regs[28];
|
||||
regs[14] = uc->uc_mcontext.regs[29]; /* FP */
|
||||
regs[15] = uc->uc_mcontext.regs[30]; /* LR */
|
||||
regs[16] = GET_FPCTX(uc)->vregs[8];
|
||||
regs[17] = GET_FPCTX(uc)->vregs[9];
|
||||
regs[18] = GET_FPCTX(uc)->vregs[10];
|
||||
regs[19] = GET_FPCTX(uc)->vregs[11];
|
||||
regs[20] = GET_FPCTX(uc)->vregs[12];
|
||||
regs[21] = GET_FPCTX(uc)->vregs[13];
|
||||
regs[22] = GET_FPCTX(uc)->vregs[14];
|
||||
regs[23] = GET_FPCTX(uc)->vregs[15];
|
||||
unsigned long sp = uc->uc_mcontext.sp;
|
||||
|
||||
struct regs_overlay {
|
||||
char x[sizeof(regs)];
|
||||
};
|
||||
|
||||
asm volatile (
|
||||
"mov x4, %0\n"
|
||||
"mov x5, %1\n"
|
||||
"ldp x0, x1, [x4]\n"
|
||||
"ldp x2, x3, [x4,16]\n"
|
||||
"ldp x19, x20, [x4,32]\n"
|
||||
"ldp x21, x22, [x4,48]\n"
|
||||
"ldp x23, x24, [x4,64]\n"
|
||||
"ldp x25, x26, [x4,80]\n"
|
||||
"ldp x27, x28, [x4,96]\n"
|
||||
"ldp x29, x30, [x4,112]\n"
|
||||
"ldp d8, d9, [x4,128]\n"
|
||||
"ldp d10, d11, [x4,144]\n"
|
||||
"ldp d12, d13, [x4,160]\n"
|
||||
"ldp d14, d15, [x4,176]\n"
|
||||
"mov sp, x5\n"
|
||||
"ret \n"
|
||||
:
|
||||
: "r" (regs),
|
||||
"r" (sp),
|
||||
"m" (*(struct regs_overlay *)regs)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
|
||||
|
||||
if (c->dwarf.eh_valid_mask & 0x1) sc->regs[0] = c->dwarf.eh_args[0];
|
||||
if (c->dwarf.eh_valid_mask & 0x2) sc->regs[1] = c->dwarf.eh_args[1];
|
||||
if (c->dwarf.eh_valid_mask & 0x4) sc->regs[2] = c->dwarf.eh_args[2];
|
||||
if (c->dwarf.eh_valid_mask & 0x8) sc->regs[3] = c->dwarf.eh_args[3];
|
||||
|
||||
sc->regs[4] = uc->uc_mcontext.regs[4];
|
||||
sc->regs[5] = uc->uc_mcontext.regs[5];
|
||||
sc->regs[6] = uc->uc_mcontext.regs[6];
|
||||
sc->regs[7] = uc->uc_mcontext.regs[7];
|
||||
sc->regs[8] = uc->uc_mcontext.regs[8];
|
||||
sc->regs[9] = uc->uc_mcontext.regs[9];
|
||||
sc->regs[10] = uc->uc_mcontext.regs[10];
|
||||
sc->regs[11] = uc->uc_mcontext.regs[11];
|
||||
sc->regs[12] = uc->uc_mcontext.regs[12];
|
||||
sc->regs[13] = uc->uc_mcontext.regs[13];
|
||||
sc->regs[14] = uc->uc_mcontext.regs[14];
|
||||
sc->regs[15] = uc->uc_mcontext.regs[15];
|
||||
sc->regs[16] = uc->uc_mcontext.regs[16];
|
||||
sc->regs[17] = uc->uc_mcontext.regs[17];
|
||||
sc->regs[18] = uc->uc_mcontext.regs[18];
|
||||
sc->regs[19] = uc->uc_mcontext.regs[19];
|
||||
sc->regs[20] = uc->uc_mcontext.regs[20];
|
||||
sc->regs[21] = uc->uc_mcontext.regs[21];
|
||||
sc->regs[22] = uc->uc_mcontext.regs[22];
|
||||
sc->regs[23] = uc->uc_mcontext.regs[23];
|
||||
sc->regs[24] = uc->uc_mcontext.regs[24];
|
||||
sc->regs[25] = uc->uc_mcontext.regs[25];
|
||||
sc->regs[26] = uc->uc_mcontext.regs[26];
|
||||
sc->regs[27] = uc->uc_mcontext.regs[27];
|
||||
sc->regs[28] = uc->uc_mcontext.regs[28];
|
||||
sc->regs[29] = uc->uc_mcontext.regs[29];
|
||||
sc->regs[30] = uc->uc_mcontext.regs[30];
|
||||
sc->sp = uc->uc_mcontext.sp;
|
||||
sc->pc = uc->uc_mcontext.pc;
|
||||
sc->pstate = uc->uc_mcontext.pstate;
|
||||
|
||||
asm volatile (
|
||||
"mov sp, %0\n"
|
||||
"ret %1\n"
|
||||
: : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc)
|
||||
);
|
||||
}
|
||||
unreachable();
|
||||
#else
|
||||
printf ("%s: implement me\n", __FUNCTION__);
|
||||
#endif
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
||||
|
||||
static inline void
|
||||
establish_machine_state (struct cursor *c)
|
||||
{
|
||||
unw_addr_space_t as = c->dwarf.as;
|
||||
void *arg = c->dwarf.as_arg;
|
||||
unw_fpreg_t fpval;
|
||||
unw_word_t val;
|
||||
int reg;
|
||||
|
||||
Debug (8, "copying out cursor state\n");
|
||||
|
||||
for (reg = 0; reg <= UNW_AARCH64_V31; ++reg)
|
||||
{
|
||||
Debug (16, "copying %s %d\n", unw_regname (reg), reg);
|
||||
if (unw_is_fpreg (reg))
|
||||
{
|
||||
if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
|
||||
as->acc.access_fpreg (as, reg, &fpval, 1, arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tdep_access_reg (c, reg, &val, 0) >= 0)
|
||||
as->acc.access_reg (as, reg, &val, 1, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PROTECTED int
|
||||
unw_resume (unw_cursor_t *cursor)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
|
||||
Debug (1, "(cursor=%p)\n", c);
|
||||
|
||||
if (!c->dwarf.ip)
|
||||
{
|
||||
/* This can happen easily when the frame-chain gets truncated
|
||||
due to bad or missing unwind-info. */
|
||||
Debug (1, "refusing to resume execution at address 0\n");
|
||||
return -UNW_EINVAL;
|
||||
}
|
||||
|
||||
establish_machine_state (c);
|
||||
|
||||
return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
|
||||
c->dwarf.as_arg);
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
||||
Copyright (C) 2014 CERN and Aalto University
|
||||
Contributed by Filip Nyback
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
HIDDEN void
|
||||
tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) dwarf_to_cursor (d);
|
||||
unw_tdep_frame_t *f = &c->frame_info;
|
||||
|
||||
Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
|
||||
" ra=0x%lx fp [where=%d val=%ld @0x%lx] lr [where=%d val=%ld @0x%lx] "
|
||||
"sp [where=%d val=%ld @0x%lx]\n",
|
||||
d->ip, d->cfa, f->frame_type,
|
||||
rs->reg.where[DWARF_CFA_REG_COLUMN],
|
||||
rs->reg.val[DWARF_CFA_REG_COLUMN],
|
||||
rs->reg.val[DWARF_CFA_OFF_COLUMN],
|
||||
DWARF_GET_LOC(d->loc[rs->ret_addr_column]),
|
||||
rs->reg.where[FP], rs->reg.val[FP], DWARF_GET_LOC(d->loc[FP]),
|
||||
rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]),
|
||||
rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP]));
|
||||
|
||||
/* A standard frame is defined as:
|
||||
- CFA is register-relative offset off FP or SP;
|
||||
- Return address is saved in LR;
|
||||
- FP is unsaved or saved at CFA+offset, offset != -1;
|
||||
- LR is unsaved or saved at CFA+offset, offset != -1;
|
||||
- SP is unsaved or saved at CFA+offset, offset != -1. */
|
||||
if (f->frame_type == UNW_AARCH64_FRAME_OTHER
|
||||
&& (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
|
||||
&& (rs->reg.val[DWARF_CFA_REG_COLUMN] == FP
|
||||
|| rs->reg.val[DWARF_CFA_REG_COLUMN] == SP)
|
||||
&& labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29)
|
||||
&& rs->ret_addr_column == LR
|
||||
&& (rs->reg.where[FP] == DWARF_WHERE_UNDEF
|
||||
|| rs->reg.where[FP] == DWARF_WHERE_SAME
|
||||
|| (rs->reg.where[FP] == DWARF_WHERE_CFAREL
|
||||
&& labs(rs->reg.val[FP]) < (1 << 29)
|
||||
&& rs->reg.val[FP]+1 != 0))
|
||||
&& (rs->reg.where[LR] == DWARF_WHERE_UNDEF
|
||||
|| rs->reg.where[LR] == DWARF_WHERE_SAME
|
||||
|| (rs->reg.where[LR] == DWARF_WHERE_CFAREL
|
||||
&& labs(rs->reg.val[LR]) < (1 << 29)
|
||||
&& rs->reg.val[LR]+1 != 0))
|
||||
&& (rs->reg.where[SP] == DWARF_WHERE_UNDEF
|
||||
|| rs->reg.where[SP] == DWARF_WHERE_SAME
|
||||
|| (rs->reg.where[SP] == DWARF_WHERE_CFAREL
|
||||
&& labs(rs->reg.val[SP]) < (1 << 29)
|
||||
&& rs->reg.val[SP]+1 != 0)))
|
||||
{
|
||||
/* Save information for a standard frame. */
|
||||
f->frame_type = UNW_AARCH64_FRAME_STANDARD;
|
||||
f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP);
|
||||
f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN];
|
||||
if (rs->reg.where[FP] == DWARF_WHERE_CFAREL)
|
||||
f->fp_cfa_offset = rs->reg.val[FP];
|
||||
if (rs->reg.where[LR] == DWARF_WHERE_CFAREL)
|
||||
f->lr_cfa_offset = rs->reg.val[LR];
|
||||
if (rs->reg.where[SP] == DWARF_WHERE_CFAREL)
|
||||
f->sp_cfa_offset = rs->reg.val[SP];
|
||||
Debug (4, " standard frame\n");
|
||||
}
|
||||
else
|
||||
Debug (4, " unusual frame\n");
|
||||
}
|
@ -1,189 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 CodeSourcery
|
||||
Copyright (C) 2011-2013 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 "unwind_i.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
|
||||
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;
|
||||
|
||||
ret = unw_is_signal_frame (cursor);
|
||||
Debug(1, "unw_is_signal_frame()=%d\n", ret);
|
||||
|
||||
/* 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;
|
||||
|
||||
if (ret)
|
||||
{
|
||||
c->sigcontext_format = AARCH64_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_AARCH64_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_AARCH64_X0] = DWARF_LOC (sc_addr + LINUX_SC_X0_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X1] = DWARF_LOC (sc_addr + LINUX_SC_X1_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X2] = DWARF_LOC (sc_addr + LINUX_SC_X2_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X3] = DWARF_LOC (sc_addr + LINUX_SC_X3_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X4] = DWARF_LOC (sc_addr + LINUX_SC_X4_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X5] = DWARF_LOC (sc_addr + LINUX_SC_X5_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X6] = DWARF_LOC (sc_addr + LINUX_SC_X6_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X7] = DWARF_LOC (sc_addr + LINUX_SC_X7_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X8] = DWARF_LOC (sc_addr + LINUX_SC_X8_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X9] = DWARF_LOC (sc_addr + LINUX_SC_X9_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X10] = DWARF_LOC (sc_addr + LINUX_SC_X10_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X11] = DWARF_LOC (sc_addr + LINUX_SC_X11_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X12] = DWARF_LOC (sc_addr + LINUX_SC_X12_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X13] = DWARF_LOC (sc_addr + LINUX_SC_X13_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X14] = DWARF_LOC (sc_addr + LINUX_SC_X14_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X15] = DWARF_LOC (sc_addr + LINUX_SC_X15_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X16] = DWARF_LOC (sc_addr + LINUX_SC_X16_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X17] = DWARF_LOC (sc_addr + LINUX_SC_X17_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X18] = DWARF_LOC (sc_addr + LINUX_SC_X18_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X19] = DWARF_LOC (sc_addr + LINUX_SC_X19_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X20] = DWARF_LOC (sc_addr + LINUX_SC_X20_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X21] = DWARF_LOC (sc_addr + LINUX_SC_X21_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X22] = DWARF_LOC (sc_addr + LINUX_SC_X22_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X23] = DWARF_LOC (sc_addr + LINUX_SC_X23_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X24] = DWARF_LOC (sc_addr + LINUX_SC_X24_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X25] = DWARF_LOC (sc_addr + LINUX_SC_X25_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X26] = DWARF_LOC (sc_addr + LINUX_SC_X26_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X27] = DWARF_LOC (sc_addr + LINUX_SC_X27_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X28] = DWARF_LOC (sc_addr + LINUX_SC_X28_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X29] = DWARF_LOC (sc_addr + LINUX_SC_X29_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_X30] = DWARF_LOC (sc_addr + LINUX_SC_X30_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_SP] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);
|
||||
c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_LOC (sc_addr + LINUX_SC_PSTATE_OFF, 0);
|
||||
|
||||
/* Set SP/CFA and PC/IP. */
|
||||
dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa);
|
||||
dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);
|
||||
|
||||
c->dwarf.pi_valid = 0;
|
||||
c->dwarf.use_prev_instr = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
PROTECTED int
|
||||
unw_step (unw_cursor_t *cursor)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
int ret;
|
||||
|
||||
Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n",
|
||||
c, c->dwarf.ip, c->dwarf.cfa);
|
||||
|
||||
/* Check if this is a signal frame. */
|
||||
if (unw_is_signal_frame (cursor) > 0)
|
||||
return unw_handle_signal_frame (cursor);
|
||||
|
||||
ret = dwarf_step (&c->dwarf);
|
||||
Debug(1, "dwarf_step()=%d\n", ret);
|
||||
|
||||
if (unlikely (ret == -UNW_ESTOPUNWIND))
|
||||
return ret;
|
||||
|
||||
if (unlikely (ret < 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;
|
||||
}
|
@ -1,548 +0,0 @@
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
||||
Copyright (C) 2014 CERN and Aalto University
|
||||
Contributed by Filip Nyback
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "unwind_i.h"
|
||||
#include "offsets.h"
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
|
||||
#pragma weak pthread_once
|
||||
#pragma weak pthread_key_create
|
||||
#pragma weak pthread_getspecific
|
||||
#pragma weak pthread_setspecific
|
||||
|
||||
/* Initial hash table size. Table expands by 2 bits (times four). */
|
||||
#define HASH_MIN_BITS 14
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unw_tdep_frame_t *frames;
|
||||
size_t log_size;
|
||||
size_t used;
|
||||
size_t dtor_count; /* Counts how many times our destructor has already
|
||||
been called. */
|
||||
} unw_trace_cache_t;
|
||||
|
||||
static const unw_tdep_frame_t empty_frame = { 0, UNW_AARCH64_FRAME_OTHER, -1, -1, 0, -1, -1, -1 };
|
||||
static define_lock (trace_init_lock);
|
||||
static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT;
|
||||
static sig_atomic_t trace_cache_once_happen;
|
||||
static pthread_key_t trace_cache_key;
|
||||
static struct mempool trace_cache_pool;
|
||||
static __thread unw_trace_cache_t *tls_cache;
|
||||
static __thread int tls_cache_destroyed;
|
||||
|
||||
/* Free memory for a thread's trace cache. */
|
||||
static void
|
||||
trace_cache_free (void *arg)
|
||||
{
|
||||
unw_trace_cache_t *cache = arg;
|
||||
if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS)
|
||||
{
|
||||
/* Not yet our turn to get destroyed. Re-install ourselves into the key. */
|
||||
pthread_setspecific(trace_cache_key, cache);
|
||||
Debug(5, "delayed freeing cache %p (%zx to go)\n", cache,
|
||||
PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count);
|
||||
return;
|
||||
}
|
||||
tls_cache_destroyed = 1;
|
||||
tls_cache = NULL;
|
||||
munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t));
|
||||
mempool_free (&trace_cache_pool, cache);
|
||||
Debug(5, "freed cache %p\n", cache);
|
||||
}
|
||||
|
||||
/* Initialise frame tracing for threaded use. */
|
||||
static void
|
||||
trace_cache_init_once (void)
|
||||
{
|
||||
pthread_key_create (&trace_cache_key, &trace_cache_free);
|
||||
mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
|
||||
trace_cache_once_happen = 1;
|
||||
}
|
||||
|
||||
static unw_tdep_frame_t *
|
||||
trace_cache_buckets (size_t n)
|
||||
{
|
||||
unw_tdep_frame_t *frames;
|
||||
size_t i;
|
||||
|
||||
GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t));
|
||||
if (likely(frames != NULL))
|
||||
for (i = 0; i < n; ++i)
|
||||
frames[i] = empty_frame;
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
/* Allocate and initialise hash table for frame cache lookups.
|
||||
Returns the cache initialised with (1u << HASH_LOW_BITS) hash
|
||||
buckets, or NULL if there was a memory allocation problem. */
|
||||
static unw_trace_cache_t *
|
||||
trace_cache_create (void)
|
||||
{
|
||||
unw_trace_cache_t *cache;
|
||||
|
||||
if (tls_cache_destroyed)
|
||||
{
|
||||
/* The current thread is in the process of exiting. Don't recreate
|
||||
cache, as we wouldn't have another chance to free it. */
|
||||
Debug(5, "refusing to reallocate cache: "
|
||||
"thread-locals are being deallocated\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! (cache = mempool_alloc(&trace_cache_pool)))
|
||||
{
|
||||
Debug(5, "failed to allocate cache\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS)))
|
||||
{
|
||||
Debug(5, "failed to allocate buckets\n");
|
||||
mempool_free(&trace_cache_pool, cache);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cache->log_size = HASH_MIN_BITS;
|
||||
cache->used = 0;
|
||||
cache->dtor_count = 0;
|
||||
tls_cache_destroyed = 0; /* Paranoia: should already be 0. */
|
||||
Debug(5, "allocated cache %p\n", cache);
|
||||
return cache;
|
||||
}
|
||||
|
||||
/* Expand the hash table in the frame cache if possible. This always
|
||||
quadruples the hash size, and clears all previous frame entries. */
|
||||
static int
|
||||
trace_cache_expand (unw_trace_cache_t *cache)
|
||||
{
|
||||
size_t old_size = (1u << cache->log_size);
|
||||
size_t new_log_size = cache->log_size + 2;
|
||||
unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size);
|
||||
|
||||
if (unlikely(! new_frames))
|
||||
{
|
||||
Debug(5, "failed to expand cache to 2^%lu buckets\n", new_log_size);
|
||||
return -UNW_ENOMEM;
|
||||
}
|
||||
|
||||
Debug(5, "expanded cache from 2^%lu to 2^%lu buckets\n", cache->log_size, new_log_size);
|
||||
munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t));
|
||||
cache->frames = new_frames;
|
||||
cache->log_size = new_log_size;
|
||||
cache->used = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unw_trace_cache_t *
|
||||
trace_cache_get_unthreaded (void)
|
||||
{
|
||||
unw_trace_cache_t *cache;
|
||||
intrmask_t saved_mask;
|
||||
static unw_trace_cache_t *global_cache = NULL;
|
||||
lock_acquire (&trace_init_lock, saved_mask);
|
||||
if (! global_cache)
|
||||
{
|
||||
mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
|
||||
global_cache = trace_cache_create ();
|
||||
}
|
||||
cache = global_cache;
|
||||
lock_release (&trace_init_lock, saved_mask);
|
||||
Debug(5, "using cache %p\n", cache);
|
||||
return cache;
|
||||
}
|
||||
|
||||
/* Get the frame cache for the current thread. Create it if there is none. */
|
||||
static unw_trace_cache_t *
|
||||
trace_cache_get (void)
|
||||
{
|
||||
unw_trace_cache_t *cache;
|
||||
if (likely (pthread_once != NULL))
|
||||
{
|
||||
pthread_once(&trace_cache_once, &trace_cache_init_once);
|
||||
if (!trace_cache_once_happen)
|
||||
{
|
||||
return trace_cache_get_unthreaded();
|
||||
}
|
||||
if (! (cache = tls_cache))
|
||||
{
|
||||
cache = trace_cache_create();
|
||||
pthread_setspecific(trace_cache_key, cache);
|
||||
tls_cache = cache;
|
||||
}
|
||||
Debug(5, "using cache %p\n", cache);
|
||||
return cache;
|
||||
}
|
||||
else
|
||||
{
|
||||
return trace_cache_get_unthreaded();
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise frame properties for address cache slot F at address
|
||||
PC using current CFA, FP and SP values. Modifies CURSOR to
|
||||
that location, performs one unw_step(), and fills F with what
|
||||
was discovered about the location. Returns F.
|
||||
|
||||
FIXME: This probably should tell DWARF handling to never evaluate
|
||||
or use registers other than FP, SP and PC in case there is
|
||||
highly unusual unwind info which uses these creatively. */
|
||||
static unw_tdep_frame_t *
|
||||
trace_init_addr (unw_tdep_frame_t *f,
|
||||
unw_cursor_t *cursor,
|
||||
unw_word_t cfa,
|
||||
unw_word_t pc,
|
||||
unw_word_t fp,
|
||||
unw_word_t sp)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
struct dwarf_cursor *d = &c->dwarf;
|
||||
int ret = -UNW_EINVAL;
|
||||
|
||||
/* Initialise frame properties: unknown, not last. */
|
||||
f->virtual_address = pc;
|
||||
f->frame_type = UNW_AARCH64_FRAME_OTHER;
|
||||
f->last_frame = 0;
|
||||
f->cfa_reg_sp = -1;
|
||||
f->cfa_reg_offset = 0;
|
||||
f->fp_cfa_offset = -1;
|
||||
f->lr_cfa_offset = -1;
|
||||
f->sp_cfa_offset = -1;
|
||||
|
||||
/* Reinitialise cursor to this instruction - but undo next/prev PC
|
||||
adjustment because unw_step will redo it - and force PC, FP and
|
||||
SP into register locations (=~ ucontext we keep), then set
|
||||
their desired values. Then perform the step. */
|
||||
d->ip = pc + d->use_prev_instr;
|
||||
d->cfa = cfa;
|
||||
d->loc[UNW_AARCH64_X29] = DWARF_REG_LOC (d, UNW_AARCH64_X29);
|
||||
d->loc[UNW_AARCH64_SP] = DWARF_REG_LOC (d, UNW_AARCH64_SP);
|
||||
d->loc[UNW_AARCH64_PC] = DWARF_REG_LOC (d, UNW_AARCH64_PC);
|
||||
c->frame_info = *f;
|
||||
|
||||
if (likely(dwarf_put (d, d->loc[UNW_AARCH64_X29], fp) >= 0)
|
||||
&& likely(dwarf_put (d, d->loc[UNW_AARCH64_SP], sp) >= 0)
|
||||
&& likely(dwarf_put (d, d->loc[UNW_AARCH64_PC], pc) >= 0)
|
||||
&& likely((ret = unw_step (cursor)) >= 0))
|
||||
*f = c->frame_info;
|
||||
|
||||
/* If unw_step() stopped voluntarily, remember that, even if it
|
||||
otherwise could not determine anything useful. This avoids
|
||||
failing trace if we hit frames without unwind info, which is
|
||||
common for the outermost frame (CRT stuff) on many systems.
|
||||
This avoids failing trace in very common circumstances; failing
|
||||
to unw_step() loop wouldn't produce any better result. */
|
||||
if (ret == 0)
|
||||
f->last_frame = -1;
|
||||
|
||||
Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
|
||||
f->virtual_address, f->frame_type, f->last_frame,
|
||||
f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset,
|
||||
f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Look up and if necessary fill in frame attributes for address PC
|
||||
in CACHE using current CFA, FP and SP values. Uses CURSOR to
|
||||
perform any unwind steps necessary to fill the cache. Returns the
|
||||
frame cache slot which describes RIP. */
|
||||
static unw_tdep_frame_t *
|
||||
trace_lookup (unw_cursor_t *cursor,
|
||||
unw_trace_cache_t *cache,
|
||||
unw_word_t cfa,
|
||||
unw_word_t pc,
|
||||
unw_word_t fp,
|
||||
unw_word_t sp)
|
||||
{
|
||||
/* First look up for previously cached information using cache as
|
||||
linear probing hash table with probe step of 1. Majority of
|
||||
lookups should be completed within few steps, but it is very
|
||||
important the hash table does not fill up, or performance falls
|
||||
off the cliff. */
|
||||
uint64_t i, addr;
|
||||
uint64_t cache_size = 1u << cache->log_size;
|
||||
uint64_t slot = ((pc * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1);
|
||||
unw_tdep_frame_t *frame;
|
||||
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
frame = &cache->frames[slot];
|
||||
addr = frame->virtual_address;
|
||||
|
||||
/* Return if we found the address. */
|
||||
if (likely(addr == pc))
|
||||
{
|
||||
Debug (4, "found address after %ld steps\n", i);
|
||||
return frame;
|
||||
}
|
||||
|
||||
/* If slot is empty, reuse it. */
|
||||
if (likely(! addr))
|
||||
break;
|
||||
|
||||
/* Linear probe to next slot candidate, step = 1. */
|
||||
if (++slot >= cache_size)
|
||||
slot -= cache_size;
|
||||
}
|
||||
|
||||
/* If we collided after 16 steps, or if the hash is more than half
|
||||
full, force the hash to expand. Fill the selected slot, whether
|
||||
it's free or collides. Note that hash expansion drops previous
|
||||
contents; further lookups will refill the hash. */
|
||||
Debug (4, "updating slot %lu after %ld steps, replacing 0x%lx\n", slot, i, addr);
|
||||
if (unlikely(addr || cache->used >= cache_size / 2))
|
||||
{
|
||||
if (unlikely(trace_cache_expand (cache) < 0))
|
||||
return NULL;
|
||||
|
||||
cache_size = 1u << cache->log_size;
|
||||
slot = ((pc * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1);
|
||||
frame = &cache->frames[slot];
|
||||
addr = frame->virtual_address;
|
||||
}
|
||||
|
||||
if (! addr)
|
||||
++cache->used;
|
||||
|
||||
return trace_init_addr (frame, cursor, cfa, pc, fp, sp);
|
||||
}
|
||||
|
||||
/* Fast stack backtrace for AArch64.
|
||||
|
||||
This is used by backtrace() implementation to accelerate frequent
|
||||
queries for current stack, without any desire to unwind. It fills
|
||||
BUFFER with the call tree from CURSOR upwards for at most SIZE
|
||||
stack levels. The first frame, backtrace itself, is omitted. When
|
||||
called, SIZE should give the maximum number of entries that can be
|
||||
stored into BUFFER. Uses an internal thread-specific cache to
|
||||
accelerate queries.
|
||||
|
||||
The caller should fall back to a unw_step() loop if this function
|
||||
fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a
|
||||
stack frame that is too complex to be traced in the fast path.
|
||||
|
||||
This function is tuned for clients which only need to walk the
|
||||
stack to get the call tree as fast as possible but without any
|
||||
other details, for example profilers sampling the stack thousands
|
||||
to millions of times per second. The routine handles the most
|
||||
common AArch64 ABI stack layouts: CFA is FP or SP plus/minus
|
||||
constant offset, return address is in LR, and FP, LR and SP are
|
||||
either unchanged or saved on stack at constant offset from the CFA;
|
||||
the signal return frame; and frames without unwind info provided
|
||||
they are at the outermost (final) frame or can conservatively be
|
||||
assumed to be frame-pointer based.
|
||||
|
||||
Any other stack layout will cause the routine to give up. There
|
||||
are only a handful of relatively rarely used functions which do
|
||||
not have a stack in the standard form: vfork, longjmp, setcontext
|
||||
and _dl_runtime_profile on common linux systems for example.
|
||||
|
||||
On success BUFFER and *SIZE reflect the trace progress up to *SIZE
|
||||
stack levels or the outermost frame, which ever is less. It may
|
||||
stop short of outermost frame if unw_step() loop would also do so,
|
||||
e.g. if there is no more unwind information; this is not reported
|
||||
as an error.
|
||||
|
||||
The function returns a negative value for errors, -UNW_ESTOPUNWIND
|
||||
if tracing stopped because of an unusual frame unwind info. The
|
||||
BUFFER and *SIZE reflect tracing progress up to the error frame.
|
||||
|
||||
Callers of this function would normally look like this:
|
||||
|
||||
unw_cursor_t cur;
|
||||
unw_context_t ctx;
|
||||
void addrs[128];
|
||||
int depth = 128;
|
||||
int ret;
|
||||
|
||||
unw_getcontext(&ctx);
|
||||
unw_init_local(&cur, &ctx);
|
||||
if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0)
|
||||
{
|
||||
depth = 0;
|
||||
unw_getcontext(&ctx);
|
||||
unw_init_local(&cur, &ctx);
|
||||
while ((ret = unw_step(&cur)) > 0 && depth < 128)
|
||||
{
|
||||
unw_word_t ip;
|
||||
unw_get_reg(&cur, UNW_REG_IP, &ip);
|
||||
addresses[depth++] = (void *) ip;
|
||||
}
|
||||
}
|
||||
*/
|
||||
HIDDEN int
|
||||
tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
struct dwarf_cursor *d = &c->dwarf;
|
||||
unw_trace_cache_t *cache;
|
||||
unw_word_t fp, sp, pc, cfa, lr;
|
||||
int maxdepth = 0;
|
||||
int depth = 0;
|
||||
int ret;
|
||||
|
||||
/* Check input parametres. */
|
||||
if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0))
|
||||
return -UNW_EINVAL;
|
||||
|
||||
Debug (1, "begin ip 0x%lx cfa 0x%lx\n", d->ip, d->cfa);
|
||||
|
||||
/* Tell core dwarf routines to call back to us. */
|
||||
d->stash_frames = 1;
|
||||
|
||||
/* Determine initial register values. These are direct access safe
|
||||
because we know they come from the initial machine context. */
|
||||
pc = d->ip;
|
||||
sp = cfa = d->cfa;
|
||||
ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_AARCH64_X29]), fp);
|
||||
assert(ret == 0);
|
||||
lr = 0;
|
||||
|
||||
/* Get frame cache. */
|
||||
if (unlikely(! (cache = trace_cache_get())))
|
||||
{
|
||||
Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM);
|
||||
*size = 0;
|
||||
d->stash_frames = 0;
|
||||
return -UNW_ENOMEM;
|
||||
}
|
||||
|
||||
/* Trace the stack upwards, starting from current RIP. Adjust
|
||||
the RIP address for previous/next instruction as the main
|
||||
unwinding logic would also do. We undo this before calling
|
||||
back into unw_step(). */
|
||||
while (depth < maxdepth)
|
||||
{
|
||||
pc -= d->use_prev_instr;
|
||||
Debug (2, "depth %d cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n",
|
||||
depth, cfa, pc, sp, fp);
|
||||
|
||||
/* See if we have this address cached. If not, evaluate enough of
|
||||
the dwarf unwind information to fill the cache line data, or to
|
||||
decide this frame cannot be handled in fast trace mode. We
|
||||
cache negative results too to prevent unnecessary dwarf parsing
|
||||
for common failures. */
|
||||
unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, pc, fp, sp);
|
||||
|
||||
/* If we don't have information for this frame, give up. */
|
||||
if (unlikely(! f))
|
||||
{
|
||||
ret = -UNW_ENOINFO;
|
||||
break;
|
||||
}
|
||||
|
||||
Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
|
||||
f->virtual_address, f->frame_type, f->last_frame,
|
||||
f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset,
|
||||
f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
|
||||
|
||||
assert (f->virtual_address == pc);
|
||||
|
||||
/* Stop if this was the last frame. In particular don't evaluate
|
||||
new register values as it may not be safe - we don't normally
|
||||
run with full validation on, and do not want to - and there's
|
||||
enough bad unwind info floating around that we need to trust
|
||||
what unw_step() previously said, in potentially bogus frames. */
|
||||
if (f->last_frame)
|
||||
break;
|
||||
|
||||
/* Evaluate CFA and registers for the next frame. */
|
||||
switch (f->frame_type)
|
||||
{
|
||||
case UNW_AARCH64_FRAME_GUESSED:
|
||||
/* Fall thru to standard processing after forcing validation. */
|
||||
c->validate = 1;
|
||||
|
||||
case UNW_AARCH64_FRAME_STANDARD:
|
||||
/* Advance standard traceable frame. */
|
||||
cfa = (f->cfa_reg_sp ? sp : fp) + f->cfa_reg_offset;
|
||||
if (likely(f->lr_cfa_offset != -1))
|
||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc);
|
||||
else if (lr != 0)
|
||||
{
|
||||
/* Use the saved link register as the new pc. */
|
||||
pc = lr;
|
||||
lr = 0;
|
||||
}
|
||||
if (likely(ret >= 0) && likely(f->fp_cfa_offset != -1))
|
||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->fp_cfa_offset, fp);
|
||||
|
||||
/* Don't bother reading SP from DWARF, CFA becomes new SP. */
|
||||
sp = cfa;
|
||||
|
||||
/* Next frame needs to back up for unwind info lookup. */
|
||||
d->use_prev_instr = 1;
|
||||
break;
|
||||
|
||||
case UNW_AARCH64_FRAME_SIGRETURN:
|
||||
cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */
|
||||
|
||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc);
|
||||
if (likely(ret >= 0))
|
||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_X29_OFF, fp);
|
||||
if (likely(ret >= 0))
|
||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_SP_OFF, sp);
|
||||
/* Save the link register here in case we end up in a function that
|
||||
doesn't save the link register in the prologue, e.g. kill. */
|
||||
if (likely(ret >= 0))
|
||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_X30_OFF, lr);
|
||||
|
||||
/* Resume stack at signal restoration point. The stack is not
|
||||
necessarily continuous here, especially with sigaltstack(). */
|
||||
cfa = sp;
|
||||
|
||||
/* Next frame should not back up. */
|
||||
d->use_prev_instr = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* We cannot trace through this frame, give up and tell the
|
||||
caller we had to stop. Data collected so far may still be
|
||||
useful to the caller, so let it know how far we got. */
|
||||
ret = -UNW_ESTOPUNWIND;
|
||||
break;
|
||||
}
|
||||
|
||||
Debug (4, "new cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n",
|
||||
cfa, pc, sp, fp);
|
||||
|
||||
/* If we failed or ended up somewhere bogus, stop. */
|
||||
if (unlikely(ret < 0 || pc < 0x4000))
|
||||
break;
|
||||
|
||||
/* Record this address in stack trace. We skipped the first address. */
|
||||
buffer[depth++] = (void *) (pc - d->use_prev_instr);
|
||||
}
|
||||
|
||||
#if UNW_DEBUG
|
||||
Debug (1, "returning %d, depth %d\n", ret, depth);
|
||||
#endif
|
||||
*size = depth;
|
||||
return ret;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gapply_reg_state.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gcreate_addr_space.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gget_proc_info.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gget_save_loc.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gglobal.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Ginit.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Ginit_local.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Ginit_remote.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gis_signal_frame.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Greg_states_iterate.c"
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gregs.c"
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user