Imported unwind library from https://github.com/libunwind/libunwind, rev. 2934cf40529e0261801a4142fabae449a65effd0 [#CLICKHOUSE-3094].

This commit is contained in:
Alexey Milovidov 2017-06-23 08:12:40 +03:00
parent bb602835de
commit 2aec6efddc
608 changed files with 49778 additions and 0 deletions

View File

@ -0,0 +1 @@
David Mosberger <dmosberger@gmail.org>

20
contrib/libunwind/COPYING Normal file
View File

@ -0,0 +1,20 @@
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.

View File

@ -0,0 +1,74 @@
/* 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 */

View File

@ -0,0 +1,231 @@
/* 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. */
/* #undef 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_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 */
#define HAVE_LZMA 0
/* 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. */
#define HAVE___THREAD 1
/* Define to the sub-directory where 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 */

View File

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

View File

@ -0,0 +1,128 @@
/* 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 dwarf_eh_frame_hdr
{
unsigned char version;
unsigned char eh_frame_ptr_enc;
unsigned char fde_count_enc;
unsigned char table_enc;
/* The rest of the header is variable-length and consists of the
following members:
encoded_t eh_frame_ptr;
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 */

View File

@ -0,0 +1,455 @@
/* 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
#ifdef HAVE___THREAD
/* For now, turn off per-thread caching. It uses up too much TLS
memory per thread even when the thread never uses libunwind at
all. */
# undef HAVE___THREAD
#endif
#ifndef UNW_REMOTE_ONLY
#if defined(HAVE_LINK_H)
#include <link.h>
#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 */

View File

@ -0,0 +1,490 @@
#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 */

View File

@ -0,0 +1,210 @@
/* 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 */

View File

@ -0,0 +1,302 @@
/* 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]" \
: [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 */

View File

@ -0,0 +1,273 @@
/* 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 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_local_signal UNW_OBJ(init_local_signal)
#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_local_signal (unw_cursor_t *, unw_context_t *);
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;

View File

@ -0,0 +1,273 @@
/* 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 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_local_signal UNW_OBJ(init_local_signal)
#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_local_signal (unw_cursor_t *, unw_context_t *);
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;

View File

@ -0,0 +1,73 @@
/* 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 */

View File

@ -0,0 +1,214 @@
/* 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

View File

@ -0,0 +1,125 @@
/* 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 */

View File

@ -0,0 +1,194 @@
/* 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 */

View File

@ -0,0 +1,160 @@
/* 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 */

View File

@ -0,0 +1,207 @@
/* 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 */

View File

@ -0,0 +1,271 @@
/* 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 */

View File

@ -0,0 +1,63 @@
/* 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 */

View File

@ -0,0 +1,114 @@
/* 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 */

View File

@ -0,0 +1,161 @@
/* 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 */

View File

@ -0,0 +1,187 @@
/* 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 */

View File

@ -0,0 +1,141 @@
/* 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 */

View File

@ -0,0 +1,36 @@
/* 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 */

View File

@ -0,0 +1,36 @@
/* 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 */

View File

@ -0,0 +1,357 @@
/* 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"
#ifdef HAVE___THREAD
/* For now, turn off per-thread caching. It uses up too much TLS
memory per thread even when the thread never uses libunwind at
all. */
# undef HAVE___THREAD
#endif
/* 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>
#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 */

View File

@ -0,0 +1,89 @@
/* 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 */

View File

@ -0,0 +1,129 @@
#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 */

View File

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

View File

@ -0,0 +1,52 @@
/* 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 */

View File

@ -0,0 +1,33 @@
/* 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

View File

@ -0,0 +1,320 @@
/* 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 */

View File

@ -0,0 +1,51 @@
/* 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 */

View File

@ -0,0 +1,55 @@
/* 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

View File

@ -0,0 +1,32 @@
/* 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

View File

@ -0,0 +1,323 @@
/* 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_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 : 2; /* 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 */
}
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 */

View File

@ -0,0 +1,54 @@
/* 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 */

View File

@ -0,0 +1,33 @@
/* 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

View File

@ -0,0 +1,279 @@
/* 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 */

View File

@ -0,0 +1,32 @@
/* 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

View File

@ -0,0 +1,281 @@
/* 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 */

View File

@ -0,0 +1,67 @@
/*
* 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 */

View File

@ -0,0 +1,85 @@
/* 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);

View File

@ -0,0 +1,54 @@
/* 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 */

View File

@ -0,0 +1,32 @@
/* 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

View File

@ -0,0 +1,331 @@
/* 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 */

View File

@ -0,0 +1,56 @@
/* 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 */

View File

@ -0,0 +1,37 @@
/* 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

View File

@ -0,0 +1,314 @@
/* 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 */

View File

@ -0,0 +1,56 @@
/* 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 */

View File

@ -0,0 +1,37 @@
/* 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

View File

@ -0,0 +1,369 @@
/* 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 "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 */

View File

@ -0,0 +1,49 @@
/* 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 */

View File

@ -0,0 +1,48 @@
/* 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

View File

@ -0,0 +1,280 @@
/* 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 */

View File

@ -0,0 +1,50 @@
/* 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 */

View File

@ -0,0 +1,33 @@
/* 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

View File

@ -0,0 +1,267 @@
/* 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"
#ifdef HAVE___THREAD
# undef HAVE___THREAD
#endif
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 */

View File

@ -0,0 +1,52 @@
/* 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 */

View File

@ -0,0 +1,42 @@
/* 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

View File

@ -0,0 +1,293 @@
/* 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 */

View File

@ -0,0 +1,57 @@
/* 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 */

View File

@ -0,0 +1,43 @@
/* 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

View File

@ -0,0 +1,264 @@
/* 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 */

View File

@ -0,0 +1,28 @@
/* 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

View File

@ -0,0 +1,30 @@
/* 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"
#if 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 */

View File

@ -0,0 +1,37 @@
/* 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 */

View File

@ -0,0 +1,37 @@
/* 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 */

View File

@ -0,0 +1,154 @@
/* 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 */

View File

@ -0,0 +1,31 @@
/* 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

View File

@ -0,0 +1,37 @@
/* libunwind - a platform-independent unwind library
Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
PROTECTED int
unw_apply_reg_state (unw_cursor_t *cursor,
void *reg_states_data)
{
struct cursor *c = (struct cursor *) cursor;
return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data);
}

View File

@ -0,0 +1,60 @@
/* 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
}

View File

@ -0,0 +1,39 @@
/* 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;
}

View File

@ -0,0 +1,100 @@
/* 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;
}

View File

@ -0,0 +1,57 @@
/* 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);
}

View File

@ -0,0 +1,188 @@
/* 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_V31)
return &uc->uc_mcontext.regs[reg];
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 = UNW_CACHE_GLOBAL;
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
local_addr_space.acc.access_mem = access_mem;
local_addr_space.acc.access_reg = access_reg;
local_addr_space.acc.access_fpreg = access_fpreg;
local_addr_space.acc.resume = 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 */

View File

@ -0,0 +1,67 @@
/* 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_local_signal (unw_cursor_t *cursor, unw_context_t *uc)
{
return unw_init_local_common(cursor, uc, 0);
}
#endif /* !UNW_REMOTE_ONLY */

View File

@ -0,0 +1,45 @@
/* 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 */
}

View File

@ -0,0 +1,64 @@
/* 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
}

View File

@ -0,0 +1,37 @@
/* libunwind - a platform-independent unwind library
Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
PROTECTED int
unw_reg_states_iterate (unw_cursor_t *cursor,
unw_reg_states_callback cb, void *token)
{
struct cursor *c = (struct cursor *) cursor;
return dwarf_reg_states_iterate (&c->dwarf, cb, token);
}

View File

@ -0,0 +1,113 @@
/* 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_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_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)
{
Debug (1, "bad register number %u\n", reg);
return -UNW_EBADREG;
}

View File

@ -0,0 +1,185 @@
/* 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[15];
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[30]; /* LR */
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"
"ldr x30, [x4,112]\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_PSTATE; ++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);
}

View File

@ -0,0 +1,89 @@
/* 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");
}

View File

@ -0,0 +1,131 @@
/* 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"
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;
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))
return 0;
return (c->dwarf.ip == 0) ? 0 : 1;
}

View File

@ -0,0 +1,548 @@
/* 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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More