l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
/* 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__
#ifndef __has_attribute
# define __has_attribute(x) (0)
#endif
# define CONST_ATTR __attribute__((__const__))
# define UNUSED __attribute__((unused))
# define NOINLINE __attribute__((noinline))
# define NORETURN __attribute__((noreturn))
# define ALIAS2(name) #name
# define ALIAS(name) __attribute__((alias (ALIAS2(name))))
# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
# define ALWAYS_INLINE inline __attribute__((always_inline))
# define HIDDEN __attribute__((visibility ("hidden")))
# if __has_attribute(fallthrough)
# define FALLTHROUGH __attribute__((fallthrough))
# else
# define FALLTHROUGH
# endif
# else
# define ALWAYS_INLINE
# define HIDDEN
# define FALLTHROUGH
# 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 ALWAYS_INLINE
# define CONST_ATTR
# define UNUSED
# define NOINLINE
# define NORETURN
# define ALIAS(name)
# define HIDDEN
# define FALLTHROUGH
# 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,261 @@
/* 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 if the weak 'backtrace' symbol is provided. */
#define CONFIG_WEAK_BACKTRACE 1
/* Define to 1 if you want every memory access validated */
#define CONSERVATIVE_CHECKS 1
/* Define to 1 if you have the <asm/ptrace.h> header file. */
/* #undef HAVE_ASM_PTRACE_H */
/* 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 <asm/vsyscall.h> header file. */
/* #undef HAVE_ASM_VSYSCALL_H */
/* Define to 1 if you have the <byteswap.h> header file. */
#define HAVE_BYTESWAP_H 1
/* Define to 1 if you have the declaration of 'PTRACE_CONT', and to 0 if you
don't. */
#define HAVE_DECL_PTRACE_CONT 1
/* Define to 1 if you have the declaration of 'PTRACE_POKEDATA', and to 0 if
you don't. */
#define HAVE_DECL_PTRACE_POKEDATA 1
/* Define to 1 if you have the declaration of 'PTRACE_POKEUSER', and to 0 if
you don't. */
#define HAVE_DECL_PTRACE_POKEUSER 1
/* Define to 1 if you have the declaration of 'PTRACE_SETREGSET', and to 0 if
you don't. */
#define HAVE_DECL_PTRACE_SETREGSET 1
/* Define to 1 if you have the declaration of 'PTRACE_SINGLESTEP', and to 0 if
you don't. */
#define HAVE_DECL_PTRACE_SINGLESTEP 1
/* Define to 1 if you have the declaration of 'PTRACE_SYSCALL', and to 0 if
you don't. */
#define HAVE_DECL_PTRACE_SYSCALL 1
/* Define to 1 if you have the declaration of 'PTRACE_TRACEME', and to 0 if
you don't. */
#define HAVE_DECL_PTRACE_TRACEME 1
/* Define to 1 if you have the declaration of 'PT_CONTINUE', and to 0 if you
don't. */
#define HAVE_DECL_PT_CONTINUE 1
/* Define to 1 if you have the declaration of 'PT_GETFPREGS', and to 0 if you
don't. */
#define HAVE_DECL_PT_GETFPREGS 1
/* Define to 1 if you have the declaration of 'PT_GETREGS', and to 0 if you
don't. */
#define HAVE_DECL_PT_GETREGS 1
/* Define to 1 if you have the declaration of 'PT_IO', and to 0 if you don't.
*/
#define HAVE_DECL_PT_IO 0
/* Define to 1 if you have the declaration of 'PT_STEP', and to 0 if you
don't. */
#define HAVE_DECL_PT_STEP 1
/* Define to 1 if you have the declaration of 'PT_SYSCALL', and to 0 if you
don't. */
#define HAVE_DECL_PT_SYSCALL 1
/* Define to 1 if you have the declaration of 'PT_TRACE_ME', and to 0 if you
don't. */
#define HAVE_DECL_PT_TRACE_ME 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the 'dlmodinfo' function. */
/* #undef HAVE_DLMODINFO */
/* Define to 1 if you have the 'dl_iterate_phdr' function. */
#define HAVE_DL_ITERATE_PHDR 1
/* Define to 1 if you have the 'dl_phdr_removals_counter' function. */
/* #undef HAVE_DL_PHDR_REMOVALS_COUNTER */
/* Define to 1 if the system has the type 'elf_fpregset_t'. */
#define HAVE_ELF_FPREGSET_T 1
/* 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 'execvpe' function. */
/* #undef HAVE_EXECVPE */
/* 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 <link.h> header file. */
#define HAVE_LINK_H 1
/* Define if you have liblzma */
/* #undef HAVE_LZMA */
/* Define to 1 if you have the 'mincore' function. */
/* #undef HAVE_MINCORE */
/* Define to 1 if you have the 'pipe2' function. */
/* #undef HAVE_PIPE2 */
/* Define to 1 if the system has the type 'procfs_status'. */
/* #undef HAVE_PROCFS_STATUS */
/* Define to 1 if you have the 'sigaltstack' function. */
#define HAVE_SIGALTSTACK 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 <stdio.h> header file. */
#define HAVE_STDIO_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'. */
/* #undef HAVE_STRUCT_DL_PHDR_INFO_DLPI_SUBS */
/* 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 */
/* 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/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* 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/syscall.h> header file. */
/* #undef HAVE_SYS_SYSCALL_H */
/* 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
/* Define if you have libz */
/* undef HAVE_ZLIB */
/* 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 --enable-per-thread-cache */
/* #undef HAVE___CACHE_PER_THREAD */
/* 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 "https://github.com/libunwind/libunwind"
/* 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.9-pre"
/* 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.9-pre"
/* The size of 'off_t', as computed by sizeof. */
#define SIZEOF_OFF_T sizeof(off_t)
/* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "1.9-pre"
/* 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 as 'unsigned int' if <stddef.h> doesn't define. */
/* #undef size_t */

View File

@@ -0,0 +1,10 @@
#ifndef CONFIG_H
#define CONFIG_H
#cmakedefine01 HAVE_ELF_H
#cmakedefine01 HAVE_ENDIAN_H
#define PACKAGE_STRING "@PACKAGE_STRING@"
#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
#endif // CONFIG_H

View File

@@ -0,0 +1,260 @@
/* 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 if the weak 'backtrace' symbol is provided. */
#undef CONFIG_WEAK_BACKTRACE
/* Define to 1 if you want every memory access validated */
#undef CONSERVATIVE_CHECKS
/* Define to 1 if you have the <asm/ptrace.h> header file. */
#undef HAVE_ASM_PTRACE_H
/* 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 <asm/vsyscall.h> header file. */
#undef HAVE_ASM_VSYSCALL_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_SETREGSET', and to 0 if
you don't. */
#undef HAVE_DECL_PTRACE_SETREGSET
/* 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 the system has the type 'elf_fpregset_t'. */
#undef HAVE_ELF_FPREGSET_T
/* 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 'execvpe' function. */
#undef HAVE_EXECVPE
/* 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 <link.h> header file. */
#undef HAVE_LINK_H
/* Define if you have liblzma */
#undef HAVE_LZMA
/* Define to 1 if you have the 'mincore' function. */
#undef HAVE_MINCORE
/* Define to 1 if you have the 'pipe2' function. */
#undef HAVE_PIPE2
/* Define to 1 if the system has the type 'procfs_status'. */
#undef HAVE_PROCFS_STATUS
/* Define to 1 if you have the 'sigaltstack' function. */
#undef HAVE_SIGALTSTACK
/* 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 <stdio.h> header file. */
#undef HAVE_STDIO_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
/* 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/param.h> header file. */
#undef HAVE_SYS_PARAM_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/syscall.h> header file. */
#undef HAVE_SYS_SYSCALL_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
/* Define if you have libz */
#undef HAVE_ZLIB
/* 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 --enable-per-thread-cache */
#undef HAVE___CACHE_PER_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 all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#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 as 'unsigned int' if <stddef.h> doesn't define. */
#undef size_t

View File

@@ -0,0 +1,139 @@
/* 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"
#include "libunwind_i.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 */
#ifdef _MSC_VER
#pragma pack(push, 1)
#define __attribute__(x)
#endif
struct __attribute__((packed)) dwarf_eh_frame_hdr
{
unsigned char version;
unsigned char eh_frame_ptr_enc;
unsigned char fde_count_enc;
unsigned char table_enc;
Elf_W (Addr) eh_frame;
/* The rest of the header is variable-length and consists of the
following members:
encoded_t fde_count;
struct
{
encoded_t start_ip; // first address covered by this FDE
encoded_t fde_addr; // address of the FDE
}
binary_search_table[fde_count]; */
};
#ifdef _MSC_VER
#pragma pack(pop)
#undef __attribute__
#endif
#endif /* dwarf_eh_h */

View File

@@ -0,0 +1,457 @@
/* 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>
#include <stdatomic.h>
struct dwarf_cursor; /* forward-declaration */
struct elf_dyn_info;
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "dwarf-config.h"
#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
#if defined(__ANDROID__) && defined(__arm__) && __ANDROID_API__ < 21
int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), void *);
#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
#define DWARF_CIE_VERSION_MAX 4
#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_CFA, /* register is set to the computed cfa 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_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-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;
_Atomic 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;
/* ELF load offset */
unw_word_t load_offset;
/* 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,
const 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 stack_val, 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 UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr,
int8_t *val, void *arg UNUSED)
{
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 UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr,
int16_t *val, void *arg UNUSED)
{
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 UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr,
int32_t *val, void *arg UNUSED)
{
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 UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr,
int64_t *val, void *arg UNUSED)
{
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 UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr,
uint8_t *val, void *arg UNUSED)
{
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 UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr,
uint16_t *val, void *arg UNUSED)
{
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 UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr,
uint32_t *val, void *arg UNUSED)
{
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 UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr,
uint64_t *val, void *arg UNUSED)
{
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) + 1);
unw_word_t off = *addr - aligned_addr;
int ret;
*addr += 1;
ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
#if UNW_BYTE_ORDER == UNW_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 = (unw_word_t) 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 = (unw_word_t) 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 = (unw_word_t) 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,284 @@
/* 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
Copyright 2022 Blackberry 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>
#include <stdalign.h>
#include <stdint.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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.
Calculation is regs used (64 + 34) * 2 + 40 (bytes of rest of
cursor) + padding
*/
#define UNW_TDEP_CURSOR_LEN 250
typedef uint64_t unw_word_t;
typedef int64_t unw_sword_t;
typedef long double unw_tdep_fpreg_t;
#define UNW_WORD_MAX UINT64_MAX
typedef struct
{
/* no aarch64-specific auxiliary proc-info */
UNW_EMPTY_STRUCT
}
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,
/* Pseudo-register */
UNW_AARCH64_RA_SIGN_STATE = 34,
/* SVE Vector Granule pseudo register */
UNW_AARCH64_VG = 46,
/* 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_EMPTY_STRUCT
}
unw_tdep_save_loc_t;
#ifdef __linux__
/* On AArch64, we can directly use ucontext_t as the unwind context,
* however, the __reserved struct is quite large: tune it down to only
* the necessary used fields. */
struct unw_sigcontext
{
uint64_t fault_address;
uint64_t regs[31];
uint64_t sp;
uint64_t pc;
uint64_t pstate;
alignas(16) uint8_t __reserved[(66 * 8)];
};
typedef struct
{
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
#ifndef __ANDROID__
sigset_t uc_sigmask;
#else
union {
sigset_t uc_sigmask;
sigset64_t uc_sigmask64;
};
char __padding[128 - sizeof(sigset_t)];
#endif
struct unw_sigcontext uc_mcontext;
} unw_tdep_context_t;
typedef struct
{
uint32_t _ctx_magic;
uint32_t _ctx_size;
uint32_t fpsr;
uint32_t fpcr;
uint64_t vregs[64];
} unw_fpsimd_context_t;
#else
/* On AArch64, we can directly use ucontext_t as the unwind context. */
typedef ucontext_t unw_tdep_context_t;
#endif
#include "libunwind-common.h"
#include "libunwind-dynamic.h"
#if defined(__FreeBSD__)
# define UNW_BASE register uint64_t unw_base __asm__ ("x0") = (uint64_t) unw_ctx->uc_mcontext.mc_gpregs.gp_x;
#elif defined(__QNX__)
# define UNW_BASE register uint64_t unw_base __asm__ ("x0") = (uint64_t) unw_ctx->uc_mcontext.cpu.gpr;
#else
# define UNW_BASE register uint64_t unw_base __asm__ ("x0") = (uint64_t) unw_ctx->uc_mcontext.regs;
#endif
#define unw_tdep_getcontext(uc) ({ \
unw_tdep_context_t *unw_ctx = (uc); \
UNW_BASE \
__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, x15, [%[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" \
"mov x1, sp\n" \
"stp x30, x1, [%[base], #240]\n" \
"adr x1, ret%=\n" \
"str x1, [%[base], #256]\n" \
"mov %[base], #0\n" \
"ret%=:\n" \
: [base] "+r" (unw_base) : : "x1", "memory"); \
(int)unw_base; })
#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,335 @@
/* 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>
#include <stdint.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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;
#define UNW_WORD_MAX UINT32_MAX
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_R15,
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_EMPTY_STRUCT
}
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];
unsigned long long fpregs[16];
}
unw_tdep_context_t;
/* FIXME: this is a stub version which only saves GP registers. Not ideal, but
may be sufficient for all libunwind use cases.
In thumb mode, we return directly back to thumb mode on return (with bx), to
avoid altering any registers after unw_resume. */
#ifdef __SOFTFP__
#define VSTMIA "nop\n\t" /* align return address to value stored by stmia */
#else
#define VSTMIA "vstmia %[base], {d0-d15}\n\t" /* this also aligns return address to value stored by stmia */
#endif
#ifndef __thumb__
#define unw_tdep_getcontext(uc) ({ \
unw_tdep_context_t *unw_ctx = (uc); \
register unsigned long *r0 __asm__ ("r0"); \
register unsigned long *unw_base __asm__ ("r1") = unw_ctx->regs; \
__asm__ __volatile__ ( \
"mov r0, #0\n\t" \
"stmia %[base]!, {r0-r15}\n\t" \
VSTMIA \
: [r0] "=r" (r0), [base] "+r" (unw_base) : : "memory"); \
(int)r0; })
#else /* __thumb__ */
#define unw_tdep_getcontext(uc) ({ \
unw_tdep_context_t *unw_ctx = (uc); \
register unsigned long *r0 __asm__ ("r0"); \
register unsigned long *unw_base __asm__ ("r1") = unw_ctx->regs; \
__asm__ __volatile__ ( \
".align 2\n\t" \
"bx pc\n\t" \
"nop\n\t" \
".code 32\n\t" \
"mov r0, #0\n\t" \
"stmia %[base]!, {r0-r14}\n\t" \
"adr r0, ret%=+1\n\t" \
"stmia %[base]!, {r0}\n\t" \
VSTMIA \
"orr r0, pc, #1\n\t" \
"bx r0\n\t" \
".code 16\n\t" \
"mov r0, #0\n\t" \
"ret%=:\n" \
: [r0] "=r" (r0), [base] "+r" (unw_base) : : "memory", "cc"); \
(int)r0; })
#endif
#include "libunwind-dynamic.h"
typedef struct
{
/* no arm-specific auxiliary proc-info */
UNW_EMPTY_STRUCT
}
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,346 @@
/* 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 7
#define UNW_VERSION_EXTRA -pre
#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min))
#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR)
#ifdef __sun
// On SmartOS, gcc fails with the following error:
//
// ../include/libunwind-common.h:43:41: error: expected identifier or '(' before numeric constant
// # define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
// ^
//
// workaround is to undefine _U explicitly.
// see https://github.com/libunwind/libunwind/issues/118 for more details.
//
#undef _U
#endif
#define UNW_PASTE2(x,y) x##y
#define UNW_PASTE(x,y) UNW_PASTE2(x,y)
#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn)
#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn)
#ifdef UNW_LOCAL_ONLY
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_)
#else /* !UNW_LOCAL_ONLY */
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
#endif /* !UNW_LOCAL_ONLY */
/* Error codes. The unwind routines return the *negated* values of
these error codes on error and a non-negative value on success. */
typedef enum
{
UNW_ESUCCESS = 0, /* no error */
UNW_EUNSPEC, /* unspecified (general) error */
UNW_ENOMEM, /* out of memory */
UNW_EBADREG, /* bad register number */
UNW_EREADONLYREG, /* attempt to write read-only register */
UNW_ESTOPUNWIND, /* stop unwinding */
UNW_EINVALIDIP, /* invalid IP */
UNW_EBADFRAME, /* bad frame */
UNW_EINVAL, /* unsupported operation or bad value */
UNW_EBADVERSION, /* unwind info has unsupported version */
UNW_ENOINFO /* no unwind info found */
}
unw_error_t;
/* The following enum defines the indices for a couple of
(pseudo-)registers which have the same meaning across all
platforms. (RO) means read-only. (RW) means read-write. General
registers (aka "integer registers") are expected to start with
index 0. The number of such registers is architecture-dependent.
The remaining indices can be used as an architecture sees fit. The
last valid register index is given by UNW_REG_LAST. */
typedef enum
{
UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */
UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */
UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */
UNW_REG_LAST = UNW_TDEP_LAST_REG
}
unw_frame_regnum_t;
/* Number of exception-handler argument registers: */
#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS
typedef enum
{
UNW_CACHE_NONE, /* no caching */
UNW_CACHE_GLOBAL, /* shared global cache */
UNW_CACHE_PER_THREAD /* per-thread caching */
}
unw_caching_policy_t;
typedef enum
{
UNW_INIT_SIGNAL_FRAME = 1, /* We know this is a signal frame */
}
unw_init_local2_flags_t;
typedef int unw_regnum_t;
/* The unwind cursor starts at the youngest (most deeply nested) frame
and is used to track the frame state as the unwinder steps from
frame to frame. It is safe to make (shallow) copies of variables
of this type. */
typedef struct unw_cursor
{
unw_word_t opaque[UNW_TDEP_CURSOR_LEN];
}
unw_cursor_t;
/* This type encapsulates the entire (preserved) machine-state. */
typedef unw_tdep_context_t unw_context_t;
/* unw_getcontext() fills the unw_context_t pointed to by UC with the
machine state as it exists at the call-site. For implementation
reasons, this needs to be a target-dependent macro. It's easiest
to think of unw_getcontext() as being identical to getcontext(). */
#define unw_getcontext(uc) unw_tdep_getcontext(uc)
/* Return 1 if register number R is a floating-point register, zero
otherwise.
This routine is signal-safe. */
#define unw_is_fpreg(r) unw_tdep_is_fpreg(r)
typedef unw_tdep_fpreg_t unw_fpreg_t;
typedef struct unw_addr_space *unw_addr_space_t;
/* Each target may define it's own set of flags, but bits 0-15 are
reserved for general libunwind-use. */
#define UNW_PI_FLAG_FIRST_TDEP_BIT 16
/* The information comes from a .debug_frame section. */
#define UNW_PI_FLAG_DEBUG_FRAME 32
typedef struct unw_proc_info
{
unw_word_t start_ip; /* first IP covered by this procedure */
unw_word_t end_ip; /* first IP NOT covered by this procedure */
#if defined(NEED_LAST_IP)
unw_word_t last_ip; /* first IP that could begin another procedure */
#endif
unw_word_t lsda; /* address of lang.-spec. data area (if any) */
unw_word_t handler; /* optional personality routine */
unw_word_t gp; /* global-pointer value for this procedure */
unw_word_t flags; /* misc. flags */
int format; /* unwind-info format (arch-specific) */
int unwind_info_size; /* size of the information (if applicable) */
void *unwind_info; /* unwind-info (arch-specific) */
unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */
}
unw_proc_info_t;
typedef int (*unw_reg_states_callback)(void *token,
void *reg_states_data,
size_t reg_states_data_size,
unw_word_t start_ip, unw_word_t end_ip);
/* These are backend callback routines that provide access to the
state of a "remote" process. This can be used, for example, to
unwind another process through the ptrace() interface. */
typedef struct unw_accessors
{
/* Look up the unwind info associated with instruction-pointer IP.
On success, the routine fills in the PROC_INFO structure. */
int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *,
int, void *);
/* Release any resources (e.g., memory) that were allocated for
the unwind info returned in by a previous call to
find_proc_info() with NEED_UNWIND_INFO set to 1. */
void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *);
/* Return the list-head of the dynamically registered unwind
info. */
int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *);
/* Access aligned word at address ADDR. The value is returned
according to the endianness of the host (e.g., if the host is
little-endian and the target is big-endian, access_mem() needs
to byte-swap the value before returning it). */
int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int,
void *);
/* Access register number REG at address ADDR. */
int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int,
void *);
/* Access register number REG at address ADDR. */
int (*access_fpreg) (unw_addr_space_t, unw_regnum_t,
unw_fpreg_t *, int, void *);
int (*resume) (unw_addr_space_t, unw_cursor_t *, void *);
/* Optional call back to obtain the name of a (static) procedure.
Dynamically generated procedures are handled automatically by
libunwind. This callback is optional and may be set to
NULL. */
int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t,
unw_word_t *, void *);
/* Optional call back to obtain the name of a elf file where the ip belongs to.
This callback is optional and may be set to NULL. */
int (*get_elf_filename) (unw_addr_space_t, unw_word_t, char *, size_t,
unw_word_t *, void *);
/* Optional call back to obtain the start and end ip of a procedure.
* procedure ip range is [start, end), the range is without end.
* This callback is optional and may be set to NULL.
*/
int (*get_proc_ip_range) (unw_addr_space_t, unw_word_t, unw_word_t *,
unw_word_t *, void *);
/* Optional call back to return a mask to be used with pointer
* authentication on arm64.
*
* The on bits in the returned mask indicate which bits in a return address
* are part of a pointer authentication code. These are the bits in the
* return address to turn off so that the calling frame can be found
* for the unwinding to continue.
*
* The return value must be host-endian. e.g. if the target is big-endian
* and the host is little endian, the implementation of this function
* must byte swap.
*
* This callback is optional and may be set to NULL. In this case all
* the bits in the return address are used, as if no masking were done.
*/
unw_word_t (*ptrauth_insn_mask) (unw_addr_space_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;
struct dl_phdr_info;
typedef int (*unw_iterate_phdr_callback_t) (struct dl_phdr_info *, size_t, void *);
typedef int (*unw_iterate_phdr_func_t) (unw_iterate_phdr_callback_t, void *);
/* 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_get_accessors_int UNW_ARCH_OBJ(get_accessors_int)
#define unw_init_local UNW_OBJ(init_local)
#define unw_init_local2 UNW_OBJ(init_local2)
#define unw_init_remote UNW_OBJ(init_remote)
#define unw_step UNW_OBJ(step)
#define unw_resume UNW_OBJ(resume)
#define unw_get_proc_info UNW_OBJ(get_proc_info)
#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip)
#define unw_get_proc_info_in_range UNW_OBJ(get_proc_info_in_range)
#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_is_plt_entry UNW_OBJ(is_plt_entry)
#define unw_get_proc_name UNW_OBJ(get_proc_name)
#define unw_get_proc_name_by_ip UNW_OBJ(get_proc_name_by_ip)
#define unw_get_elf_filename UNW_OBJ(get_elf_filename)
#define unw_get_elf_filename_by_ip UNW_OBJ(get_elf_filename_by_ip)
#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
#define unw_set_cache_size UNW_OBJ(set_cache_size)
#define unw_set_iterate_phdr_function UNW_OBJ(set_iterate_phdr_function)
#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 unw_accessors_t *unw_get_accessors_int (unw_addr_space_t);
extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t);
extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t);
extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
extern void unw_set_iterate_phdr_function (unw_addr_space_t, unw_iterate_phdr_func_t);
extern const char *unw_regname (unw_regnum_t);
extern int unw_init_local (unw_cursor_t *, unw_context_t *);
extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int);
extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *);
extern int unw_step (unw_cursor_t *);
extern int unw_resume (unw_cursor_t *);
extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *);
extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t,
unw_proc_info_t *, void *);
extern int unw_get_proc_info_in_range (unw_word_t, unw_word_t,
unw_word_t, unw_word_t,
unw_word_t, unw_word_t,
unw_addr_space_t, unw_word_t,
unw_proc_info_t *, int,
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_is_plt_entry (unw_cursor_t *);
extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *);
extern int unw_get_proc_name_by_ip (unw_addr_space_t, unw_word_t, char *,
size_t, unw_word_t *, void *);
extern int unw_get_elf_filename (unw_cursor_t *, char *, size_t, unw_word_t *);
extern int unw_get_elf_filename_by_ip (unw_addr_space_t, unw_word_t, char *,
size_t, unw_word_t *, void *);
extern const char *unw_strerror (int);
extern int unw_backtrace (void **, int);
extern int unw_backtrace2 (void **, int, unw_context_t*, int);
extern unw_addr_space_t unw_local_addr_space;

View File

@@ -0,0 +1,346 @@
/* 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)
#ifdef __sun
// On SmartOS, gcc fails with the following error:
//
// ../include/libunwind-common.h:43:41: error: expected identifier or '(' before numeric constant
// # define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
// ^
//
// workaround is to undefine _U explicitly.
// see https://github.com/libunwind/libunwind/issues/118 for more details.
//
#undef _U
#endif
#define UNW_PASTE2(x,y) x##y
#define UNW_PASTE(x,y) UNW_PASTE2(x,y)
#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn)
#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn)
#ifdef UNW_LOCAL_ONLY
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_)
#else /* !UNW_LOCAL_ONLY */
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
#endif /* !UNW_LOCAL_ONLY */
/* Error codes. The unwind routines return the *negated* values of
these error codes on error and a non-negative value on success. */
typedef enum
{
UNW_ESUCCESS = 0, /* no error */
UNW_EUNSPEC, /* unspecified (general) error */
UNW_ENOMEM, /* out of memory */
UNW_EBADREG, /* bad register number */
UNW_EREADONLYREG, /* attempt to write read-only register */
UNW_ESTOPUNWIND, /* stop unwinding */
UNW_EINVALIDIP, /* invalid IP */
UNW_EBADFRAME, /* bad frame */
UNW_EINVAL, /* unsupported operation or bad value */
UNW_EBADVERSION, /* unwind info has unsupported version */
UNW_ENOINFO /* no unwind info found */
}
unw_error_t;
/* The following enum defines the indices for a couple of
(pseudo-)registers which have the same meaning across all
platforms. (RO) means read-only. (RW) means read-write. General
registers (aka "integer registers") are expected to start with
index 0. The number of such registers is architecture-dependent.
The remaining indices can be used as an architecture sees fit. The
last valid register index is given by UNW_REG_LAST. */
typedef enum
{
UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */
UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */
UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */
UNW_REG_LAST = UNW_TDEP_LAST_REG
}
unw_frame_regnum_t;
/* Number of exception-handler argument registers: */
#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS
typedef enum
{
UNW_CACHE_NONE, /* no caching */
UNW_CACHE_GLOBAL, /* shared global cache */
UNW_CACHE_PER_THREAD /* per-thread caching */
}
unw_caching_policy_t;
typedef enum
{
UNW_INIT_SIGNAL_FRAME = 1 /* We know this is a signal frame */
}
unw_init_local2_flags_t;
typedef int unw_regnum_t;
/* The unwind cursor starts at the youngest (most deeply nested) frame
and is used to track the frame state as the unwinder steps from
frame to frame. It is safe to make (shallow) copies of variables
of this type. */
typedef struct unw_cursor
{
unw_word_t opaque[UNW_TDEP_CURSOR_LEN];
}
unw_cursor_t;
/* This type encapsulates the entire (preserved) machine-state. */
typedef unw_tdep_context_t unw_context_t;
/* unw_getcontext() fills the unw_context_t pointed to by UC with the
machine state as it exists at the call-site. For implementation
reasons, this needs to be a target-dependent macro. It's easiest
to think of unw_getcontext() as being identical to getcontext(). */
#define unw_getcontext(uc) unw_tdep_getcontext(uc)
/* Return 1 if register number R is a floating-point register, zero
otherwise.
This routine is signal-safe. */
#define unw_is_fpreg(r) unw_tdep_is_fpreg(r)
typedef unw_tdep_fpreg_t unw_fpreg_t;
typedef struct unw_addr_space *unw_addr_space_t;
/* Each target may define it's own set of flags, but bits 0-15 are
reserved for general libunwind-use. */
#define UNW_PI_FLAG_FIRST_TDEP_BIT 16
/* The information comes from a .debug_frame section. */
#define UNW_PI_FLAG_DEBUG_FRAME 32
typedef struct unw_proc_info
{
unw_word_t start_ip; /* first IP covered by this procedure */
unw_word_t end_ip; /* first IP NOT covered by this procedure */
#if defined(NEED_LAST_IP)
unw_word_t last_ip; /* first IP that could begin another procedure */
#endif
unw_word_t lsda; /* address of lang.-spec. data area (if any) */
unw_word_t handler; /* optional personality routine */
unw_word_t gp; /* global-pointer value for this procedure */
unw_word_t flags; /* misc. flags */
int format; /* unwind-info format (arch-specific) */
int unwind_info_size; /* size of the information (if applicable) */
void *unwind_info; /* unwind-info (arch-specific) */
unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */
}
unw_proc_info_t;
typedef int (*unw_reg_states_callback)(void *token,
void *reg_states_data,
size_t reg_states_data_size,
unw_word_t start_ip, unw_word_t end_ip);
/* These are backend callback routines that provide access to the
state of a "remote" process. This can be used, for example, to
unwind another process through the ptrace() interface. */
typedef struct unw_accessors
{
/* Look up the unwind info associated with instruction-pointer IP.
On success, the routine fills in the PROC_INFO structure. */
int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *,
int, void *);
/* Release any resources (e.g., memory) that were allocated for
the unwind info returned in by a previous call to
find_proc_info() with NEED_UNWIND_INFO set to 1. */
void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *);
/* Return the list-head of the dynamically registered unwind
info. */
int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *);
/* Access aligned word at address ADDR. The value is returned
according to the endianness of the host (e.g., if the host is
little-endian and the target is big-endian, access_mem() needs
to byte-swap the value before returning it). */
int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int,
void *);
/* Access register number REG at address ADDR. */
int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int,
void *);
/* Access register number REG at address ADDR. */
int (*access_fpreg) (unw_addr_space_t, unw_regnum_t,
unw_fpreg_t *, int, void *);
int (*resume) (unw_addr_space_t, unw_cursor_t *, void *);
/* Optional call back to obtain the name of a (static) procedure.
Dynamically generated procedures are handled automatically by
libunwind. This callback is optional and may be set to
NULL. */
int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t,
unw_word_t *, void *);
/* Optional call back to obtain the name of a elf file where the ip belongs to.
This callback is optional and may be set to NULL. */
int (*get_elf_filename) (unw_addr_space_t, unw_word_t, char *, size_t,
unw_word_t *, void *);
/* Optional call back to obtain the start and end ip of a procedure.
* procedure ip range is [start, end), the range is without end.
* This callback is optional and may be set to NULL.
*/
int (*get_proc_ip_range) (unw_addr_space_t, unw_word_t, unw_word_t *,
unw_word_t *, void *);
/* Optional call back to return a mask to be used with pointer
* authentication on arm64.
*
* The on bits in the returned mask indicate which bits in a return address
* are part of a pointer authentication code. These are the bits in the
* return address to turn off so that the calling frame can be found
* for the unwinding to continue.
*
* The return value must be host-endian. e.g. if the target is big-endian
* and the host is little endian, the implementation of this function
* must byte swap.
*
* This callback is optional and may be set to NULL. In this case all
* the bits in the return address are used, as if no masking were done.
*/
unw_word_t (*ptrauth_insn_mask) (unw_addr_space_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;
struct dl_phdr_info;
typedef int (*unw_iterate_phdr_callback_t) (struct dl_phdr_info *, size_t, void *);
typedef int (*unw_iterate_phdr_func_t) (unw_iterate_phdr_callback_t, void *);
/* 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_get_accessors_int UNW_ARCH_OBJ(get_accessors_int)
#define unw_init_local UNW_OBJ(init_local)
#define unw_init_local2 UNW_OBJ(init_local2)
#define unw_init_remote UNW_OBJ(init_remote)
#define unw_step UNW_OBJ(step)
#define unw_resume UNW_OBJ(resume)
#define unw_get_proc_info UNW_OBJ(get_proc_info)
#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip)
#define unw_get_proc_info_in_range UNW_OBJ(get_proc_info_in_range)
#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_is_plt_entry UNW_OBJ(is_plt_entry)
#define unw_get_proc_name UNW_OBJ(get_proc_name)
#define unw_get_proc_name_by_ip UNW_OBJ(get_proc_name_by_ip)
#define unw_get_elf_filename UNW_OBJ(get_elf_filename)
#define unw_get_elf_filename_by_ip UNW_OBJ(get_elf_filename_by_ip)
#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
#define unw_set_cache_size UNW_OBJ(set_cache_size)
#define unw_set_iterate_phdr_function UNW_OBJ(set_iterate_phdr_function)
#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 unw_accessors_t *unw_get_accessors_int (unw_addr_space_t);
extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t);
extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t);
extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
extern void unw_set_iterate_phdr_function (unw_addr_space_t, unw_iterate_phdr_func_t);
extern const char *unw_regname (unw_regnum_t);
extern int unw_init_local (unw_cursor_t *, unw_context_t *);
extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int);
extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *);
extern int unw_step (unw_cursor_t *);
extern int unw_resume (unw_cursor_t *);
extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *);
extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t,
unw_proc_info_t *, void *);
extern int unw_get_proc_info_in_range (unw_word_t, unw_word_t,
unw_word_t, unw_word_t,
unw_word_t, unw_word_t,
unw_addr_space_t, unw_word_t,
unw_proc_info_t *, int,
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_is_plt_entry (unw_cursor_t *);
extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *);
extern int unw_get_proc_name_by_ip (unw_addr_space_t, unw_word_t, char *,
size_t, unw_word_t *, void *);
extern int unw_get_elf_filename (unw_cursor_t *, char *, size_t, unw_word_t *);
extern int unw_get_elf_filename_by_ip (unw_addr_space_t, unw_word_t, char *,
size_t, unw_word_t *, void *);
extern const char *unw_strerror (int);
extern int unw_backtrace (void **, int);
extern int unw_backtrace2 (void **, int, unw_context_t*, int);
extern unw_addr_space_t unw_local_addr_space;

View File

@@ -0,0 +1,71 @@
/* 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_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_get_elf_filename (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,215 @@
/* 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;
unw_word_t load_offset; /* ELF load offset */
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,134 @@
/* 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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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;
#define UNW_WORD_MAX UINT32_MAX
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_EMPTY_STRUCT
}
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_EMPTY_STRUCT
}
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,202 @@
/* 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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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;
#define UNW_WORD_MAX UINT64_MAX
/* 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_EMPTY_STRUCT
}
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,146 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2001-2004 Hewlett-Packard Co
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
Copyright (C) 2021 Loongson Technology Corporation 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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#define UNW_TARGET loongarch64
#define UNW_TARGET_LOONGARCH64 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 LoongArch64. Too big? What do other things use for similar tasks? */
#define UNW_TDEP_CURSOR_LEN 4096
typedef uint64_t unw_word_t;
typedef int64_t unw_sword_t;
typedef long double unw_tdep_fpreg_t;
#define UNW_WORD_MAX UINT64_MAX
typedef enum
{
UNW_LOONGARCH64_R0,
UNW_LOONGARCH64_R1,
UNW_LOONGARCH64_R2,
UNW_LOONGARCH64_R3,
UNW_LOONGARCH64_R4,
UNW_LOONGARCH64_R5,
UNW_LOONGARCH64_R6,
UNW_LOONGARCH64_R7,
UNW_LOONGARCH64_R8,
UNW_LOONGARCH64_R9,
UNW_LOONGARCH64_R10,
UNW_LOONGARCH64_R11,
UNW_LOONGARCH64_R12,
UNW_LOONGARCH64_R13,
UNW_LOONGARCH64_R14,
UNW_LOONGARCH64_R15,
UNW_LOONGARCH64_R16,
UNW_LOONGARCH64_R17,
UNW_LOONGARCH64_R18,
UNW_LOONGARCH64_R19,
UNW_LOONGARCH64_R20,
UNW_LOONGARCH64_R21,
UNW_LOONGARCH64_R22,
UNW_LOONGARCH64_R23,
UNW_LOONGARCH64_R24,
UNW_LOONGARCH64_R25,
UNW_LOONGARCH64_R26,
UNW_LOONGARCH64_R27,
UNW_LOONGARCH64_R28,
UNW_LOONGARCH64_R29,
UNW_LOONGARCH64_R30,
UNW_LOONGARCH64_R31,
UNW_LOONGARCH64_PC = 33,
/* FIXME: Other registers! */
/* For LoongArch64, the CFA is the value of SP (r3) at the call site in the
previous frame. */
UNW_LOONGARCH64_CFA,
UNW_TDEP_LAST_REG = UNW_LOONGARCH64_PC,
UNW_TDEP_IP = UNW_LOONGARCH64_R1,
UNW_TDEP_SP = UNW_LOONGARCH64_R3,
UNW_TDEP_EH = UNW_LOONGARCH64_R0 /* FIXME. */
}
loongarch64_regnum_t;
#define UNW_TDEP_NUM_EH_REGS 4
typedef struct unw_tdep_save_loc
{
/* Additional target-dependent info on a save location. */
UNW_EMPTY_STRUCT
}
unw_tdep_save_loc_t;
/* On LoongArch64, we can directly use ucontext_t as the unwind context. */
typedef ucontext_t unw_tdep_context_t;
typedef struct
{
/* no loongarch64-specific auxiliary proc-info */
UNW_EMPTY_STRUCT
}
unw_tdep_proc_info_t;
#include "libunwind-dynamic.h"
#include "libunwind-common.h"
#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,169 @@
/* 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 <stdint.h>
#include <ucontext.h>
#ifdef mips
# undef mips
#endif
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#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;
# define UNW_WORD_MAX UINT64_MAX
#else
typedef uint32_t unw_word_t;
# define UNW_WORD_MAX UINT32_MAX
#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 = 64,
/* 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_EMPTY_STRUCT
}
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_EMPTY_STRUCT
}
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,69 @@
/**
* Public interface for the QNX Neutrino remote unwinding library.
*
* This library provides helper routines to make it possible to use libunwind
* via the QNX Neutrino procfs.
*/
/*
* Copyright 2020, 2022 QNX Blackberry 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_NTO_H
#define LIBUNWIND_NTO_H
#include <libunwind.h>
#include <pthread.h>
#if defined(__cplusplus)
extern "C" {
#endif
static const pthread_t LUT_ALL_THREADS = -1;
/**
* Helper routines to make it easy to unwind using devctl() on unw_nto.
*/
extern void *unw_nto_create(pid_t, pthread_t);
extern void unw_nto_destroy(void *);
extern int unw_nto_find_proc_info(unw_addr_space_t, unw_word_t, unw_proc_info_t *, int, void *);
extern void unw_nto_put_unwind_info(unw_addr_space_t, unw_proc_info_t *, void *);
extern int unw_nto_get_dyn_info_list_addr(unw_addr_space_t, unw_word_t *, void *);
extern int unw_nto_access_mem(unw_addr_space_t, unw_word_t, unw_word_t *, int, void *);
extern int unw_nto_access_reg(unw_addr_space_t, unw_regnum_t, unw_word_t *, int, void *);
extern int unw_nto_access_fpreg(unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, int, void *);
extern int unw_nto_get_proc_name(unw_addr_space_t, unw_word_t, char *, size_t, unw_word_t *, void *);
extern int unw_nto_get_proc_ip_range (unw_addr_space_t as, unw_word_t ip, unw_word_t *start, unw_word_t *end, void *);
extern int unw_nto_get_elf_filename(unw_addr_space_t, unw_word_t, char *, size_t, unw_word_t *, void *);
extern int unw_nto_resume(unw_addr_space_t, unw_cursor_t *, void *);
/**
* A handy pre-defined accessor with all of the above.
*/
extern unw_accessors_t unw_nto_accessors;
#if defined(__cplusplus)
} /* extern "C" */
#endif
#endif /* LIBUNWIND_NTO_H */

View File

@@ -0,0 +1,216 @@
/* 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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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;
# define UNW_WORD_MAX UINT32_MAX
#else
typedef uint64_t unw_word_t;
typedef int64_t unw_sword_t;
# define UNW_WORD_MAX UINT64_MAX
#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_EMPTY_STRUCT
}
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_EMPTY_STRUCT
}
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,280 @@
/* 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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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;
#define UNW_WORD_MAX UINT32_MAX
#else
typedef uint64_t unw_word_t;
typedef int64_t unw_sword_t;
#define UNW_WORD_MAX UINT64_MAX
#endif
typedef 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_EMPTY_STRUCT
}
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_EMPTY_STRUCT
}
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,67 @@
/* 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>
#include <sys/types.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_get_elf_filename (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_word_t _UPT_ptrauth_insn_mask (unw_addr_space_t, void *);
extern unw_accessors_t _UPT_accessors;
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif /* libunwind_ptrace_h */

View File

@@ -0,0 +1,194 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002-2004 Hewlett-Packard Co
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
Modified for riscv by Zhaofeng Li <hello@zhaofeng.li>
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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#define UNW_TARGET riscv
#define UNW_TARGET_RISCV 1
#define _U_TDEP_QP_TRUE 0 /* ignored - 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 riscv: Figure out a more reasonable size */
#define UNW_TDEP_CURSOR_LEN 4096
#if __riscv_xlen == 32
typedef uint32_t unw_word_t;
typedef int32_t unw_sword_t;
# define UNW_WORD_MAX UINT32_MAX
#elif __riscv_xlen == 64
typedef uint64_t unw_word_t;
typedef int64_t unw_sword_t;
# define UNW_WORD_MAX UINT64_MAX
#endif
#if __riscv_flen == 64
typedef double unw_tdep_fpreg_t;
#elif __riscv_flen == 32
typedef float unw_tdep_fpreg_t;
#else
# error "Unsupported RISC-V floating-point size"
#endif
/* Also see src/riscv/Gglobal.c. This ordering is consistent with
https://github.com/riscv/riscv-elf-psabi-doc/blob/74ecf07bcebd0cb4bf3c39f3f9d96946cd6aba61/riscv-elf.md#dwarf-register-numbers- */
typedef enum
{
/* integer registers */
UNW_RISCV_X0,
UNW_RISCV_X1,
UNW_RISCV_X2,
UNW_RISCV_X3,
UNW_RISCV_X4,
UNW_RISCV_X5,
UNW_RISCV_X6,
UNW_RISCV_X7,
UNW_RISCV_X8,
UNW_RISCV_X9,
UNW_RISCV_X10,
UNW_RISCV_X11,
UNW_RISCV_X12,
UNW_RISCV_X13,
UNW_RISCV_X14,
UNW_RISCV_X15,
UNW_RISCV_X16,
UNW_RISCV_X17,
UNW_RISCV_X18,
UNW_RISCV_X19,
UNW_RISCV_X20,
UNW_RISCV_X21,
UNW_RISCV_X22,
UNW_RISCV_X23,
UNW_RISCV_X24,
UNW_RISCV_X25,
UNW_RISCV_X26,
UNW_RISCV_X27,
UNW_RISCV_X28,
UNW_RISCV_X29,
UNW_RISCV_X30,
UNW_RISCV_X31,
/* floating point registers */
UNW_RISCV_F0,
UNW_RISCV_F1,
UNW_RISCV_F2,
UNW_RISCV_F3,
UNW_RISCV_F4,
UNW_RISCV_F5,
UNW_RISCV_F6,
UNW_RISCV_F7,
UNW_RISCV_F8,
UNW_RISCV_F9,
UNW_RISCV_F10,
UNW_RISCV_F11,
UNW_RISCV_F12,
UNW_RISCV_F13,
UNW_RISCV_F14,
UNW_RISCV_F15,
UNW_RISCV_F16,
UNW_RISCV_F17,
UNW_RISCV_F18,
UNW_RISCV_F19,
UNW_RISCV_F20,
UNW_RISCV_F21,
UNW_RISCV_F22,
UNW_RISCV_F23,
UNW_RISCV_F24,
UNW_RISCV_F25,
UNW_RISCV_F26,
UNW_RISCV_F27,
UNW_RISCV_F28,
UNW_RISCV_F29,
UNW_RISCV_F30,
UNW_RISCV_F31,
UNW_RISCV_PC,
UNW_TDEP_LAST_REG = UNW_RISCV_PC,
/* The CFA is the value of SP in previous frame */
UNW_RISCV_CFA = UNW_RISCV_X2,
UNW_TDEP_IP = UNW_RISCV_PC,
UNW_TDEP_SP = UNW_RISCV_X2,
UNW_TDEP_EH = UNW_RISCV_X10,
}
riscv_regnum_t;
/* https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/gcc/config/riscv/riscv.h#L104-L106 */
#define UNW_TDEP_NUM_EH_REGS 4
typedef struct unw_tdep_save_loc
{
/* Additional target-dependent info on a save location. */
UNW_EMPTY_STRUCT
}
unw_tdep_save_loc_t;
/* On riscv, we can directly use ucontext_t as the unwind context. */
typedef ucontext_t unw_tdep_context_t;
typedef struct
{
/* no riscv-specific auxiliary proc-info */
UNW_EMPTY_STRUCT
}
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,150 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002-2004 Hewlett-Packard Co
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
Modified for s390x by Michael Munday <mike.munday@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>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#define UNW_TARGET s390x
#define UNW_TARGET_S390X 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 384
typedef uint64_t unw_word_t;
typedef int64_t unw_sword_t;
typedef double unw_tdep_fpreg_t;
#define UNW_WORD_MAX UINT64_MAX
typedef enum
{
/* general purpose registers */
UNW_S390X_R0,
UNW_S390X_R1,
UNW_S390X_R2,
UNW_S390X_R3,
UNW_S390X_R4,
UNW_S390X_R5,
UNW_S390X_R6,
UNW_S390X_R7,
UNW_S390X_R8,
UNW_S390X_R9,
UNW_S390X_R10,
UNW_S390X_R11,
UNW_S390X_R12,
UNW_S390X_R13,
UNW_S390X_R14,
UNW_S390X_R15,
/* floating point registers */
UNW_S390X_F0,
UNW_S390X_F1,
UNW_S390X_F2,
UNW_S390X_F3,
UNW_S390X_F4,
UNW_S390X_F5,
UNW_S390X_F6,
UNW_S390X_F7,
UNW_S390X_F8,
UNW_S390X_F9,
UNW_S390X_F10,
UNW_S390X_F11,
UNW_S390X_F12,
UNW_S390X_F13,
UNW_S390X_F14,
UNW_S390X_F15,
/* PSW */
UNW_S390X_IP,
UNW_TDEP_LAST_REG = UNW_S390X_IP,
/* TODO: access, vector registers */
/* frame info (read-only) */
UNW_S390X_CFA,
UNW_TDEP_IP = UNW_S390X_IP,
UNW_TDEP_SP = UNW_S390X_R15,
/* TODO: placeholders */
UNW_TDEP_EH = UNW_S390X_R0,
}
s390x_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. */
UNW_EMPTY_STRUCT
}
unw_tdep_save_loc_t;
/* On s390x, we can directly use ucontext_t as the unwind context. */
typedef ucontext_t unw_tdep_context_t;
typedef struct
{
/* no s390x-specific auxiliary proc-info */
UNW_EMPTY_STRUCT
}
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,123 @@
/* 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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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;
#define UNW_WORD_MAX UINT32_MAX
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_EMPTY_STRUCT
}
unw_tdep_save_loc_t;
#include "libunwind-dynamic.h"
typedef struct
{
/* no sh-specific auxiliary proc-info */
UNW_EMPTY_STRUCT
}
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,196 @@
/* 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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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;
#define UNW_WORD_MAX UINT32_MAX
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_EMPTY_STRUCT
}
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_EMPTY_STRUCT
}
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,148 @@
/* 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 <stdint.h>
#include <ucontext.h>
#ifndef UNW_EMPTY_STRUCT
# define UNW_EMPTY_STRUCT uint8_t unused;
#endif
#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;
#define UNW_WORD_MAX UINT64_MAX
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. */
UNW_EMPTY_STRUCT
}
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 */
UNW_EMPTY_STRUCT
}
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,40 @@
/* 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 __s390x__
# include "libunwind-s390x.h"
#elif defined __riscv || defined __riscv__
# include "libunwind-riscv.h"
#elif defined __loongarch64
# include "libunwind-loongarch64.h"
#else
# error "Unsupported arch"
#endif
#else /* UNW_REMOTE_ONLY */
# include "libunwind-x86_64.h"
#endif /* UNW_REMOTE_ONLY */

View File

@@ -0,0 +1,40 @@
/* 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 __s390x__
# include "libunwind-s390x.h"
#elif defined __riscv || defined __riscv__
# include "libunwind-riscv.h"
#elif defined __loongarch64
# include "libunwind-loongarch64.h"
#else
# error "Unsupported arch"
#endif
#else /* UNW_REMOTE_ONLY */
# include "libunwind-@arch@.h"
#endif /* UNW_REMOTE_ONLY */

View File

@@ -0,0 +1,436 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2001-2005 Hewlett-Packard Co
Copyright (C) 2007 David Mosberger-Tang
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/* This files contains libunwind-internal definitions which are
subject to frequent change and are not to be exposed to
libunwind-users. */
#ifndef libunwind_i_h
#define libunwind_i_h
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "compiler.h"
#if defined(HAVE___CACHE_PER_THREAD) && HAVE___CACHE_PER_THREAD
#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_PER_THREAD
#else
#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_GLOBAL
#endif
/* Platform-independent libunwind-internal declarations. */
#include <sys/types.h> /* HP-UX needs this before include of pthread.h */
#include <assert.h>
#include <libunwind.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#if defined(HAVE_SYS_SYSCALL_H)
# include <sys/syscall.h> /* For SYS_xxx definitions */
#endif
#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(ELFCLASS32)
# define UNW_ELFCLASS32 ELFCLASS32
#else
# define UNW_ELFCLASS32 1
#endif
#if defined(ELFCLASS64)
# define UNW_ELFCLASS64 ELFCLASS64
#else
# define UNW_ELFCLASS64 2
#endif
#if defined(HAVE_ENDIAN_H)
# include <endian.h>
#elif defined(HAVE_SYS_ENDIAN_H)
# include <sys/endian.h>
#elif defined(HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#if defined(__LITTLE_ENDIAN)
# define UNW_LITTLE_ENDIAN __LITTLE_ENDIAN
#elif defined(_LITTLE_ENDIAN)
# define UNW_LITTLE_ENDIAN _LITTLE_ENDIAN
#elif defined(LITTLE_ENDIAN)
# define UNW_LITTLE_ENDIAN LITTLE_ENDIAN
#else
# define UNW_LITTLE_ENDIAN 1234
#endif
#if defined(__BIG_ENDIAN)
# define UNW_BIG_ENDIAN __BIG_ENDIAN
#elif defined(_BIG_ENDIAN)
# define UNW_BIG_ENDIAN _BIG_ENDIAN
#elif defined(BIG_ENDIAN)
# define UNW_BIG_ENDIAN BIG_ENDIAN
#else
# define UNW_BIG_ENDIAN 4321
#endif
#if defined(__BYTE_ORDER)
# define UNW_BYTE_ORDER __BYTE_ORDER
#elif defined(_BYTE_ORDER)
# define UNW_BYTE_ORDER _BYTE_ORDER
#elif defined(BIG_ENDIAN)
# define UNW_BYTE_ORDER BYTE_ORDER
#else
# if defined(__hpux)
# define UNW_BYTE_ORDER UNW_BIG_ENDIAN
# else
# error Target has unknown byte ordering.
# endif
#endif
static inline int
byte_order_is_valid(int byte_order)
{
return byte_order == UNW_BIG_ENDIAN
|| byte_order == UNW_LITTLE_ENDIAN;
}
static inline int
byte_order_is_big_endian(int byte_order)
{
return byte_order == UNW_BIG_ENDIAN;
}
static inline int
target_is_big_endian(void)
{
return byte_order_is_big_endian(UNW_BYTE_ORDER);
}
#if defined(HAVE__BUILTIN_UNREACHABLE)
# define unreachable() __builtin_unreachable()
#else
# define unreachable() do { } while (1)
#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
#pragma weak pthread_sigmask
#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)
#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 contrast, 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)
/* SIGPROCMASK ignores return values, so we do not have to correct for pthread_sigmask() returning
errno on failure when sigprocmask() returns -1. */
# define SIGPROCMASK(how, new_mask, old_mask) \
(pthread_sigmask != NULL ? pthread_sigmask((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 */
/* Provide an internal syscall version of mmap to improve signal safety. */
static ALWAYS_INLINE void *
mi_mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
#if defined(SYS_mmap) && !defined(__i386__) && !defined(__s390x__)
/* Where supported, bypass libc and invoke the syscall directly. */
# if defined(__FreeBSD__) // prefer over syscall on *BSD
long int ret = __syscall (SYS_mmap, addr, len, prot, flags, fd, offset);
# else
long int ret = syscall (SYS_mmap, addr, len, prot, flags, fd, offset);
# endif
// @todo this is very likely Linux specific
if ((unsigned long int)ret > -4096UL)
return MAP_FAILED;
else
return (void *)ret;
#else
/* Where direct syscalls are not supported, forward to the libc call. */
return mmap (addr, len, prot, flags, fd, offset);
#endif
}
/* Provide an internal syscall version of munmap to improve signal safety. */
static ALWAYS_INLINE int
mi_munmap (void *addr, size_t len)
{
#ifdef SYS_munmap
return syscall (SYS_munmap, addr, len);
#else
return munmap (addr, len);
#endif
}
#ifndef MAP_ANONYMOUS
# define MAP_ANONYMOUS MAP_ANON
#endif
#define GET_MEMORY(mem, size) \
do { \
mem = mi_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;
#define unw_address_is_valid UNWI_ARCH_OBJ(address_is_valid)
HIDDEN bool unw_address_is_valid(unw_word_t, size_t);
#if defined(UNW_DEBUG)
# define unwi_debug_level UNWI_ARCH_OBJ(debug_level)
extern long unwi_debug_level;
# include <stdarg.h>
# include <stdio.h>
# include <unistd.h>
#define Debug(level, ...) _unw_debug(level, __FUNCTION__, __VA_ARGS__)
/**
* Send a debug message to stderr.
*
* This function may be called from within a signal handler context where
* fprintf(3) is not safe to call. The write(2) call is safe, however, and we're
* going to have to assume that snprintf(3) is signal safe otherwise it's pretty
* pointless to use Debug() calls anywhere.
*/
static inline void _unw_debug(int level, char const * const fname, char const * const fmt, ...)
{
if (unwi_debug_level >= level)
{
enum { buf_size = 512 };
char buf[buf_size];
if (level > 16) level = 16;
int bcount = snprintf (buf, buf_size, "%*c>%s: ", level, ' ', fname);
ssize_t res = write(STDERR_FILENO, buf, bcount);
va_list ap;
va_start(ap, fmt);
bcount = vsnprintf (buf, buf_size, fmt, ap);
va_end(ap);
res = write(STDERR_FILENO, buf, bcount);
(void)res; /* silence "variable set but not used" warning */
}
}
# define Dprintf(/* format */ ...) \
fprintf (stderr, /* format */ __VA_ARGS__)
#else /* defined(UNW_DEBUG) */
# define Debug(level, /* format */ ...)
# define Dprintf( /* format */ ...)
#endif /* defined(UNW_DEBUG) */
static ALWAYS_INLINE ssize_t
print_error (const char *string)
{
return write (2, string, strlen (string));
}
HIDDEN extern long unw_page_size;
static inline unw_word_t unw_page_start(unw_word_t addr)
{
return addr & ~(unw_page_size - 1);
}
#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)
mi_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 */
#define DWARF_GET_MEM_LOC(l) DWARF_GET_LOC(l)
#define DWARF_GET_REG_LOC(l) ((unw_regnum_t) DWARF_GET_LOC(l))
#include "tdep/libunwind_i.h"
#ifndef TDEP_DWARF_SP
#define TDEP_DWARF_SP UNW_TDEP_SP
#endif
#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 */
size_t reserve; /* minimum (desired) size of the free-list */
size_t 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 UNUSED, unw_accessors_t *a UNUSED,
unw_word_t *addr, int8_t *valp, void *arg UNUSED)
{
*valp = *(int8_t *) (uintptr_t) *addr;
*addr += 1;
return 0;
}
static inline int
fetch16 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED,
unw_word_t *addr, int16_t *valp, void *arg UNUSED)
{
*valp = *(int16_t *) (uintptr_t) *addr;
*addr += 2;
return 0;
}
static inline int
fetch32 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED,
unw_word_t *addr, int32_t *valp, void *arg UNUSED)
{
*valp = *(int32_t *) (uintptr_t) *addr;
*addr += 4;
return 0;
}
static inline int
fetchw (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED,
unw_word_t *addr, unw_word_t *valp, void *arg UNUSED)
{
*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 + 1), off = *addr - aligned_addr;
int ret;
*addr += 1;
ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
#if UNW_BYTE_ORDER == UNW_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 + 1), 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 UNW_BYTE_ORDER == UNW_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 + 1), 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 UNW_BYTE_ORDER == UNW_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,13 @@
// This is an incomplete & imprecice implementation
// It defers to the open source freebsd-elf implementations.
#ifndef ELF_H
#define ELF_H
#include <inttypes.h>
#include "freebsd-elf_common.h"
#include "freebsd-elf32.h"
#include "freebsd-elf64.h"
#endif // ELF_H

View File

@@ -0,0 +1,12 @@
// This is an incomplete & imprecice implementation of the
// standard file by the same name
#ifndef ENDIAN_H
#define ENDIAN_H
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif // ENDIAN_H

View File

@@ -0,0 +1,245 @@
/*-
* Copyright (c) 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.2.2.1 2008/10/02 02:57:24 kensmith Exp $
*/
#ifndef _SYS_ELF32_H_
#define _SYS_ELF32_H_ 1
#include "freebsd-elf_common.h"
/*
* ELF definitions common to all 32-bit architectures.
*/
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word;
typedef uint64_t Elf32_Lword;
typedef Elf32_Word Elf32_Hashelt;
/* Non-standard class-dependent datatype used for abstraction. */
typedef Elf32_Word Elf32_Size;
typedef Elf32_Sword Elf32_Ssize;
/*
* ELF header.
*/
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf32_Half e_type; /* File type. */
Elf32_Half e_machine; /* Machine architecture. */
Elf32_Word e_version; /* ELF format version. */
Elf32_Addr e_entry; /* Entry point. */
Elf32_Off e_phoff; /* Program header file offset. */
Elf32_Off e_shoff; /* Section header file offset. */
Elf32_Word e_flags; /* Architecture-specific flags. */
Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
Elf32_Half e_phentsize; /* Size of program header entry. */
Elf32_Half e_phnum; /* Number of program header entries. */
Elf32_Half e_shentsize; /* Size of section header entry. */
Elf32_Half e_shnum; /* Number of section header entries. */
Elf32_Half e_shstrndx; /* Section name strings section. */
} Elf32_Ehdr;
/*
* Section header.
*/
typedef struct {
Elf32_Word sh_name; /* Section name (index into the
section header string table). */
Elf32_Word sh_type; /* Section type. */
Elf32_Word sh_flags; /* Section flags. */
Elf32_Addr sh_addr; /* Address in memory image. */
Elf32_Off sh_offset; /* Offset in file. */
Elf32_Word sh_size; /* Size in bytes. */
Elf32_Word sh_link; /* Index of a related section. */
Elf32_Word sh_info; /* Depends on section type. */
Elf32_Word sh_addralign; /* Alignment in bytes. */
Elf32_Word sh_entsize; /* Size of each entry in section. */
} Elf32_Shdr;
/*
* Program header.
*/
typedef struct {
Elf32_Word p_type; /* Entry type. */
Elf32_Off p_offset; /* File offset of contents. */
Elf32_Addr p_vaddr; /* Virtual address in memory image. */
Elf32_Addr p_paddr; /* Physical address (not used). */
Elf32_Word p_filesz; /* Size of contents in file. */
Elf32_Word p_memsz; /* Size of contents in memory. */
Elf32_Word p_flags; /* Access permission flags. */
Elf32_Word p_align; /* Alignment in memory and file. */
} Elf32_Phdr;
/*
* Dynamic structure. The ".dynamic" section contains an array of them.
*/
typedef struct {
Elf32_Sword d_tag; /* Entry type. */
union {
Elf32_Word d_val; /* Integer value. */
Elf32_Addr d_ptr; /* Address value. */
} d_un;
} Elf32_Dyn;
/*
* Relocation entries.
*/
/* Relocations that don't need an addend field. */
typedef struct {
Elf32_Addr r_offset; /* Location to be relocated. */
Elf32_Word r_info; /* Relocation type and symbol index. */
} Elf32_Rel;
/* Relocations that need an addend field. */
typedef struct {
Elf32_Addr r_offset; /* Location to be relocated. */
Elf32_Word r_info; /* Relocation type and symbol index. */
Elf32_Sword r_addend; /* Addend. */
} Elf32_Rela;
/* Macros for accessing the fields of r_info. */
#define ELF32_R_SYM(info) ((info) >> 8)
#define ELF32_R_TYPE(info) ((unsigned char)(info))
/* Macro for constructing r_info from field values. */
#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
/*
* Note entry header
*/
typedef Elf_Note Elf32_Nhdr;
/*
* Move entry
*/
typedef struct {
Elf32_Lword m_value; /* symbol value */
Elf32_Word m_info; /* size + index */
Elf32_Word m_poffset; /* symbol offset */
Elf32_Half m_repeat; /* repeat count */
Elf32_Half m_stride; /* stride info */
} Elf32_Move;
/*
* The macros compose and decompose values for Move.r_info
*
* sym = ELF32_M_SYM(M.m_info)
* size = ELF32_M_SIZE(M.m_info)
* M.m_info = ELF32_M_INFO(sym, size)
*/
#define ELF32_M_SYM(info) ((info)>>8)
#define ELF32_M_SIZE(info) ((unsigned char)(info))
#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
/*
* Hardware/Software capabilities entry
*/
typedef struct {
Elf32_Word c_tag; /* how to interpret value */
union {
Elf32_Word c_val;
Elf32_Addr c_ptr;
} c_un;
} Elf32_Cap;
/*
* Symbol table entries.
*/
typedef struct {
Elf32_Word st_name; /* String table index of name. */
Elf32_Addr st_value; /* Symbol value. */
Elf32_Word st_size; /* Size of associated object. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
Elf32_Half st_shndx; /* Section index of symbol. */
} Elf32_Sym;
/* Macros for accessing the fields of st_info. */
#define ELF32_ST_BIND(info) ((info) >> 4)
#define ELF32_ST_TYPE(info) ((info) & 0xf)
/* Macro for constructing st_info from field values. */
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
/* Macro for accessing the fields of st_other. */
#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3)
/* Structures used by Sun & GNU symbol versioning. */
typedef struct
{
Elf32_Half vd_version;
Elf32_Half vd_flags;
Elf32_Half vd_ndx;
Elf32_Half vd_cnt;
Elf32_Word vd_hash;
Elf32_Word vd_aux;
Elf32_Word vd_next;
} Elf32_Verdef;
typedef struct
{
Elf32_Word vda_name;
Elf32_Word vda_next;
} Elf32_Verdaux;
typedef struct
{
Elf32_Half vn_version;
Elf32_Half vn_cnt;
Elf32_Word vn_file;
Elf32_Word vn_aux;
Elf32_Word vn_next;
} Elf32_Verneed;
typedef struct
{
Elf32_Word vna_hash;
Elf32_Half vna_flags;
Elf32_Half vna_other;
Elf32_Word vna_name;
Elf32_Word vna_next;
} Elf32_Vernaux;
typedef Elf32_Half Elf32_Versym;
typedef struct {
Elf32_Half si_boundto; /* direct bindings - symbol bound to */
Elf32_Half si_flags; /* per symbol flags */
} Elf32_Syminfo;
#endif /* !_SYS_ELF32_H_ */

View File

@@ -0,0 +1,252 @@
/*-
* Copyright (c) 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.2.2.1 2008/10/02 02:57:24 kensmith Exp $
*/
#ifndef _SYS_ELF64_H_
#define _SYS_ELF64_H_ 1
#include "freebsd-elf_common.h"
/*
* ELF definitions common to all 64-bit architectures.
*/
typedef uint64_t Elf64_Addr;
typedef uint16_t Elf64_Half;
typedef uint64_t Elf64_Off;
typedef int32_t Elf64_Sword;
typedef int64_t Elf64_Sxword;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Lword;
typedef uint64_t Elf64_Xword;
/*
* Types of dynamic symbol hash table bucket and chain elements.
*
* This is inconsistent among 64 bit architectures, so a machine dependent
* typedef is required.
*/
#ifdef __alpha__
typedef Elf64_Off Elf64_Hashelt;
#else
typedef Elf64_Word Elf64_Hashelt;
#endif
/* Non-standard class-dependent datatype used for abstraction. */
typedef Elf64_Xword Elf64_Size;
typedef Elf64_Sxword Elf64_Ssize;
/*
* ELF header.
*/
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf64_Half e_type; /* File type. */
Elf64_Half e_machine; /* Machine architecture. */
Elf64_Word e_version; /* ELF format version. */
Elf64_Addr e_entry; /* Entry point. */
Elf64_Off e_phoff; /* Program header file offset. */
Elf64_Off e_shoff; /* Section header file offset. */
Elf64_Word e_flags; /* Architecture-specific flags. */
Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
Elf64_Half e_phentsize; /* Size of program header entry. */
Elf64_Half e_phnum; /* Number of program header entries. */
Elf64_Half e_shentsize; /* Size of section header entry. */
Elf64_Half e_shnum; /* Number of section header entries. */
Elf64_Half e_shstrndx; /* Section name strings section. */
} Elf64_Ehdr;
/*
* Section header.
*/
typedef struct {
Elf64_Word sh_name; /* Section name (index into the
section header string table). */
Elf64_Word sh_type; /* Section type. */
Elf64_Xword sh_flags; /* Section flags. */
Elf64_Addr sh_addr; /* Address in memory image. */
Elf64_Off sh_offset; /* Offset in file. */
Elf64_Xword sh_size; /* Size in bytes. */
Elf64_Word sh_link; /* Index of a related section. */
Elf64_Word sh_info; /* Depends on section type. */
Elf64_Xword sh_addralign; /* Alignment in bytes. */
Elf64_Xword sh_entsize; /* Size of each entry in section. */
} Elf64_Shdr;
/*
* Program header.
*/
typedef struct {
Elf64_Word p_type; /* Entry type. */
Elf64_Word p_flags; /* Access permission flags. */
Elf64_Off p_offset; /* File offset of contents. */
Elf64_Addr p_vaddr; /* Virtual address in memory image. */
Elf64_Addr p_paddr; /* Physical address (not used). */
Elf64_Xword p_filesz; /* Size of contents in file. */
Elf64_Xword p_memsz; /* Size of contents in memory. */
Elf64_Xword p_align; /* Alignment in memory and file. */
} Elf64_Phdr;
/*
* Dynamic structure. The ".dynamic" section contains an array of them.
*/
typedef struct {
Elf64_Sxword d_tag; /* Entry type. */
union {
Elf64_Xword d_val; /* Integer value. */
Elf64_Addr d_ptr; /* Address value. */
} d_un;
} Elf64_Dyn;
/*
* Relocation entries.
*/
/* Relocations that don't need an addend field. */
typedef struct {
Elf64_Addr r_offset; /* Location to be relocated. */
Elf64_Xword r_info; /* Relocation type and symbol index. */
} Elf64_Rel;
/* Relocations that need an addend field. */
typedef struct {
Elf64_Addr r_offset; /* Location to be relocated. */
Elf64_Xword r_info; /* Relocation type and symbol index. */
Elf64_Sxword r_addend; /* Addend. */
} Elf64_Rela;
/* Macros for accessing the fields of r_info. */
#define ELF64_R_SYM(info) ((info) >> 32)
#define ELF64_R_TYPE(info) ((info) & 0xffffffffL)
/* Macro for constructing r_info from field values. */
#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL))
#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40)
#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56)
#define ELF64_R_TYPE_INFO(data, type) \
(((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type))
/*
* Note entry header
*/
typedef Elf_Note Elf64_Nhdr;
/*
* Move entry
*/
typedef struct {
Elf64_Lword m_value; /* symbol value */
Elf64_Xword m_info; /* size + index */
Elf64_Xword m_poffset; /* symbol offset */
Elf64_Half m_repeat; /* repeat count */
Elf64_Half m_stride; /* stride info */
} Elf64_Move;
#define ELF64_M_SYM(info) ((info)>>8)
#define ELF64_M_SIZE(info) ((unsigned char)(info))
#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
/*
* Hardware/Software capabilities entry
*/
typedef struct {
Elf64_Xword c_tag; /* how to interpret value */
union {
Elf64_Xword c_val;
Elf64_Addr c_ptr;
} c_un;
} Elf64_Cap;
/*
* Symbol table entries.
*/
typedef struct {
Elf64_Word st_name; /* String table index of name. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
Elf64_Half st_shndx; /* Section index of symbol. */
Elf64_Addr st_value; /* Symbol value. */
Elf64_Xword st_size; /* Size of associated object. */
} Elf64_Sym;
/* Macros for accessing the fields of st_info. */
#define ELF64_ST_BIND(info) ((info) >> 4)
#define ELF64_ST_TYPE(info) ((info) & 0xf)
/* Macro for constructing st_info from field values. */
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
/* Macro for accessing the fields of st_other. */
#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3)
/* Structures used by Sun & GNU-style symbol versioning. */
typedef struct {
Elf64_Half vd_version;
Elf64_Half vd_flags;
Elf64_Half vd_ndx;
Elf64_Half vd_cnt;
Elf64_Word vd_hash;
Elf64_Word vd_aux;
Elf64_Word vd_next;
} Elf64_Verdef;
typedef struct {
Elf64_Word vda_name;
Elf64_Word vda_next;
} Elf64_Verdaux;
typedef struct {
Elf64_Half vn_version;
Elf64_Half vn_cnt;
Elf64_Word vn_file;
Elf64_Word vn_aux;
Elf64_Word vn_next;
} Elf64_Verneed;
typedef struct {
Elf64_Word vna_hash;
Elf64_Half vna_flags;
Elf64_Half vna_other;
Elf64_Word vna_name;
Elf64_Word vna_next;
} Elf64_Vernaux;
typedef Elf64_Half Elf64_Versym;
typedef struct {
Elf64_Half si_boundto; /* direct bindings - symbol bound to */
Elf64_Half si_flags; /* per symbol flags */
} Elf64_Syminfo;
#endif /* !_SYS_ELF64_H_ */

View File

@@ -0,0 +1,866 @@
/*-
* Copyright (c) 1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/sys/elf_common.h,v 1.24 2008/08/02 01:20:10 imp Exp $
*/
#ifndef _SYS_ELF_COMMON_H_
#define _SYS_ELF_COMMON_H_ 1
/*
* ELF definitions that are independent of architecture or word size.
*/
/*
* Note header. The ".note" section contains an array of notes. Each
* begins with this header, aligned to a word boundary. Immediately
* following the note header is n_namesz bytes of name, padded to the
* next word boundary. Then comes n_descsz bytes of descriptor, again
* padded to a word boundary. The values of n_namesz and n_descsz do
* not include the padding.
*/
typedef struct {
uint32_t n_namesz; /* Length of name. */
uint32_t n_descsz; /* Length of descriptor. */
uint32_t n_type; /* Type of this note. */
} Elf_Note;
/* Indexes into the e_ident array. Keep synced with
http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
#define EI_MAG0 0 /* Magic number, byte 0. */
#define EI_MAG1 1 /* Magic number, byte 1. */
#define EI_MAG2 2 /* Magic number, byte 2. */
#define EI_MAG3 3 /* Magic number, byte 3. */
#define EI_CLASS 4 /* Class of machine. */
#define EI_DATA 5 /* Data format. */
#define EI_VERSION 6 /* ELF format version. */
#define EI_OSABI 7 /* Operating system / ABI identification */
#define EI_ABIVERSION 8 /* ABI version */
#define OLD_EI_BRAND 8 /* Start of architecture identification. */
#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */
#define EI_NIDENT 16 /* Size of e_ident array. */
/* Values for the magic number bytes. */
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define ELFMAG "\177ELF" /* magic string */
#define SELFMAG 4 /* magic string size */
/* Values for e_ident[EI_VERSION] and e_version. */
#define EV_NONE 0
#define EV_CURRENT 1
/* Values for e_ident[EI_CLASS]. */
#define ELFCLASSNONE 0 /* Unknown class. */
#define ELFCLASS32 1 /* 32-bit architecture. */
#define ELFCLASS64 2 /* 64-bit architecture. */
/* Values for e_ident[EI_DATA]. */
#define ELFDATANONE 0 /* Unknown data format. */
#define ELFDATA2LSB 1 /* 2's complement little-endian. */
#define ELFDATA2MSB 2 /* 2's complement big-endian. */
/* Values for e_ident[EI_OSABI]. */
#define ELFOSABI_NONE 0 /* UNIX System V ABI */
#define ELFOSABI_HPUX 1 /* HP-UX operating system */
#define ELFOSABI_NETBSD 2 /* NetBSD */
#define ELFOSABI_LINUX 3 /* GNU/Linux */
#define ELFOSABI_HURD 4 /* GNU/Hurd */
#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
#define ELFOSABI_SOLARIS 6 /* Solaris */
#define ELFOSABI_AIX 7 /* AIX */
#define ELFOSABI_IRIX 8 /* IRIX */
#define ELFOSABI_FREEBSD 9 /* FreeBSD */
#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
#define ELFOSABI_MODESTO 11 /* Novell Modesto */
#define ELFOSABI_OPENBSD 12 /* OpenBSD */
#define ELFOSABI_OPENVMS 13 /* Open VMS */
#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */
/* e_ident */
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
(ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
(ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
(ehdr).e_ident[EI_MAG3] == ELFMAG3)
/* Values for e_type. */
#define ET_NONE 0 /* Unknown type. */
#define ET_REL 1 /* Relocatable. */
#define ET_EXEC 2 /* Executable. */
#define ET_DYN 3 /* Shared object. */
#define ET_CORE 4 /* Core file. */
#define ET_LOOS 0xfe00 /* First operating system specific. */
#define ET_HIOS 0xfeff /* Last operating system-specific. */
#define ET_LOPROC 0xff00 /* First processor-specific. */
#define ET_HIPROC 0xffff /* Last processor-specific. */
/* Values for e_machine. */
#define EM_NONE 0 /* Unknown machine. */
#define EM_M32 1 /* AT&T WE32100. */
#define EM_SPARC 2 /* Sun SPARC. */
#define EM_386 3 /* Intel i386. */
#define EM_68K 4 /* Motorola 68000. */
#define EM_88K 5 /* Motorola 88000. */
#define EM_860 7 /* Intel i860. */
#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */
#define EM_S370 9 /* IBM System/370. */
#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */
#define EM_PARISC 15 /* HP PA-RISC. */
#define EM_VPP500 17 /* Fujitsu VPP500. */
#define EM_SPARC32PLUS 18 /* SPARC v8plus. */
#define EM_960 19 /* Intel 80960. */
#define EM_PPC 20 /* PowerPC 32-bit. */
#define EM_PPC64 21 /* PowerPC 64-bit. */
#define EM_S390 22 /* IBM System/390. */
#define EM_V800 36 /* NEC V800. */
#define EM_FR20 37 /* Fujitsu FR20. */
#define EM_RH32 38 /* TRW RH-32. */
#define EM_RCE 39 /* Motorola RCE. */
#define EM_ARM 40 /* ARM. */
#define EM_SH 42 /* Hitachi SH. */
#define EM_SPARCV9 43 /* SPARC v9 64-bit. */
#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */
#define EM_ARC 45 /* Argonaut RISC Core. */
#define EM_H8_300 46 /* Hitachi H8/300. */
#define EM_H8_300H 47 /* Hitachi H8/300H. */
#define EM_H8S 48 /* Hitachi H8S. */
#define EM_H8_500 49 /* Hitachi H8/500. */
#define EM_IA_64 50 /* Intel IA-64 Processor. */
#define EM_MIPS_X 51 /* Stanford MIPS-X. */
#define EM_COLDFIRE 52 /* Motorola ColdFire. */
#define EM_68HC12 53 /* Motorola M68HC12. */
#define EM_MMA 54 /* Fujitsu MMA. */
#define EM_PCP 55 /* Siemens PCP. */
#define EM_NCPU 56 /* Sony nCPU. */
#define EM_NDR1 57 /* Denso NDR1 microprocessor. */
#define EM_STARCORE 58 /* Motorola Star*Core processor. */
#define EM_ME16 59 /* Toyota ME16 processor. */
#define EM_ST100 60 /* STMicroelectronics ST100 processor. */
#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */
#define EM_RISCV 243 /* RISC-V. */
/* Non-standard or deprecated. */
#define EM_486 6 /* Intel i486. */
#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */
#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */
/* Special section indexes. */
#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */
#define SHN_LORESERVE 0xff00 /* First of reserved range. */
#define SHN_LOPROC 0xff00 /* First processor-specific. */
#define SHN_HIPROC 0xff1f /* Last processor-specific. */
#define SHN_LOOS 0xff20 /* First operating system-specific. */
#define SHN_HIOS 0xff3f /* Last operating system-specific. */
#define SHN_ABS 0xfff1 /* Absolute values. */
#define SHN_COMMON 0xfff2 /* Common data. */
#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */
#define SHN_HIRESERVE 0xffff /* Last of reserved range. */
/* sh_type */
#define SHT_NULL 0 /* inactive */
#define SHT_PROGBITS 1 /* program defined information */
#define SHT_SYMTAB 2 /* symbol table section */
#define SHT_STRTAB 3 /* string table section */
#define SHT_RELA 4 /* relocation section with addends */
#define SHT_HASH 5 /* symbol hash table section */
#define SHT_DYNAMIC 6 /* dynamic section */
#define SHT_NOTE 7 /* note section */
#define SHT_NOBITS 8 /* no space section */
#define SHT_REL 9 /* relocation section - no addends */
#define SHT_SHLIB 10 /* reserved - purpose unknown */
#define SHT_DYNSYM 11 /* dynamic symbol table section */
#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */
#define SHT_FINI_ARRAY 15 /* Termination function pointers. */
#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */
#define SHT_GROUP 17 /* Section group. */
#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
#define SHT_LOSUNW 0x6ffffff4
#define SHT_SUNW_dof 0x6ffffff4
#define SHT_SUNW_cap 0x6ffffff5
#define SHT_SUNW_SIGNATURE 0x6ffffff6
#define SHT_SUNW_ANNOTATE 0x6ffffff7
#define SHT_SUNW_DEBUGSTR 0x6ffffff8
#define SHT_SUNW_DEBUG 0x6ffffff9
#define SHT_SUNW_move 0x6ffffffa
#define SHT_SUNW_COMDAT 0x6ffffffb
#define SHT_SUNW_syminfo 0x6ffffffc
#define SHT_SUNW_verdef 0x6ffffffd
#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */
#define SHT_SUNW_verneed 0x6ffffffe
#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */
#define SHT_SUNW_versym 0x6fffffff
#define SHT_GNU_versym 0x6fffffff /* Symbol version table */
#define SHT_HISUNW 0x6fffffff
#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */
#define SHT_HIPROC 0x7fffffff /* specific section header types */
#define SHT_LOUSER 0x80000000 /* reserved range for application */
#define SHT_HIUSER 0xffffffff /* specific indexes */
/* Flags for sh_flags. */
#define SHF_WRITE 0x1 /* Section contains writable data. */
#define SHF_ALLOC 0x2 /* Section occupies memory. */
#define SHF_EXECINSTR 0x4 /* Section contains instructions. */
#define SHF_MERGE 0x10 /* Section may be merged. */
#define SHF_STRINGS 0x20 /* Section contains strings. */
#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */
#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */
#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */
#define SHF_GROUP 0x200 /* Member of section group. */
#define SHF_TLS 0x400 /* Section contains TLS data. */
#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */
#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */
/* Values for p_type. */
#define PT_NULL 0 /* Unused entry. */
#define PT_LOAD 1 /* Loadable segment. */
#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
#define PT_INTERP 3 /* Pathname of interpreter. */
#define PT_NOTE 4 /* Auxiliary information. */
#define PT_SHLIB 5 /* Reserved (not used). */
#define PT_PHDR 6 /* Location of program header itself. */
#define PT_TLS 7 /* Thread local storage segment */
#define PT_LOOS 0x60000000 /* First OS-specific. */
#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */
#define PT_GNU_EH_FRAME 0x6474e550
#define PT_GNU_STACK 0x6474e551
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */
#define PT_SUNWDTRACE 0x6ffffffc /* private */
#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */
#define PT_HISUNW 0x6fffffff
#define PT_HIOS 0x6fffffff /* Last OS-specific. */
#define PT_LOPROC 0x70000000 /* First processor-specific type. */
#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
/* Values for p_flags. */
#define PF_X 0x1 /* Executable. */
#define PF_W 0x2 /* Writable. */
#define PF_R 0x4 /* Readable. */
#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */
#define PF_MASKPROC 0xf0000000 /* Processor-specific. */
/* Extended program header index. */
#define PN_XNUM 0xffff
/* Values for d_tag. */
#define DT_NULL 0 /* Terminating entry. */
#define DT_NEEDED 1 /* String table offset of a needed shared
library. */
#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
#define DT_PLTGOT 3 /* Processor-dependent address. */
#define DT_HASH 4 /* Address of symbol hash table. */
#define DT_STRTAB 5 /* Address of string table. */
#define DT_SYMTAB 6 /* Address of symbol table. */
#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
#define DT_STRSZ 10 /* Size of string table. */
#define DT_SYMENT 11 /* Size of each symbol table entry. */
#define DT_INIT 12 /* Address of initialization function. */
#define DT_FINI 13 /* Address of finalization function. */
#define DT_SONAME 14 /* String table offset of shared object
name. */
#define DT_RPATH 15 /* String table offset of library path. [sup] */
#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */
#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */
#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
#define DT_PLTREL 20 /* Type of relocation used for PLT. */
#define DT_DEBUG 21 /* Reserved (not used). */
#define DT_TEXTREL 22 /* Indicates there may be relocations in
non-writable segments. [sup] */
#define DT_JMPREL 23 /* Address of PLT relocations. */
#define DT_BIND_NOW 24 /* [sup] */
#define DT_INIT_ARRAY 25 /* Address of the array of pointers to
initialization functions */
#define DT_FINI_ARRAY 26 /* Address of the array of pointers to
termination functions */
#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of
initialization functions. */
#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of
terminationfunctions. */
#define DT_RUNPATH 29 /* String table offset of a null-terminated
library search path string. */
#define DT_FLAGS 30 /* Object specific flag values. */
#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING
and less than DT_LOOS follow the rules for
the interpretation of the d_un union
as follows: even == 'd_ptr', even == 'd_val'
or none */
#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to
pre-initialization functions. */
#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of
pre-initialization functions. */
#define DT_MAXPOSTAGS 34 /* number of positive tags */
#define DT_LOOS 0x6000000d /* First OS-specific */
#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */
#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */
#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */
#define DT_SUNW_CAP 0x60000010 /* hardware/software */
#define DT_HIOS 0x6ffff000 /* Last OS-specific */
/*
* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
* Dyn.d_un.d_val field of the Elf*_Dyn structure.
*/
#define DT_VALRNGLO 0x6ffffd00
#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */
#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */
#define DT_MOVEENT 0x6ffffdfa /* move table entry size */
#define DT_MOVESZ 0x6ffffdfb /* move table size */
#define DT_FEATURE_1 0x6ffffdfc /* feature holder */
#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */
/* the following DT_* entry. */
/* See DF_P1_* definitions */
#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */
#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */
#define DT_VALRNGHI 0x6ffffdff
/*
* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
* Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
*
* If any adjustment is made to the ELF object after it has been
* built, these entries will need to be adjusted.
*/
#define DT_ADDRRNGLO 0x6ffffe00
#define DT_CONFIG 0x6ffffefa /* configuration information */
#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */
#define DT_AUDIT 0x6ffffefc /* object auditing */
#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */
#define DT_MOVETAB 0x6ffffefe /* move table */
#define DT_SYMINFO 0x6ffffeff /* syminfo table */
#define DT_ADDRRNGHI 0x6ffffeff
#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */
#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */
#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */
#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */
#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */
#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */
#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */
#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */
#define DT_LOPROC 0x70000000 /* First processor-specific type. */
#define DT_DEPRECATED_SPARC_REGISTER 0x7000001
#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */
#define DT_USED 0x7ffffffe /* ignored - same as needed */
#define DT_FILTER 0x7fffffff /* shared library filter name */
#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */
/* Values for DT_FLAGS */
#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may
make reference to the $ORIGIN substitution
string */
#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */
#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in
non-writable segments. */
#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should
process all relocations for the object
containing this entry before transferring
control to the program. */
#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or
executable contains code using a static
thread-local storage scheme. */
/* Values for n_type. Used in core files. */
#define NT_PRSTATUS 1 /* Process status. */
#define NT_FPREGSET 2 /* Floating point registers. */
#define NT_PRPSINFO 3 /* Process state info. */
/* Symbol Binding - ELFNN_ST_BIND - st_info */
#define STB_LOCAL 0 /* Local symbol */
#define STB_GLOBAL 1 /* Global symbol */
#define STB_WEAK 2 /* like global - lower precedence */
#define STB_LOOS 10 /* Reserved range for operating system */
#define STB_HIOS 12 /* specific semantics. */
#define STB_LOPROC 13 /* reserved range for processor */
#define STB_HIPROC 15 /* specific semantics. */
/* Symbol type - ELFNN_ST_TYPE - st_info */
#define STT_NOTYPE 0 /* Unspecified type. */
#define STT_OBJECT 1 /* Data object. */
#define STT_FUNC 2 /* Function. */
#define STT_SECTION 3 /* Section. */
#define STT_FILE 4 /* Source file. */
#define STT_COMMON 5 /* Uninitialized common block. */
#define STT_TLS 6 /* TLS object. */
#define STT_NUM 7
#define STT_LOOS 10 /* Reserved range for operating system */
#define STT_HIOS 12 /* specific semantics. */
#define STT_LOPROC 13 /* reserved range for processor */
#define STT_HIPROC 15 /* specific semantics. */
/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */
#define STV_DEFAULT 0x0 /* Default visibility (see binding). */
#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */
#define STV_HIDDEN 0x2 /* Not visible. */
#define STV_PROTECTED 0x3 /* Visible but not preemptible. */
#define STV_EXPORTED 0x4
#define STV_SINGLETON 0x5
#define STV_ELIMINATE 0x6
/* Special symbol table indexes. */
#define STN_UNDEF 0 /* Undefined symbol index. */
/* Symbol versioning flags. */
#define VER_DEF_CURRENT 1
#define VER_DEF_IDX(x) VER_NDX(x)
#define VER_FLG_BASE 0x01
#define VER_FLG_WEAK 0x02
#define VER_NEED_CURRENT 1
#define VER_NEED_WEAK (1u << 15)
#define VER_NEED_HIDDEN VER_NDX_HIDDEN
#define VER_NEED_IDX(x) VER_NDX(x)
#define VER_NDX_LOCAL 0
#define VER_NDX_GLOBAL 1
#define VER_NDX_GIVEN 2
#define VER_NDX_HIDDEN (1u << 15)
#define VER_NDX(x) ((x) & ~(1u << 15))
#define CA_SUNW_NULL 0
#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */
#define CA_SUNW_SF_1 2 /* first software capabilities entry */
/*
* Syminfo flag values
*/
#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */
/* to object containing defn. */
#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */
#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */
#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */
/* lazily-loaded */
#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */
/* object containing defn. */
#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */
/* directly bind to this symbol */
#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */
#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */
/*
* Syminfo.si_boundto values.
*/
#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */
#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */
#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */
#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */
#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */
/*
* Syminfo version values.
*/
#define SYMINFO_NONE 0 /* Syminfo version */
#define SYMINFO_CURRENT 1
#define SYMINFO_NUM 2
/*
* Relocation types.
*
* All machine architectures are defined here to allow tools on one to
* handle others.
*/
#define R_386_NONE 0 /* No relocation. */
#define R_386_32 1 /* Add symbol value. */
#define R_386_PC32 2 /* Add PC-relative symbol value. */
#define R_386_GOT32 3 /* Add PC-relative GOT offset. */
#define R_386_PLT32 4 /* Add PC-relative PLT offset. */
#define R_386_COPY 5 /* Copy data from shared object. */
#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */
#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */
#define R_386_RELATIVE 8 /* Add load address of shared object. */
#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */
#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */
#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */
#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */
#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */
#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */
#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */
#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */
#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */
#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */
#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */
#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */
#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */
#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */
#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */
#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */
#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */
#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */
#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */
#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */
#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */
#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
#define R_ARM_NONE 0 /* No relocation. */
#define R_ARM_PC24 1
#define R_ARM_ABS32 2
#define R_ARM_REL32 3
#define R_ARM_PC13 4
#define R_ARM_ABS16 5
#define R_ARM_ABS12 6
#define R_ARM_THM_ABS5 7
#define R_ARM_ABS8 8
#define R_ARM_SBREL32 9
#define R_ARM_THM_PC22 10
#define R_ARM_THM_PC8 11
#define R_ARM_AMP_VCALL9 12
#define R_ARM_SWI24 13
#define R_ARM_THM_SWI8 14
#define R_ARM_XPC25 15
#define R_ARM_THM_XPC22 16
#define R_ARM_COPY 20 /* Copy data from shared object. */
#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */
#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */
#define R_ARM_RELATIVE 23 /* Add load address of shared object. */
#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */
#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */
#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */
#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_RSBREL32 250
#define R_ARM_THM_RPC22 251
#define R_ARM_RREL32 252
#define R_ARM_RABS32 253
#define R_ARM_RPC24 254
#define R_ARM_RBASE 255
/* Name Value Field Calculation */
#define R_IA_64_NONE 0 /* None */
#define R_IA_64_IMM14 0x21 /* immediate14 S + A */
#define R_IA_64_IMM22 0x22 /* immediate22 S + A */
#define R_IA_64_IMM64 0x23 /* immediate64 S + A */
#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */
#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */
#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */
#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */
#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */
#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */
#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */
#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */
#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */
#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */
#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */
#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */
#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */
#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */
#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */
#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */
#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */
#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */
#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */
#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */
#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */
#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */
#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */
#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */
#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */
#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */
#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */
#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */
#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */
#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */
#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */
#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */
#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */
#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */
#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */
#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */
#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */
#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */
#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */
#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */
#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */
#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */
#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */
#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */
#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */
#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */
#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */
#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */
#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */
#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */
#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */
#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */
#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */
#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */
#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */
#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB special */
#define R_IA_64_SUB 0x85 /* immediate64 A - S */
#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */
#define R_IA_64_LDXMOV 0x87 /* immediate22 special */
#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */
#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */
#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */
#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */
#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */
#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */
#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */
#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */
#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */
#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */
#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */
#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */
#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */
#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */
#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */
#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */
#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */
#define R_MIPS_NONE 0 /* No reloc */
#define R_MIPS_16 1 /* Direct 16 bit */
#define R_MIPS_32 2 /* Direct 32 bit */
#define R_MIPS_REL32 3 /* PC relative 32 bit */
#define R_MIPS_26 4 /* Direct 26 bit shifted */
#define R_MIPS_HI16 5 /* High 16 bit */
#define R_MIPS_LO16 6 /* Low 16 bit */
#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
#define R_MIPS_PC16 10 /* PC relative 16 bit */
#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */
#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */
#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */
#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */
#define R_PPC_NONE 0 /* No relocation. */
#define R_PPC_ADDR32 1
#define R_PPC_ADDR24 2
#define R_PPC_ADDR16 3
#define R_PPC_ADDR16_LO 4
#define R_PPC_ADDR16_HI 5
#define R_PPC_ADDR16_HA 6
#define R_PPC_ADDR14 7
#define R_PPC_ADDR14_BRTAKEN 8
#define R_PPC_ADDR14_BRNTAKEN 9
#define R_PPC_REL24 10
#define R_PPC_REL14 11
#define R_PPC_REL14_BRTAKEN 12
#define R_PPC_REL14_BRNTAKEN 13
#define R_PPC_GOT16 14
#define R_PPC_GOT16_LO 15
#define R_PPC_GOT16_HI 16
#define R_PPC_GOT16_HA 17
#define R_PPC_PLTREL24 18
#define R_PPC_COPY 19
#define R_PPC_GLOB_DAT 20
#define R_PPC_JMP_SLOT 21
#define R_PPC_RELATIVE 22
#define R_PPC_LOCAL24PC 23
#define R_PPC_UADDR32 24
#define R_PPC_UADDR16 25
#define R_PPC_REL32 26
#define R_PPC_PLT32 27
#define R_PPC_PLTREL32 28
#define R_PPC_PLT16_LO 29
#define R_PPC_PLT16_HI 30
#define R_PPC_PLT16_HA 31
#define R_PPC_SDAREL16 32
#define R_PPC_SECTOFF 33
#define R_PPC_SECTOFF_LO 34
#define R_PPC_SECTOFF_HI 35
#define R_PPC_SECTOFF_HA 36
/*
* TLS relocations
*/
#define R_PPC_TLS 67
#define R_PPC_DTPMOD32 68
#define R_PPC_TPREL16 69
#define R_PPC_TPREL16_LO 70
#define R_PPC_TPREL16_HI 71
#define R_PPC_TPREL16_HA 72
#define R_PPC_TPREL32 73
#define R_PPC_DTPREL16 74
#define R_PPC_DTPREL16_LO 75
#define R_PPC_DTPREL16_HI 76
#define R_PPC_DTPREL16_HA 77
#define R_PPC_DTPREL32 78
#define R_PPC_GOT_TLSGD16 79
#define R_PPC_GOT_TLSGD16_LO 80
#define R_PPC_GOT_TLSGD16_HI 81
#define R_PPC_GOT_TLSGD16_HA 82
#define R_PPC_GOT_TLSLD16 83
#define R_PPC_GOT_TLSLD16_LO 84
#define R_PPC_GOT_TLSLD16_HI 85
#define R_PPC_GOT_TLSLD16_HA 86
#define R_PPC_GOT_TPREL16 87
#define R_PPC_GOT_TPREL16_LO 88
#define R_PPC_GOT_TPREL16_HI 89
#define R_PPC_GOT_TPREL16_HA 90
/*
* The remaining relocs are from the Embedded ELF ABI, and are not in the
* SVR4 ELF ABI.
*/
#define R_PPC_EMB_NADDR32 101
#define R_PPC_EMB_NADDR16 102
#define R_PPC_EMB_NADDR16_LO 103
#define R_PPC_EMB_NADDR16_HI 104
#define R_PPC_EMB_NADDR16_HA 105
#define R_PPC_EMB_SDAI16 106
#define R_PPC_EMB_SDA2I16 107
#define R_PPC_EMB_SDA2REL 108
#define R_PPC_EMB_SDA21 109
#define R_PPC_EMB_MRKREF 110
#define R_PPC_EMB_RELSEC16 111
#define R_PPC_EMB_RELST_LO 112
#define R_PPC_EMB_RELST_HI 113
#define R_PPC_EMB_RELST_HA 114
#define R_PPC_EMB_BIT_FLD 115
#define R_PPC_EMB_RELSDA 116
#define R_SPARC_NONE 0
#define R_SPARC_8 1
#define R_SPARC_16 2
#define R_SPARC_32 3
#define R_SPARC_DISP8 4
#define R_SPARC_DISP16 5
#define R_SPARC_DISP32 6
#define R_SPARC_WDISP30 7
#define R_SPARC_WDISP22 8
#define R_SPARC_HI22 9
#define R_SPARC_22 10
#define R_SPARC_13 11
#define R_SPARC_LO10 12
#define R_SPARC_GOT10 13
#define R_SPARC_GOT13 14
#define R_SPARC_GOT22 15
#define R_SPARC_PC10 16
#define R_SPARC_PC22 17
#define R_SPARC_WPLT30 18
#define R_SPARC_COPY 19
#define R_SPARC_GLOB_DAT 20
#define R_SPARC_JMP_SLOT 21
#define R_SPARC_RELATIVE 22
#define R_SPARC_UA32 23
#define R_SPARC_PLT32 24
#define R_SPARC_HIPLT22 25
#define R_SPARC_LOPLT10 26
#define R_SPARC_PCPLT32 27
#define R_SPARC_PCPLT22 28
#define R_SPARC_PCPLT10 29
#define R_SPARC_10 30
#define R_SPARC_11 31
#define R_SPARC_64 32
#define R_SPARC_OLO10 33
#define R_SPARC_HH22 34
#define R_SPARC_HM10 35
#define R_SPARC_LM22 36
#define R_SPARC_PC_HH22 37
#define R_SPARC_PC_HM10 38
#define R_SPARC_PC_LM22 39
#define R_SPARC_WDISP16 40
#define R_SPARC_WDISP19 41
#define R_SPARC_GLOB_JMP 42
#define R_SPARC_7 43
#define R_SPARC_5 44
#define R_SPARC_6 45
#define R_SPARC_DISP64 46
#define R_SPARC_PLT64 47
#define R_SPARC_HIX22 48
#define R_SPARC_LOX10 49
#define R_SPARC_H44 50
#define R_SPARC_M44 51
#define R_SPARC_L44 52
#define R_SPARC_REGISTER 53
#define R_SPARC_UA64 54
#define R_SPARC_UA16 55
#define R_SPARC_TLS_GD_HI22 56
#define R_SPARC_TLS_GD_LO10 57
#define R_SPARC_TLS_GD_ADD 58
#define R_SPARC_TLS_GD_CALL 59
#define R_SPARC_TLS_LDM_HI22 60
#define R_SPARC_TLS_LDM_LO10 61
#define R_SPARC_TLS_LDM_ADD 62
#define R_SPARC_TLS_LDM_CALL 63
#define R_SPARC_TLS_LDO_HIX22 64
#define R_SPARC_TLS_LDO_LOX10 65
#define R_SPARC_TLS_LDO_ADD 66
#define R_SPARC_TLS_IE_HI22 67
#define R_SPARC_TLS_IE_LO10 68
#define R_SPARC_TLS_IE_LD 69
#define R_SPARC_TLS_IE_LDX 70
#define R_SPARC_TLS_IE_ADD 71
#define R_SPARC_TLS_LE_HIX22 72
#define R_SPARC_TLS_LE_LOX10 73
#define R_SPARC_TLS_DTPMOD32 74
#define R_SPARC_TLS_DTPMOD64 75
#define R_SPARC_TLS_DTPOFF32 76
#define R_SPARC_TLS_DTPOFF64 77
#define R_SPARC_TLS_TPOFF32 78
#define R_SPARC_TLS_TPOFF64 79
#define R_X86_64_NONE 0 /* No relocation. */
#define R_X86_64_64 1 /* Add 64 bit symbol value. */
#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */
#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */
#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */
#define R_X86_64_COPY 5 /* Copy data from shared object. */
#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */
#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */
#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */
#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */
#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */
#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */
#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */
#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */
#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */
#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */
#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */
#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */
#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */
#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */
#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */
#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */
#endif /* !_SYS_ELF_COMMON_H_ */

View File

@@ -0,0 +1,47 @@
/* Copyright (C) 2022 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 UC_MCONTEXT_GREGS_R8 0x28
#define UC_MCONTEXT_GREGS_R9 0x30
#define UC_MCONTEXT_GREGS_R10 0x38
#define UC_MCONTEXT_GREGS_R11 0x40
#define UC_MCONTEXT_GREGS_R12 0x48
#define UC_MCONTEXT_GREGS_R13 0x50
#define UC_MCONTEXT_GREGS_R14 0x58
#define UC_MCONTEXT_GREGS_R15 0x60
#define UC_MCONTEXT_GREGS_RDI 0x68
#define UC_MCONTEXT_GREGS_RSI 0x70
#define UC_MCONTEXT_GREGS_RBP 0x78
#define UC_MCONTEXT_GREGS_RBX 0x80
#define UC_MCONTEXT_GREGS_RDX 0x88
#define UC_MCONTEXT_GREGS_RAX 0x90
#define UC_MCONTEXT_GREGS_RCX 0x98
#define UC_MCONTEXT_GREGS_RSP 0xa0
#define UC_MCONTEXT_GREGS_RIP 0xa8
#define UC_MCONTEXT_FPREGS_PTR 0x1a8
#define UC_MCONTEXT_FPREGS_MEM 0xe0
#define UC_SIGMASK 0x128
#define FPREGS_OFFSET_MXCSR 0x18
#include <sys/ucontext.h>

View File

@@ -0,0 +1,9 @@
// This is a fake implementation of stdalign.h for when
// compiler C11 stdaliagn.h support is missing
#ifndef FAKE_STD_ALIGN_H
#define FAKE_STD_ALIGN_H
#define alignas(x)
#endif // FAKE_STD_ALIGN_H

View File

@@ -0,0 +1,36 @@
// This is a non-atomic fake implementation of stdatomic.h for when
// compiler C11 stdatomic support is missing and only single threaded
// operation is required
#ifndef FAKE_STD_ATOMICS_H
#define FAKE_STD_ATOMICS_H
#include <inttypes.h>
#define _Atomic volatile
#define ATOMIC_FLAG_INIT 0
typedef uint8_t atomic_bool;
typedef uint8_t atomic_flag;
#define atomic_compare_and_exchange_strong(x, y, z) return ((*(x) == *(y)) ? ((*(x) = z), true) : ((*(y) = *(x)),false))
#define atomic_fetch_add(x, y) *(x) += (y), (*(x) - (y))
static inline void atomic_flag_clear(volatile atomic_flag* flag)
{
*flag = ATOMIC_FLAG_INIT;
}
static inline atomic_bool atomic_flag_test_and_set( volatile atomic_flag* flag )
{
atomic_bool result = *flag;
*flag = 1;
return result;
}
#define atomic_load(x) (*(x))
#define atomic_store(x, y) do { *(x) = (y); } while (0)
#endif // FAKE_STD_ATOMICS_H

View File

@@ -0,0 +1,30 @@
// This is an incomplete & imprecice implementation of the Posix
// standard file by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
// #include <sched.h>
#include <sys/types.h>
#define PTHREAD_DESTRUCTOR_ITERATIONS 0
#define PTHREAD_MUTEX_INITIALIZER 0
#define PTHREAD_ONCE_INIT 0
typedef long pthread_key_t;
typedef long pthread_mutex_t;
typedef long pthread_mutexattr_t;
typedef long pthread_once_t;
int pthread_key_create(pthread_key_t *, void (*)(void*));
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_lock(pthread_mutex_t *);
int pthread_mutex_unlock(pthread_mutex_t *);
int pthread_once(pthread_once_t *, void (*)(void));
int pthread_setspecific(pthread_key_t, const void *);
#endif // _MSC_VER

View File

@@ -0,0 +1,40 @@
// This is an incomplete & imprecice implementation of the Posix
// standard file by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
// Posix is a superset of the ISO C signal.h
// include ISO C version first
#include <../ucrt/signal.h>
#include <sys/types.h>
#include <sys/ucontext.h>
#if defined(__linux__) && defined(__x86_64__)
# define SIZEOF_SIGINFO 128
#elif defined(__linux__) && defined(__aarch64__)
# define SIZEOF_SIGINFO 128
#elif defined(__linux__) && defined(__arm__)
# define SIZEOF_SIGINFO 128
#elif !defined(SIZEOF_SIGINFO)
// It is not clear whether the sizeof(siginfo_t) is important
// While compiling on Windows the members are not referenced...
// However the size maybe important during a case or a memcpy
// Barring a full audit it could be important so require the size to be defined
# error SIZEOF_SIGINFO is unknown for this target
#endif
typedef struct siginfo
{
uint8_t content[SIZEOF_SIGINFO];
} siginfo_t;
typedef long sigset_t;
int sigfillset(sigset_t *set);
#endif // _MSC_VER

View File

@@ -0,0 +1,24 @@
// This is an incomplete & imprecice implementation of the Posix
// standard file by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
#include <sys/types.h>
#define MAP_FAILED (void *) -1
#define MAP_ANONYMOUS 1
#define MAP_ANON MAP_ANONYMOUS
#define MAP_PRIVATE 2
#define PROT_READ 4
#define PROT_WRITE 8
#define PROT_EXEC 16
void* mmap(void *, size_t, int, int, int, size_t);
int munmap(void *, size_t);
#endif // _MSC_VER

View File

@@ -0,0 +1,35 @@
// This is an incomplete & imprecice implementation of the Posix
// standard file by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
#include <sys/types.h>
#define S_IFMT 00170000
#define S_IFDIR 0040000
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
struct stat
{
unsigned short st_dev;
unsigned short st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
unsigned short st_rdev;
unsigned short st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
};
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
#endif // _MSC_VER

View File

@@ -0,0 +1,11 @@
// This is an incomplete & imprecice implementation of the Posix
// standard file by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
#endif // _MSC_VER

View File

@@ -0,0 +1,19 @@
// This is an incomplete & imprecice implementation of the Posix
// standard file by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
// Posix is a superset of the ISO C sys/types
// include ISO C version first
#include <../ucrt/sys/types.h>
#include <stddef.h>
typedef int pid_t;
typedef ptrdiff_t ssize_t;
#endif // _MSC_VER

View File

@@ -0,0 +1,42 @@
// This is an incomplete & imprecice implementation of the *nix file
// by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
#include <inttypes.h>
#if defined(__linux__) && defined(__x86_64__)
# define SIZEOF_UCONTEXT 936
#elif defined(__linux__) && defined(__aarch64__)
# define SIZEOF_UCONTEXT 4560
#elif defined(__linux__) && defined(__arm__)
# define SIZEOF_UCONTEXT 744
#elif !defined(SIZEOF_UCONTEXT)
// It is not clear whether the sizeof(ucontext_t) is important
// While compiling on Windows the members are not referenced...
// However the size maybe important during a case or a memcpy
// Barring a full audit it could be important so require the size to be defined
# error SIZEOF_UCONTEXT is unknown for this target
#endif
typedef struct ucontext
{
uint8_t content[SIZEOF_UCONTEXT];
} ucontext_t;
#ifdef __aarch64__
// These types are used in the definition of the aarch64 unw_tdep_context_t
// They are not used in UNW_REMOTE_ONLY, so typedef them as something
typedef long sigset_t;
typedef long stack_t;
// Windows SDK defines reserved. It conflicts with arm64 ucontext
// Undefine it
#undef __reserved
#endif
#endif // _MSC_VER

View File

@@ -0,0 +1,13 @@
// This is an incomplete & imprecice implementation of the *nix file
// by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
#include <sys/ucontext.h>
#endif // _MSC_VER

View File

@@ -0,0 +1,37 @@
// This is an incomplete & imprecice implementation of the Posix
// standard file by the same name
// Since this is only intended for VC++ compilers
// use #pragma once instead of guard macros
#pragma once
#ifdef _MSC_VER // Only for cross compilation to windows
#ifndef UNW_REMOTE_ONLY
// This is solely intended to enable compilation of libunwind
// for UNW_REMOTE_ONLY on windows
#error Cross compilation of libunwind on Windows can only support UNW_REMOTE_ONLY
#endif
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
int close(int);
int getpagesize(void);
int open(const char *, int, ...);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int, const void *, size_t);
long sysconf(int name);
#define _SC_PAGESIZE 11
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#define S_ISREG(x) 0
#endif // _MSC_VER

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,41 @@
/* 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 */
#if defined __FreeBSD__
#define JB_SP 1
#define JB_RP 13
#define JB_MASK_SAVED 0
#define JB_MASK 22
#define _JB_STK_SHIFT 0
#else
#define JB_SP 13
#define JB_RP 14
#define JB_MASK_SAVED 15
#define JB_MASK 16
#endif

View File

@@ -0,0 +1,338 @@
/* 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 <stdatomic.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;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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,
AARCH64_SCF_FREEBSD_RT_SIGFRAME,
AARCH64_SCF_QNX_RT_SIGFRAME,
}
sigcontext_format;
unw_word_t sigcontext_addr;
unw_word_t sigcontext_sp;
unw_word_t sigcontext_pc;
int validate;
unw_context_t *uc;
};
static inline unw_context_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 UNUSED, 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 UNUSED, 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 UNUSED, 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 UNUSED, 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)
static inline int
dwarf_is_null_loc(dwarf_loc_t l)
{
return l.val == 0 && l.type == 0;
}
# define DWARF_IS_NULL_LOC(l) dwarf_is_null_loc(l)
# 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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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)
#define tdep_strip_ptrauth_insn_mask UNW_OBJ(tdep_strip_ptrauth_insn_mask)
#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 atomic_bool 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_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_context_t *);
extern unw_word_t tdep_strip_ptrauth_insn_mask (unw_cursor_t *cursor, unw_word_t ip);
#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, int 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,337 @@
/* 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 <stdatomic.h>
#include "elf32.h"
#include "mempool.h"
#include "dwarf.h"
#include "ex_tables.h"
typedef enum
{
UNW_ARM_FRAME_SYSCALL = -3, /* r7 saved in r12, sp offset zero */
UNW_ARM_FRAME_STANDARD = -2, /* regular r7, sp +/- offset */
UNW_ARM_FRAME_SIGRETURN = -1, /* special sigreturn frame */
UNW_ARM_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
UNW_ARM_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
}
unw_tdep_frame_type_t;
typedef struct
{
uint32_t virtual_address;
int32_t frame_type : 3; /* unw_tdep_frame_type_t classification */
int32_t last_frame : 1; /* non-zero if last frame in chain */
int32_t cfa_reg_sp : 1; /* cfa dwarf base register is sp vs. r7 */
int32_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
int32_t r7_cfa_offset : 30; /* r7 saved at this offset from cfa (-1 = not saved) */
int32_t lr_cfa_offset : 30; /* lr saved at this offset from cfa (-1 = not saved) */
int32_t sp_cfa_offset : 30; /* sp saved at this offset from cfa (-1 = not saved) */
}
unw_tdep_frame_t;
struct unw_addr_space
{
struct unw_accessors acc;
int big_endian;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct dwarf_rs_cache global_cache;
struct unw_debug_frame_list *debug_frames;
};
struct cursor
{
struct dwarf_cursor dwarf; /* must be first */
unw_tdep_frame_t frame_info; /* quick tracing assist info */
enum
{
ARM_SCF_NONE, /* no signal frame */
ARM_SCF_LINUX_SIGFRAME, /* non-RT signal frame, kernel >=2.6.18 */
ARM_SCF_LINUX_RT_SIGFRAME, /* RT signal frame, kernel >=2.6.18 */
ARM_SCF_LINUX_OLD_SIGFRAME, /* non-RT signal frame, kernel < 2.6.18 */
ARM_SCF_LINUX_OLD_RT_SIGFRAME, /* RT signal frame, kernel < 2.6.18 */
ARM_SCF_FREEBSD_SIGFRAME, /* FreeBSD sigframe */
ARM_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall stub */
}
sigcontext_format;
unw_word_t sigcontext_addr;
unw_word_t sigcontext_sp;
unw_word_t sigcontext_pc;
int validate;
};
#define DWARF_GET_LOC(l) ((l).val)
#ifdef UNW_LOCAL_ONLY
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
# define DWARF_IS_REG_LOC(l) 0
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
static inline int
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
return 0;
}
static inline int
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = val;
return 0;
}
static inline int
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
return 0;
}
static inline int
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
return 0;
}
#else /* !UNW_LOCAL_ONLY */
# define DWARF_LOC_TYPE_FP (1 << 0)
# define DWARF_LOC_TYPE_REG (1 << 1)
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
static inline int
dwarf_is_null_loc(dwarf_loc_t l)
{
return l.val == 0 && l.type == 0;
}
# define DWARF_IS_NULL_LOC(l) dwarf_is_null_loc(l)
# 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_REG_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_REG_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_REG_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_find_proc_info2 UNW_OBJ(find_proc_info2)
#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 atomic_bool 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 int arm_find_proc_info2 (unw_addr_space_t as, unw_word_t ip,
unw_proc_info_t *pi, int need_unwind_info,
void *arg, int methods);
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 UNW_ARM_METHOD_LR 0x08
#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 <stdatomic.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;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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 atomic_bool 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"
#include <stdatomic.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 */
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
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. */
#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,83 @@
/* 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. */
#include <stdatomic.h>
#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
{
atomic_flag busy; /* is the script-cache busy? */
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,59 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2008 CodeSourcery
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
Copyright (C) 2021 Loongson Technology Corporation 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 is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
explicitly defined.
Number of hardware registers. We have:
- 32 integer registers
- 32 floating point registers
- 8 condition code registers
- 2 fake registers:
- ARG_POINTER_REGNUM
- FRAME_POINTER_REGNUM */
#define DWARF_NUM_PRESERVED_REGS 74
#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0)
/* Not big-endian. */
#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,34 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2008 CodeSourcery
Copyright (C) 2021 Loongson Technology Corporation 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: */
/* https://github.com/loongson/glibc/blob/loongarch_2_33/sysdeps/loongarch/setjmp.S
https://github.com/loongson/glibc/blob/loongarch_2_33/sysdeps/unix/sysv/linux/loongarch/lp64/jmp_buf-macros.h */
#define JB_SP 1
#define JB_RP 0
#define JB_MASK_SAVED (168>>3)
#define JB_MASK (176>>3)

View File

@@ -0,0 +1,251 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2008 CodeSourcery
Copyright (C) 2021 Loongson Technology Corporation 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 LOONGARCH64_LIBUNWIND_I_H
#define LOONGARCH64_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 loongarch64-specific fast trace */
}
unw_tdep_frame_t;
struct unw_addr_space
{
struct unw_accessors acc;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct dwarf_rs_cache global_cache;
struct unw_debug_frame_list *debug_frames;
};
/* LoongArch64 supports only little-endian. */
#define tdep_big_endian(as) 0
struct cursor
{
struct dwarf_cursor dwarf; /* must be first */
enum
{
LOONGARCH64_SCF_NONE,
LOONGARCH64_SCF_LINUX_RT_SIGFRAME,
}
sigcontext_format;
unw_word_t sigcontext_addr;
unw_word_t sigcontext_sp;
unw_word_t sigcontext_pc;
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) (intptr_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) (intptr_t) \
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
/* FIXME: Implement these for the LoongArch64 FPU. */
static inline int
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
{
return 0;
}
static inline int
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t 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 *) (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;
*(unw_word_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))
/* FIXME: Implement these for the LoongArch64 FPU. */
static inline int
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
{
return 0;
}
static inline int
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
{
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_REG_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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,rs) 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 atomic_bool 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 /* LOONGARCH64_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 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)
/* 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,339 @@
/* 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>
#include <stdatomic.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;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc), val,
0, c->as_arg);
else if (c->as->abi == UNW_MIPS_ABI_O32)
return read_s32 (c, DWARF_GET_MEM_LOC (loc), val);
else if (c->as->abi == UNW_MIPS_ABI_N32) {
if (tdep_big_endian(c->as))
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_LOC (loc) + 4, val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_LOC (loc), val,
0, c->as_arg);
}
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else if (c->as->abi == UNW_MIPS_ABI_O32)
return write_s32 (c, DWARF_GET_MEM_LOC (loc), &val);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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 atomic_bool 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 <stdatomic.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;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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 atomic_bool 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,367 @@
/* 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 <stdatomic.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;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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 atomic_bool 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,50 @@
/* 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 riscv by Zhaofeng Li <hello@zhaofeng.li>
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
/* 32 integer registers + 32 floating-point registers + 2 pseudo-registers */
#define DWARF_NUM_PRESERVED_REGS 66
#define DWARF_REGNUM_MAP_LENGTH DWARF_NUM_PRESERVED_REGS
/* Not big-endian. */
#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 RISCV_LOC_TYPE_* macros. */
}
dwarf_loc_t;
#endif /* dwarf_config_h */

View File

@@ -0,0 +1,49 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2004 Hewlett-Packard Co
Contributed by Zhaofeng Li <hello@zhaofeng.li>
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__
/* https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/riscv/setjmp.S;h=0b92016b311b11aa9eeb62b38c670a262f1924c9;hb=HEAD */
#define JB_SP 13
#define JB_RP 0
#if __riscv_xlen == 64
/* GCC's internal structure for this depends on the floating-point ABI:
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/riscv/rv64/jmp_buf-macros.h;h=be9199e514bf4f15f0612327b8b762e29a2b7862;hb=HEAD
*/
#if defined __riscv_float_abi_double
# define JB_MASK_SAVED (208>>3)
# define JB_MASK (216>>3)
#else
# error "Unsupported RISC-V floating point ABI"
#endif /* __riscv_float_abi_double */
#else
# error "Add offsets here"
#endif /* __riscv_xlen */
#endif

View File

@@ -0,0 +1,321 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2008 CodeSourcery
Modified for riscv by Zhaofeng Li <hello@zhaofeng.li>
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 RISCV_LIBUNWIND_I_H
#define RISCV_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 <stdatomic.h>
/* FIXME: Remote across address sizes? */
#if __riscv_xlen == 64
# include "elf64.h"
#elif __riscv_xlen == 32
# include "elf32.h"
#else
# error "Unsupported address size"
#endif
#include "mempool.h"
#include "dwarf.h"
typedef struct
{
/* no riscv-specific fast trace */
}
unw_tdep_frame_t;
struct unw_addr_space
{
struct unw_accessors acc;
int big_endian;
unsigned int addr_size;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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 */
enum
{
RISCV_SCF_NONE, // 0
RISCV_SCF_LINUX_RT_SIGFRAME, // 1
}
sigcontext_format;
unw_word_t sigcontext_addr;
unw_word_t sigcontext_sp;
unw_word_t sigcontext_pc;
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 UNUSED, 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 UNUSED, 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 UNUSED, dwarf_loc_t loc, unw_word_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_word_t *) (intptr_t) DWARF_GET_LOC (loc);
return 0;
}
static inline int
dwarf_put (struct dwarf_cursor *c UNUSED, dwarf_loc_t loc, unw_word_t val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_word_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
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
{
char *valp = (char *) &val;
unw_word_t addr;
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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_LOC (loc);
#if __riscv_xlen == __riscv_flen
return (*c->as->acc.access_mem) (c->as, addr, (unw_word_t *) valp,
0, c->as_arg);
// https://github.com/libunwind/libunwind/pull/854
#elif __riscv_xlen * 2 == __riscv_flen
int r = (*c->as->acc.access_mem) (c->as, addr,
(unw_word_t *) valp,
0, c->as_arg);
if (r < 0)
return r;
return (*c->as->acc.access_mem) (c->as, addr + sizeof(unw_word_t),
(unw_word_t *)valp + 1,
0, c->as_arg);
#else
# error "dwarf_getfp: FIXME"
#endif
}
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;
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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_LOC (loc);
#if __riscv_xlen == __riscv_flen
return (*c->as->acc.access_mem) (c->as, addr, (unw_word_t *) valp,
1, c->as_arg);
// https://github.com/libunwind/libunwind/pull/854
#elif __riscv_xlen * 2 == __riscv_flen
int r = (*c->as->acc.access_mem) (c->as, addr, (unw_word_t *) valp,
1, c->as_arg);
if (r < 0)
return r;
return (*c->as->acc.access_mem) (c->as, addr + sizeof(unw_word_t),
(unw_word_t *) valp + 1,
1, c->as_arg);
#else
# error "dwarf_putfp: FIXME"
#endif
}
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_REG_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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 atomic_bool 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 /* RISCV_LIBUNWIND_I_H */

View File

@@ -0,0 +1,52 @@
/* 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
/* derived from DWARF register mappings in Z ELF ABI */
#define DWARF_NUM_PRESERVED_REGS 66
#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) 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;
unw_word_t type; /* see S390X_LOC_TYPE_* macros. */
}
dwarf_loc_t;
#endif /* dwarf_config_h */

View File

@@ -0,0 +1,35 @@
/* 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 9 // __gregs[9]
#define JB_RP 8 // __gregs[8]
#define JB_MASK_SAVED 18 // __mask_was_saved
#define JB_MASK 19 // __saved_mask
#endif

View File

@@ -0,0 +1,260 @@
/* 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 S390X_LIBUNWIND_I_H
#define S390X_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 <stdatomic.h>
#include "elf64.h"
#include "mempool.h"
#include "dwarf.h"
struct unw_addr_space
{
struct unw_accessors acc;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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
{
S390X_SCF_NONE = 0, /* no signal frame encountered */
S390X_SCF_LINUX_SIGFRAME = 1, /* Linux struct sigcontext */
S390X_SCF_LINUX_RT_SIGFRAME = 2, /* Linux ucontext_t */
}
sigcontext_format;
unw_word_t sigcontext_addr;
unw_word_t sigcontext_sp;
unw_word_t sigcontext_pc;
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) \
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_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)
{
assert(sizeof(unw_fpreg_t) == sizeof(unw_word_t));
if (DWARF_IS_NULL_LOC (loc))
return -UNW_EBADREG;
if (DWARF_IS_FP_LOC (loc))
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_REG_LOC (loc), val,
0, c->as_arg);
/* FPRs may be saved in GPRs */
if (DWARF_IS_REG_LOC (loc))
return (*c->as->acc.access_reg) (c->as, DWARF_GET_REG_LOC (loc), (unw_word_t*)val,
0, c->as_arg);
if (DWARF_IS_MEM_LOC (loc))
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_LOC (loc), (unw_word_t*)val,
0, c->as_arg);
assert(DWARF_IS_VAL_LOC (loc));
*val = *(unw_fpreg_t*) DWARF_GET_MEM_LOC (loc);
return 0;
}
static inline int
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
{
assert(sizeof(unw_fpreg_t) == sizeof(unw_word_t));
assert(!DWARF_IS_VAL_LOC (loc));
if (DWARF_IS_NULL_LOC (loc))
return -UNW_EBADREG;
if (DWARF_IS_FP_LOC (loc))
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_REG_LOC (loc), &val,
1, c->as_arg);
/* FPRs may be saved in GPRs */
if (DWARF_IS_REG_LOC (loc))
return (*c->as->acc.access_reg) (c->as, DWARF_GET_REG_LOC (loc), (unw_word_t*) &val,
1, c->as_arg);
assert(DWARF_IS_MEM_LOC (loc));
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_LOC (loc), (unw_word_t*) &val,
1, c->as_arg);
}
static inline int
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
{
assert(sizeof(unw_fpreg_t) == sizeof(unw_word_t));
if (DWARF_IS_NULL_LOC (loc))
return -UNW_EBADREG;
/* GPRs may be saved in FPRs */
if (DWARF_IS_FP_LOC (loc))
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_REG_LOC (loc), (unw_fpreg_t*)val,
0, c->as_arg);
if (DWARF_IS_REG_LOC (loc))
return (*c->as->acc.access_reg) (c->as, DWARF_GET_REG_LOC (loc), val,
0, c->as_arg);
if (DWARF_IS_MEM_LOC (loc))
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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(sizeof(unw_fpreg_t) == sizeof(unw_word_t));
assert(!DWARF_IS_VAL_LOC (loc));
if (DWARF_IS_NULL_LOC (loc))
return -UNW_EBADREG;
/* GPRs may be saved in FPRs */
if (DWARF_IS_FP_LOC (loc))
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_REG_LOC (loc), (unw_fpreg_t*) &val,
1, c->as_arg);
if (DWARF_IS_REG_LOC (loc))
return (*c->as->acc.access_reg) (c->as, DWARF_GET_REG_LOC (loc), &val,
1, c->as_arg);
assert(DWARF_IS_MEM_LOC (loc));
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_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,rs) do {} while(0)
#define tdep_stash_frame(cs,rs) do {} while(0)
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
#define tdep_uc_addr UNW_OBJ(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) 1
extern atomic_bool 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 /* S390X_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 <stdatomic.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;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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 atomic_bool 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) 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;
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. */
/* 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
#define _JB_STK_SHIFT 4
#endif

View File

@@ -0,0 +1,274 @@
/* 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 <stdatomic.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;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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)
# 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_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_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_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr(dwarf_get_uc(c), (r)), 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 UNUSED, 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 UNUSED, 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;
}
#else /* !UNW_LOCAL_ONLY */
# 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))
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_REG_LOC (loc),
val, 0, c->as_arg);
addr = DWARF_GET_MEM_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_REG_LOC (loc),
&val, 1, c->as_arg);
addr = DWARF_GET_MEM_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);
}
#endif /* !UNW_LOCAL_ONLY */
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_REG_LOC (loc), val,
0, c->as_arg);
if (DWARF_IS_MEM_LOC (loc))
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_LOC (loc), &val,
1, c->as_arg);
}
// For historical reasons, the DWARF numbering does not match the libunwind
// numbering, necessitating this override
#define TDEP_DWARF_SP 4
#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 atomic_bool 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,49 @@
/* 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__ || defined __sun
/* Use glibc's jump-buffer indices; NPTL peeks at SP:
https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=sysdeps/x86_64/jmpbuf-offsets.h;h=ea94a1f90554deecceaf995ca5ee485ae8bffab7;hb=HEAD */
#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
#ifdef __amd64__
#define JB_MASK_SAVED 11
#else
/* Pretend the ip cannot be 0 and mask is always saved */
#define JB_MASK_SAVED 0
#endif
#define JB_MASK 9
#define _JB_STK_SHIFT 8
#endif

View File

@@ -0,0 +1,299 @@
/* 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 <stdint.h>
#include <stdlib.h>
#include <stdatomic.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;
#ifndef UNW_REMOTE_ONLY
unw_iterate_phdr_func_t iterate_phdr_function;
#endif
unw_caching_policy_t caching_policy;
_Atomic uint32_t cache_generation;
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct 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 */
X86_64_SCF_SOLARIS_SIGFRAME, /* illumos/Solaris signal frame */
}
sigcontext_format;
unw_word_t sigcontext_addr;
};
#define AS_ARG_UCONTEXT_MASK ~0x1UL
#define AS_ARG_VALIDATE_MASK 0x1UL
#define AS_ARG_GET_UC_PTR(arg) \
((ucontext_t *) ((uintptr_t) arg & AS_ARG_UCONTEXT_MASK))
#define AS_ARG_GET_VALIDATE(arg) \
((int) ((uintptr_t) arg & AS_ARG_VALIDATE_MASK))
static inline ucontext_t *
dwarf_get_uc(const struct dwarf_cursor *cursor)
{
assert(cursor->as == unw_local_addr_space);
return AS_ARG_GET_UC_PTR(cursor->as_arg);
}
static inline int
dwarf_get_validate(const struct dwarf_cursor *cursor)
{
assert(cursor->as == unw_local_addr_space);
return AS_ARG_GET_VALIDATE(cursor->as_arg);
}
static inline void
dwarf_set_validate(const struct dwarf_cursor *cursor, const int validate)
{
assert(cursor->as == unw_local_addr_space);
uintptr_t *packed_args = (uintptr_t *) &cursor->as_arg;
*packed_args |= (AS_ARG_VALIDATE_MASK & validate);
}
static inline void *
dwarf_build_as_arg(const ucontext_t *uc, const int validate) {
uintptr_t packed_args = (uintptr_t) uc;
assert((packed_args & AS_ARG_VALIDATE_MASK) == 0);
packed_args |= (AS_ARG_VALIDATE_MASK & validate);
return (void *) packed_args;
}
#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)
static inline int
dwarf_is_null_loc(dwarf_loc_t l)
{
return l.val == 0 && l.type == 0;
}
# define DWARF_IS_NULL_LOC(l) dwarf_is_null_loc(l)
# 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 UNUSED, dwarf_loc_t loc, unw_fpreg_t *val UNUSED)
{
if (DWARF_IS_NULL_LOC (loc))
return -UNW_EBADREG;
abort ();
}
static inline int
dwarf_putfp (struct dwarf_cursor *c UNUSED, dwarf_loc_t loc, unw_fpreg_t val UNUSED)
{
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_REG_LOC (loc), val,
0, c->as_arg);
if (DWARF_IS_MEM_LOC (loc))
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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_REG_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_MEM_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 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 atomic_bool 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 *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);
#endif
extern void tdep_stash_frame (struct dwarf_cursor *c,
struct dwarf_reg_state *rs);
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,32 @@
/* 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 __s390x__
# include "tdep-s390x/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 __riscv || defined __riscv__
# include "tdep-riscv/dwarf-config.h"
#elif defined __loongarch64
# include "tdep-loongarch64/dwarf-config.h"
#else
# error "Unsupported arch"
#endif

View File

@@ -0,0 +1,32 @@
/* Provide a real file - not a symlink - as it would cause multiarch conflicts
when multiple different arch releases are installed simultaneously. */
#ifndef UNW_REMOTE_ONLY
#if defined __aarch64__
# include "tdep-aarch64/jmpbuf.h"
#elif defined __arm__
# include "tdep-arm/jmpbuf.h"
#elif defined __hppa__
# include "tdep-hppa/jmpbuf.h"
#elif defined __ia64__
# include "tdep-ia64/jmpbuf.h"
#elif defined __mips__
# include "tdep-mips/jmpbuf.h"
#elif defined __powerpc__ && !defined __powerpc64__
# include "tdep-ppc32/jmpbuf.h"
#elif defined __powerpc64__
# include "tdep-ppc64/jmpbuf.h"
#elif defined __i386__
# include "tdep-x86/jmpbuf.h"
#elif defined __x86_64__
# include "tdep-x86_64/jmpbuf.h"
#elif defined __riscv || defined __riscv__
# include "tdep-riscv/jmpbuf.h"
#elif defined __loongarch64
# include "tdep-loongarch64/jmpbuf.h"
#else
# error "Unsupported arch"
#endif
#endif /* !UNW_REMOTE_ONLY */

View File

@@ -0,0 +1,41 @@
/* 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 __s390x__
# include "tdep-s390x/libunwind_i.h"
#elif defined __riscv || defined __riscv__
# include "tdep-riscv/libunwind_i.h"
#elif defined __loongarch64
# include "tdep-loongarch64/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,41 @@
/* 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 __s390x__
# include "tdep-s390x/libunwind_i.h"
#elif defined __riscv || defined __riscv__
# include "tdep-riscv/libunwind_i.h"
#elif defined __loongarch64
# include "tdep-loongarch64/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,155 @@
/* 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>
#include <stdalign.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
{
alignas(8) uint64_t exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
unsigned long private_1;
unsigned long private_2;
};
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 */