Exception Handling #24

Closed
pca006132 wants to merge 8 commits from pca006132:eh-clean into master
113 changed files with 28981 additions and 37 deletions

20
examples/exception.py Normal file
View File

@ -0,0 +1,20 @@
from artiq.experiment import *
class ExceptionDemo(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("led0")
@kernel
def run(self):
self.core.reset()
print("OK!")
try:
try:
raise Exception
except ValueError as e:
print("re-raise")
raise e
except:
print("error")

43
src/Cargo.lock generated
View File

@ -35,6 +35,12 @@ version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "cc"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
[[package]]
name = "cfg-if"
version = "0.1.10"
@ -76,6 +82,16 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7313c0d620d0cb4dbd9d019e461a4beb501071ff46ec0ab933efb4daa76d73e3"
[[package]]
name = "dwarf"
version = "0.0.0"
dependencies = [
"cfg-if",
"compiler_builtins",
"libc",
"unwind",
]
[[package]]
name = "dyld"
version = "0.1.0"
@ -184,7 +200,7 @@ dependencies = [
[[package]]
name = "libasync"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#ec252b099cf67a51ba9daa72b3292db8c21ba1b8"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#6195ad40c334a847cd01cd4adadf6b8f8d730908"
dependencies = [
"embedded-hal",
"libcortex_a9",
@ -196,7 +212,7 @@ dependencies = [
[[package]]
name = "libboard_zynq"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#ec252b099cf67a51ba9daa72b3292db8c21ba1b8"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#6195ad40c334a847cd01cd4adadf6b8f8d730908"
dependencies = [
"bit_field",
"embedded-hal",
@ -209,10 +225,14 @@ dependencies = [
"volatile-register",
]
[[package]]
name = "libc"
version = "0.1.0"
[[package]]
name = "libcortex_a9"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#ec252b099cf67a51ba9daa72b3292db8c21ba1b8"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#6195ad40c334a847cd01cd4adadf6b8f8d730908"
dependencies = [
"bit_field",
"libregister",
@ -221,7 +241,7 @@ dependencies = [
[[package]]
name = "libregister"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#ec252b099cf67a51ba9daa72b3292db8c21ba1b8"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#6195ad40c334a847cd01cd4adadf6b8f8d730908"
dependencies = [
"bit_field",
"vcell",
@ -231,7 +251,7 @@ dependencies = [
[[package]]
name = "libsupport_zynq"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#ec252b099cf67a51ba9daa72b3292db8c21ba1b8"
source = "git+https://git.m-labs.hk/M-Labs/zc706.git#6195ad40c334a847cd01cd4adadf6b8f8d730908"
dependencies = [
"compiler_builtins",
"libboard_zynq",
@ -364,16 +384,19 @@ dependencies = [
"byteorder",
"core_io",
"cslice",
"dwarf",
"dyld",
"fatfs",
"futures",
"libasync",
"libboard_zynq",
"libc",
"libcortex_a9",
"libsupport_zynq",
"log",
"num-derive",
"num-traits",
"unwind",
"void",
]
@ -416,6 +439,16 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "unwind"
version = "0.0.0"
dependencies = [
"cc",
"cfg-if",
"compiler_builtins",
"libc",
]
[[package]]
name = "vcell"
version = "0.1.2"

View File

@ -1,7 +1,10 @@
[workspace]
members = [
"libc",
"libdyld",
"libcoreio",
"libdwarf",
"libunwind",
"runtime",
"szl"
]

View File

@ -9,7 +9,7 @@ all: ../build/firmware/armv7-none-eabihf/release/szl
mkdir -p ../build
python zc706.py -r ../build/pl.rs -V $(VARIANT)
../build/firmware/armv7-none-eabihf/release/runtime: .cargo/* armv7-none-eabihf.json Cargo.lock Cargo.toml libdyld/* libdyld/src/* libcoreio/* libcoreio/src/* libcoreio/src/io/* runtime/* runtime/src/* ../build/pl.rs
../build/firmware/armv7-none-eabihf/release/runtime: .cargo/* armv7-none-eabihf.json Cargo.lock Cargo.toml libdyld/* libdyld/src/* libcoreio/* libcoreio/src/* libcoreio/src/io/* runtime/* runtime/src/* ../build/pl.rs libc/* libc/src/* libdwarf/* libdwarf/src/* libunwind/* llvm_libunwind/src/*
XBUILD_SYSROOT_PATH=`pwd`/../build/sysroot cargo xbuild --release -p runtime --target-dir ../build/firmware
../build/szl-payload.bin.lzma: ../build/firmware/armv7-none-eabihf/release/runtime

View File

@ -20,6 +20,8 @@
"max-atomic-width": 32,
"os": "none",
"panic-strategy": "abort",
"requires-uwtable": true,
"force-unwind-tables": "yes",
"relocation-model": "static",
"target-c-int-width": "32",
"target-endian": "little",

82
src/include/_ansi.h Executable file
View File

@ -0,0 +1,82 @@
/* Provide support for both ANSI and non-ANSI environments. */
/* To get a strict ANSI C environment, define macro __STRICT_ANSI__. This will
"comment out" the non-ANSI parts of the ANSI header files (non-ANSI header
files aren't affected). */
#ifndef _ANSIDECL_H_
#define _ANSIDECL_H_
#include <newlib.h>
#include <sys/config.h>
/* ISO C++. */
#ifdef __cplusplus
#if !(defined(_BEGIN_STD_C) && defined(_END_STD_C))
#ifdef _HAVE_STD_CXX
#define _BEGIN_STD_C namespace std { extern "C" {
#define _END_STD_C } }
#else
#define _BEGIN_STD_C extern "C" {
#define _END_STD_C }
#endif
#if __GNUC_PREREQ (3, 3)
#define _NOTHROW __attribute__ ((__nothrow__))
#else
#define _NOTHROW throw()
#endif
#endif
#else
#define _BEGIN_STD_C
#define _END_STD_C
#define _NOTHROW
#endif
#ifndef _LONG_DOUBLE
#define _LONG_DOUBLE long double
#endif
/* Support gcc's __attribute__ facility. */
#ifdef __GNUC__
#define _ATTRIBUTE(attrs) __attribute__ (attrs)
#else
#define _ATTRIBUTE(attrs)
#endif
/* The traditional meaning of 'extern inline' for GCC is not
to emit the function body unless the address is explicitly
taken. However this behaviour is changing to match the C99
standard, which uses 'extern inline' to indicate that the
function body *must* be emitted. Likewise, a function declared
without either 'extern' or 'static' defaults to extern linkage
(C99 6.2.2p5), and the compiler may choose whether to use the
inline version or call the extern linkage version (6.7.4p6).
If we are using GCC, but do not have the new behaviour, we need
to use extern inline; if we are using a new GCC with the
C99-compatible behaviour, or a non-GCC compiler (which we will
have to hope is C99, since there is no other way to achieve the
effect of omitting the function if it isn't referenced) we use
'static inline', which c99 defines to mean more-or-less the same
as the Gnu C 'extern inline'. */
#if defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__)
/* We're using GCC, but without the new C99-compatible behaviour. */
#define _ELIDABLE_INLINE extern __inline__ _ATTRIBUTE ((__always_inline__))
#else
/* We're using GCC in C99 mode, or an unknown compiler which
we just have to hope obeys the C99 semantics of inline. */
#define _ELIDABLE_INLINE static __inline__
#endif
#if __GNUC_PREREQ (3, 1)
#define _NOINLINE __attribute__ ((__noinline__))
#define _NOINLINE_STATIC _NOINLINE static
#else
/* On non-GNU compilers and GCC prior to version 3.1 the compiler can't be
trusted not to inline if it is static. */
#define _NOINLINE
#define _NOINLINE_STATIC
#endif
#endif /* _ANSIDECL_H_ */

12
src/include/_newlib_version.h Executable file
View File

@ -0,0 +1,12 @@
/* _newlib_version.h. Generated from _newlib_version.hin by configure. */
/* Version macros for internal and downstream use. */
#ifndef _NEWLIB_VERSION_H__
#define _NEWLIB_VERSION_H__ 1
#define _NEWLIB_VERSION "3.1.0"
#define __NEWLIB__ 3
#define __NEWLIB_MINOR__ 1
#define __NEWLIB_PATCHLEVEL__ 0
#endif /* !_NEWLIB_VERSION_H__ */

21
src/include/alloca.h Executable file
View File

@ -0,0 +1,21 @@
/* libc/include/alloca.h - Allocate memory on stack */
/* Written 2000 by Werner Almesberger */
/* Rearranged for general inclusion by stdlib.h.
2001, Corinna Vinschen <vinschen@redhat.com> */
#ifndef _NEWLIB_ALLOCA_H
#define _NEWLIB_ALLOCA_H
#include "_ansi.h"
#include <sys/reent.h>
#undef alloca
#ifdef __GNUC__
#define alloca(size) __builtin_alloca(size)
#else
void * alloca (size_t);
#endif
#endif

50
src/include/assert.h Executable file
View File

@ -0,0 +1,50 @@
/*
assert.h
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "_ansi.h"
#undef assert
#ifdef NDEBUG /* required by ANSI standard */
# define assert(__e) ((void)0)
#else
# define assert(__e) ((__e) ? (void)0 : __assert_func (__FILE__, __LINE__, \
__ASSERT_FUNC, #__e))
# ifndef __ASSERT_FUNC
/* Use g++'s demangled names in C++. */
# if defined __cplusplus && defined __GNUC__
# define __ASSERT_FUNC __PRETTY_FUNCTION__
/* C99 requires the use of __func__. */
# elif __STDC_VERSION__ >= 199901L
# define __ASSERT_FUNC __func__
/* Older versions of gcc don't have __func__ but can use __FUNCTION__. */
# elif __GNUC__ >= 2
# define __ASSERT_FUNC __FUNCTION__
/* failed to detect __func__ support. */
# else
# define __ASSERT_FUNC ((char *) 0)
# endif
# endif /* !__ASSERT_FUNC */
#endif /* !NDEBUG */
void __assert (const char *, int, const char *)
_ATTRIBUTE ((__noreturn__));
void __assert_func (const char *, int, const char *, const char *)
_ATTRIBUTE ((__noreturn__));
#if __STDC_VERSION__ >= 201112L && !defined __cplusplus
# define static_assert _Static_assert
#endif
#ifdef __cplusplus
}
#endif

345
src/include/inttypes.h Executable file
View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 2004, 2005 by
* Ralf Corsepius, Ulm/Germany. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
/**
* @file inttypes.h
*/
#ifndef _INTTYPES_H
#define _INTTYPES_H
#include <newlib.h>
#include <sys/config.h>
#include <sys/_intsup.h>
#include "_ansi.h"
#include <stdint.h>
#define __need_wchar_t
#include <stddef.h>
#if __BSD_VISIBLE
#include <xlocale.h>
#endif
#define __STRINGIFY(a) #a
/* 8-bit types */
#define __PRI8(x) __INT8 __STRINGIFY(x)
#define __PRI8LEAST(x) __LEAST8 __STRINGIFY(x)
#define __PRI8FAST(x) __FAST8 __STRINGIFY(x)
/* NOTICE: scanning 8-bit types requires use of the hh specifier
* which is only supported on newlib platforms that
* are built with C99 I/O format support enabled. If the flag in
* newlib.h hasn't been set during configuration to indicate this, the 8-bit
* scanning format macros are disabled here as they result in undefined
* behaviour which can include memory overwrite. Overriding the flag after the
* library has been built is not recommended as it will expose the underlying
* undefined behaviour.
*/
#if defined(_WANT_IO_C99_FORMATS)
#define __SCN8(x) __INT8 __STRINGIFY(x)
#define __SCN8LEAST(x) __LEAST8 __STRINGIFY(x)
#define __SCN8FAST(x) __FAST8 __STRINGIFY(x)
#endif /* _WANT_IO_C99_FORMATS */
#define PRId8 __PRI8(d)
#define PRIi8 __PRI8(i)
#define PRIo8 __PRI8(o)
#define PRIu8 __PRI8(u)
#define PRIx8 __PRI8(x)
#define PRIX8 __PRI8(X)
/* Macros below are only enabled for a newlib built with C99 I/O format support. */
#if defined(_WANT_IO_C99_FORMATS)
#define SCNd8 __SCN8(d)
#define SCNi8 __SCN8(i)
#define SCNo8 __SCN8(o)
#define SCNu8 __SCN8(u)
#define SCNx8 __SCN8(x)
#endif /* _WANT_IO_C99_FORMATS */
#define PRIdLEAST8 __PRI8LEAST(d)
#define PRIiLEAST8 __PRI8LEAST(i)
#define PRIoLEAST8 __PRI8LEAST(o)
#define PRIuLEAST8 __PRI8LEAST(u)
#define PRIxLEAST8 __PRI8LEAST(x)
#define PRIXLEAST8 __PRI8LEAST(X)
/* Macros below are only enabled for a newlib built with C99 I/O format support. */
#if defined(_WANT_IO_C99_FORMATS)
#define SCNdLEAST8 __SCN8LEAST(d)
#define SCNiLEAST8 __SCN8LEAST(i)
#define SCNoLEAST8 __SCN8LEAST(o)
#define SCNuLEAST8 __SCN8LEAST(u)
#define SCNxLEAST8 __SCN8LEAST(x)
#endif /* _WANT_IO_C99_FORMATS */
#define PRIdFAST8 __PRI8FAST(d)
#define PRIiFAST8 __PRI8FAST(i)
#define PRIoFAST8 __PRI8FAST(o)
#define PRIuFAST8 __PRI8FAST(u)
#define PRIxFAST8 __PRI8FAST(x)
#define PRIXFAST8 __PRI8FAST(X)
/* Macros below are only enabled for a newlib built with C99 I/O format support. */
#if defined(_WANT_IO_C99_FORMATS)
#define SCNdFAST8 __SCN8FAST(d)
#define SCNiFAST8 __SCN8FAST(i)
#define SCNoFAST8 __SCN8FAST(o)
#define SCNuFAST8 __SCN8FAST(u)
#define SCNxFAST8 __SCN8FAST(x)
#endif /* _WANT_IO_C99_FORMATS */
/* 16-bit types */
#define __PRI16(x) __INT16 __STRINGIFY(x)
#define __PRI16LEAST(x) __LEAST16 __STRINGIFY(x)
#define __PRI16FAST(x) __FAST16 __STRINGIFY(x)
#define __SCN16(x) __INT16 __STRINGIFY(x)
#define __SCN16LEAST(x) __LEAST16 __STRINGIFY(x)
#define __SCN16FAST(x) __FAST16 __STRINGIFY(x)
#define PRId16 __PRI16(d)
#define PRIi16 __PRI16(i)
#define PRIo16 __PRI16(o)
#define PRIu16 __PRI16(u)
#define PRIx16 __PRI16(x)
#define PRIX16 __PRI16(X)
#define SCNd16 __SCN16(d)
#define SCNi16 __SCN16(i)
#define SCNo16 __SCN16(o)
#define SCNu16 __SCN16(u)
#define SCNx16 __SCN16(x)
#define PRIdLEAST16 __PRI16LEAST(d)
#define PRIiLEAST16 __PRI16LEAST(i)
#define PRIoLEAST16 __PRI16LEAST(o)
#define PRIuLEAST16 __PRI16LEAST(u)
#define PRIxLEAST16 __PRI16LEAST(x)
#define PRIXLEAST16 __PRI16LEAST(X)
#define SCNdLEAST16 __SCN16LEAST(d)
#define SCNiLEAST16 __SCN16LEAST(i)
#define SCNoLEAST16 __SCN16LEAST(o)
#define SCNuLEAST16 __SCN16LEAST(u)
#define SCNxLEAST16 __SCN16LEAST(x)
#define PRIdFAST16 __PRI16FAST(d)
#define PRIiFAST16 __PRI16FAST(i)
#define PRIoFAST16 __PRI16FAST(o)
#define PRIuFAST16 __PRI16FAST(u)
#define PRIxFAST16 __PRI16FAST(x)
#define PRIXFAST16 __PRI16FAST(X)
#define SCNdFAST16 __SCN16FAST(d)
#define SCNiFAST16 __SCN16FAST(i)
#define SCNoFAST16 __SCN16FAST(o)
#define SCNuFAST16 __SCN16FAST(u)
#define SCNxFAST16 __SCN16FAST(x)
/* 32-bit types */
#define __PRI32(x) __INT32 __STRINGIFY(x)
#define __SCN32(x) __INT32 __STRINGIFY(x)
#define __PRI32LEAST(x) __LEAST32 __STRINGIFY(x)
#define __SCN32LEAST(x) __LEAST32 __STRINGIFY(x)
#define __PRI32FAST(x) __FAST32 __STRINGIFY(x)
#define __SCN32FAST(x) __FAST32 __STRINGIFY(x)
#define PRId32 __PRI32(d)
#define PRIi32 __PRI32(i)
#define PRIo32 __PRI32(o)
#define PRIu32 __PRI32(u)
#define PRIx32 __PRI32(x)
#define PRIX32 __PRI32(X)
#define SCNd32 __SCN32(d)
#define SCNi32 __SCN32(i)
#define SCNo32 __SCN32(o)
#define SCNu32 __SCN32(u)
#define SCNx32 __SCN32(x)
#define PRIdLEAST32 __PRI32LEAST(d)
#define PRIiLEAST32 __PRI32LEAST(i)
#define PRIoLEAST32 __PRI32LEAST(o)
#define PRIuLEAST32 __PRI32LEAST(u)
#define PRIxLEAST32 __PRI32LEAST(x)
#define PRIXLEAST32 __PRI32LEAST(X)
#define SCNdLEAST32 __SCN32LEAST(d)
#define SCNiLEAST32 __SCN32LEAST(i)
#define SCNoLEAST32 __SCN32LEAST(o)
#define SCNuLEAST32 __SCN32LEAST(u)
#define SCNxLEAST32 __SCN32LEAST(x)
#define PRIdFAST32 __PRI32FAST(d)
#define PRIiFAST32 __PRI32FAST(i)
#define PRIoFAST32 __PRI32FAST(o)
#define PRIuFAST32 __PRI32FAST(u)
#define PRIxFAST32 __PRI32FAST(x)
#define PRIXFAST32 __PRI32FAST(X)
#define SCNdFAST32 __SCN32FAST(d)
#define SCNiFAST32 __SCN32FAST(i)
#define SCNoFAST32 __SCN32FAST(o)
#define SCNuFAST32 __SCN32FAST(u)
#define SCNxFAST32 __SCN32FAST(x)
/* 64-bit types */
#define __PRI64(x) __INT64 __STRINGIFY(x)
#define __SCN64(x) __INT64 __STRINGIFY(x)
#define __PRI64LEAST(x) __LEAST64 __STRINGIFY(x)
#define __SCN64LEAST(x) __LEAST64 __STRINGIFY(x)
#define __PRI64FAST(x) __FAST64 __STRINGIFY(x)
#define __SCN64FAST(x) __FAST64 __STRINGIFY(x)
#if __int64_t_defined
#define PRId64 __PRI64(d)
#define PRIi64 __PRI64(i)
#define PRIo64 __PRI64(o)
#define PRIu64 __PRI64(u)
#define PRIx64 __PRI64(x)
#define PRIX64 __PRI64(X)
#define SCNd64 __SCN64(d)
#define SCNi64 __SCN64(i)
#define SCNo64 __SCN64(o)
#define SCNu64 __SCN64(u)
#define SCNx64 __SCN64(x)
#endif
#if __int_least64_t_defined
#define PRIdLEAST64 __PRI64LEAST(d)
#define PRIiLEAST64 __PRI64LEAST(i)
#define PRIoLEAST64 __PRI64LEAST(o)
#define PRIuLEAST64 __PRI64LEAST(u)
#define PRIxLEAST64 __PRI64LEAST(x)
#define PRIXLEAST64 __PRI64LEAST(X)
#define SCNdLEAST64 __SCN64LEAST(d)
#define SCNiLEAST64 __SCN64LEAST(i)
#define SCNoLEAST64 __SCN64LEAST(o)
#define SCNuLEAST64 __SCN64LEAST(u)
#define SCNxLEAST64 __SCN64LEAST(x)
#endif
#if __int_fast64_t_defined
#define PRIdFAST64 __PRI64FAST(d)
#define PRIiFAST64 __PRI64FAST(i)
#define PRIoFAST64 __PRI64FAST(o)
#define PRIuFAST64 __PRI64FAST(u)
#define PRIxFAST64 __PRI64FAST(x)
#define PRIXFAST64 __PRI64FAST(X)
#define SCNdFAST64 __SCN64FAST(d)
#define SCNiFAST64 __SCN64FAST(i)
#define SCNoFAST64 __SCN64FAST(o)
#define SCNuFAST64 __SCN64FAST(u)
#define SCNxFAST64 __SCN64FAST(x)
#endif
/* max-bit types */
#if __have_long64
#define __PRIMAX(x) __STRINGIFY(l##x)
#define __SCNMAX(x) __STRINGIFY(l##x)
#elif __have_longlong64
#define __PRIMAX(x) __STRINGIFY(ll##x)
#define __SCNMAX(x) __STRINGIFY(ll##x)
#else
#define __PRIMAX(x) __STRINGIFY(x)
#define __SCNMAX(x) __STRINGIFY(x)
#endif
#define PRIdMAX __PRIMAX(d)
#define PRIiMAX __PRIMAX(i)
#define PRIoMAX __PRIMAX(o)
#define PRIuMAX __PRIMAX(u)
#define PRIxMAX __PRIMAX(x)
#define PRIXMAX __PRIMAX(X)
#define SCNdMAX __SCNMAX(d)
#define SCNiMAX __SCNMAX(i)
#define SCNoMAX __SCNMAX(o)
#define SCNuMAX __SCNMAX(u)
#define SCNxMAX __SCNMAX(x)
/* ptr types */
#if defined (_INTPTR_EQ_LONGLONG)
# define __PRIPTR(x) __STRINGIFY(ll##x)
# define __SCNPTR(x) __STRINGIFY(ll##x)
#elif defined (_INTPTR_EQ_LONG)
# define __PRIPTR(x) __STRINGIFY(l##x)
# define __SCNPTR(x) __STRINGIFY(l##x)
#else
# define __PRIPTR(x) __STRINGIFY(x)
# define __SCNPTR(x) __STRINGIFY(x)
#endif
#define PRIdPTR __PRIPTR(d)
#define PRIiPTR __PRIPTR(i)
#define PRIoPTR __PRIPTR(o)
#define PRIuPTR __PRIPTR(u)
#define PRIxPTR __PRIPTR(x)
#define PRIXPTR __PRIPTR(X)
#define SCNdPTR __SCNPTR(d)
#define SCNiPTR __SCNPTR(i)
#define SCNoPTR __SCNPTR(o)
#define SCNuPTR __SCNPTR(u)
#define SCNxPTR __SCNPTR(x)
typedef struct {
intmax_t quot;
intmax_t rem;
} imaxdiv_t;
struct _reent;
#ifdef __cplusplus
extern "C" {
#endif
extern intmax_t imaxabs(intmax_t j);
extern imaxdiv_t imaxdiv(intmax_t numer, intmax_t denomer);
extern intmax_t strtoimax(const char *__restrict, char **__restrict, int);
extern intmax_t _strtoimax_r(struct _reent *, const char *__restrict, char **__restrict, int);
extern uintmax_t strtoumax(const char *__restrict, char **__restrict, int);
extern uintmax_t _strtoumax_r(struct _reent *, const char *__restrict, char **__restrict, int);
extern intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int);
extern intmax_t _wcstoimax_r(struct _reent *, const wchar_t *__restrict, wchar_t **__restrict, int);
extern uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int);
extern uintmax_t _wcstoumax_r(struct _reent *, const wchar_t *__restrict, wchar_t **__restrict, int);
#if __BSD_VISIBLE
extern intmax_t strtoimax_l(const char *__restrict, char **_restrict, int, locale_t);
extern uintmax_t strtoumax_l(const char *__restrict, char **_restrict, int, locale_t);
extern intmax_t wcstoimax_l(const wchar_t *__restrict, wchar_t **_restrict, int, locale_t);
extern uintmax_t wcstoumax_l(const wchar_t *__restrict, wchar_t **_restrict, int, locale_t);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,250 @@
/*
* $Id$
*/
#ifndef _MACHINE__DEFAULT_TYPES_H
#define _MACHINE__DEFAULT_TYPES_H
#include <sys/features.h>
/*
* Guess on types by examining *_MIN / *_MAX defines.
*/
#if __GNUC_PREREQ (3, 3)
/* GCC >= 3.3.0 has __<val>__ implicitly defined. */
#define __EXP(x) __##x##__
#else
/* Fall back to POSIX versions from <limits.h> */
#define __EXP(x) x
#include <limits.h>
#endif
/* Check if "long long" is 64bit wide */
/* Modern GCCs provide __LONG_LONG_MAX__, SUSv3 wants LLONG_MAX */
#if ( defined(__LONG_LONG_MAX__) && (__LONG_LONG_MAX__ > 0x7fffffff) ) \
|| ( defined(LLONG_MAX) && (LLONG_MAX > 0x7fffffff) )
#define __have_longlong64 1
#endif
/* Check if "long" is 64bit or 32bit wide */
#if __EXP(LONG_MAX) > 0x7fffffff
#define __have_long64 1
#elif __EXP(LONG_MAX) == 0x7fffffff && !defined(__SPU__)
#define __have_long32 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __INT8_TYPE__
typedef __INT8_TYPE__ __int8_t;
#ifdef __UINT8_TYPE__
typedef __UINT8_TYPE__ __uint8_t;
#else
typedef unsigned __INT8_TYPE__ __uint8_t;
#endif
#define ___int8_t_defined 1
#elif __EXP(SCHAR_MAX) == 0x7f
typedef signed char __int8_t ;
typedef unsigned char __uint8_t ;
#define ___int8_t_defined 1
#endif
#ifdef __INT16_TYPE__
typedef __INT16_TYPE__ __int16_t;
#ifdef __UINT16_TYPE__
typedef __UINT16_TYPE__ __uint16_t;
#else
typedef unsigned __INT16_TYPE__ __uint16_t;
#endif
#define ___int16_t_defined 1
#elif __EXP(INT_MAX) == 0x7fff
typedef signed int __int16_t;
typedef unsigned int __uint16_t;
#define ___int16_t_defined 1
#elif __EXP(SHRT_MAX) == 0x7fff
typedef signed short __int16_t;
typedef unsigned short __uint16_t;
#define ___int16_t_defined 1
#elif __EXP(SCHAR_MAX) == 0x7fff
typedef signed char __int16_t;
typedef unsigned char __uint16_t;
#define ___int16_t_defined 1
#endif
#ifdef __INT32_TYPE__
typedef __INT32_TYPE__ __int32_t;
#ifdef __UINT32_TYPE__
typedef __UINT32_TYPE__ __uint32_t;
#else
typedef unsigned __INT32_TYPE__ __uint32_t;
#endif
#define ___int32_t_defined 1
#elif __EXP(INT_MAX) == 0x7fffffffL
typedef signed int __int32_t;
typedef unsigned int __uint32_t;
#define ___int32_t_defined 1
#elif __EXP(LONG_MAX) == 0x7fffffffL
typedef signed long __int32_t;
typedef unsigned long __uint32_t;
#define ___int32_t_defined 1
#elif __EXP(SHRT_MAX) == 0x7fffffffL
typedef signed short __int32_t;
typedef unsigned short __uint32_t;
#define ___int32_t_defined 1
#elif __EXP(SCHAR_MAX) == 0x7fffffffL
typedef signed char __int32_t;
typedef unsigned char __uint32_t;
#define ___int32_t_defined 1
#endif
#ifdef __INT64_TYPE__
typedef __INT64_TYPE__ __int64_t;
#ifdef __UINT64_TYPE__
typedef __UINT64_TYPE__ __uint64_t;
#else
typedef unsigned __INT64_TYPE__ __uint64_t;
#endif
#define ___int64_t_defined 1
#elif __EXP(LONG_MAX) > 0x7fffffff
typedef signed long __int64_t;
typedef unsigned long __uint64_t;
#define ___int64_t_defined 1
/* GCC has __LONG_LONG_MAX__ */
#elif defined(__LONG_LONG_MAX__) && (__LONG_LONG_MAX__ > 0x7fffffff)
typedef signed long long __int64_t;
typedef unsigned long long __uint64_t;
#define ___int64_t_defined 1
/* POSIX mandates LLONG_MAX in <limits.h> */
#elif defined(LLONG_MAX) && (LLONG_MAX > 0x7fffffff)
typedef signed long long __int64_t;
typedef unsigned long long __uint64_t;
#define ___int64_t_defined 1
#elif __EXP(INT_MAX) > 0x7fffffff
typedef signed int __int64_t;
typedef unsigned int __uint64_t;
#define ___int64_t_defined 1
#endif
#ifdef __INT_LEAST8_TYPE__
typedef __INT_LEAST8_TYPE__ __int_least8_t;
#ifdef __UINT_LEAST8_TYPE__
typedef __UINT_LEAST8_TYPE__ __uint_least8_t;
#else
typedef unsigned __INT_LEAST8_TYPE__ __uint_least8_t;
#endif
#define ___int_least8_t_defined 1
#elif defined(___int8_t_defined)
typedef __int8_t __int_least8_t;
typedef __uint8_t __uint_least8_t;
#define ___int_least8_t_defined 1
#elif defined(___int16_t_defined)
typedef __int16_t __int_least8_t;
typedef __uint16_t __uint_least8_t;
#define ___int_least8_t_defined 1
#elif defined(___int32_t_defined)
typedef __int32_t __int_least8_t;
typedef __uint32_t __uint_least8_t;
#define ___int_least8_t_defined 1
#elif defined(___int64_t_defined)
typedef __int64_t __int_least8_t;
typedef __uint64_t __uint_least8_t;
#define ___int_least8_t_defined 1
#endif
#ifdef __INT_LEAST16_TYPE__
typedef __INT_LEAST16_TYPE__ __int_least16_t;
#ifdef __UINT_LEAST16_TYPE__
typedef __UINT_LEAST16_TYPE__ __uint_least16_t;
#else
typedef unsigned __INT_LEAST16_TYPE__ __uint_least16_t;
#endif
#define ___int_least16_t_defined 1
#elif defined(___int16_t_defined)
typedef __int16_t __int_least16_t;
typedef __uint16_t __uint_least16_t;
#define ___int_least16_t_defined 1
#elif defined(___int32_t_defined)
typedef __int32_t __int_least16_t;
typedef __uint32_t __uint_least16_t;
#define ___int_least16_t_defined 1
#elif defined(___int64_t_defined)
typedef __int64_t __int_least16_t;
typedef __uint64_t __uint_least16_t;
#define ___int_least16_t_defined 1
#endif
#ifdef __INT_LEAST32_TYPE__
typedef __INT_LEAST32_TYPE__ __int_least32_t;
#ifdef __UINT_LEAST32_TYPE__
typedef __UINT_LEAST32_TYPE__ __uint_least32_t;
#else
typedef unsigned __INT_LEAST32_TYPE__ __uint_least32_t;
#endif
#define ___int_least32_t_defined 1
#elif defined(___int32_t_defined)
typedef __int32_t __int_least32_t;
typedef __uint32_t __uint_least32_t;
#define ___int_least32_t_defined 1
#elif defined(___int64_t_defined)
typedef __int64_t __int_least32_t;
typedef __uint64_t __uint_least32_t;
#define ___int_least32_t_defined 1
#endif
#ifdef __INT_LEAST64_TYPE__
typedef __INT_LEAST64_TYPE__ __int_least64_t;
#ifdef __UINT_LEAST64_TYPE__
typedef __UINT_LEAST64_TYPE__ __uint_least64_t;
#else
typedef unsigned __INT_LEAST64_TYPE__ __uint_least64_t;
#endif
#define ___int_least64_t_defined 1
#elif defined(___int64_t_defined)
typedef __int64_t __int_least64_t;
typedef __uint64_t __uint_least64_t;
#define ___int_least64_t_defined 1
#endif
#if defined(__INTMAX_TYPE__)
typedef __INTMAX_TYPE__ __intmax_t;
#elif __have_longlong64
typedef signed long long __intmax_t;
#else
typedef signed long __intmax_t;
#endif
#if defined(__UINTMAX_TYPE__)
typedef __UINTMAX_TYPE__ __uintmax_t;
#elif __have_longlong64
typedef unsigned long long __uintmax_t;
#else
typedef unsigned long __uintmax_t;
#endif
#ifdef __INTPTR_TYPE__
typedef __INTPTR_TYPE__ __intptr_t;
#ifdef __UINTPTR_TYPE__
typedef __UINTPTR_TYPE__ __uintptr_t;
#else
typedef unsigned __INTPTR_TYPE__ __uintptr_t;
#endif
#elif defined(__PTRDIFF_TYPE__)
typedef __PTRDIFF_TYPE__ __intptr_t;
typedef unsigned __PTRDIFF_TYPE__ __uintptr_t;
#else
typedef long __intptr_t;
typedef unsigned long __uintptr_t;
#endif
#undef __EXP
#ifdef __cplusplus
}
#endif
#endif /* _MACHINE__DEFAULT_TYPES_H */

39
src/include/machine/_endian.h Executable file
View File

@ -0,0 +1,39 @@
/* ARM configuration file.
Copyright (c) 2015 ARM Ltd. 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.
3. The name of the company may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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. */
#ifndef __MACHINE_ENDIAN_H__
#error "must be included via <machine/endian.h>"
#endif /* !__MACHINE_ENDIAN_H__ */
#define _LITTLE_ENDIAN 1234
#define _BIG_ENDIAN 4321
#define _PDP_ENDIAN 3412
#ifdef __ARMEB__
#define _BYTE_ORDER _BIG_ENDIAN
#else
#define _BYTE_ORDER _LITTLE_ENDIAN
#endif

8
src/include/machine/_types.h Executable file
View File

@ -0,0 +1,8 @@
/*
* $Id$
*/
#ifndef _MACHINE__TYPES_H
#define _MACHINE__TYPES_H
#include <machine/_default_types.h>
#endif

69
src/include/machine/endian.h Executable file
View File

@ -0,0 +1,69 @@
#ifndef __MACHINE_ENDIAN_H__
#define __MACHINE_ENDIAN_H__
#include <sys/cdefs.h>
#include <sys/_types.h>
#include <machine/_endian.h>
#if _BYTE_ORDER == _LITTLE_ENDIAN
#define _QUAD_HIGHWORD 1
#define _QUAD_LOWWORD 0
#else
#define _QUAD_HIGHWORD 0
#define _QUAD_LOWWORD 1
#endif
#if __BSD_VISIBLE
#define LITTLE_ENDIAN _LITTLE_ENDIAN
#define BIG_ENDIAN _BIG_ENDIAN
#define PDP_ENDIAN _PDP_ENDIAN
#define BYTE_ORDER _BYTE_ORDER
#endif
#ifdef __GNUC__
#define __bswap16(_x) __builtin_bswap16(_x)
#define __bswap32(_x) __builtin_bswap32(_x)
#define __bswap64(_x) __builtin_bswap64(_x)
#else /* __GNUC__ */
static __inline __uint16_t
__bswap16(__uint16_t _x)
{
return ((__uint16_t)((_x >> 8) | ((_x << 8) & 0xff00)));
}
static __inline __uint32_t
__bswap32(__uint32_t _x)
{
return ((__uint32_t)((_x >> 24) | ((_x >> 8) & 0xff00) |
((_x << 8) & 0xff0000) | ((_x << 24) & 0xff000000)));
}
static __inline __uint64_t
__bswap64(__uint64_t _x)
{
return ((__uint64_t)((_x >> 56) | ((_x >> 40) & 0xff00) |
((_x >> 24) & 0xff0000) | ((_x >> 8) & 0xff000000) |
((_x << 8) & ((__uint64_t)0xff << 32)) |
((_x << 24) & ((__uint64_t)0xff << 40)) |
((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56))));
}
#endif /* !__GNUC__ */
#ifndef __machine_host_to_from_network_defined
#if _BYTE_ORDER == _LITTLE_ENDIAN
#define __htonl(_x) __bswap32(_x)
#define __htons(_x) __bswap16(_x)
#define __ntohl(_x) __bswap32(_x)
#define __ntohs(_x) __bswap16(_x)
#else
#define __htonl(_x) ((__uint32_t)(_x))
#define __htons(_x) ((__uint16_t)(_x))
#define __ntohl(_x) ((__uint32_t)(_x))
#define __ntohs(_x) ((__uint16_t)(_x))
#endif
#endif /* __machine_host_to_from_network_defined */
#endif /* __MACHINE_ENDIAN_H__ */

475
src/include/machine/ieeefp.h Executable file
View File

@ -0,0 +1,475 @@
#ifndef __IEEE_BIG_ENDIAN
#ifndef __IEEE_LITTLE_ENDIAN
/* This file can define macros to choose variations of the IEEE float
format:
_FLT_LARGEST_EXPONENT_IS_NORMAL
Defined if the float format uses the largest exponent for finite
numbers rather than NaN and infinity representations. Such a
format cannot represent NaNs or infinities at all, but it's FLT_MAX
is twice the IEEE value.
_FLT_NO_DENORMALS
Defined if the float format does not support IEEE denormals. Every
float with a zero exponent is taken to be a zero representation.
??? At the moment, there are no equivalent macros above for doubles and
the macros are not fully supported by --enable-newlib-hw-fp.
__IEEE_BIG_ENDIAN
Defined if the float format is big endian. This is mutually exclusive
with __IEEE_LITTLE_ENDIAN.
__IEEE_LITTLE_ENDIAN
Defined if the float format is little endian. This is mutually exclusive
with __IEEE_BIG_ENDIAN.
Note that one of __IEEE_BIG_ENDIAN or __IEEE_LITTLE_ENDIAN must be specified for a
platform or error will occur.
__IEEE_BYTES_LITTLE_ENDIAN
This flag is used in conjunction with __IEEE_BIG_ENDIAN to describe a situation
whereby multiple words of an IEEE floating point are in big endian order, but the
words themselves are little endian with respect to the bytes.
_DOUBLE_IS_32BITS
This is used on platforms that support double by using the 32-bit IEEE
float type.
_FLOAT_ARG
This represents what type a float arg is passed as. It is used when the type is
not promoted to double.
__OBSOLETE_MATH_DEFAULT
Default value for __OBSOLETE_MATH if that's not set by the user.
It should be set here based on predefined feature macros.
__OBSOLETE_MATH
If set to 1 then some new math code will be disabled and older libm
code will be used instead. This is necessary because the new math
code does not support all targets, it assumes that the toolchain has
ISO C99 support (hexfloat literals, standard fenv semantics), the
target has IEEE-754 conforming binary32 float and binary64 double
(not mixed endian) representation, standard SNaN representation,
double and single precision arithmetics has similar latency and it
has no legacy SVID matherr support, only POSIX errno and fenv
exception based error handling.
*/
#if (defined(__arm__) || defined(__thumb__)) && !defined(__MAVERICK__)
/* ARM traditionally used big-endian words; and within those words the
byte ordering was big or little endian depending upon the target.
Modern floating-point formats are naturally ordered; in this case
__VFP_FP__ will be defined, even if soft-float. */
#ifdef __VFP_FP__
# ifdef __ARMEL__
# define __IEEE_LITTLE_ENDIAN
# else
# define __IEEE_BIG_ENDIAN
# endif
# if __ARM_FP & 0x8
# define __OBSOLETE_MATH_DEFAULT 0
# endif
#else
# define __IEEE_BIG_ENDIAN
# ifdef __ARMEL__
# define __IEEE_BYTES_LITTLE_ENDIAN
# endif
#endif
#endif
#if defined (__aarch64__)
#if defined (__AARCH64EL__)
#define __IEEE_LITTLE_ENDIAN
#else
#define __IEEE_BIG_ENDIAN
#endif
#define __OBSOLETE_MATH_DEFAULT 0
#endif
#ifdef __epiphany__
#define __IEEE_LITTLE_ENDIAN
#define Sudden_Underflow 1
#endif
#ifdef __hppa__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __nds32__
#ifdef __big_endian__
#define __IEEE_BIG_ENDIAN
#else
#define __IEEE_LITTLE_ENDIAN
#endif
#endif
#ifdef __SPU__
#define __IEEE_BIG_ENDIAN
#define isfinite(__y) \
(__extension__ ({int __cy; \
(sizeof (__y) == sizeof (float)) ? (1) : \
(__cy = fpclassify(__y)) != FP_INFINITE && __cy != FP_NAN;}))
#define isinf(__x) ((sizeof (__x) == sizeof (float)) ? (0) : __isinfd(__x))
#define isnan(__x) ((sizeof (__x) == sizeof (float)) ? (0) : __isnand(__x))
/*
* Macros for use in ieeefp.h. We can't just define the real ones here
* (like those above) as we have name space issues when this is *not*
* included via generic the ieeefp.h.
*/
#define __ieeefp_isnanf(x) 0
#define __ieeefp_isinff(x) 0
#define __ieeefp_finitef(x) 1
#endif
#ifdef __sparc__
#ifdef __LITTLE_ENDIAN_DATA__
#define __IEEE_LITTLE_ENDIAN
#else
#define __IEEE_BIG_ENDIAN
#endif
#endif
#if defined(__m68k__) || defined(__mc68000__)
#define __IEEE_BIG_ENDIAN
#endif
#if defined(__mc68hc11__) || defined(__mc68hc12__) || defined(__mc68hc1x__)
#define __IEEE_BIG_ENDIAN
#ifdef __HAVE_SHORT_DOUBLE__
# define _DOUBLE_IS_32BITS
#endif
#endif
#if defined (__H8300__) || defined (__H8300H__) || defined (__H8300S__) || defined (__H8500__) || defined (__H8300SX__)
#define __IEEE_BIG_ENDIAN
#define _FLOAT_ARG float
#define _DOUBLE_IS_32BITS
#endif
#if defined (__xc16x__) || defined (__xc16xL__) || defined (__xc16xS__)
#define __IEEE_LITTLE_ENDIAN
#define _FLOAT_ARG float
#define _DOUBLE_IS_32BITS
#endif
#ifdef __sh__
#ifdef __LITTLE_ENDIAN__
#define __IEEE_LITTLE_ENDIAN
#else
#define __IEEE_BIG_ENDIAN
#endif
#if defined(__SH2E__) || defined(__SH3E__) || defined(__SH4_SINGLE_ONLY__) || defined(__SH2A_SINGLE_ONLY__)
#define _DOUBLE_IS_32BITS
#endif
#endif
#ifdef _AM29K
#define __IEEE_BIG_ENDIAN
#endif
#ifdef _WIN32
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __i386__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __riscv
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __i960__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __lm32__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __M32R__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __nvptx__
#define __IEEE_LITTLE_ENDIAN
#endif
#if defined(_C4x) || defined(_C3x)
#define __IEEE_BIG_ENDIAN
#define _DOUBLE_IS_32BITS
#endif
#ifdef __TMS320C6X__
#ifdef _BIG_ENDIAN
#define __IEEE_BIG_ENDIAN
#else
#define __IEEE_LITTLE_ENDIAN
#endif
#endif
#ifdef __TIC80__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __MIPSEL__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __MIPSEB__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __MMIX__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __D30V__
#define __IEEE_BIG_ENDIAN
#endif
/* necv70 was __IEEE_LITTLE_ENDIAN. */
#ifdef __W65__
#define __IEEE_LITTLE_ENDIAN
#define _DOUBLE_IS_32BITS
#endif
#if defined(__Z8001__) || defined(__Z8002__)
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __m88k__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __mn10300__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __mn10200__
#define __IEEE_LITTLE_ENDIAN
#define _DOUBLE_IS_32BITS
#endif
#ifdef __v800
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __v850
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __D10V__
#define __IEEE_BIG_ENDIAN
#if __DOUBLE__ == 32
#define _DOUBLE_IS_32BITS
#endif
#endif
#ifdef __PPC__
#if (defined(_BIG_ENDIAN) && _BIG_ENDIAN) || (defined(_AIX) && _AIX)
#define __IEEE_BIG_ENDIAN
#else
#if (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN) || (defined(__sun__) && __sun__) || (defined(_WIN32) && _WIN32)
#define __IEEE_LITTLE_ENDIAN
#endif
#endif
#endif
#ifdef __xstormy16__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __arc__
#ifdef __big_endian__
#define __IEEE_BIG_ENDIAN
#else
#define __IEEE_LITTLE_ENDIAN
#endif
#endif
#ifdef __CRX__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __fr30__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __FT32__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __mcore__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __mt__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __frv__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __moxie__
#ifdef __MOXIE_BIG_ENDIAN__
#define __IEEE_BIG_ENDIAN
#else
#define __IEEE_LITTLE_ENDIAN
#endif
#endif
#ifdef __ia64__
#ifdef __BIG_ENDIAN__
#define __IEEE_BIG_ENDIAN
#else
#define __IEEE_LITTLE_ENDIAN
#endif
#endif
#ifdef __AVR__
#define __IEEE_LITTLE_ENDIAN
#define _DOUBLE_IS_32BITS
#endif
#if defined(__or1k__) || defined(__OR1K__) || defined(__OR1KND__)
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __IP2K__
#define __IEEE_BIG_ENDIAN
#define __SMALL_BITFIELDS
#define _DOUBLE_IS_32BITS
#endif
#ifdef __iq2000__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __MAVERICK__
#ifdef __ARMEL__
# define __IEEE_LITTLE_ENDIAN
#else /* must be __ARMEB__ */
# define __IEEE_BIG_ENDIAN
#endif /* __ARMEL__ */
#endif /* __MAVERICK__ */
#ifdef __m32c__
#define __IEEE_LITTLE_ENDIAN
#define __SMALL_BITFIELDS
#endif
#ifdef __CRIS__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __BFIN__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __x86_64__
#define __IEEE_LITTLE_ENDIAN
#endif
#ifdef __mep__
#ifdef __LITTLE_ENDIAN__
#define __IEEE_LITTLE_ENDIAN
#else
#define __IEEE_BIG_ENDIAN
#endif
#endif
#ifdef __MICROBLAZE__
#ifndef __MICROBLAZEEL__
#define __IEEE_BIG_ENDIAN
#else
#define __IEEE_LITTLE_ENDIAN
#endif
#endif
#ifdef __MSP430__
#define __IEEE_LITTLE_ENDIAN
#define __SMALL_BITFIELDS /* 16 Bit INT */
#endif
#ifdef __RL78__
#define __IEEE_LITTLE_ENDIAN
#define __SMALL_BITFIELDS /* 16 Bit INT */
#ifndef __RL78_64BIT_DOUBLES__
#define _DOUBLE_IS_32BITS
#endif
#endif
#ifdef __RX__
#ifdef __RX_BIG_ENDIAN__
#define __IEEE_BIG_ENDIAN
#else
#define __IEEE_LITTLE_ENDIAN
#endif
#ifndef __RX_64BIT_DOUBLES__
#define _DOUBLE_IS_32BITS
#endif
#ifdef __RX_16BIT_INTS__
#define __SMALL_BITFIELDS
#endif
#endif
#if (defined(__CR16__) || defined(__CR16C__) ||defined(__CR16CP__))
#define __IEEE_LITTLE_ENDIAN
#define __SMALL_BITFIELDS /* 16 Bit INT */
#endif
#ifdef __NIOS2__
# ifdef __nios2_big_endian__
# define __IEEE_BIG_ENDIAN
# else
# define __IEEE_LITTLE_ENDIAN
# endif
#endif
#ifdef __VISIUM__
#define __IEEE_BIG_ENDIAN
#endif
#ifdef __CYGWIN__
#define __OBSOLETE_MATH_DEFAULT 0
#endif
#ifndef __OBSOLETE_MATH_DEFAULT
/* Use old math code by default. */
#define __OBSOLETE_MATH_DEFAULT 1
#endif
#ifndef __OBSOLETE_MATH
#define __OBSOLETE_MATH __OBSOLETE_MATH_DEFAULT
#endif
#ifndef __IEEE_BIG_ENDIAN
#ifndef __IEEE_LITTLE_ENDIAN
#error Endianess not declared!!
#endif /* not __IEEE_LITTLE_ENDIAN */
#endif /* not __IEEE_BIG_ENDIAN */
#endif /* not __IEEE_LITTLE_ENDIAN */
#endif /* not __IEEE_BIG_ENDIAN */

8
src/include/machine/stdlib.h Executable file
View File

@ -0,0 +1,8 @@
#ifndef _MACHSTDLIB_H_
#define _MACHSTDLIB_H_
/* place holder so platforms may add stdlib.h extensions */
#endif /* _MACHSTDLIB_H_ */

7
src/include/machine/types.h Executable file
View File

@ -0,0 +1,7 @@
/*
* Newlib targets may provide an own version of this file in their machine
* directory to add custom user types for <sys/types.h>.
*/
#ifndef _SYS_TYPES_H
#error "must be included via <sys/types.h>"
#endif /* !_SYS_TYPES_H */

206
src/include/newlib.h Executable file
View File

@ -0,0 +1,206 @@
/* newlib.h. Generated from newlib.hin by configure. */
/* newlib.hin. Manually edited from the output of autoheader to
remove all PACKAGE_ macros which will collide with any user
package using newlib header files and having its own package name,
version, etc... */
#ifndef __NEWLIB_H__
#define __NEWLIB_H__ 1
/* EL/IX level */
/* #undef _ELIX_LEVEL */
/* Newlib version */
#include <_newlib_version.h>
/* C99 formats support (such as %a, %zu, ...) in IO functions like
* printf/scanf enabled */
#define _WANT_IO_C99_FORMATS 1
/* long long type support in IO functions like printf/scanf enabled */
#define _WANT_IO_LONG_LONG 1
/* Register application finalization function using atexit. */
#define _WANT_REGISTER_FINI 1
/* long double type support in IO functions like printf/scanf enabled */
/* #undef _WANT_IO_LONG_DOUBLE */
/* Positional argument support in printf functions enabled. */
/* #undef _WANT_IO_POS_ARGS */
/* Optional reentrant struct support. Used mostly on platforms with
very restricted storage. */
/* #undef _WANT_REENT_SMALL */
/* Multibyte supported */
/* #undef _MB_CAPABLE */
/* MB_LEN_MAX */
#define _MB_LEN_MAX 1
/* ICONV enabled */
/* #undef _ICONV_ENABLED */
/* Enable ICONV external CCS files loading capabilities */
/* #undef _ICONV_ENABLE_EXTERNAL_CCS */
/* Define if the linker supports .preinit_array/.init_array/.fini_array
* sections. */
#define HAVE_INITFINI_ARRAY 1
/* True if atexit() may dynamically allocate space for cleanup
functions. */
#define _ATEXIT_DYNAMIC_ALLOC 1
/* True if long double supported. */
#define _HAVE_LONG_DOUBLE 1
/* Define if compiler supports -fno-tree-loop-distribute-patterns. */
#define _HAVE_CC_INHIBIT_LOOP_TO_LIBCALL 1
/* True if long double supported and it is equal to double. */
#define _LDBL_EQ_DBL 1
/* Define if ivo supported in streamio. */
#define _FVWRITE_IN_STREAMIO 1
/* Define if fseek functions support seek optimization. */
#define _FSEEK_OPTIMIZATION 1
/* Define if wide char orientation is supported. */
#define _WIDE_ORIENT 1
/* Define if unbuffered stream file optimization is supported. */
#define _UNBUF_STREAM_OPT 1
/* Define if lite version of exit supported. */
/* #undef _LITE_EXIT */
/* Define if declare atexit data as global. */
/* #undef _REENT_GLOBAL_ATEXIT */
/* Define to move the stdio stream FILE objects out of struct _reent and make
them global. The stdio stream pointers of struct _reent are initialized to
point to the global stdio FILE stream objects. */
/* #undef _WANT_REENT_GLOBAL_STDIO_STREAMS */
/* Define if small footprint nano-formatted-IO implementation used. */
/* #undef _NANO_FORMATTED_IO */
/* Define if using retargetable functions for default lock routines. */
#define _RETARGETABLE_LOCKING 1
/* Define to use type long for time_t. */
/* #undef _WANT_USE_LONG_TIME_T */
/*
* Iconv encodings enabled ("to" direction)
*/
/* #undef _ICONV_TO_ENCODING_BIG5 */
/* #undef _ICONV_TO_ENCODING_CP775 */
/* #undef _ICONV_TO_ENCODING_CP850 */
/* #undef _ICONV_TO_ENCODING_CP852 */
/* #undef _ICONV_TO_ENCODING_CP855 */
/* #undef _ICONV_TO_ENCODING_CP866 */
/* #undef _ICONV_TO_ENCODING_EUC_JP */
/* #undef _ICONV_TO_ENCODING_EUC_TW */
/* #undef _ICONV_TO_ENCODING_EUC_KR */
/* #undef _ICONV_TO_ENCODING_ISO_8859_1 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_10 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_11 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_13 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_14 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_15 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_2 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_3 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_4 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_5 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_6 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_7 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_8 */
/* #undef _ICONV_TO_ENCODING_ISO_8859_9 */
/* #undef _ICONV_TO_ENCODING_ISO_IR_111 */
/* #undef _ICONV_TO_ENCODING_KOI8_R */
/* #undef _ICONV_TO_ENCODING_KOI8_RU */
/* #undef _ICONV_TO_ENCODING_KOI8_U */
/* #undef _ICONV_TO_ENCODING_KOI8_UNI */
/* #undef _ICONV_TO_ENCODING_UCS_2 */
/* #undef _ICONV_TO_ENCODING_UCS_2_INTERNAL */
/* #undef _ICONV_TO_ENCODING_UCS_2BE */
/* #undef _ICONV_TO_ENCODING_UCS_2LE */
/* #undef _ICONV_TO_ENCODING_UCS_4 */
/* #undef _ICONV_TO_ENCODING_UCS_4_INTERNAL */
/* #undef _ICONV_TO_ENCODING_UCS_4BE */
/* #undef _ICONV_TO_ENCODING_UCS_4LE */
/* #undef _ICONV_TO_ENCODING_US_ASCII */
/* #undef _ICONV_TO_ENCODING_UTF_16 */
/* #undef _ICONV_TO_ENCODING_UTF_16BE */
/* #undef _ICONV_TO_ENCODING_UTF_16LE */
/* #undef _ICONV_TO_ENCODING_UTF_8 */
/* #undef _ICONV_TO_ENCODING_WIN_1250 */
/* #undef _ICONV_TO_ENCODING_WIN_1251 */
/* #undef _ICONV_TO_ENCODING_WIN_1252 */
/* #undef _ICONV_TO_ENCODING_WIN_1253 */
/* #undef _ICONV_TO_ENCODING_WIN_1254 */
/* #undef _ICONV_TO_ENCODING_WIN_1255 */
/* #undef _ICONV_TO_ENCODING_WIN_1256 */
/* #undef _ICONV_TO_ENCODING_WIN_1257 */
/* #undef _ICONV_TO_ENCODING_WIN_1258 */
/*
* Iconv encodings enabled ("from" direction)
*/
/* #undef _ICONV_FROM_ENCODING_BIG5 */
/* #undef _ICONV_FROM_ENCODING_CP775 */
/* #undef _ICONV_FROM_ENCODING_CP850 */
/* #undef _ICONV_FROM_ENCODING_CP852 */
/* #undef _ICONV_FROM_ENCODING_CP855 */
/* #undef _ICONV_FROM_ENCODING_CP866 */
/* #undef _ICONV_FROM_ENCODING_EUC_JP */
/* #undef _ICONV_FROM_ENCODING_EUC_TW */
/* #undef _ICONV_FROM_ENCODING_EUC_KR */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_1 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_10 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_11 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_13 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_14 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_15 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_2 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_3 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_4 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_5 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_6 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_7 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_8 */
/* #undef _ICONV_FROM_ENCODING_ISO_8859_9 */
/* #undef _ICONV_FROM_ENCODING_ISO_IR_111 */
/* #undef _ICONV_FROM_ENCODING_KOI8_R */
/* #undef _ICONV_FROM_ENCODING_KOI8_RU */
/* #undef _ICONV_FROM_ENCODING_KOI8_U */
/* #undef _ICONV_FROM_ENCODING_KOI8_UNI */
/* #undef _ICONV_FROM_ENCODING_UCS_2 */
/* #undef _ICONV_FROM_ENCODING_UCS_2_INTERNAL */
/* #undef _ICONV_FROM_ENCODING_UCS_2BE */
/* #undef _ICONV_FROM_ENCODING_UCS_2LE */
/* #undef _ICONV_FROM_ENCODING_UCS_4 */
/* #undef _ICONV_FROM_ENCODING_UCS_4_INTERNAL */
/* #undef _ICONV_FROM_ENCODING_UCS_4BE */
/* #undef _ICONV_FROM_ENCODING_UCS_4LE */
/* #undef _ICONV_FROM_ENCODING_US_ASCII */
/* #undef _ICONV_FROM_ENCODING_UTF_16 */
/* #undef _ICONV_FROM_ENCODING_UTF_16BE */
/* #undef _ICONV_FROM_ENCODING_UTF_16LE */
/* #undef _ICONV_FROM_ENCODING_UTF_8 */
/* #undef _ICONV_FROM_ENCODING_WIN_1250 */
/* #undef _ICONV_FROM_ENCODING_WIN_1251 */
/* #undef _ICONV_FROM_ENCODING_WIN_1252 */
/* #undef _ICONV_FROM_ENCODING_WIN_1253 */
/* #undef _ICONV_FROM_ENCODING_WIN_1254 */
/* #undef _ICONV_FROM_ENCODING_WIN_1255 */
/* #undef _ICONV_FROM_ENCODING_WIN_1256 */
/* #undef _ICONV_FROM_ENCODING_WIN_1257 */
/* #undef _ICONV_FROM_ENCODING_WIN_1258 */
#endif /* !__NEWLIB_H__ */

466
src/include/stdint.h Executable file
View File

@ -0,0 +1,466 @@
/*
* Copyright (c) 2004, 2005 by
* Ralf Corsepius, Ulm/Germany. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
#ifndef _STDINT_H
#define _STDINT_H
#include <machine/_default_types.h>
#include <sys/_intsup.h>
#include <sys/_stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ___int_least8_t_defined
typedef __int_least8_t int_least8_t;
typedef __uint_least8_t uint_least8_t;
#define __int_least8_t_defined 1
#endif
#ifdef ___int_least16_t_defined
typedef __int_least16_t int_least16_t;
typedef __uint_least16_t uint_least16_t;
#define __int_least16_t_defined 1
#endif
#ifdef ___int_least32_t_defined
typedef __int_least32_t int_least32_t;
typedef __uint_least32_t uint_least32_t;
#define __int_least32_t_defined 1
#endif
#ifdef ___int_least64_t_defined
typedef __int_least64_t int_least64_t;
typedef __uint_least64_t uint_least64_t;
#define __int_least64_t_defined 1
#endif
/*
* Fastest minimum-width integer types
*
* Assume int to be the fastest type for all types with a width
* less than __INT_MAX__ rsp. INT_MAX
*/
#ifdef __INT_FAST8_TYPE__
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
#define __int_fast8_t_defined 1
#elif __STDINT_EXP(INT_MAX) >= 0x7f
typedef signed int int_fast8_t;
typedef unsigned int uint_fast8_t;
#define __int_fast8_t_defined 1
#endif
#ifdef __INT_FAST16_TYPE__
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
#define __int_fast16_t_defined 1
#elif __STDINT_EXP(INT_MAX) >= 0x7fff
typedef signed int int_fast16_t;
typedef unsigned int uint_fast16_t;
#define __int_fast16_t_defined 1
#endif
#ifdef __INT_FAST32_TYPE__
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
#define __int_fast32_t_defined 1
#elif __STDINT_EXP(INT_MAX) >= 0x7fffffff
typedef signed int int_fast32_t;
typedef unsigned int uint_fast32_t;
#define __int_fast32_t_defined 1
#endif
#ifdef __INT_FAST64_TYPE__
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define __int_fast64_t_defined 1
#elif __STDINT_EXP(INT_MAX) > 0x7fffffff
typedef signed int int_fast64_t;
typedef unsigned int uint_fast64_t;
#define __int_fast64_t_defined 1
#endif
/*
* Fall back to [u]int_least<N>_t for [u]int_fast<N>_t types
* not having been defined, yet.
* Leave undefined, if [u]int_least<N>_t should not be available.
*/
#if !__int_fast8_t_defined
#if __int_least8_t_defined
typedef int_least8_t int_fast8_t;
typedef uint_least8_t uint_fast8_t;
#define __int_fast8_t_defined 1
#endif
#endif
#if !__int_fast16_t_defined
#if __int_least16_t_defined
typedef int_least16_t int_fast16_t;
typedef uint_least16_t uint_fast16_t;
#define __int_fast16_t_defined 1
#endif
#endif
#if !__int_fast32_t_defined
#if __int_least32_t_defined
typedef int_least32_t int_fast32_t;
typedef uint_least32_t uint_fast32_t;
#define __int_fast32_t_defined 1
#endif
#endif
#if !__int_fast64_t_defined
#if __int_least64_t_defined
typedef int_least64_t int_fast64_t;
typedef uint_least64_t uint_fast64_t;
#define __int_fast64_t_defined 1
#endif
#endif
#ifdef __INTPTR_TYPE__
#define INTPTR_MIN (-__INTPTR_MAX__ - 1)
#define INTPTR_MAX (__INTPTR_MAX__)
#define UINTPTR_MAX (__UINTPTR_MAX__)
#elif defined(__PTRDIFF_TYPE__)
#define INTPTR_MAX PTRDIFF_MAX
#define INTPTR_MIN PTRDIFF_MIN
#ifdef __UINTPTR_MAX__
#define UINTPTR_MAX (__UINTPTR_MAX__)
#else
#define UINTPTR_MAX (2UL * PTRDIFF_MAX + 1)
#endif
#else
/*
* Fallback to hardcoded values,
* should be valid on cpu's with 32bit int/32bit void*
*/
#define INTPTR_MAX (__STDINT_EXP(LONG_MAX))
#define INTPTR_MIN (-__STDINT_EXP(LONG_MAX) - 1)
#define UINTPTR_MAX (__STDINT_EXP(LONG_MAX) * 2UL + 1)
#endif
/* Limits of Specified-Width Integer Types */
#ifdef __INT8_MAX__
#define INT8_MIN (-__INT8_MAX__ - 1)
#define INT8_MAX (__INT8_MAX__)
#define UINT8_MAX (__UINT8_MAX__)
#elif defined(__int8_t_defined)
#define INT8_MIN (-128)
#define INT8_MAX (127)
#define UINT8_MAX (255)
#endif
#ifdef __INT_LEAST8_MAX__
#define INT_LEAST8_MIN (-__INT_LEAST8_MAX__ - 1)
#define INT_LEAST8_MAX (__INT_LEAST8_MAX__)
#define UINT_LEAST8_MAX (__UINT_LEAST8_MAX__)
#elif defined(__int_least8_t_defined)
#define INT_LEAST8_MIN (-128)
#define INT_LEAST8_MAX (127)
#define UINT_LEAST8_MAX (255)
#else
#error required type int_least8_t missing
#endif
#ifdef __INT16_MAX__
#define INT16_MIN (-__INT16_MAX__ - 1)
#define INT16_MAX (__INT16_MAX__)
#define UINT16_MAX (__UINT16_MAX__)
#elif defined(__int16_t_defined)
#define INT16_MIN (-32768)
#define INT16_MAX (32767)
#define UINT16_MAX (65535)
#endif
#ifdef __INT_LEAST16_MAX__
#define INT_LEAST16_MIN (-__INT_LEAST16_MAX__ - 1)
#define INT_LEAST16_MAX (__INT_LEAST16_MAX__)
#define UINT_LEAST16_MAX (__UINT_LEAST16_MAX__)
#elif defined(__int_least16_t_defined)
#define INT_LEAST16_MIN (-32768)
#define INT_LEAST16_MAX (32767)
#define UINT_LEAST16_MAX (65535)
#else
#error required type int_least16_t missing
#endif
#ifdef __INT32_MAX__
#define INT32_MIN (-__INT32_MAX__ - 1)
#define INT32_MAX (__INT32_MAX__)
#define UINT32_MAX (__UINT32_MAX__)
#elif defined(__int32_t_defined)
#if defined (_INT32_EQ_LONG)
#define INT32_MIN (-2147483647L-1)
#define INT32_MAX (2147483647L)
#define UINT32_MAX (4294967295UL)
#else
#define INT32_MIN (-2147483647-1)
#define INT32_MAX (2147483647)
#define UINT32_MAX (4294967295U)
#endif
#endif
#ifdef __INT_LEAST32_MAX__
#define INT_LEAST32_MIN (-__INT_LEAST32_MAX__ - 1)
#define INT_LEAST32_MAX (__INT_LEAST32_MAX__)
#define UINT_LEAST32_MAX (__UINT_LEAST32_MAX__)
#elif defined(__int_least32_t_defined)
#if defined (_INT32_EQ_LONG)
#define INT_LEAST32_MIN (-2147483647L-1)
#define INT_LEAST32_MAX (2147483647L)
#define UINT_LEAST32_MAX (4294967295UL)
#else
#define INT_LEAST32_MIN (-2147483647-1)
#define INT_LEAST32_MAX (2147483647)
#define UINT_LEAST32_MAX (4294967295U)
#endif
#else
#error required type int_least32_t missing
#endif
#ifdef __INT64_MAX__
#define INT64_MIN (-__INT64_MAX__ - 1)
#define INT64_MAX (__INT64_MAX__)
#define UINT64_MAX (__UINT64_MAX__)
#elif defined(__int64_t_defined)
#if __have_long64
#define INT64_MIN (-9223372036854775807L-1L)
#define INT64_MAX (9223372036854775807L)
#define UINT64_MAX (18446744073709551615U)
#elif __have_longlong64
#define INT64_MIN (-9223372036854775807LL-1LL)
#define INT64_MAX (9223372036854775807LL)
#define UINT64_MAX (18446744073709551615ULL)
#endif
#endif
#ifdef __INT_LEAST64_MAX__
#define INT_LEAST64_MIN (-__INT_LEAST64_MAX__ - 1)
#define INT_LEAST64_MAX (__INT_LEAST64_MAX__)
#define UINT_LEAST64_MAX (__UINT_LEAST64_MAX__)
#elif defined(__int_least64_t_defined)
#if __have_long64
#define INT_LEAST64_MIN (-9223372036854775807L-1L)
#define INT_LEAST64_MAX (9223372036854775807L)
#define UINT_LEAST64_MAX (18446744073709551615U)
#elif __have_longlong64
#define INT_LEAST64_MIN (-9223372036854775807LL-1LL)
#define INT_LEAST64_MAX (9223372036854775807LL)
#define UINT_LEAST64_MAX (18446744073709551615ULL)
#endif
#endif
#ifdef __INT_FAST8_MAX__
#define INT_FAST8_MIN (-__INT_FAST8_MAX__ - 1)
#define INT_FAST8_MAX (__INT_FAST8_MAX__)
#define UINT_FAST8_MAX (__UINT_FAST8_MAX__)
#elif defined(__int_fast8_t_defined)
#if __STDINT_EXP(INT_MAX) >= 0x7f
#define INT_FAST8_MIN (-__STDINT_EXP(INT_MAX)-1)
#define INT_FAST8_MAX (__STDINT_EXP(INT_MAX))
#define UINT_FAST8_MAX (__STDINT_EXP(INT_MAX)*2U+1U)
#else
#define INT_FAST8_MIN INT_LEAST8_MIN
#define INT_FAST8_MAX INT_LEAST8_MAX
#define UINT_FAST8_MAX UINT_LEAST8_MAX
#endif
#endif
#ifdef __INT_FAST16_MAX__
#define INT_FAST16_MIN (-__INT_FAST16_MAX__ - 1)
#define INT_FAST16_MAX (__INT_FAST16_MAX__)
#define UINT_FAST16_MAX (__UINT_FAST16_MAX__)
#elif defined(__int_fast16_t_defined)
#if __STDINT_EXP(INT_MAX) >= 0x7fff
#define INT_FAST16_MIN (-__STDINT_EXP(INT_MAX)-1)
#define INT_FAST16_MAX (__STDINT_EXP(INT_MAX))
#define UINT_FAST16_MAX (__STDINT_EXP(INT_MAX)*2U+1U)
#else
#define INT_FAST16_MIN INT_LEAST16_MIN
#define INT_FAST16_MAX INT_LEAST16_MAX
#define UINT_FAST16_MAX UINT_LEAST16_MAX
#endif
#endif
#ifdef __INT_FAST32_MAX__
#define INT_FAST32_MIN (-__INT_FAST32_MAX__ - 1)
#define INT_FAST32_MAX (__INT_FAST32_MAX__)
#define UINT_FAST32_MAX (__UINT_FAST32_MAX__)
#elif defined(__int_fast32_t_defined)
#if __STDINT_EXP(INT_MAX) >= 0x7fffffff
#define INT_FAST32_MIN (-__STDINT_EXP(INT_MAX)-1)
#define INT_FAST32_MAX (__STDINT_EXP(INT_MAX))
#define UINT_FAST32_MAX (__STDINT_EXP(INT_MAX)*2U+1U)
#else
#define INT_FAST32_MIN INT_LEAST32_MIN
#define INT_FAST32_MAX INT_LEAST32_MAX
#define UINT_FAST32_MAX UINT_LEAST32_MAX
#endif
#endif
#ifdef __INT_FAST64_MAX__
#define INT_FAST64_MIN (-__INT_FAST64_MAX__ - 1)
#define INT_FAST64_MAX (__INT_FAST64_MAX__)
#define UINT_FAST64_MAX (__UINT_FAST64_MAX__)
#elif defined(__int_fast64_t_defined)
#if __STDINT_EXP(INT_MAX) > 0x7fffffff
#define INT_FAST64_MIN (-__STDINT_EXP(INT_MAX)-1)
#define INT_FAST64_MAX (__STDINT_EXP(INT_MAX))
#define UINT_FAST64_MAX (__STDINT_EXP(INT_MAX)*2U+1U)
#else
#define INT_FAST64_MIN INT_LEAST64_MIN
#define INT_FAST64_MAX INT_LEAST64_MAX
#define UINT_FAST64_MAX UINT_LEAST64_MAX
#endif
#endif
#ifdef __INTMAX_MAX__
#define INTMAX_MAX (__INTMAX_MAX__)
#define INTMAX_MIN (-INTMAX_MAX - 1)
#elif defined(__INTMAX_TYPE__)
/* All relevant GCC versions prefer long to long long for intmax_t. */
#define INTMAX_MAX INT64_MAX
#define INTMAX_MIN INT64_MIN
#endif
#ifdef __UINTMAX_MAX__
#define UINTMAX_MAX (__UINTMAX_MAX__)
#elif defined(__UINTMAX_TYPE__)
/* All relevant GCC versions prefer long to long long for intmax_t. */
#define UINTMAX_MAX UINT64_MAX
#endif
/* This must match size_t in stddef.h, currently long unsigned int */
#ifdef __SIZE_MAX__
#define SIZE_MAX (__SIZE_MAX__)
#else
#define SIZE_MAX (__STDINT_EXP(LONG_MAX) * 2UL + 1)
#endif
/* This must match sig_atomic_t in <signal.h> (currently int) */
#define SIG_ATOMIC_MIN (-__STDINT_EXP(INT_MAX) - 1)
#define SIG_ATOMIC_MAX (__STDINT_EXP(INT_MAX))
/* This must match ptrdiff_t in <stddef.h> (currently long int) */
#ifdef __PTRDIFF_MAX__
#define PTRDIFF_MAX (__PTRDIFF_MAX__)
#else
#define PTRDIFF_MAX (__STDINT_EXP(LONG_MAX))
#endif
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
/* This must match definition in <wchar.h> */
#ifndef WCHAR_MIN
#ifdef __WCHAR_MIN__
#define WCHAR_MIN (__WCHAR_MIN__)
#elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0)
#define WCHAR_MIN (0 + L'\0')
#else
#define WCHAR_MIN (-0x7fffffff - 1 + L'\0')
#endif
#endif
/* This must match definition in <wchar.h> */
#ifndef WCHAR_MAX
#ifdef __WCHAR_MAX__
#define WCHAR_MAX (__WCHAR_MAX__)
#elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0)
#define WCHAR_MAX (0xffffffffu + L'\0')
#else
#define WCHAR_MAX (0x7fffffff + L'\0')
#endif
#endif
/* wint_t is unsigned int on almost all GCC targets. */
#ifdef __WINT_MAX__
#define WINT_MAX (__WINT_MAX__)
#else
#define WINT_MAX (__STDINT_EXP(INT_MAX) * 2U + 1U)
#endif
#ifdef __WINT_MIN__
#define WINT_MIN (__WINT_MIN__)
#else
#define WINT_MIN (0U)
#endif
/** Macros for minimum-width integer constant expressions */
#ifdef __INT8_C
#define INT8_C(x) __INT8_C(x)
#define UINT8_C(x) __UINT8_C(x)
#else
#define INT8_C(x) x
#if __STDINT_EXP(INT_MAX) > 0x7f
#define UINT8_C(x) x
#else
#define UINT8_C(x) x##U
#endif
#endif
#ifdef __INT16_C
#define INT16_C(x) __INT16_C(x)
#define UINT16_C(x) __UINT16_C(x)
#else
#define INT16_C(x) x
#if __STDINT_EXP(INT_MAX) > 0x7fff
#define UINT16_C(x) x
#else
#define UINT16_C(x) x##U
#endif
#endif
#ifdef __INT32_C
#define INT32_C(x) __INT32_C(x)
#define UINT32_C(x) __UINT32_C(x)
#else
#if defined (_INT32_EQ_LONG)
#define INT32_C(x) x##L
#define UINT32_C(x) x##UL
#else
#define INT32_C(x) x
#define UINT32_C(x) x##U
#endif
#endif
#ifdef __INT64_C
#define INT64_C(x) __INT64_C(x)
#define UINT64_C(x) __UINT64_C(x)
#else
#if __int64_t_defined
#if __have_long64
#define INT64_C(x) x##L
#define UINT64_C(x) x##UL
#else
#define INT64_C(x) x##LL
#define UINT64_C(x) x##ULL
#endif
#endif
#endif
/** Macros for greatest-width integer constant expression */
#ifdef __INTMAX_C
#define INTMAX_C(x) __INTMAX_C(x)
#define UINTMAX_C(x) __UINTMAX_C(x)
#else
#if __have_long64
#define INTMAX_C(x) x##L
#define UINTMAX_C(x) x##UL
#else
#define INTMAX_C(x) x##LL
#define UINTMAX_C(x) x##ULL
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* _STDINT_H */

803
src/include/stdio.h Executable file
View File

@ -0,0 +1,803 @@
/*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#)stdio.h 5.3 (Berkeley) 3/15/86
*/
/*
* NB: to fit things in six character monocase externals, the
* stdio code uses the prefix `__s' for stdio objects, typically
* followed by a three-character attempt at a mnemonic.
*/
#ifndef _STDIO_H_
#define _STDIO_H_
#include "_ansi.h"
#define _FSTDIO /* ``function stdio'' */
#define __need_size_t
#define __need_NULL
#include <sys/cdefs.h>
#include <stddef.h>
/* typedef only __gnuc_va_list, used throughout the header */
#define __need___va_list
#include <stdarg.h>
/* typedef va_list only when required */
#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE
#ifdef __GNUC__
#ifndef _VA_LIST_DEFINED
typedef __gnuc_va_list va_list;
#define _VA_LIST_DEFINED
#endif
#else /* !__GNUC__ */
#include <stdarg.h>
#endif
#endif /* __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE */
/*
* <sys/reent.h> defines __FILE, _fpos_t.
* They must be defined there because struct _reent needs them (and we don't
* want reent.h to include this file.
*/
#include <sys/reent.h>
#include <sys/types.h>
_BEGIN_STD_C
#if !defined(__FILE_defined)
typedef __FILE FILE;
# define __FILE_defined
#endif
#ifdef __CYGWIN__
typedef _fpos64_t fpos_t;
#else
typedef _fpos_t fpos_t;
#ifdef __LARGE64_FILES
typedef _fpos64_t fpos64_t;
#endif
#endif /* !__CYGWIN__ */
#include <sys/stdio.h>
#define __SLBF 0x0001 /* line buffered */
#define __SNBF 0x0002 /* unbuffered */
#define __SRD 0x0004 /* OK to read */
#define __SWR 0x0008 /* OK to write */
/* RD and WR are never simultaneously asserted */
#define __SRW 0x0010 /* open for reading & writing */
#define __SEOF 0x0020 /* found EOF */
#define __SERR 0x0040 /* found error */
#define __SMBF 0x0080 /* _buf is from malloc */
#define __SAPP 0x0100 /* fdopen()ed in append mode - so must write to end */
#define __SSTR 0x0200 /* this is an sprintf/snprintf string */
#define __SOPT 0x0400 /* do fseek() optimisation */
#define __SNPT 0x0800 /* do not do fseek() optimisation */
#define __SOFF 0x1000 /* set iff _offset is in fact correct */
#define __SORD 0x2000 /* true => stream orientation (byte/wide) decided */
#if defined(__CYGWIN__)
# define __SCLE 0x4000 /* convert line endings CR/LF <-> NL */
#endif
#define __SL64 0x8000 /* is 64-bit offset large file */
/* _flags2 flags */
#define __SNLK 0x0001 /* stdio functions do not lock streams themselves */
#define __SWID 0x2000 /* true => stream orientation wide, false => byte, only valid if __SORD in _flags is true */
/*
* The following three definitions are for ANSI C, which took them
* from System V, which stupidly took internal interface macros and
* made them official arguments to setvbuf(), without renaming them.
* Hence, these ugly _IOxxx names are *supposed* to appear in user code.
*
* Although these happen to match their counterparts above, the
* implementation does not rely on that (so these could be renumbered).
*/
#define _IOFBF 0 /* setvbuf should set fully buffered */
#define _IOLBF 1 /* setvbuf should set line buffered */
#define _IONBF 2 /* setvbuf should set unbuffered */
#define EOF (-1)
#ifdef __BUFSIZ__
#define BUFSIZ __BUFSIZ__
#else
#define BUFSIZ 1024
#endif
#ifdef __FOPEN_MAX__
#define FOPEN_MAX __FOPEN_MAX__
#else
#define FOPEN_MAX 20
#endif
#ifdef __FILENAME_MAX__
#define FILENAME_MAX __FILENAME_MAX__
#else
#define FILENAME_MAX 1024
#endif
#ifdef __L_tmpnam__
#define L_tmpnam __L_tmpnam__
#else
#define L_tmpnam FILENAME_MAX
#endif
#if __BSD_VISIBLE || __XSI_VISIBLE
#define P_tmpdir "/tmp"
#endif
#ifndef SEEK_SET
#define SEEK_SET 0 /* set file offset to offset */
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1 /* set file offset to current plus offset */
#endif
#ifndef SEEK_END
#define SEEK_END 2 /* set file offset to EOF plus offset */
#endif
#define TMP_MAX 26
#define stdin (_REENT->_stdin)
#define stdout (_REENT->_stdout)
#define stderr (_REENT->_stderr)
#define _stdin_r(x) ((x)->_stdin)
#define _stdout_r(x) ((x)->_stdout)
#define _stderr_r(x) ((x)->_stderr)
/*
* Functions defined in ANSI C standard.
*/
#ifndef __VALIST
#ifdef __GNUC__
#define __VALIST __gnuc_va_list
#else
#define __VALIST char*
#endif
#endif
#if __POSIX_VISIBLE
char * ctermid (char *);
#endif
#if __GNU_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 600)
char * cuserid (char *);
#endif
FILE * tmpfile (void);
char * tmpnam (char *);
#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112
char * tempnam (const char *, const char *) __malloc_like __result_use_check;
#endif
int fclose (FILE *);
int fflush (FILE *);
FILE * freopen (const char *__restrict, const char *__restrict, FILE *__restrict);
void setbuf (FILE *__restrict, char *__restrict);
int setvbuf (FILE *__restrict, char *__restrict, int, size_t);
int fprintf (FILE *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
int fscanf (FILE *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3)));
int printf (const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 1, 2)));
int scanf (const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 1, 2)));
int sscanf (const char *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3)));
int vfprintf (FILE *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int vprintf (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 1, 0)));
int vsprintf (char *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int fgetc (FILE *);
char * fgets (char *__restrict, int, FILE *__restrict);
int fputc (int, FILE *);
int fputs (const char *__restrict, FILE *__restrict);
int getc (FILE *);
int getchar (void);
char * gets (char *);
int putc (int, FILE *);
int putchar (int);
int puts (const char *);
int ungetc (int, FILE *);
size_t fread (void *__restrict, size_t _size, size_t _n, FILE *__restrict);
size_t fwrite (const void *__restrict , size_t _size, size_t _n, FILE *);
#ifdef _COMPILING_NEWLIB
int fgetpos (FILE *, _fpos_t *);
#else
int fgetpos (FILE *__restrict, fpos_t *__restrict);
#endif
int fseek (FILE *, long, int);
#ifdef _COMPILING_NEWLIB
int fsetpos (FILE *, const _fpos_t *);
#else
int fsetpos (FILE *, const fpos_t *);
#endif
long ftell ( FILE *);
void rewind (FILE *);
void clearerr (FILE *);
int feof (FILE *);
int ferror (FILE *);
void perror (const char *);
#ifndef _REENT_ONLY
FILE * fopen (const char *__restrict _name, const char *__restrict _type);
int sprintf (char *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
int remove (const char *);
int rename (const char *, const char *);
#ifdef _COMPILING_NEWLIB
int _rename (const char *, const char *);
#endif
#endif
#if __LARGEFILE_VISIBLE || __POSIX_VISIBLE >= 200112
#ifdef _COMPILING_NEWLIB
int fseeko (FILE *, _off_t, int);
_off_t ftello (FILE *);
#else
int fseeko (FILE *, off_t, int);
off_t ftello (FILE *);
#endif
#endif
#if __GNU_VISIBLE
int fcloseall (void);
#endif
#ifndef _REENT_ONLY
#if __ISO_C_VISIBLE >= 1999
int snprintf (char *__restrict, size_t, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int vsnprintf (char *__restrict, size_t, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int vfscanf (FILE *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0)));
int vscanf (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 1, 0)));
int vsscanf (const char *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0)));
#endif
#if __GNU_VISIBLE
int asprintf (char **__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
int vasprintf (char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
#endif
#if __MISC_VISIBLE /* Newlib-specific */
int asiprintf (char **, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
char * asniprintf (char *, size_t *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
char * asnprintf (char *__restrict, size_t *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
#ifndef diprintf
int diprintf (int, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
#endif
int fiprintf (FILE *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
int fiscanf (FILE *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3)));
int iprintf (const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 1, 2)));
int iscanf (const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 1, 2)));
int siprintf (char *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
int siscanf (const char *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3)));
int sniprintf (char *, size_t, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int vasiprintf (char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
char * vasniprintf (char *, size_t *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
char * vasnprintf (char *, size_t *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int vdiprintf (int, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int vfiprintf (FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int vfiscanf (FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0)));
int viprintf (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 1, 0)));
int viscanf (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 1, 0)));
int vsiprintf (char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int vsiscanf (const char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0)));
int vsniprintf (char *, size_t, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
#endif /* __MISC_VISIBLE */
#endif /* !_REENT_ONLY */
/*
* Routines in POSIX 1003.1:2001.
*/
#if __POSIX_VISIBLE
#ifndef _REENT_ONLY
FILE * fdopen (int, const char *);
#endif
int fileno (FILE *);
#endif
#if __MISC_VISIBLE || __POSIX_VISIBLE >= 199209
int pclose (FILE *);
FILE * popen (const char *, const char *);
#endif
#if __BSD_VISIBLE
void setbuffer (FILE *, char *, int);
int setlinebuf (FILE *);
#endif
#if __MISC_VISIBLE || (__XSI_VISIBLE && __POSIX_VISIBLE < 200112)
int getw (FILE *);
int putw (int, FILE *);
#endif
#if __MISC_VISIBLE || __POSIX_VISIBLE
int getc_unlocked (FILE *);
int getchar_unlocked (void);
void flockfile (FILE *);
int ftrylockfile (FILE *);
void funlockfile (FILE *);
int putc_unlocked (int, FILE *);
int putchar_unlocked (int);
#endif
/*
* Routines in POSIX 1003.1:200x.
*/
#if __POSIX_VISIBLE >= 200809
# ifndef _REENT_ONLY
# ifndef dprintf
int dprintf (int, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
# endif
FILE * fmemopen (void *__restrict, size_t, const char *__restrict);
/* getdelim - see __getdelim for now */
/* getline - see __getline for now */
FILE * open_memstream (char **, size_t *);
int vdprintf (int, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
# endif
#endif
#if __ATFILE_VISIBLE
int renameat (int, const char *, int, const char *);
# ifdef __CYGWIN__
int renameat2 (int, const char *, int, const char *, unsigned int);
# endif
#endif
/*
* Recursive versions of the above.
*/
int _asiprintf_r (struct _reent *, char **, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
char * _asniprintf_r (struct _reent *, char *, size_t *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 4, 5)));
char * _asnprintf_r (struct _reent *, char *__restrict, size_t *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 4, 5)));
int _asprintf_r (struct _reent *, char **__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int _diprintf_r (struct _reent *, int, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int _dprintf_r (struct _reent *, int, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int _fclose_r (struct _reent *, FILE *);
int _fcloseall_r (struct _reent *);
FILE * _fdopen_r (struct _reent *, int, const char *);
int _fflush_r (struct _reent *, FILE *);
int _fgetc_r (struct _reent *, FILE *);
int _fgetc_unlocked_r (struct _reent *, FILE *);
char * _fgets_r (struct _reent *, char *__restrict, int, FILE *__restrict);
char * _fgets_unlocked_r (struct _reent *, char *__restrict, int, FILE *__restrict);
#ifdef _COMPILING_NEWLIB
int _fgetpos_r (struct _reent *, FILE *__restrict, _fpos_t *__restrict);
int _fsetpos_r (struct _reent *, FILE *, const _fpos_t *);
#else
int _fgetpos_r (struct _reent *, FILE *, fpos_t *);
int _fsetpos_r (struct _reent *, FILE *, const fpos_t *);
#endif
int _fiprintf_r (struct _reent *, FILE *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int _fiscanf_r (struct _reent *, FILE *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 3, 4)));
FILE * _fmemopen_r (struct _reent *, void *__restrict, size_t, const char *__restrict);
FILE * _fopen_r (struct _reent *, const char *__restrict, const char *__restrict);
FILE * _freopen_r (struct _reent *, const char *__restrict, const char *__restrict, FILE *__restrict);
int _fprintf_r (struct _reent *, FILE *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int _fpurge_r (struct _reent *, FILE *);
int _fputc_r (struct _reent *, int, FILE *);
int _fputc_unlocked_r (struct _reent *, int, FILE *);
int _fputs_r (struct _reent *, const char *__restrict, FILE *__restrict);
int _fputs_unlocked_r (struct _reent *, const char *__restrict, FILE *__restrict);
size_t _fread_r (struct _reent *, void *__restrict, size_t _size, size_t _n, FILE *__restrict);
size_t _fread_unlocked_r (struct _reent *, void *__restrict, size_t _size, size_t _n, FILE *__restrict);
int _fscanf_r (struct _reent *, FILE *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 3, 4)));
int _fseek_r (struct _reent *, FILE *, long, int);
int _fseeko_r (struct _reent *, FILE *, _off_t, int);
long _ftell_r (struct _reent *, FILE *);
_off_t _ftello_r (struct _reent *, FILE *);
void _rewind_r (struct _reent *, FILE *);
size_t _fwrite_r (struct _reent *, const void *__restrict, size_t _size, size_t _n, FILE *__restrict);
size_t _fwrite_unlocked_r (struct _reent *, const void *__restrict, size_t _size, size_t _n, FILE *__restrict);
int _getc_r (struct _reent *, FILE *);
int _getc_unlocked_r (struct _reent *, FILE *);
int _getchar_r (struct _reent *);
int _getchar_unlocked_r (struct _reent *);
char * _gets_r (struct _reent *, char *);
int _iprintf_r (struct _reent *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
int _iscanf_r (struct _reent *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3)));
FILE * _open_memstream_r (struct _reent *, char **, size_t *);
void _perror_r (struct _reent *, const char *);
int _printf_r (struct _reent *, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3)));
int _putc_r (struct _reent *, int, FILE *);
int _putc_unlocked_r (struct _reent *, int, FILE *);
int _putchar_unlocked_r (struct _reent *, int);
int _putchar_r (struct _reent *, int);
int _puts_r (struct _reent *, const char *);
int _remove_r (struct _reent *, const char *);
int _rename_r (struct _reent *,
const char *_old, const char *_new);
int _scanf_r (struct _reent *, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3)));
int _siprintf_r (struct _reent *, char *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int _siscanf_r (struct _reent *, const char *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 3, 4)));
int _sniprintf_r (struct _reent *, char *, size_t, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 4, 5)));
int _snprintf_r (struct _reent *, char *__restrict, size_t, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 4, 5)));
int _sprintf_r (struct _reent *, char *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4)));
int _sscanf_r (struct _reent *, const char *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 3, 4)));
char * _tempnam_r (struct _reent *, const char *, const char *);
FILE * _tmpfile_r (struct _reent *);
char * _tmpnam_r (struct _reent *, char *);
int _ungetc_r (struct _reent *, int, FILE *);
int _vasiprintf_r (struct _reent *, char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
char * _vasniprintf_r (struct _reent*, char *, size_t *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0)));
char * _vasnprintf_r (struct _reent*, char *, size_t *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0)));
int _vasprintf_r (struct _reent *, char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int _vdiprintf_r (struct _reent *, int, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int _vdprintf_r (struct _reent *, int, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int _vfiprintf_r (struct _reent *, FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int _vfiscanf_r (struct _reent *, FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0)));
int _vfprintf_r (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int _vfscanf_r (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0)));
int _viprintf_r (struct _reent *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int _viscanf_r (struct _reent *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0)));
int _vprintf_r (struct _reent *, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0)));
int _vscanf_r (struct _reent *, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0)));
int _vsiprintf_r (struct _reent *, char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int _vsiscanf_r (struct _reent *, const char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0)));
int _vsniprintf_r (struct _reent *, char *, size_t, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0)));
int _vsnprintf_r (struct _reent *, char *__restrict, size_t, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0)));
int _vsprintf_r (struct _reent *, char *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0)));
int _vsscanf_r (struct _reent *, const char *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0)));
/* Other extensions. */
int fpurge (FILE *);
ssize_t __getdelim (char **, size_t *, int, FILE *);
ssize_t __getline (char **, size_t *, FILE *);
#if __MISC_VISIBLE
void clearerr_unlocked (FILE *);
int feof_unlocked (FILE *);
int ferror_unlocked (FILE *);
int fileno_unlocked (FILE *);
int fflush_unlocked (FILE *);
int fgetc_unlocked (FILE *);
int fputc_unlocked (int, FILE *);
size_t fread_unlocked (void *__restrict, size_t _size, size_t _n, FILE *__restrict);
size_t fwrite_unlocked (const void *__restrict , size_t _size, size_t _n, FILE *);
#endif
#if __GNU_VISIBLE
char * fgets_unlocked (char *__restrict, int, FILE *__restrict);
int fputs_unlocked (const char *__restrict, FILE *__restrict);
#endif
#ifdef __LARGE64_FILES
#if !defined(__CYGWIN__) || defined(_COMPILING_NEWLIB)
FILE * fdopen64 (int, const char *);
FILE * fopen64 (const char *, const char *);
FILE * freopen64 (const char *, const char *, FILE *);
_off64_t ftello64 (FILE *);
_off64_t fseeko64 (FILE *, _off64_t, int);
int fgetpos64 (FILE *, _fpos64_t *);
int fsetpos64 (FILE *, const _fpos64_t *);
FILE * tmpfile64 (void);
FILE * _fdopen64_r (struct _reent *, int, const char *);
FILE * _fopen64_r (struct _reent *,const char *, const char *);
FILE * _freopen64_r (struct _reent *, const char *, const char *, FILE *);
_off64_t _ftello64_r (struct _reent *, FILE *);
_off64_t _fseeko64_r (struct _reent *, FILE *, _off64_t, int);
int _fgetpos64_r (struct _reent *, FILE *, _fpos64_t *);
int _fsetpos64_r (struct _reent *, FILE *, const _fpos64_t *);
FILE * _tmpfile64_r (struct _reent *);
#endif /* !__CYGWIN__ */
#endif /* __LARGE64_FILES */
/*
* Routines internal to the implementation.
*/
int __srget_r (struct _reent *, FILE *);
int __swbuf_r (struct _reent *, int, FILE *);
/*
* Stdio function-access interface.
*/
#if __BSD_VISIBLE
# ifdef __LARGE64_FILES
FILE *funopen (const void *__cookie,
int (*__readfn)(void *__c, char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
int (*__writefn)(void *__c, const char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
_fpos64_t (*__seekfn)(void *__c, _fpos64_t __off, int __whence),
int (*__closefn)(void *__c));
FILE *_funopen_r (struct _reent *, const void *__cookie,
int (*__readfn)(void *__c, char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
int (*__writefn)(void *__c, const char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
_fpos64_t (*__seekfn)(void *__c, _fpos64_t __off, int __whence),
int (*__closefn)(void *__c));
# else
FILE *funopen (const void *__cookie,
int (*__readfn)(void *__cookie, char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
int (*__writefn)(void *__cookie, const char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
fpos_t (*__seekfn)(void *__cookie, fpos_t __off, int __whence),
int (*__closefn)(void *__cookie));
FILE *_funopen_r (struct _reent *, const void *__cookie,
int (*__readfn)(void *__cookie, char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
int (*__writefn)(void *__cookie, const char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
fpos_t (*__seekfn)(void *__cookie, fpos_t __off, int __whence),
int (*__closefn)(void *__cookie));
# endif /* !__LARGE64_FILES */
# define fropen(__cookie, __fn) funopen(__cookie, __fn, (int (*)())0, \
(fpos_t (*)())0, (int (*)())0)
# define fwopen(__cookie, __fn) funopen(__cookie, (int (*)())0, __fn, \
(fpos_t (*)())0, (int (*)())0)
#endif /* __BSD_VISIBLE */
#if __GNU_VISIBLE
typedef ssize_t cookie_read_function_t(void *__cookie, char *__buf, size_t __n);
typedef ssize_t cookie_write_function_t(void *__cookie, const char *__buf,
size_t __n);
# ifdef __LARGE64_FILES
typedef int cookie_seek_function_t(void *__cookie, _off64_t *__off,
int __whence);
# else
typedef int cookie_seek_function_t(void *__cookie, off_t *__off, int __whence);
# endif /* !__LARGE64_FILES */
typedef int cookie_close_function_t(void *__cookie);
typedef struct
{
/* These four struct member names are dictated by Linux; hopefully,
they don't conflict with any macros. */
cookie_read_function_t *read;
cookie_write_function_t *write;
cookie_seek_function_t *seek;
cookie_close_function_t *close;
} cookie_io_functions_t;
FILE *fopencookie (void *__cookie,
const char *__mode, cookie_io_functions_t __functions);
FILE *_fopencookie_r (struct _reent *, void *__cookie,
const char *__mode, cookie_io_functions_t __functions);
#endif /* __GNU_VISIBLE */
#ifndef __CUSTOM_FILE_IO__
/*
* The __sfoo macros are here so that we can
* define function versions in the C library.
*/
#define __sgetc_raw_r(__ptr, __f) (--(__f)->_r < 0 ? __srget_r(__ptr, __f) : (int)(*(__f)->_p++))
#ifdef __SCLE
/* For a platform with CR/LF, additional logic is required by
__sgetc_r which would otherwise simply be a macro; therefore we
use an inlined function. The function is only meant to be inlined
in place as used and the function body should never be emitted.
There are two possible means to this end when compiling with GCC,
one when compiling with a standard C99 compiler, and for other
compilers we're just stuck. At the moment, this issue only
affects the Cygwin target, so we'll most likely be using GCC. */
_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p);
_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p)
{
int __c = __sgetc_raw_r(__ptr, __p);
if ((__p->_flags & __SCLE) && (__c == '\r'))
{
int __c2 = __sgetc_raw_r(__ptr, __p);
if (__c2 == '\n')
__c = __c2;
else
ungetc(__c2, __p);
}
return __c;
}
#else
#define __sgetc_r(__ptr, __p) __sgetc_raw_r(__ptr, __p)
#endif
#ifdef __GNUC__
_ELIDABLE_INLINE int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) {
#ifdef __SCLE
if ((_p->_flags & __SCLE) && _c == '\n')
__sputc_r (_ptr, '\r', _p);
#endif
if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
return (*_p->_p++ = _c);
else
return (__swbuf_r(_ptr, _c, _p));
}
#else
/*
* This has been tuned to generate reasonable code on the vax using pcc
*/
#define __sputc_raw_r(__ptr, __c, __p) \
(--(__p)->_w < 0 ? \
(__p)->_w >= (__p)->_lbfsize ? \
(*(__p)->_p = (__c)), *(__p)->_p != '\n' ? \
(int)*(__p)->_p++ : \
__swbuf_r(__ptr, '\n', __p) : \
__swbuf_r(__ptr, (int)(__c), __p) : \
(*(__p)->_p = (__c), (int)*(__p)->_p++))
#ifdef __SCLE
#define __sputc_r(__ptr, __c, __p) \
((((__p)->_flags & __SCLE) && ((__c) == '\n')) \
? __sputc_raw_r(__ptr, '\r', (__p)) : 0 , \
__sputc_raw_r((__ptr), (__c), (__p)))
#else
#define __sputc_r(__ptr, __c, __p) __sputc_raw_r(__ptr, __c, __p)
#endif
#endif
#define __sfeof(p) ((int)(((p)->_flags & __SEOF) != 0))
#define __sferror(p) ((int)(((p)->_flags & __SERR) != 0))
#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
#define __sfileno(p) ((p)->_file)
#ifndef __cplusplus
#ifndef _REENT_SMALL
#define feof(p) __sfeof(p)
#define ferror(p) __sferror(p)
#define clearerr(p) __sclearerr(p)
#if __MISC_VISIBLE
#define feof_unlocked(p) __sfeof(p)
#define ferror_unlocked(p) __sferror(p)
#define clearerr_unlocked(p) __sclearerr(p)
#endif /* __MISC_VISIBLE */
#endif /* _REENT_SMALL */
#if 0 /* __POSIX_VISIBLE - FIXME: must initialize stdio first, use fn */
#define fileno(p) __sfileno(p)
#endif
static __inline int
_getchar_unlocked(void)
{
struct _reent *_ptr;
_ptr = _REENT;
return (__sgetc_r(_ptr, _stdin_r(_ptr)));
}
static __inline int
_putchar_unlocked(int _c)
{
struct _reent *_ptr;
_ptr = _REENT;
return (__sputc_r(_ptr, _c, _stdout_r(_ptr)));
}
#ifdef __SINGLE_THREAD__
#define getc(_p) __sgetc_r(_REENT, _p)
#define putc(_c, _p) __sputc_r(_REENT, _c, _p)
#define getchar() _getchar_unlocked()
#define putchar(_c) _putchar_unlocked(_c)
#endif /* __SINGLE_THREAD__ */
#if __MISC_VISIBLE || __POSIX_VISIBLE
#define getchar_unlocked() _getchar_unlocked()
#define putchar_unlocked(_c) _putchar_unlocked(_c)
#endif
#endif /* __cplusplus */
#if __MISC_VISIBLE
/* fast always-buffered version, true iff error */
#define fast_putc(x,p) (--(p)->_w < 0 ? \
__swbuf_r(_REENT, (int)(x), p) == EOF : (*(p)->_p = (x), (p)->_p++, 0))
#endif
#if __GNU_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 600)
#define L_cuserid 9 /* posix says it goes in stdio.h :( */
#endif
#if __POSIX_VISIBLE
#define L_ctermid 16
#endif
#else /* __CUSTOM_FILE_IO__ */
#define getchar() getc(stdin)
#define putchar(x) putc(x, stdout)
#if __MISC_VISIBLE || __POSIX_VISIBLE
#define getchar_unlocked() getc_unlocked(stdin)
#define putchar_unlocked(x) putc_unlocked(x, stdout)
#endif
#endif /* !__CUSTOM_FILE_IO__ */
_END_STD_C
#if __SSP_FORTIFY_LEVEL > 0
#include <ssp/stdio.h>
#endif
#endif /* _STDIO_H_ */

342
src/include/stdlib.h Executable file
View File

@ -0,0 +1,342 @@
/*
* stdlib.h
*
* Definitions for common types, variables, and functions.
*/
#ifndef _STDLIB_H_
#define _STDLIB_H_
#include <machine/ieeefp.h>
#include "_ansi.h"
#define __need_size_t
#define __need_wchar_t
#define __need_NULL
#include <stddef.h>
#include <sys/reent.h>
#include <sys/cdefs.h>
#include <machine/stdlib.h>
#ifndef __STRICT_ANSI__
#include <alloca.h>
#endif
#ifdef __CYGWIN__
#include <cygwin/stdlib.h>
#endif
#if __GNU_VISIBLE
#include <xlocale.h>
#endif
_BEGIN_STD_C
typedef struct
{
int quot; /* quotient */
int rem; /* remainder */
} div_t;
typedef struct
{
long quot; /* quotient */
long rem; /* remainder */
} ldiv_t;
#if __ISO_C_VISIBLE >= 1999
typedef struct
{
long long int quot; /* quotient */
long long int rem; /* remainder */
} lldiv_t;
#endif
#ifndef __compar_fn_t_defined
#define __compar_fn_t_defined
typedef int (*__compar_fn_t) (const void *, const void *);
#endif
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#define RAND_MAX __RAND_MAX
int __locale_mb_cur_max (void);
#define MB_CUR_MAX __locale_mb_cur_max()
void abort (void) _ATTRIBUTE ((__noreturn__));
int abs (int);
#if __BSD_VISIBLE
__uint32_t arc4random (void);
__uint32_t arc4random_uniform (__uint32_t);
void arc4random_buf (void *, size_t);
#endif
int atexit (void (*__func)(void));
double atof (const char *__nptr);
#if __MISC_VISIBLE
float atoff (const char *__nptr);
#endif
int atoi (const char *__nptr);
int _atoi_r (struct _reent *, const char *__nptr);
long atol (const char *__nptr);
long _atol_r (struct _reent *, const char *__nptr);
void * bsearch (const void *__key,
const void *__base,
size_t __nmemb,
size_t __size,
__compar_fn_t _compar);
void *calloc(size_t, size_t) __malloc_like __result_use_check
__alloc_size2(1, 2) _NOTHROW;
div_t div (int __numer, int __denom);
void exit (int __status) _ATTRIBUTE ((__noreturn__));
void free (void *) _NOTHROW;
char * getenv (const char *__string);
char * _getenv_r (struct _reent *, const char *__string);
char * _findenv (const char *, int *);
char * _findenv_r (struct _reent *, const char *, int *);
#if __POSIX_VISIBLE >= 200809
extern char *suboptarg; /* getsubopt(3) external variable */
int getsubopt (char **, char * const *, char **);
#endif
long labs (long);
ldiv_t ldiv (long __numer, long __denom);
void *malloc(size_t) __malloc_like __result_use_check __alloc_size(1) _NOTHROW;
int mblen (const char *, size_t);
int _mblen_r (struct _reent *, const char *, size_t, _mbstate_t *);
int mbtowc (wchar_t *__restrict, const char *__restrict, size_t);
int _mbtowc_r (struct _reent *, wchar_t *__restrict, const char *__restrict, size_t, _mbstate_t *);
int wctomb (char *, wchar_t);
int _wctomb_r (struct _reent *, char *, wchar_t, _mbstate_t *);
size_t mbstowcs (wchar_t *__restrict, const char *__restrict, size_t);
size_t _mbstowcs_r (struct _reent *, wchar_t *__restrict, const char *__restrict, size_t, _mbstate_t *);
size_t wcstombs (char *__restrict, const wchar_t *__restrict, size_t);
size_t _wcstombs_r (struct _reent *, char *__restrict, const wchar_t *__restrict, size_t, _mbstate_t *);
#ifndef _REENT_ONLY
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809
char * mkdtemp (char *);
#endif
#if __GNU_VISIBLE
int mkostemp (char *, int);
int mkostemps (char *, int, int);
#endif
#if __MISC_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 4
int mkstemp (char *);
#endif
#if __MISC_VISIBLE
int mkstemps (char *, int);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112)
char * mktemp (char *) _ATTRIBUTE ((__deprecated__("the use of `mktemp' is dangerous; use `mkstemp' instead")));
#endif
#endif /* !_REENT_ONLY */
char * _mkdtemp_r (struct _reent *, char *);
int _mkostemp_r (struct _reent *, char *, int);
int _mkostemps_r (struct _reent *, char *, int, int);
int _mkstemp_r (struct _reent *, char *);
int _mkstemps_r (struct _reent *, char *, int);
char * _mktemp_r (struct _reent *, char *) _ATTRIBUTE ((__deprecated__("the use of `mktemp' is dangerous; use `mkstemp' instead")));
void qsort (void *__base, size_t __nmemb, size_t __size, __compar_fn_t _compar);
int rand (void);
void *realloc(void *, size_t) __result_use_check __alloc_size(2) _NOTHROW;
#if __BSD_VISIBLE
void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size2(2, 3);
void *reallocf(void *, size_t) __result_use_check __alloc_size(2);
#endif
#if __BSD_VISIBLE || __XSI_VISIBLE >= 4
char * realpath (const char *__restrict path, char *__restrict resolved_path);
#endif
#if __BSD_VISIBLE
int rpmatch (const char *response);
#endif
#if __XSI_VISIBLE
void setkey (const char *__key);
#endif
void srand (unsigned __seed);
double strtod (const char *__restrict __n, char **__restrict __end_PTR);
double _strtod_r (struct _reent *,const char *__restrict __n, char **__restrict __end_PTR);
#if __ISO_C_VISIBLE >= 1999
float strtof (const char *__restrict __n, char **__restrict __end_PTR);
#endif
#if __MISC_VISIBLE
/* the following strtodf interface is deprecated...use strtof instead */
# ifndef strtodf
# define strtodf strtof
# endif
#endif
long strtol (const char *__restrict __n, char **__restrict __end_PTR, int __base);
long _strtol_r (struct _reent *,const char *__restrict __n, char **__restrict __end_PTR, int __base);
unsigned long strtoul (const char *__restrict __n, char **__restrict __end_PTR, int __base);
unsigned long _strtoul_r (struct _reent *,const char *__restrict __n, char **__restrict __end_PTR, int __base);
#if __GNU_VISIBLE
double strtod_l (const char *__restrict, char **__restrict, locale_t);
float strtof_l (const char *__restrict, char **__restrict, locale_t);
#ifdef _HAVE_LONG_DOUBLE
extern long double strtold_l (const char *__restrict, char **__restrict,
locale_t);
#endif /* _HAVE_LONG_DOUBLE */
long strtol_l (const char *__restrict, char **__restrict, int, locale_t);
unsigned long strtoul_l (const char *__restrict, char **__restrict, int,
locale_t __loc);
long long strtoll_l (const char *__restrict, char **__restrict, int, locale_t);
unsigned long long strtoull_l (const char *__restrict, char **__restrict, int,
locale_t __loc);
#endif
int system (const char *__string);
#if __SVID_VISIBLE || __XSI_VISIBLE >= 4
long a64l (const char *__input);
char * l64a (long __input);
char * _l64a_r (struct _reent *,long __input);
#endif
#if __MISC_VISIBLE
int on_exit (void (*__func)(int, void *),void *__arg);
#endif
#if __ISO_C_VISIBLE >= 1999
void _Exit (int __status) _ATTRIBUTE ((__noreturn__));
#endif
#if __SVID_VISIBLE || __XSI_VISIBLE
int putenv (char *__string);
#endif
int _putenv_r (struct _reent *, char *__string);
void * _reallocf_r (struct _reent *, void *, size_t);
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112
int setenv (const char *__string, const char *__value, int __overwrite);
#endif
int _setenv_r (struct _reent *, const char *__string, const char *__value, int __overwrite);
#if __XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112
char * gcvt (double,int,char *);
char * gcvtf (float,int,char *);
char * fcvt (double,int,int *,int *);
char * fcvtf (float,int,int *,int *);
char * ecvt (double,int,int *,int *);
char * ecvtbuf (double, int, int*, int*, char *);
char * fcvtbuf (double, int, int*, int*, char *);
char * ecvtf (float,int,int *,int *);
#endif
char * __itoa (int, char *, int);
char * __utoa (unsigned, char *, int);
#if __MISC_VISIBLE
char * itoa (int, char *, int);
char * utoa (unsigned, char *, int);
#endif
#if __POSIX_VISIBLE
int rand_r (unsigned *__seed);
#endif
#if __SVID_VISIBLE || __XSI_VISIBLE
double drand48 (void);
double _drand48_r (struct _reent *);
double erand48 (unsigned short [3]);
double _erand48_r (struct _reent *, unsigned short [3]);
long jrand48 (unsigned short [3]);
long _jrand48_r (struct _reent *, unsigned short [3]);
void lcong48 (unsigned short [7]);
void _lcong48_r (struct _reent *, unsigned short [7]);
long lrand48 (void);
long _lrand48_r (struct _reent *);
long mrand48 (void);
long _mrand48_r (struct _reent *);
long nrand48 (unsigned short [3]);
long _nrand48_r (struct _reent *, unsigned short [3]);
unsigned short *
seed48 (unsigned short [3]);
unsigned short *
_seed48_r (struct _reent *, unsigned short [3]);
void srand48 (long);
void _srand48_r (struct _reent *, long);
#endif /* __SVID_VISIBLE || __XSI_VISIBLE */
#if __SVID_VISIBLE || __XSI_VISIBLE >= 4 || __BSD_VISIBLE
char * initstate (unsigned, char *, size_t);
long random (void);
char * setstate (char *);
void srandom (unsigned);
#endif
#if __ISO_C_VISIBLE >= 1999
long long atoll (const char *__nptr);
#endif
long long _atoll_r (struct _reent *, const char *__nptr);
#if __ISO_C_VISIBLE >= 1999
long long llabs (long long);
lldiv_t lldiv (long long __numer, long long __denom);
long long strtoll (const char *__restrict __n, char **__restrict __end_PTR, int __base);
#endif
long long _strtoll_r (struct _reent *, const char *__restrict __n, char **__restrict __end_PTR, int __base);
#if __ISO_C_VISIBLE >= 1999
unsigned long long strtoull (const char *__restrict __n, char **__restrict __end_PTR, int __base);
#endif
unsigned long long _strtoull_r (struct _reent *, const char *__restrict __n, char **__restrict __end_PTR, int __base);
#ifndef __CYGWIN__
#if __MISC_VISIBLE
void cfree (void *);
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112
int unsetenv (const char *__string);
#endif
int _unsetenv_r (struct _reent *, const char *__string);
#endif /* !__CYGWIN__ */
#if __POSIX_VISIBLE >= 200112
int posix_memalign (void **, size_t, size_t) __nonnull((1))
__result_use_check;
#endif
char * _dtoa_r (struct _reent *, double, int, int, int *, int*, char**);
#ifndef __CYGWIN__
void * _malloc_r (struct _reent *, size_t) _NOTHROW;
void * _calloc_r (struct _reent *, size_t, size_t) _NOTHROW;
void _free_r (struct _reent *, void *) _NOTHROW;
void * _realloc_r (struct _reent *, void *, size_t) _NOTHROW;
void _mstats_r (struct _reent *, char *);
#endif
int _system_r (struct _reent *, const char *);
void __eprintf (const char *, const char *, unsigned int, const char *);
/* There are two common qsort_r variants. If you request
_BSD_SOURCE, you get the BSD version; otherwise you get the GNU
version. We want that #undef qsort_r will still let you
invoke the underlying function, but that requires gcc support. */
#if __GNU_VISIBLE
void qsort_r (void *__base, size_t __nmemb, size_t __size, int (*_compar)(const void *, const void *, void *), void *__thunk);
#elif __BSD_VISIBLE
# ifdef __GNUC__
void qsort_r (void *__base, size_t __nmemb, size_t __size, void *__thunk, int (*_compar)(void *, const void *, const void *))
__asm__ (__ASMNAME ("__bsd_qsort_r"));
# else
void __bsd_qsort_r (void *__base, size_t __nmemb, size_t __size, void *__thunk, int (*_compar)(void *, const void *, const void *));
# define qsort_r __bsd_qsort_r
# endif
#endif
/* On platforms where long double equals double. */
#ifdef _HAVE_LONG_DOUBLE
extern long double _strtold_r (struct _reent *, const char *__restrict, char **__restrict);
#if __ISO_C_VISIBLE >= 1999
extern long double strtold (const char *__restrict, char **__restrict);
#endif
#endif /* _HAVE_LONG_DOUBLE */
/*
* If we're in a mode greater than C99, expose C11 functions.
*/
#if __ISO_C_VISIBLE >= 2011
void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1)
__alloc_size(2) __result_use_check;
int at_quick_exit(void (*)(void));
_Noreturn void
quick_exit(int);
#endif /* __ISO_C_VISIBLE >= 2011 */
_END_STD_C
#if __SSP_FORTIFY_LEVEL > 0
#include <ssp/stdlib.h>
#endif
#endif /* _STDLIB_H_ */

183
src/include/string.h Executable file
View File

@ -0,0 +1,183 @@
/*
* string.h
*
* Definitions for memory and string functions.
*/
#ifndef _STRING_H_
#define _STRING_H_
#include "_ansi.h"
#include <sys/reent.h>
#include <sys/cdefs.h>
#include <sys/features.h>
#define __need_size_t
#define __need_NULL
#include <stddef.h>
#if __POSIX_VISIBLE >= 200809
#include <xlocale.h>
#endif
#if __BSD_VISIBLE
#include <strings.h>
#endif
_BEGIN_STD_C
void * memchr (const void *, int, size_t);
int memcmp (const void *, const void *, size_t);
void * memcpy (void *__restrict, const void *__restrict, size_t);
void * memmove (void *, const void *, size_t);
void * memset (void *, int, size_t);
char *strcat (char *__restrict, const char *__restrict);
char *strchr (const char *, int);
int strcmp (const char *, const char *);
int strcoll (const char *, const char *);
char *strcpy (char *__restrict, const char *__restrict);
size_t strcspn (const char *, const char *);
char *strerror (int);
size_t strlen (const char *);
char *strncat (char *__restrict, const char *__restrict, size_t);
int strncmp (const char *, const char *, size_t);
char *strncpy (char *__restrict, const char *__restrict, size_t);
char *strpbrk (const char *, const char *);
char *strrchr (const char *, int);
size_t strspn (const char *, const char *);
char *strstr (const char *, const char *);
#ifndef _REENT_ONLY
char *strtok (char *__restrict, const char *__restrict);
#endif
size_t strxfrm (char *__restrict, const char *__restrict, size_t);
#if __POSIX_VISIBLE >= 200809
int strcoll_l (const char *, const char *, locale_t);
char *strerror_l (int, locale_t);
size_t strxfrm_l (char *__restrict, const char *__restrict, size_t, locale_t);
#endif
#if __MISC_VISIBLE || __POSIX_VISIBLE
char *strtok_r (char *__restrict, const char *__restrict, char **__restrict);
#endif
#if __BSD_VISIBLE
int timingsafe_bcmp (const void *, const void *, size_t);
int timingsafe_memcmp (const void *, const void *, size_t);
#endif
#if __MISC_VISIBLE || __POSIX_VISIBLE
void * memccpy (void *__restrict, const void *__restrict, int, size_t);
#endif
#if __GNU_VISIBLE
void * mempcpy (void *, const void *, size_t);
void * memmem (const void *, size_t, const void *, size_t);
void * memrchr (const void *, int, size_t);
void * rawmemchr (const void *, int);
#endif
#if __POSIX_VISIBLE >= 200809
char *stpcpy (char *__restrict, const char *__restrict);
char *stpncpy (char *__restrict, const char *__restrict, size_t);
#endif
#if __GNU_VISIBLE
char *strcasestr (const char *, const char *);
char *strchrnul (const char *, int);
#endif
#if __MISC_VISIBLE || __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 4
char *strdup (const char *) __malloc_like __result_use_check;
#endif
char *_strdup_r (struct _reent *, const char *);
#if __POSIX_VISIBLE >= 200809
char *strndup (const char *, size_t) __malloc_like __result_use_check;
#endif
char *_strndup_r (struct _reent *, const char *, size_t);
/* There are two common strerror_r variants. If you request
_GNU_SOURCE, you get the GNU version; otherwise you get the POSIX
version. POSIX requires that #undef strerror_r will still let you
invoke the underlying function, but that requires gcc support. */
#if __GNU_VISIBLE
char *strerror_r (int, char *, size_t);
#elif __POSIX_VISIBLE >= 200112
# ifdef __GNUC__
int strerror_r (int, char *, size_t)
#ifdef __ASMNAME
__asm__ (__ASMNAME ("__xpg_strerror_r"))
#endif
;
# else
int __xpg_strerror_r (int, char *, size_t);
# define strerror_r __xpg_strerror_r
# endif
#endif
/* Reentrant version of strerror. */
char * _strerror_r (struct _reent *, int, int, int *);
#if __BSD_VISIBLE
size_t strlcat (char *, const char *, size_t);
size_t strlcpy (char *, const char *, size_t);
#endif
#if __POSIX_VISIBLE >= 200809
size_t strnlen (const char *, size_t);
#endif
#if __BSD_VISIBLE
char *strsep (char **, const char *);
#endif
#if __BSD_VISIBLE
char *strnstr(const char *, const char *, size_t) __pure;
#endif
#if __MISC_VISIBLE
char *strlwr (char *);
char *strupr (char *);
#endif
#ifndef DEFS_H /* Kludge to work around problem compiling in gdb */
char *strsignal (int __signo);
#endif
#ifdef __CYGWIN__
int strtosigno (const char *__name);
#endif
#if __GNU_VISIBLE
int strverscmp (const char *, const char *);
#endif
#if __GNU_VISIBLE && defined(__GNUC__)
#define strdupa(__s) \
(__extension__ ({const char *__sin = (__s); \
size_t __len = strlen (__sin) + 1; \
char * __sout = (char *) __builtin_alloca (__len); \
(char *) memcpy (__sout, __sin, __len);}))
#define strndupa(__s, __n) \
(__extension__ ({const char *__sin = (__s); \
size_t __len = strnlen (__sin, (__n)) + 1; \
char *__sout = (char *) __builtin_alloca (__len); \
__sout[__len-1] = '\0'; \
(char *) memcpy (__sout, __sin, __len-1);}))
#endif /* __GNU_VISIBLE && __GNUC__ */
/* There are two common basename variants. If you do NOT #include <libgen.h>
and you do
#define _GNU_SOURCE
#include <string.h>
you get the GNU version. Otherwise you get the POSIX versionfor which you
should #include <libgen.h>i for the function prototype. POSIX requires that
#undef basename will still let you invoke the underlying function. However,
this also implies that the POSIX version is used in this case. That's made
sure here. */
#if __GNU_VISIBLE && !defined(basename)
# define basename basename
char *__nonnull ((1)) basename (const char *) __asm__(__ASMNAME("__gnu_basename"));
#endif
#include <sys/string.h>
_END_STD_C
#if __SSP_FORTIFY_LEVEL > 0
#include <ssp/string.h>
#endif
#endif /* _STRING_H_ */

80
src/include/strings.h Executable file
View File

@ -0,0 +1,80 @@
/*-
* Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
* 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: head/include/strings.h 272673 2014-10-07 04:54:11Z delphij $
*/
#ifndef _STRINGS_H_
#define _STRINGS_H_
#include <sys/cdefs.h>
#include <sys/_types.h>
#if __POSIX_VISIBLE >= 200809
#include <xlocale.h>
#endif
#ifndef _SIZE_T_DECLARED
typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
__BEGIN_DECLS
#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112
int bcmp(const void *, const void *, size_t) __pure; /* LEGACY */
void bcopy(const void *, void *, size_t); /* LEGACY */
void bzero(void *, size_t); /* LEGACY */
#endif
#if __BSD_VISIBLE
void explicit_bzero(void *, size_t);
#endif
#if __MISC_VISIBLE || __POSIX_VISIBLE < 200809 || __XSI_VISIBLE >= 700
int ffs(int) __pure2;
#endif
#if __BSD_VISIBLE
int ffsl(long) __pure2;
int ffsll(long long) __pure2;
int fls(int) __pure2;
int flsl(long) __pure2;
int flsll(long long) __pure2;
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112
char *index(const char *, int) __pure; /* LEGACY */
char *rindex(const char *, int) __pure; /* LEGACY */
#endif
int strcasecmp(const char *, const char *) __pure;
int strncasecmp(const char *, const char *, size_t) __pure;
#if __POSIX_VISIBLE >= 200809
int strcasecmp_l (const char *, const char *, locale_t);
int strncasecmp_l (const char *, const char *, size_t, locale_t);
#endif
__END_DECLS
#if __SSP_FORTIFY_LEVEL > 0
#include <ssp/strings.h>
#endif
#endif /* _STRINGS_H_ */

195
src/include/sys/_intsup.h Executable file
View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2004, 2005 by
* Ralf Corsepius, Ulm/Germany. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
#ifndef _SYS__INTSUP_H
#define _SYS__INTSUP_H
#include <sys/features.h>
#if __GNUC_PREREQ (3, 2)
/* gcc > 3.2 implicitly defines the values we are interested */
#define __STDINT_EXP(x) __##x##__
#else
#define __STDINT_EXP(x) x
#include <limits.h>
#endif
/* Determine how intptr_t and intN_t fastN_t and leastN_t are defined by gcc
for this target. This is used to determine the correct printf() constant in
inttypes.h and other constants in stdint.h.
So we end up with
?(signed|unsigned) char == 0
?(signed|unsigned) short == 1
?(signed|unsigned) int == 2
?(signed|unsigned) short int == 3
?(signed|unsigned) long == 4
?(signed|unsigned) long int == 6
?(signed|unsigned) long long == 8
?(signed|unsigned) long long int == 10
*/
#pragma push_macro("signed")
#pragma push_macro("unsigned")
#pragma push_macro("char")
#pragma push_macro("short")
#pragma push_macro("__int20")
#pragma push_macro("int")
#pragma push_macro("long")
#undef signed
#undef unsigned
#undef char
#undef short
#undef int
#undef __int20
#undef long
#define signed +0
#define unsigned +0
#define char +0
#define short +1
#define __int20 +2
#define int +2
#define long +4
#if (__INTPTR_TYPE__ == 8 || __INTPTR_TYPE__ == 10)
#define _INTPTR_EQ_LONGLONG
#elif (__INTPTR_TYPE__ == 4 || __INTPTR_TYPE__ == 6)
#define _INTPTR_EQ_LONG
/* Note - the tests for _INTPTR_EQ_INT and _INTPTR_EQ_SHORT are currently
redundant as the values are not used. But one day they may be needed
and so the tests remain. */
#elif __INTPTR_TYPE__ == 2
#define _INTPTR_EQ_INT
#elif (__INTPTR_TYPE__ == 1 || __INTPTR_TYPE__ == 3)
#define _INTPTR_EQ_SHORT
#else
#error "Unable to determine type definition of intptr_t"
#endif
#if (__INT32_TYPE__ == 4 || __INT32_TYPE__ == 6)
#define _INT32_EQ_LONG
#elif __INT32_TYPE__ == 2
/* Nothing to define because int32_t is safe to print as an int. */
#else
#error "Unable to determine type definition of int32_t"
#endif
#if (__INT8_TYPE__ == 0)
#define __INT8 "hh"
#elif (__INT8_TYPE__ == 1 || __INT8_TYPE__ == 3)
#define __INT8 "h"
#elif (__INT8_TYPE__ == 2)
#define __INT8
#elif (__INT8_TYPE__ == 4 || __INT8_TYPE__ == 6)
#define __INT8 "l"
#elif (__INT8_TYPE__ == 8 || __INT8_TYPE__ == 10)
#define __INT8 "ll"
#endif
#if (__INT16_TYPE__ == 1 || __INT16_TYPE__ == 3)
#define __INT16 "h"
#elif (__INT16_TYPE__ == 2)
#define __INT16
#elif (__INT16_TYPE__ == 4 || __INT16_TYPE__ == 6)
#define __INT16 "l"
#elif (__INT16_TYPE__ == 8 || __INT16_TYPE__ == 10)
#define __INT16 "ll"
#endif
#if (__INT32_TYPE__ == 2)
#define __INT32
#elif (__INT32_TYPE__ == 4 || __INT32_TYPE__ == 6)
#define __INT32 "l"
#elif (__INT32_TYPE__ == 8 || __INT32_TYPE__ == 10)
#define __INT32 "ll"
#endif
#if (__INT64_TYPE__ == 2)
#define __INT64
#elif (__INT64_TYPE__ == 4 || __INT64_TYPE__ == 6)
#define __INT64 "l"
#elif (__INT64_TYPE__ == 8 || __INT64_TYPE__ == 10)
#define __INT64 "ll"
#endif
#if (__INT_FAST8_TYPE__ == 0)
#define __FAST8 "hh"
#elif (__INT_FAST8_TYPE__ == 1 || __INT_FAST8_TYPE__ == 3)
#define __FAST8 "h"
#elif (__INT_FAST8_TYPE__ == 2)
#define __FAST8
#elif (__INT_FAST8_TYPE__ == 4 || __INT_FAST8_TYPE__ == 6)
#define __FAST8 "l"
#elif (__INT_FAST8_TYPE__ == 8 || __INT_FAST8_TYPE__ == 10)
#define __FAST8 "ll"
#endif
#if (__INT_FAST16_TYPE__ == 1 || __INT_FAST16_TYPE__ == 3)
#define __FAST16 "h"
#elif (__INT_FAST16_TYPE__ == 2)
#define __FAST16
#elif (__INT_FAST16_TYPE__ == 4 || __INT_FAST16_TYPE__ == 6)
#define __FAST16 "l"
#elif (__INT_FAST16_TYPE__ == 8 || __INT_FAST16_TYPE__ == 10)
#define __FAST16 "ll"
#endif
#if (__INT_FAST32_TYPE__ == 2)
#define __FAST32
#elif (__INT_FAST32_TYPE__ == 4 || __INT_FAST32_TYPE__ == 6)
#define __FAST32 "l"
#elif (__INT_FAST32_TYPE__ == 8 || __INT_FAST32_TYPE__ == 10)
#define __FAST32 "ll"
#endif
#if (__INT_FAST64_TYPE__ == 2)
#define __FAST64
#elif (__INT_FAST64_TYPE__ == 4 || __INT_FAST64_TYPE__ == 6)
#define __FAST64 "l"
#elif (__INT_FAST64_TYPE__ == 8 || __INT_FAST64_TYPE__ == 10)
#define __FAST64 "ll"
#endif
#if (__INT_LEAST8_TYPE__ == 0)
#define __LEAST8 "hh"
#elif (__INT_LEAST8_TYPE__ == 1 || __INT_LEAST8_TYPE__ == 3)
#define __LEAST8 "h"
#elif (__INT_LEAST8_TYPE__ == 2)
#define __LEAST8
#elif (__INT_LEAST8_TYPE__ == 4 || __INT_LEAST8_TYPE__ == 6)
#define __LEAST8 "l"
#elif (__INT_LEAST8_TYPE__ == 8 || __INT_LEAST8_TYPE__ == 10)
#define __LEAST8 "ll"
#endif
#if (__INT_LEAST16_TYPE__ == 1 || __INT_LEAST16_TYPE__ == 3)
#define __LEAST16 "h"
#elif (__INT_LEAST16_TYPE__ == 2)
#define __LEAST16
#elif (__INT_LEAST16_TYPE__ == 4 || __INT_LEAST16_TYPE__ == 6)
#define __LEAST16 "l"
#elif (__INT_LEAST16_TYPE__ == 8 || __INT_LEAST16_TYPE__ == 10)
#define __LEAST16 "ll"
#endif
#if (__INT_LEAST32_TYPE__ == 2)
#define __LEAST32
#elif (__INT_LEAST32_TYPE__ == 4 || __INT_LEAST32_TYPE__ == 6)
#define __LEAST32 "l"
#elif (__INT_LEAST32_TYPE__ == 8 || __INT_LEAST32_TYPE__ == 10)
#define __LEAST32 "ll"
#endif
#if (__INT_LEAST64_TYPE__ == 2)
#define __LEAST64
#elif (__INT_LEAST64_TYPE__ == 4 || __INT_LEAST64_TYPE__ == 6)
#define __LEAST64 "l"
#elif (__INT_LEAST64_TYPE__ == 8 || __INT_LEAST64_TYPE__ == 10)
#define __LEAST64 "ll"
#endif
#undef signed
#undef unsigned
#undef char
#undef short
#undef int
#undef long
#pragma pop_macro("signed")
#pragma pop_macro("unsigned")
#pragma pop_macro("char")
#pragma pop_macro("short")
#pragma pop_macro("__int20")
#pragma pop_macro("int")
#pragma pop_macro("long")
#endif /* _SYS__INTSUP_H */

233
src/include/sys/_pthreadtypes.h Executable file
View File

@ -0,0 +1,233 @@
/*
* Written by Joel Sherrill <joel.sherrill@OARcorp.com>.
*
* COPYRIGHT (c) 1989-2013, 2015.
* On-Line Applications Research Corporation (OAR).
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION
* OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
* SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#ifndef _SYS__PTHREADTYPES_H_
#define _SYS__PTHREADTYPES_H_
#if defined(_POSIX_THREADS) || __POSIX_VISIBLE >= 199506
#include <sys/sched.h>
/*
* 2.5 Primitive System Data Types, P1003.1c/D10, p. 19.
*/
#if defined(__XMK__)
typedef unsigned int pthread_t; /* identify a thread */
#else
typedef __uint32_t pthread_t; /* identify a thread */
#endif
/* P1003.1c/D10, p. 118-119 */
#define PTHREAD_SCOPE_PROCESS 0
#define PTHREAD_SCOPE_SYSTEM 1
/* P1003.1c/D10, p. 111 */
#define PTHREAD_INHERIT_SCHED 1 /* scheduling policy and associated */
/* attributes are inherited from */
/* the calling thread. */
#define PTHREAD_EXPLICIT_SCHED 2 /* set from provided attribute object */
/* P1003.1c/D10, p. 141 */
#define PTHREAD_CREATE_DETACHED 0
#define PTHREAD_CREATE_JOINABLE 1
#if defined(__XMK__)
typedef struct pthread_attr_s {
int contentionscope;
struct sched_param schedparam;
int detachstate;
void *stackaddr;
size_t stacksize;
} pthread_attr_t;
#define PTHREAD_STACK_MIN 200
#else /* !defined(__XMK__) */
typedef struct {
int is_initialized;
void *stackaddr;
int stacksize;
int contentionscope;
int inheritsched;
int schedpolicy;
struct sched_param schedparam;
/* P1003.4b/D8, p. 54 adds cputime_clock_allowed attribute. */
#if defined(_POSIX_THREAD_CPUTIME)
int cputime_clock_allowed; /* see time.h */
#endif
int detachstate;
} pthread_attr_t;
#endif /* !defined(__XMK__) */
#if defined(_POSIX_THREAD_PROCESS_SHARED)
/* NOTE: P1003.1c/D10, p. 81 defines following values for process_shared. */
#define PTHREAD_PROCESS_PRIVATE 0 /* visible within only the creating process */
#define PTHREAD_PROCESS_SHARED 1 /* visible too all processes with access to */
/* the memory where the resource is */
/* located */
#endif
#if defined(_POSIX_THREAD_PRIO_PROTECT)
/* Mutexes */
/* Values for blocking protocol. */
#define PTHREAD_PRIO_NONE 0
#define PTHREAD_PRIO_INHERIT 1
#define PTHREAD_PRIO_PROTECT 2
#endif
#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES)
/* Values for mutex type */
/* The following defines are part of the X/Open System Interface (XSI). */
/*
* This type of mutex does not detect deadlock. A thread attempting to
* relock this mutex without first unlocking it shall deadlock. Attempting
* to unlock a mutex locked by a different thread results in undefined
* behavior. Attempting to unlock an unlocked mutex results in undefined
* behavior.
*/
#define PTHREAD_MUTEX_NORMAL 0
/*
* A thread attempting to relock this mutex without first unlocking
* it shall succeed in locking the mutex. The relocking deadlock which
* can occur with mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with
* this type of mutex. Multiple locks of this mutex shall require the
* same number of unlocks to release the mutex before another thread can
* acquire the mutex. A thread attempting to unlock a mutex which another
* thread has locked shall return with an error. A thread attempting to
* unlock an unlocked mutex shall return with an error.
*/
#define PTHREAD_MUTEX_RECURSIVE 1
/*
* This type of mutex provides error checking. A thread attempting
* to relock this mutex without first unlocking it shall return with an
* error. A thread attempting to unlock a mutex which another thread has
* locked shall return with an error. A thread attempting to unlock an
* unlocked mutex shall return with an error.
*/
#define PTHREAD_MUTEX_ERRORCHECK 2
/*
* Attempting to recursively lock a mutex of this type results
* in undefined behavior. Attempting to unlock a mutex of this type
* which was not locked by the calling thread results in undefined
* behavior. Attempting to unlock a mutex of this type which is not locked
* results in undefined behavior. An implementation may map this mutex to
* one of the other mutex types.
*/
#define PTHREAD_MUTEX_DEFAULT 3
#endif /* !defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) */
#if defined(__XMK__)
typedef unsigned int pthread_mutex_t; /* identify a mutex */
typedef struct {
int type;
} pthread_mutexattr_t;
#else /* !defined(__XMK__) */
typedef __uint32_t pthread_mutex_t; /* identify a mutex */
typedef struct {
int is_initialized;
#if defined(_POSIX_THREAD_PROCESS_SHARED)
int process_shared; /* allow mutex to be shared amongst processes */
#endif
#if defined(_POSIX_THREAD_PRIO_PROTECT)
int prio_ceiling;
int protocol;
#endif
#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES)
int type;
#endif
int recursive;
} pthread_mutexattr_t;
#endif /* !defined(__XMK__) */
#define _PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) 0xFFFFFFFF)
/* Condition Variables */
typedef __uint32_t pthread_cond_t; /* identify a condition variable */
#define _PTHREAD_COND_INITIALIZER ((pthread_cond_t) 0xFFFFFFFF)
typedef struct {
int is_initialized;
clock_t clock; /* specifiy clock for timeouts */
#if defined(_POSIX_THREAD_PROCESS_SHARED)
int process_shared; /* allow this to be shared amongst processes */
#endif
} pthread_condattr_t; /* a condition attribute object */
/* Keys */
typedef __uint32_t pthread_key_t; /* thread-specific data keys */
typedef struct {
int is_initialized; /* is this structure initialized? */
int init_executed; /* has the initialization routine been run? */
} pthread_once_t; /* dynamic package initialization */
#define _PTHREAD_ONCE_INIT { 1, 0 } /* is initialized and not run */
#endif /* defined(_POSIX_THREADS) || __POSIX_VISIBLE >= 199506 */
/* POSIX Barrier Types */
#if defined(_POSIX_BARRIERS)
typedef __uint32_t pthread_barrier_t; /* POSIX Barrier Object */
typedef struct {
int is_initialized; /* is this structure initialized? */
#if defined(_POSIX_THREAD_PROCESS_SHARED)
int process_shared; /* allow this to be shared amongst processes */
#endif
} pthread_barrierattr_t;
#endif /* defined(_POSIX_BARRIERS) */
/* POSIX Spin Lock Types */
#if defined(_POSIX_SPIN_LOCKS)
typedef __uint32_t pthread_spinlock_t; /* POSIX Spin Lock Object */
#endif /* defined(_POSIX_SPIN_LOCKS) */
/* POSIX Reader/Writer Lock Types */
#if defined(_POSIX_READER_WRITER_LOCKS)
typedef __uint32_t pthread_rwlock_t; /* POSIX RWLock Object */
#define _PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) 0xFFFFFFFF)
typedef struct {
int is_initialized; /* is this structure initialized? */
#if defined(_POSIX_THREAD_PROCESS_SHARED)
int process_shared; /* allow this to be shared amongst processes */
#endif
} pthread_rwlockattr_t;
#endif /* defined(_POSIX_READER_WRITER_LOCKS) */
#endif /* ! _SYS__PTHREADTYPES_H_ */

43
src/include/sys/_sigset.h Executable file
View File

@ -0,0 +1,43 @@
/*-
* Copyright (c) 1982, 1986, 1989, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)signal.h 8.4 (Berkeley) 5/4/95
* $FreeBSD$
*/
#ifndef _SYS__SIGSET_H_
#define _SYS__SIGSET_H_
typedef unsigned long __sigset_t;
#endif /* !_SYS__SIGSET_H_ */

90
src/include/sys/_stdint.h Executable file
View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2004, 2005 by
* Ralf Corsepius, Ulm/Germany. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
#ifndef _SYS__STDINT_H
#define _SYS__STDINT_H
#include <machine/_default_types.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ___int8_t_defined
#ifndef _INT8_T_DECLARED
typedef __int8_t int8_t ;
#define _INT8_T_DECLARED
#endif
#ifndef _UINT8_T_DECLARED
typedef __uint8_t uint8_t ;
#define _UINT8_T_DECLARED
#endif
#define __int8_t_defined 1
#endif /* ___int8_t_defined */
#ifdef ___int16_t_defined
#ifndef _INT16_T_DECLARED
typedef __int16_t int16_t ;
#define _INT16_T_DECLARED
#endif
#ifndef _UINT16_T_DECLARED
typedef __uint16_t uint16_t ;
#define _UINT16_T_DECLARED
#endif
#define __int16_t_defined 1
#endif /* ___int16_t_defined */
#ifdef ___int32_t_defined
#ifndef _INT32_T_DECLARED
typedef __int32_t int32_t ;
#define _INT32_T_DECLARED
#endif
#ifndef _UINT32_T_DECLARED
typedef __uint32_t uint32_t ;
#define _UINT32_T_DECLARED
#endif
#define __int32_t_defined 1
#endif /* ___int32_t_defined */
#ifdef ___int64_t_defined
#ifndef _INT64_T_DECLARED
typedef __int64_t int64_t ;
#define _INT64_T_DECLARED
#endif
#ifndef _UINT64_T_DECLARED
typedef __uint64_t uint64_t ;
#define _UINT64_T_DECLARED
#endif
#define __int64_t_defined 1
#endif /* ___int64_t_defined */
#ifndef _INTMAX_T_DECLARED
typedef __intmax_t intmax_t;
#define _INTMAX_T_DECLARED
#endif
#ifndef _UINTMAX_T_DECLARED
typedef __uintmax_t uintmax_t;
#define _UINTMAX_T_DECLARED
#endif
#ifndef _INTPTR_T_DECLARED
typedef __intptr_t intptr_t;
#define _INTPTR_T_DECLARED
#endif
#ifndef _UINTPTR_T_DECLARED
typedef __uintptr_t uintptr_t;
#define _UINTPTR_T_DECLARED
#endif
#ifdef __cplusplus
}
#endif
#endif /* _SYS__STDINT_H */

50
src/include/sys/_timespec.h Executable file
View File

@ -0,0 +1,50 @@
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
* from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp
* $FreeBSD$
*/
#ifndef _SYS__TIMESPEC_H_
#define _SYS__TIMESPEC_H_
#include <sys/_types.h>
#if !defined(__time_t_defined) && !defined(_TIME_T_DECLARED)
typedef _TIME_T_ time_t;
#define __time_t_defined
#define _TIME_T_DECLARED
#endif
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* and nanoseconds */
};
#endif /* !_SYS__TIMESPEC_H_ */

89
src/include/sys/_timeval.h Executable file
View File

@ -0,0 +1,89 @@
/*-
* Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
* 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$
*/
#ifndef _SYS__TIMEVAL_H_
#define _SYS__TIMEVAL_H_
#include <sys/_types.h>
#ifndef _SUSECONDS_T_DECLARED
typedef __suseconds_t suseconds_t;
#define _SUSECONDS_T_DECLARED
#endif
#if !defined(__time_t_defined) && !defined(_TIME_T_DECLARED)
typedef _TIME_T_ time_t;
#define __time_t_defined
#define _TIME_T_DECLARED
#endif
/* This define is also used outside of Newlib, e.g. in MinGW-w64 */
#ifndef _TIMEVAL_DEFINED
#define _TIMEVAL_DEFINED
/*
* Structure returned by gettimeofday(2) system call, and used in other calls.
*/
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* and microseconds */
};
#if __BSD_VISIBLE
#ifndef _KERNEL /* NetBSD/OpenBSD compatible interfaces */
#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define timercmp(tvp, uvp, cmp) \
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
((tvp)->tv_sec cmp (uvp)->tv_sec))
#define timeradd(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
if ((vvp)->tv_usec >= 1000000) { \
(vvp)->tv_sec++; \
(vvp)->tv_usec -= 1000000; \
} \
} while (0)
#define timersub(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
if ((vvp)->tv_usec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_usec += 1000000; \
} \
} while (0)
#endif
#endif /* __BSD_VISIBLE */
#endif /* _TIMEVAL_DEFINED */
#endif /* !_SYS__TIMEVAL_H_ */

224
src/include/sys/_types.h Executable file
View File

@ -0,0 +1,224 @@
/* ANSI C namespace clean utility typedefs */
/* This file defines various typedefs needed by the system calls that support
the C library. Basically, they're just the POSIX versions with an '_'
prepended. Targets shall use <machine/_types.h> to define their own
internal types if desired.
There are three define patterns used for type definitions. Lets assume
xyz_t is a user type.
The internal type definition uses __machine_xyz_t_defined. It is defined by
<machine/_types.h> to disable a default definition in <sys/_types.h>. It
must not be used in other files.
User type definitions are guarded by __xyz_t_defined in glibc and
_XYZ_T_DECLARED in BSD compatible systems.
*/
#ifndef _SYS__TYPES_H
#define _SYS__TYPES_H
#include <newlib.h>
#include <sys/config.h>
#include <machine/_types.h>
#include <sys/lock.h>
#ifndef __machine_blkcnt_t_defined
typedef long __blkcnt_t;
#endif
#ifndef __machine_blksize_t_defined
typedef long __blksize_t;
#endif
#ifndef __machine_fsblkcnt_t_defined
typedef __uint64_t __fsblkcnt_t;
#endif
#ifndef __machine_fsfilcnt_t_defined
typedef __uint32_t __fsfilcnt_t;
#endif
#ifndef __machine_off_t_defined
typedef long _off_t;
#endif
#if defined(__XMK__)
typedef signed char __pid_t;
#else
typedef int __pid_t;
#endif
#ifndef __machine_dev_t_defined
typedef short __dev_t;
#endif
#ifndef __machine_uid_t_defined
typedef unsigned short __uid_t;
#endif
#ifndef __machine_gid_t_defined
typedef unsigned short __gid_t;
#endif
#ifndef __machine_id_t_defined
typedef __uint32_t __id_t;
#endif
#ifndef __machine_ino_t_defined
#if (defined(__i386__) && (defined(GO32) || defined(__MSDOS__))) || \
defined(__sparc__) || defined(__SPU__)
typedef unsigned long __ino_t;
#else
typedef unsigned short __ino_t;
#endif
#endif
#ifndef __machine_mode_t_defined
#if defined(__i386__) && (defined(GO32) || defined(__MSDOS__))
typedef int __mode_t;
#else
#if defined(__sparc__) && !defined(__sparc_v9__)
#ifdef __svr4__
typedef unsigned long __mode_t;
#else
typedef unsigned short __mode_t;
#endif
#else
typedef __uint32_t __mode_t;
#endif
#endif
#endif
#ifndef __machine_off64_t_defined
__extension__ typedef long long _off64_t;
#endif
#if defined(__CYGWIN__) && !defined(__LP64__)
typedef _off64_t __off_t;
#else
typedef _off_t __off_t;
#endif
typedef _off64_t __loff_t;
#ifndef __machine_key_t_defined
typedef long __key_t;
#endif
/*
* We need fpos_t for the following, but it doesn't have a leading "_",
* so we use _fpos_t instead.
*/
#ifndef __machine_fpos_t_defined
typedef long _fpos_t; /* XXX must match off_t in <sys/types.h> */
/* (and must be `long' for now) */
#endif
#ifdef __LARGE64_FILES
#ifndef __machine_fpos64_t_defined
typedef _off64_t _fpos64_t;
#endif
#endif
/* Defined by GCC provided <stddef.h> */
#undef __size_t
#ifndef __machine_size_t_defined
#ifdef __SIZE_TYPE__
typedef __SIZE_TYPE__ __size_t;
#else
#if defined(__INT_MAX__) && __INT_MAX__ == 2147483647
typedef unsigned int __size_t;
#else
typedef unsigned long __size_t;
#endif
#endif
#endif
#ifndef __machine_ssize_t_defined
#ifdef __SIZE_TYPE__
/* If __SIZE_TYPE__ is defined (gcc) we define ssize_t based on size_t.
We simply change "unsigned" to "signed" for this single definition
to make sure ssize_t and size_t only differ by their signedness. */
#define unsigned signed
typedef __SIZE_TYPE__ _ssize_t;
#undef unsigned
#else
#if defined(__INT_MAX__) && __INT_MAX__ == 2147483647
typedef int _ssize_t;
#else
typedef long _ssize_t;
#endif
#endif
#endif
typedef _ssize_t __ssize_t;
#define __need_wint_t
#include <stddef.h>
#ifndef __machine_mbstate_t_defined
/* Conversion state information. */
typedef struct
{
int __count;
union
{
wint_t __wch;
unsigned char __wchb[4];
} __value; /* Value so far. */
} _mbstate_t;
#endif
#ifndef __machine_flock_t_defined
typedef _LOCK_RECURSIVE_T _flock_t;
#endif
#ifndef __machine_iconv_t_defined
/* Iconv descriptor type */
typedef void *_iconv_t;
#endif
#ifndef __machine_clock_t_defined
#define _CLOCK_T_ unsigned long /* clock() */
#endif
typedef _CLOCK_T_ __clock_t;
#if defined(_USE_LONG_TIME_T) || __LONG_MAX__ > 0x7fffffffL
#define _TIME_T_ long
#else
#define _TIME_T_ __int_least64_t
#endif
typedef _TIME_T_ __time_t;
#ifndef __machine_clockid_t_defined
#define _CLOCKID_T_ unsigned long
#endif
typedef _CLOCKID_T_ __clockid_t;
#define _TIMER_T_ unsigned long
typedef _TIMER_T_ __timer_t;
#ifndef __machine_sa_family_t_defined
typedef __uint8_t __sa_family_t;
#endif
#ifndef __machine_socklen_t_defined
typedef __uint32_t __socklen_t;
#endif
typedef int __nl_item;
typedef unsigned short __nlink_t;
typedef long __suseconds_t; /* microseconds (signed) */
typedef unsigned long __useconds_t; /* microseconds (unsigned) */
#ifdef __GNUCLIKE_BUILTIN_VARARGS
typedef __builtin_va_list __va_list;
#else
typedef char * __va_list;
#endif /* __GNUCLIKE_BUILTIN_VARARGS */
#endif /* _SYS__TYPES_H */

716
src/include/sys/cdefs.h Executable file
View File

@ -0,0 +1,716 @@
/* libc/sys/linux/sys/cdefs.h - Helper macros for K&R vs. ANSI C compat. */
/* Written 2000 by Werner Almesberger */
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Berkeley Software Design, Inc.
*
* 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)cdefs.h 8.8 (Berkeley) 1/9/95
* $FreeBSD$
*/
#ifndef _SYS_CDEFS_H_
#define _SYS_CDEFS_H_
#include <machine/_default_types.h>
#include <sys/features.h>
#include <stddef.h>
#define __PMT(args) args
#define __DOTS , ...
#define __THROW
#ifdef __GNUC__
# define __ASMNAME(cname) __XSTRING (__USER_LABEL_PREFIX__) cname
#endif
#define __ptr_t void *
#define __long_double_t long double
#define __attribute_malloc__
#define __attribute_pure__
#define __attribute_format_strfmon__(a,b)
#define __flexarr [0]
#ifndef __BOUNDED_POINTERS__
# define __bounded /* nothing */
# define __unbounded /* nothing */
# define __ptrvalue /* nothing */
#endif
/*
* Testing against Clang-specific extensions.
*/
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#ifndef __has_extension
#define __has_extension __has_feature
#endif
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#ifndef __has_include
#define __has_include(x) 0
#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
/*
* This code has been put in place to help reduce the addition of
* compiler specific defines in FreeBSD code. It helps to aid in
* having a compiler-agnostic source tree.
*/
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
#if __GNUC__ >= 3 || defined(__INTEL_COMPILER)
#define __GNUCLIKE_ASM 3
#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS
#else
#define __GNUCLIKE_ASM 2
#endif
#define __GNUCLIKE___TYPEOF 1
#define __GNUCLIKE___OFFSETOF 1
#define __GNUCLIKE___SECTION 1
#ifndef __INTEL_COMPILER
#define __GNUCLIKE_CTOR_SECTION_HANDLING 1
#endif
#define __GNUCLIKE_BUILTIN_CONSTANT_P 1
#if defined(__INTEL_COMPILER) && defined(__cplusplus) && \
__INTEL_COMPILER < 800
#undef __GNUCLIKE_BUILTIN_CONSTANT_P
#endif
#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3)
#define __GNUCLIKE_BUILTIN_VARARGS 1
#define __GNUCLIKE_BUILTIN_STDARG 1
#define __GNUCLIKE_BUILTIN_VAALIST 1
#endif
#if defined(__GNUC__)
#define __GNUC_VA_LIST_COMPATIBILITY 1
#endif
/*
* Compiler memory barriers, specific to gcc and clang.
*/
#if defined(__GNUC__)
#define __compiler_membar() __asm __volatile(" " : : : "memory")
#endif
#ifndef __INTEL_COMPILER
#define __GNUCLIKE_BUILTIN_NEXT_ARG 1
#define __GNUCLIKE_MATH_BUILTIN_RELOPS
#endif
#define __GNUCLIKE_BUILTIN_MEMCPY 1
/* XXX: if __GNUC__ >= 2: not tested everywhere originally, where replaced */
#define __CC_SUPPORTS_INLINE 1
#define __CC_SUPPORTS___INLINE 1
#define __CC_SUPPORTS___INLINE__ 1
#define __CC_SUPPORTS___FUNC__ 1
#define __CC_SUPPORTS_WARNING 1
#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */
#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1
#endif /* __GNUC__ || __INTEL_COMPILER */
/*
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
* The __CONCAT macro is a bit tricky to use if it must work in non-ANSI
* mode -- there must be no spaces between its arguments, and for nested
* __CONCAT's, all the __CONCAT's must be at the left. __CONCAT can also
* concatenate double-quoted strings produced by the __STRING macro, but
* this only works with ANSI C.
*
* __XSTRING is like __STRING, but it expands any macros in its argument
* first. It is only available with ANSI C.
*/
#if defined(__STDC__) || defined(__cplusplus)
#define __P(protos) protos /* full-blown ANSI C */
#define __CONCAT1(x,y) x ## y
#define __CONCAT(x,y) __CONCAT1(x,y)
#define __STRING(x) #x /* stringify without expanding x */
#define __XSTRING(x) __STRING(x) /* expand x, then stringify */
#define __const const /* define reserved names to standard */
#define __signed signed
#define __volatile volatile
#if defined(__cplusplus)
#define __inline inline /* convert to C++ keyword */
#else
#if !(defined(__CC_SUPPORTS___INLINE))
#define __inline /* delete GCC keyword */
#endif /* ! __CC_SUPPORTS___INLINE */
#endif /* !__cplusplus */
#else /* !(__STDC__ || __cplusplus) */
#define __P(protos) () /* traditional C preprocessor */
#define __CONCAT(x,y) x/**/y
#define __STRING(x) "x"
#if !defined(__CC_SUPPORTS___INLINE)
#define __const /* delete pseudo-ANSI C keywords */
#define __inline
#define __signed
#define __volatile
/*
* In non-ANSI C environments, new programs will want ANSI-only C keywords
* deleted from the program and old programs will want them left alone.
* When using a compiler other than gcc, programs using the ANSI C keywords
* const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
* When using "gcc -traditional", we assume that this is the intent; if
* __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
*/
#ifndef NO_ANSI_KEYWORDS
#define const /* delete ANSI C keywords */
#define inline
#define signed
#define volatile
#endif /* !NO_ANSI_KEYWORDS */
#endif /* !__CC_SUPPORTS___INLINE */
#endif /* !(__STDC__ || __cplusplus) */
/*
* Compiler-dependent macros to help declare dead (non-returning) and
* pure (no side effects) functions, and unused variables. They are
* null except for versions of gcc that are known to support the features
* properly (old versions of gcc-2 supported the dead and pure features
* in a different (wrong) way). If we do not provide an implementation
* for a given compiler, let the compile fail if it is told to use
* a feature that we cannot live without.
*/
#define __weak_symbol __attribute__((__weak__))
#if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER)
#define __dead2
#define __pure2
#define __unused
#endif
#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 && !defined(__INTEL_COMPILER)
#define __dead2 __attribute__((__noreturn__))
#define __pure2 __attribute__((__const__))
#define __unused
/* XXX Find out what to do for __packed, __aligned and __section */
#endif
#if __GNUC_PREREQ__(2, 7) || defined(__INTEL_COMPILER)
#define __dead2 __attribute__((__noreturn__))
#define __pure2 __attribute__((__const__))
#define __unused __attribute__((__unused__))
#define __used __attribute__((__used__))
#define __packed __attribute__((__packed__))
#define __aligned(x) __attribute__((__aligned__(x)))
#define __section(x) __attribute__((__section__(x)))
#endif
#if __GNUC_PREREQ__(4, 3) || __has_attribute(__alloc_size__)
#define __alloc_size(x) __attribute__((__alloc_size__(x)))
#define __alloc_size2(n, x) __attribute__((__alloc_size__(n, x)))
#else
#define __alloc_size(x)
#define __alloc_size2(n, x)
#endif
#if __GNUC_PREREQ__(4, 9) || __has_attribute(__alloc_align__)
#define __alloc_align(x) __attribute__((__alloc_align__(x)))
#else
#define __alloc_align(x)
#endif
#if !__GNUC_PREREQ__(2, 95)
#define __alignof(x) __offsetof(struct { char __a; x __b; }, __b)
#endif
/*
* Keywords added in C11.
*/
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
#if !__has_extension(c_alignas)
#if (defined(__cplusplus) && __cplusplus >= 201103L) || \
__has_extension(cxx_alignas)
#define _Alignas(x) alignas(x)
#else
/* XXX: Only emulates _Alignas(constant-expression); not _Alignas(type-name). */
#define _Alignas(x) __aligned(x)
#endif
#endif
#if defined(__cplusplus) && __cplusplus >= 201103L
#define _Alignof(x) alignof(x)
#else
#define _Alignof(x) __alignof(x)
#endif
#if !defined(__cplusplus) && !__has_extension(c_atomic) && \
!__has_extension(cxx_atomic)
/*
* No native support for _Atomic(). Place object in structure to prevent
* most forms of direct non-atomic access.
*/
#define _Atomic(T) struct { T volatile __val; }
#endif
#if defined(__cplusplus) && __cplusplus >= 201103L
#define _Noreturn [[noreturn]]
#else
#define _Noreturn __dead2
#endif
#if !__has_extension(c_static_assert)
#if (defined(__cplusplus) && __cplusplus >= 201103L) || \
__has_extension(cxx_static_assert)
#define _Static_assert(x, y) static_assert(x, y)
#elif __GNUC_PREREQ__(4,6) && !defined(__cplusplus)
/* Nothing, gcc 4.6 and higher has _Static_assert built-in */
#elif defined(__COUNTER__)
#define _Static_assert(x, y) __Static_assert(x, __COUNTER__)
#define __Static_assert(x, y) ___Static_assert(x, y)
#define ___Static_assert(x, y) typedef char __assert_ ## y[(x) ? 1 : -1] \
__unused
#else
#define _Static_assert(x, y) struct __hack
#endif
#endif
#if !__has_extension(c_thread_local)
/*
* XXX: Some compilers (Clang 3.3, GCC 4.7) falsely announce C++11 mode
* without actually supporting the thread_local keyword. Don't check for
* the presence of C++11 when defining _Thread_local.
*/
#if /* (defined(__cplusplus) && __cplusplus >= 201103L) || */ \
__has_extension(cxx_thread_local)
#define _Thread_local thread_local
#else
#define _Thread_local __thread
#endif
#endif
#endif /* __STDC_VERSION__ || __STDC_VERSION__ < 201112L */
/*
* Emulation of C11 _Generic(). Unlike the previously defined C11
* keywords, it is not possible to implement this using exactly the same
* syntax. Therefore implement something similar under the name
* __generic(). Unlike _Generic(), this macro can only distinguish
* between a single type, so it requires nested invocations to
* distinguish multiple cases.
*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
__has_extension(c_generic_selections)
#define __generic(expr, t, yes, no) \
_Generic(expr, t: yes, default: no)
#elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus)
#define __generic(expr, t, yes, no) \
__builtin_choose_expr( \
__builtin_types_compatible_p(__typeof(expr), t), yes, no)
#endif
/*
* C99 Static array indices in function parameter declarations. Syntax such as:
* void bar(int myArray[static 10]);
* is allowed in C99 but not in C++. Define __min_size appropriately so
* headers using it can be compiled in either language. Use like this:
* void bar(int myArray[__min_size(10)]);
*/
#if !defined(__cplusplus) && \
(defined(__clang__) || __GNUC_PREREQ__(4, 6)) && \
(!defined(__STDC_VERSION__) || (__STDC_VERSION__ >= 199901))
#define __min_size(x) static (x)
#else
#define __min_size(x) (x)
#endif
#if __GNUC_PREREQ__(2, 96)
#define __malloc_like __attribute__((__malloc__))
#define __pure __attribute__((__pure__))
#else
#define __malloc_like
#define __pure
#endif
#if __GNUC_PREREQ__(3, 1) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
#define __always_inline __inline__ __attribute__((__always_inline__))
#else
#define __always_inline
#endif
#if __GNUC_PREREQ__(3, 1)
#define __noinline __attribute__ ((__noinline__))
#else
#define __noinline
#endif
#if __GNUC_PREREQ__(3, 3)
#define __nonnull(x) __attribute__((__nonnull__ x))
#define __nonnull_all __attribute__((__nonnull__))
#else
#define __nonnull(x)
#define __nonnull_all
#endif
#if __GNUC_PREREQ__(3, 4)
#define __fastcall __attribute__((__fastcall__))
#define __result_use_check __attribute__((__warn_unused_result__))
#else
#define __fastcall
#define __result_use_check
#endif
#if __GNUC_PREREQ__(4, 1)
#define __returns_twice __attribute__((__returns_twice__))
#else
#define __returns_twice
#endif
#if __GNUC_PREREQ__(4, 6) || __has_builtin(__builtin_unreachable)
#define __unreachable() __builtin_unreachable()
#else
#define __unreachable() ((void)0)
#endif
/* XXX: should use `#if __STDC_VERSION__ < 199901'. */
#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER)
#define __func__ NULL
#endif
/*
* GCC 2.95 provides `__restrict' as an extension to C90 to support the
* C99-specific `restrict' type qualifier. We happen to use `__restrict' as
* a way to define the `restrict' type qualifier without disturbing older
* software that is unaware of C99 keywords.
*/
#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95)
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901
#define __restrict
#else
#define __restrict restrict
#endif
#endif
/*
* GNU C version 2.96 adds explicit branch prediction so that
* the CPU back-end can hint the processor and also so that
* code blocks can be reordered such that the predicted path
* sees a more linear flow, thus improving cache behavior, etc.
*
* The following two macros provide us with a way to utilize this
* compiler feature. Use __predict_true() if you expect the expression
* to evaluate to true, and __predict_false() if you expect the
* expression to evaluate to false.
*
* A few notes about usage:
*
* * Generally, __predict_false() error condition checks (unless
* you have some _strong_ reason to do otherwise, in which case
* document it), and/or __predict_true() `no-error' condition
* checks, assuming you want to optimize for the no-error case.
*
* * Other than that, if you don't know the likelihood of a test
* succeeding from empirical or other `hard' evidence, don't
* make predictions.
*
* * These are meant to be used in places that are run `a lot'.
* It is wasteful to make predictions in code that is run
* seldomly (e.g. at subsystem initialization time) as the
* basic block reordering that this affects can often generate
* larger code.
*/
#if __GNUC_PREREQ__(2, 96)
#define __predict_true(exp) __builtin_expect((exp), 1)
#define __predict_false(exp) __builtin_expect((exp), 0)
#else
#define __predict_true(exp) (exp)
#define __predict_false(exp) (exp)
#endif
#if __GNUC_PREREQ__(4, 0)
#define __null_sentinel __attribute__((__sentinel__))
#define __exported __attribute__((__visibility__("default")))
/* Only default visibility is supported on PE/COFF targets. */
#ifndef __CYGWIN__
#define __hidden __attribute__((__visibility__("hidden")))
#else
#define __hidden
#endif
#else
#define __null_sentinel
#define __exported
#define __hidden
#endif
#define __offsetof(type, field) offsetof(type, field)
#define __rangeof(type, start, end) \
(__offsetof(type, end) - __offsetof(type, start))
/*
* Given the pointer x to the member m of the struct s, return
* a pointer to the containing structure. When using GCC, we first
* assign pointer x to a local variable, to check that its type is
* compatible with member m.
*/
#if __GNUC_PREREQ__(3, 1)
#define __containerof(x, s, m) ({ \
const volatile __typeof(((s *)0)->m) *__x = (x); \
__DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m));\
})
#else
#define __containerof(x, s, m) \
__DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m))
#endif
/*
* Compiler-dependent macros to declare that functions take printf-like
* or scanf-like arguments. They are null except for versions of gcc
* that are known to support the features properly (old versions of gcc-2
* didn't permit keeping the keywords out of the application namespace).
*/
#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER)
#define __printflike(fmtarg, firstvararg)
#define __scanflike(fmtarg, firstvararg)
#define __format_arg(fmtarg)
#define __strfmonlike(fmtarg, firstvararg)
#define __strftimelike(fmtarg, firstvararg)
#else
#define __printflike(fmtarg, firstvararg) \
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
#define __scanflike(fmtarg, firstvararg) \
__attribute__((__format__ (__scanf__, fmtarg, firstvararg)))
#define __format_arg(fmtarg) __attribute__((__format_arg__ (fmtarg)))
#define __strfmonlike(fmtarg, firstvararg) \
__attribute__((__format__ (__strfmon__, fmtarg, firstvararg)))
#define __strftimelike(fmtarg, firstvararg) \
__attribute__((__format__ (__strftime__, fmtarg, firstvararg)))
#endif
/* Compiler-dependent macros that rely on FreeBSD-specific extensions. */
#if defined(__FreeBSD_cc_version) && __FreeBSD_cc_version >= 300001 && \
defined(__GNUC__) && !defined(__INTEL_COMPILER)
#define __printf0like(fmtarg, firstvararg) \
__attribute__((__format__ (__printf0__, fmtarg, firstvararg)))
#else
#define __printf0like(fmtarg, firstvararg)
#endif
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
#ifndef __INTEL_COMPILER
#define __strong_reference(sym,aliassym) \
extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym)))
#endif
#ifdef __ELF__
#ifdef __STDC__
#define __weak_reference(sym,alias) \
__asm__(".weak " #alias); \
__asm__(".equ " #alias ", " #sym)
#define __warn_references(sym,msg) \
__asm__(".section .gnu.warning." #sym); \
__asm__(".asciz \"" msg "\""); \
__asm__(".previous")
#define __sym_compat(sym,impl,verid) \
__asm__(".symver " #impl ", " #sym "@" #verid)
#define __sym_default(sym,impl,verid) \
__asm__(".symver " #impl ", " #sym "@@" #verid)
#else
#define __weak_reference(sym,alias) \
__asm__(".weak alias"); \
__asm__(".equ alias, sym")
#define __warn_references(sym,msg) \
__asm__(".section .gnu.warning.sym"); \
__asm__(".asciz \"msg\""); \
__asm__(".previous")
#define __sym_compat(sym,impl,verid) \
__asm__(".symver impl, sym@verid")
#define __sym_default(impl,sym,verid) \
__asm__(".symver impl, sym@@verid")
#endif /* __STDC__ */
#else /* !__ELF__ */
#ifdef __STDC__
#define __weak_reference(sym,alias) \
__asm__(".stabs \"_" #alias "\",11,0,0,0"); \
__asm__(".stabs \"_" #sym "\",1,0,0,0")
#define __warn_references(sym,msg) \
__asm__(".stabs \"" msg "\",30,0,0,0"); \
__asm__(".stabs \"_" #sym "\",1,0,0,0")
#else
#define __weak_reference(sym,alias) \
__asm__(".stabs \"_/**/alias\",11,0,0,0"); \
__asm__(".stabs \"_/**/sym\",1,0,0,0")
#define __warn_references(sym,msg) \
__asm__(".stabs msg,30,0,0,0"); \
__asm__(".stabs \"_/**/sym\",1,0,0,0")
#endif /* __STDC__ */
#endif /* __ELF__ */
#endif /* __GNUC__ || __INTEL_COMPILER */
#ifndef __FBSDID
#define __FBSDID(s) struct __hack
#endif
#ifndef __RCSID
#define __RCSID(s) struct __hack
#endif
#ifndef __RCSID_SOURCE
#define __RCSID_SOURCE(s) struct __hack
#endif
#ifndef __SCCSID
#define __SCCSID(s) struct __hack
#endif
#ifndef __COPYRIGHT
#define __COPYRIGHT(s) struct __hack
#endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var))
#endif
#ifndef __DEVOLATILE
#define __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var))
#endif
#ifndef __DEQUALIFY
#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var))
#endif
/*
* Nullability qualifiers: currently only supported by Clang.
*/
#if !(defined(__clang__) && __has_feature(nullability))
#define _Nonnull
#define _Nullable
#define _Null_unspecified
#define __NULLABILITY_PRAGMA_PUSH
#define __NULLABILITY_PRAGMA_POP
#else
#define __NULLABILITY_PRAGMA_PUSH _Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wnullability-completeness\"")
#define __NULLABILITY_PRAGMA_POP _Pragma("clang diagnostic pop")
#endif
/*
* Type Safety Checking
*
* Clang provides additional attributes to enable checking type safety
* properties that cannot be enforced by the C type system.
*/
#if __has_attribute(__argument_with_type_tag__) && \
__has_attribute(__type_tag_for_datatype__)
#define __arg_type_tag(arg_kind, arg_idx, type_tag_idx) \
__attribute__((__argument_with_type_tag__(arg_kind, arg_idx, type_tag_idx)))
#define __datatype_type_tag(kind, type) \
__attribute__((__type_tag_for_datatype__(kind, type)))
#else
#define __arg_type_tag(arg_kind, arg_idx, type_tag_idx)
#define __datatype_type_tag(kind, type)
#endif
/*
* Lock annotations.
*
* Clang provides support for doing basic thread-safety tests at
* compile-time, by marking which locks will/should be held when
* entering/leaving a functions.
*
* Furthermore, it is also possible to annotate variables and structure
* members to enforce that they are only accessed when certain locks are
* held.
*/
#if __has_extension(c_thread_safety_attributes)
#define __lock_annotate(x) __attribute__((x))
#else
#define __lock_annotate(x)
#endif
/* Structure implements a lock. */
/* FIXME: Use __lockable__, etc. to avoid colliding with user namespace macros,
* once clang is fixed: https://bugs.llvm.org/show_bug.cgi?id=34319 */
#define __lockable __lock_annotate(lockable)
/* Function acquires an exclusive or shared lock. */
#define __locks_exclusive(...) \
__lock_annotate(exclusive_lock_function(__VA_ARGS__))
#define __locks_shared(...) \
__lock_annotate(shared_lock_function(__VA_ARGS__))
/* Function attempts to acquire an exclusive or shared lock. */
#define __trylocks_exclusive(...) \
__lock_annotate(exclusive_trylock_function(__VA_ARGS__))
#define __trylocks_shared(...) \
__lock_annotate(shared_trylock_function(__VA_ARGS__))
/* Function releases a lock. */
#define __unlocks(...) __lock_annotate(unlock_function(__VA_ARGS__))
/* Function asserts that an exclusive or shared lock is held. */
#define __asserts_exclusive(...) \
__lock_annotate(assert_exclusive_lock(__VA_ARGS__))
#define __asserts_shared(...) \
__lock_annotate(assert_shared_lock(__VA_ARGS__))
/* Function requires that an exclusive or shared lock is or is not held. */
#define __requires_exclusive(...) \
__lock_annotate(exclusive_locks_required(__VA_ARGS__))
#define __requires_shared(...) \
__lock_annotate(shared_locks_required(__VA_ARGS__))
#define __requires_unlocked(...) \
__lock_annotate(locks_excluded(__VA_ARGS__))
/* Function should not be analyzed. */
#define __no_lock_analysis __lock_annotate(no_thread_safety_analysis)
/* Guard variables and structure members by lock. */
#define __guarded_by(x) __lock_annotate(guarded_by(x))
#define __pt_guarded_by(x) __lock_annotate(pt_guarded_by(x))
#endif /* !_SYS_CDEFS_H_ */

300
src/include/sys/config.h Executable file
View File

@ -0,0 +1,300 @@
#ifndef __SYS_CONFIG_H__
#define __SYS_CONFIG_H__
#include <machine/ieeefp.h> /* floating point macros */
#include <sys/features.h> /* POSIX defs */
#ifdef __aarch64__
#define MALLOC_ALIGNMENT 16
#endif
/* exceptions first */
#if defined(__H8500__) || defined(__W65__)
#define __SMALL_BITFIELDS
/* ??? This conditional is true for the h8500 and the w65, defining H8300
in those cases probably isn't the right thing to do. */
#define H8300 1
#endif
/* 16 bit integer machines */
#if defined(__Z8001__) || defined(__Z8002__) || defined(__H8500__) || defined(__W65__) || defined (__mn10200__) || defined (__AVR__)
#undef INT_MAX
#undef UINT_MAX
#define INT_MAX 32767
#define UINT_MAX 65535
#endif
#if defined (__H8300__) || defined (__H8300H__) || defined(__H8300S__) || defined (__H8300SX__)
#define __SMALL_BITFIELDS
#define H8300 1
#undef INT_MAX
#undef UINT_MAX
#define INT_MAX __INT_MAX__
#define UINT_MAX (__INT_MAX__ * 2U + 1)
#endif
#if (defined(__CR16__) || defined(__CR16C__) ||defined(__CR16CP__))
#ifndef __INT32__
#define __SMALL_BITFIELDS
#undef INT_MAX
#undef UINT_MAX
#define INT_MAX 32767
#define UINT_MAX (__INT_MAX__ * 2U + 1)
#else /* INT32 */
#undef INT_MAX
#undef UINT_MAX
#define INT_MAX 2147483647
#define UINT_MAX (__INT_MAX__ * 2U + 1)
#endif /* INT32 */
#endif /* CR16C */
#if defined (__xc16x__) || defined (__xc16xL__) || defined (__xc16xS__)
#define __SMALL_BITFIELDS
#endif
#ifdef __W65__
#define __SMALL_BITFIELDS
#endif
#if defined(__D10V__)
#define __SMALL_BITFIELDS
#undef INT_MAX
#undef UINT_MAX
#define INT_MAX __INT_MAX__
#define UINT_MAX (__INT_MAX__ * 2U + 1)
#define _POINTER_INT short
#endif
#if defined(__mc68hc11__) || defined(__mc68hc12__) || defined(__mc68hc1x__)
#undef INT_MAX
#undef UINT_MAX
#define INT_MAX __INT_MAX__
#define UINT_MAX (__INT_MAX__ * 2U + 1)
#define _POINTER_INT short
#endif
#if defined(__m68k__) || defined(__mc68000__) || defined(__riscv)
#define _READ_WRITE_RETURN_TYPE _ssize_t
#endif
#ifdef ___AM29K__
#define _FLOAT_RET double
#endif
#ifdef __i386__
#ifndef __unix__
/* in other words, go32 */
#define _FLOAT_RET double
#endif
#if defined(__linux__) || defined(__RDOS__)
/* we want the reentrancy structure to be returned by a function */
#define __DYNAMIC_REENT__
#define HAVE_GETDATE
#define _READ_WRITE_RETURN_TYPE _ssize_t
#define __LARGE64_FILES 1
/* we use some glibc header files so turn on glibc large file feature */
#define _LARGEFILE64_SOURCE 1
#endif
#endif
#ifdef __mn10200__
#define __SMALL_BITFIELDS
#endif
#ifdef __AVR__
#define __SMALL_BITFIELDS
#define _POINTER_INT short
#endif
#if defined(__v850) && !defined(__rtems__)
#define __ATTRIBUTE_IMPURE_PTR__ __attribute__((__sda__))
#endif
/* For the PowerPC eabi, force the _impure_ptr to be in .sdata */
#if defined(__PPC__)
#if defined(_CALL_SYSV)
#define __ATTRIBUTE_IMPURE_PTR__ __attribute__((__section__(".sdata")))
#endif
#ifdef __SPE__
#define _LONG_DOUBLE double
#endif
#endif
/* Configure small REENT structure for Xilinx MicroBlaze platforms */
#if defined (__MICROBLAZE__)
#ifndef _REENT_SMALL
#define _REENT_SMALL
#endif
/* Xilinx XMK uses Unix98 mutex */
#ifdef __XMK__
#define _UNIX98_THREAD_MUTEX_ATTRIBUTES
#endif
#endif
#if defined(__mips__) && !defined(__rtems__)
#define __ATTRIBUTE_IMPURE_PTR__ __attribute__((__section__(".sdata")))
#endif
#ifdef __xstormy16__
#define __SMALL_BITFIELDS
#undef INT_MAX
#undef UINT_MAX
#define INT_MAX __INT_MAX__
#define UINT_MAX (__INT_MAX__ * 2U + 1)
#define MALLOC_ALIGNMENT 8
#define _POINTER_INT short
#define __BUFSIZ__ 16
#define _REENT_SMALL
#endif
#if defined __MSP430__
#ifndef _REENT_SMALL
#define _REENT_SMALL
#endif
#define __BUFSIZ__ 256
#define __SMALL_BITFIELDS
#ifdef __MSP430X_LARGE__
#define _POINTER_INT long
#else
#define _POINTER_INT int
#endif
#endif
#ifdef __m32c__
#define __SMALL_BITFIELDS
#undef INT_MAX
#undef UINT_MAX
#define INT_MAX __INT_MAX__
#define UINT_MAX (__INT_MAX__ * 2U + 1)
#define MALLOC_ALIGNMENT 8
#if defined(__r8c_cpu__) || defined(__m16c_cpu__)
#define _POINTER_INT short
#else
#define _POINTER_INT long
#endif
#define __BUFSIZ__ 16
#define _REENT_SMALL
#endif /* __m32c__ */
#ifdef __SPU__
#define MALLOC_ALIGNMENT 16
#define __CUSTOM_FILE_IO__
#endif
#if defined(__or1k__) || defined(__or1knd__)
#define __DYNAMIC_REENT__
#endif
/* This block should be kept in sync with GCC's limits.h. The point
of having these definitions here is to not include limits.h, which
would pollute the user namespace, while still using types of the
the correct widths when deciding how to define __int32_t and
__int64_t. */
#ifndef __INT_MAX__
# ifdef INT_MAX
# define __INT_MAX__ INT_MAX
# else
# define __INT_MAX__ 2147483647
# endif
#endif
#ifndef __LONG_MAX__
# ifdef LONG_MAX
# define __LONG_MAX__ LONG_MAX
# else
# if defined (__alpha__) || (defined (__sparc__) && defined(__arch64__)) \
|| defined (__sparcv9)
# define __LONG_MAX__ 9223372036854775807L
# else
# define __LONG_MAX__ 2147483647L
# endif /* __alpha__ || sparc64 */
# endif
#endif
/* End of block that should be kept in sync with GCC's limits.h. */
#ifndef _POINTER_INT
#define _POINTER_INT long
#endif
#ifdef __frv__
#define __ATTRIBUTE_IMPURE_PTR__ __attribute__((__section__(".sdata")))
#endif
#undef __RAND_MAX
#if __INT_MAX__ == 32767
#define __RAND_MAX 32767
#else
#define __RAND_MAX 0x7fffffff
#endif
#if defined(__CYGWIN__)
#include <cygwin/config.h>
#endif
#if defined(__rtems__)
#define __FILENAME_MAX__ 255
#define _READ_WRITE_RETURN_TYPE _ssize_t
#define __DYNAMIC_REENT__
#define _REENT_GLOBAL_ATEXIT
#define _REENT_GLOBAL_STDIO_STREAMS
#endif
#ifndef __EXPORT
#define __EXPORT
#endif
#ifndef __IMPORT
#define __IMPORT
#endif
/* Define return type of read/write routines. In POSIX, the return type
for read()/write() is "ssize_t" but legacy newlib code has been using
"int" for some time. If not specified, "int" is defaulted. */
#ifndef _READ_WRITE_RETURN_TYPE
#define _READ_WRITE_RETURN_TYPE int
#endif
/* Define `count' parameter of read/write routines. In POSIX, the `count'
parameter is "size_t" but legacy newlib code has been using "int" for some
time. If not specified, "int" is defaulted. */
#ifndef _READ_WRITE_BUFSIZE_TYPE
#define _READ_WRITE_BUFSIZE_TYPE int
#endif
#ifndef __WCHAR_MAX__
#if __INT_MAX__ == 32767 || defined (_WIN32)
#define __WCHAR_MAX__ 0xffffu
#endif
#endif
/* See if small reent asked for at configuration time and
is not chosen by the platform by default. */
#ifdef _WANT_REENT_SMALL
#ifndef _REENT_SMALL
#define _REENT_SMALL
#endif
#endif
#ifdef _WANT_REENT_GLOBAL_STDIO_STREAMS
#ifndef _REENT_GLOBAL_STDIO_STREAMS
#define _REENT_GLOBAL_STDIO_STREAMS
#endif
#endif
#ifdef _WANT_USE_LONG_TIME_T
#ifndef _USE_LONG_TIME_T
#define _USE_LONG_TIME_T
#endif
#endif
/* If _MB_EXTENDED_CHARSETS_ALL is set, we want all of the extended
charsets. The extended charsets add a few functions and a couple
of tables of a few K each. */
#ifdef _MB_EXTENDED_CHARSETS_ALL
#define _MB_EXTENDED_CHARSETS_ISO 1
#define _MB_EXTENDED_CHARSETS_WINDOWS 1
#endif
#endif /* __SYS_CONFIG_H__ */

533
src/include/sys/features.h Executable file
View File

@ -0,0 +1,533 @@
/*
* Written by Joel Sherrill <joel@OARcorp.com>.
*
* COPYRIGHT (c) 1989-2014.
*
* On-Line Applications Research Corporation (OAR).
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION
* OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
* SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
* $Id$
*/
#ifndef _SYS_FEATURES_H
#define _SYS_FEATURES_H
#ifdef __cplusplus
extern "C" {
#endif
#include <_newlib_version.h>
/* Macro to test version of GCC. Returns 0 for non-GCC or too old GCC. */
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif /* __GNUC_PREREQ */
/* Version with trailing underscores for BSD compatibility. */
#define __GNUC_PREREQ__(ma, mi) __GNUC_PREREQ(ma, mi)
/*
* Feature test macros control which symbols are exposed by the system
* headers. Any of these must be defined before including any headers.
*
* __STRICT_ANSI__ (defined by gcc -ansi, -std=c90, -std=c99, or -std=c11)
* ISO C
*
* _POSIX_SOURCE (deprecated by _POSIX_C_SOURCE=1)
* _POSIX_C_SOURCE >= 1
* POSIX.1-1990
*
* _POSIX_C_SOURCE >= 2
* POSIX.2-1992
*
* _POSIX_C_SOURCE >= 199309L
* POSIX.1b-1993 Real-time extensions
*
* _POSIX_C_SOURCE >= 199506L
* POSIX.1c-1995 Threads extensions
*
* _POSIX_C_SOURCE >= 200112L
* POSIX.1-2001 and C99
*
* _POSIX_C_SOURCE >= 200809L
* POSIX.1-2008
*
* _XOPEN_SOURCE
* POSIX.1-1990 and XPG4
*
* _XOPEN_SOURCE_EXTENDED
* SUSv1 (POSIX.2-1992 plus XPG4v2)
*
* _XOPEN_SOURCE >= 500
* SUSv2 (POSIX.1c-1995 plus XSI)
*
* _XOPEN_SOURCE >= 600
* SUSv3 (POSIX.1-2001 plus XSI) and C99
*
* _XOPEN_SOURCE >= 700
* SUSv4 (POSIX.1-2008 plus XSI)
*
* _ISOC99_SOURCE or gcc -std=c99 or g++
* ISO C99
*
* _ISOC11_SOURCE or gcc -std=c11 or g++ -std=c++11
* ISO C11
*
* _ATFILE_SOURCE (implied by _POSIX_C_SOURCE >= 200809L)
* "at" functions
*
* _LARGEFILE_SOURCE (deprecated by _XOPEN_SOURCE >= 500)
* fseeko, ftello
*
* _GNU_SOURCE
* All of the above plus GNU extensions
*
* _BSD_SOURCE (deprecated by _DEFAULT_SOURCE)
* _SVID_SOURCE (deprecated by _DEFAULT_SOURCE)
* _DEFAULT_SOURCE (or none of the above)
* POSIX-1.2008 with BSD and SVr4 extensions
*
* _FORTIFY_SOURCE = 1 or 2
* Object Size Checking function wrappers
*/
#ifdef _GNU_SOURCE
#undef _ATFILE_SOURCE
#define _ATFILE_SOURCE 1
#undef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE 1
#undef _ISOC99_SOURCE
#define _ISOC99_SOURCE 1
#undef _ISOC11_SOURCE
#define _ISOC11_SOURCE 1
#undef _POSIX_SOURCE
#define _POSIX_SOURCE 1
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#undef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#undef _XOPEN_SOURCE_EXTENDED
#define _XOPEN_SOURCE_EXTENDED 1
#endif /* _GNU_SOURCE */
#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || \
(!defined(__STRICT_ANSI__) && !defined(_ANSI_SOURCE) && \
!defined(_ISOC99_SOURCE) && !defined(_POSIX_SOURCE) && \
!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE))
#undef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE 1
#endif
#if defined(_DEFAULT_SOURCE)
#undef _POSIX_SOURCE
#define _POSIX_SOURCE 1
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) && \
((!defined(__STRICT_ANSI__) && !defined(_ANSI_SOURCE)) || \
(_XOPEN_SOURCE - 0) >= 500)
#define _POSIX_SOURCE 1
#if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE - 0) >= 700
#define _POSIX_C_SOURCE 200809L
#elif (_XOPEN_SOURCE - 0) >= 600
#define _POSIX_C_SOURCE 200112L
#elif (_XOPEN_SOURCE - 0) >= 500
#define _POSIX_C_SOURCE 199506L
#elif (_XOPEN_SOURCE - 0) < 500
#define _POSIX_C_SOURCE 2
#endif
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809
#undef _ATFILE_SOURCE
#define _ATFILE_SOURCE 1
#endif
/*
* The following private macros are used throughout the headers to control
* which symbols should be exposed. They are for internal use only, as
* indicated by the leading double underscore, and must never be used outside
* of these headers.
*
* __POSIX_VISIBLE
* any version of POSIX.1; enabled by default, or with _POSIX_SOURCE,
* any value of _POSIX_C_SOURCE, or _XOPEN_SOURCE >= 500.
*
* __POSIX_VISIBLE >= 2
* POSIX.2-1992; enabled by default, with _POSIX_C_SOURCE >= 2,
* or _XOPEN_SOURCE >= 500.
*
* __POSIX_VISIBLE >= 199309
* POSIX.1b-1993; enabled by default, with _POSIX_C_SOURCE >= 199309L,
* or _XOPEN_SOURCE >= 500.
*
* __POSIX_VISIBLE >= 199506
* POSIX.1c-1995; enabled by default, with _POSIX_C_SOURCE >= 199506L,
* or _XOPEN_SOURCE >= 500.
*
* __POSIX_VISIBLE >= 200112
* POSIX.1-2001; enabled by default, with _POSIX_C_SOURCE >= 200112L,
* or _XOPEN_SOURCE >= 600.
*
* __POSIX_VISIBLE >= 200809
* POSIX.1-2008; enabled by default, with _POSIX_C_SOURCE >= 200809L,
* or _XOPEN_SOURCE >= 700.
*
* __XSI_VISIBLE
* XPG4 XSI extensions; enabled with any version of _XOPEN_SOURCE.
*
* __XSI_VISIBLE >= 4
* SUSv1 XSI extensions; enabled with both _XOPEN_SOURCE and
* _XOPEN_SOURCE_EXTENDED together.
*
* __XSI_VISIBLE >= 500
* SUSv2 XSI extensions; enabled with _XOPEN_SOURCE >= 500.
*
* __XSI_VISIBLE >= 600
* SUSv3 XSI extensions; enabled with _XOPEN_SOURCE >= 600.
*
* __XSI_VISIBLE >= 700
* SUSv4 XSI extensions; enabled with _XOPEN_SOURCE >= 700.
*
* __ISO_C_VISIBLE >= 1999
* ISO C99; enabled with gcc -std=c99 or newer (on by default since GCC 5),
* any version of C++, or with _ISOC99_SOURCE, _POSIX_C_SOURCE >= 200112L,
* or _XOPEN_SOURCE >= 600.
*
* __ISO_C_VISIBLE >= 2011
* ISO C11; enabled with gcc -std=c11 or newer (on by default since GCC 5),
* g++ -std=c++11 or newer (on by default since GCC 6), or with
* _ISOC11_SOURCE.
*
* __ATFILE_VISIBLE
* "at" functions; enabled by default, with _ATFILE_SOURCE,
* _POSIX_C_SOURCE >= 200809L, or _XOPEN_SOURCE >= 700.
*
* __LARGEFILE_VISIBLE
* fseeko, ftello; enabled with _LARGEFILE_SOURCE or _XOPEN_SOURCE >= 500.
*
* __BSD_VISIBLE
* BSD extensions; enabled by default, or with _BSD_SOURCE.
*
* __SVID_VISIBLE
* SVr4 extensions; enabled by default, or with _SVID_SOURCE.
*
* __MISC_VISIBLE
* Extensions found in both BSD and SVr4 (shorthand for
* (__BSD_VISIBLE || __SVID_VISIBLE)), or newlib-specific
* extensions; enabled by default.
*
* __GNU_VISIBLE
* GNU extensions; enabled with _GNU_SOURCE.
*
* __SSP_FORTIFY_LEVEL
* Object Size Checking; defined to 0 (off), 1, or 2.
*
* In all cases above, "enabled by default" means either by defining
* _DEFAULT_SOURCE, or by not defining any of the public feature test macros.
*/
#ifdef _ATFILE_SOURCE
#define __ATFILE_VISIBLE 1
#else
#define __ATFILE_VISIBLE 0
#endif
#ifdef _DEFAULT_SOURCE
#define __BSD_VISIBLE 1
#else
#define __BSD_VISIBLE 0
#endif
#ifdef _GNU_SOURCE
#define __GNU_VISIBLE 1
#else
#define __GNU_VISIBLE 0
#endif
#if defined(_ISOC11_SOURCE) || \
(__STDC_VERSION__ - 0) >= 201112L || (__cplusplus - 0) >= 201103L
#define __ISO_C_VISIBLE 2011
#elif defined(_ISOC99_SOURCE) || (_POSIX_C_SOURCE - 0) >= 200112L || \
(__STDC_VERSION__ - 0) >= 199901L || defined(__cplusplus)
#define __ISO_C_VISIBLE 1999
#else
#define __ISO_C_VISIBLE 1990
#endif
#if defined(_LARGEFILE_SOURCE) || (_XOPEN_SOURCE - 0) >= 500
#define __LARGEFILE_VISIBLE 1
#else
#define __LARGEFILE_VISIBLE 0
#endif
#ifdef _DEFAULT_SOURCE
#define __MISC_VISIBLE 1
#else
#define __MISC_VISIBLE 0
#endif
#if (_POSIX_C_SOURCE - 0) >= 200809L
#define __POSIX_VISIBLE 200809
#elif (_POSIX_C_SOURCE - 0) >= 200112L
#define __POSIX_VISIBLE 200112
#elif (_POSIX_C_SOURCE - 0) >= 199506L
#define __POSIX_VISIBLE 199506
#elif (_POSIX_C_SOURCE - 0) >= 199309L
#define __POSIX_VISIBLE 199309
#elif (_POSIX_C_SOURCE - 0) >= 2 || defined(_XOPEN_SOURCE)
#define __POSIX_VISIBLE 199209
#elif defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
#define __POSIX_VISIBLE 199009
#else
#define __POSIX_VISIBLE 0
#endif
#ifdef _DEFAULT_SOURCE
#define __SVID_VISIBLE 1
#else
#define __SVID_VISIBLE 0
#endif
#if (_XOPEN_SOURCE - 0) >= 700
#define __XSI_VISIBLE 700
#elif (_XOPEN_SOURCE - 0) >= 600
#define __XSI_VISIBLE 600
#elif (_XOPEN_SOURCE - 0) >= 500
#define __XSI_VISIBLE 500
#elif defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)
#define __XSI_VISIBLE 4
#elif defined(_XOPEN_SOURCE)
#define __XSI_VISIBLE 1
#else
#define __XSI_VISIBLE 0
#endif
#if _FORTIFY_SOURCE > 0 && !defined(__cplusplus) && !defined(__lint__) && \
(__OPTIMIZE__ > 0 || defined(__clang__)) && __GNUC_PREREQ__(4, 1)
# if _FORTIFY_SOURCE > 1
# define __SSP_FORTIFY_LEVEL 2
# else
# define __SSP_FORTIFY_LEVEL 1
# endif
#else
# define __SSP_FORTIFY_LEVEL 0
#endif
/* RTEMS adheres to POSIX -- 1003.1b with some features from annexes. */
#ifdef __rtems__
#define _POSIX_JOB_CONTROL 1
#define _POSIX_SAVED_IDS 1
#define _POSIX_VERSION 199309L
#define _POSIX_ASYNCHRONOUS_IO 1
#define _POSIX_FSYNC 1
#define _POSIX_MAPPED_FILES 1
#define _POSIX_MEMLOCK 1
#define _POSIX_MEMLOCK_RANGE 1
#define _POSIX_MEMORY_PROTECTION 1
#define _POSIX_MESSAGE_PASSING 1
#define _POSIX_MONOTONIC_CLOCK 200112L
#define _POSIX_CLOCK_SELECTION 200112L
#define _POSIX_PRIORITIZED_IO 1
#define _POSIX_PRIORITY_SCHEDULING 1
#define _POSIX_REALTIME_SIGNALS 1
#define _POSIX_SEMAPHORES 1
#define _POSIX_SHARED_MEMORY_OBJECTS 1
#define _POSIX_SYNCHRONIZED_IO 1
#define _POSIX_TIMERS 1
#define _POSIX_BARRIERS 200112L
#define _POSIX_READER_WRITER_LOCKS 200112L
#define _POSIX_SPIN_LOCKS 200112L
/* In P1003.1b but defined by drafts at least as early as P1003.1c/D10 */
#define _POSIX_THREADS 1
#define _POSIX_THREAD_ATTR_STACKADDR 1
#define _POSIX_THREAD_ATTR_STACKSIZE 1
#define _POSIX_THREAD_PRIORITY_SCHEDULING 1
#define _POSIX_THREAD_PRIO_INHERIT 1
#define _POSIX_THREAD_PRIO_PROTECT 1
#define _POSIX_THREAD_PROCESS_SHARED 1
#define _POSIX_THREAD_SAFE_FUNCTIONS 1
/* P1003.4b/D8 defines the constants below this comment. */
#define _POSIX_SPAWN 1
#define _POSIX_TIMEOUTS 1
#define _POSIX_CPUTIME 1
#define _POSIX_THREAD_CPUTIME 1
#define _POSIX_SPORADIC_SERVER 1
#define _POSIX_THREAD_SPORADIC_SERVER 1
#define _POSIX_DEVICE_CONTROL 1
#define _POSIX_DEVCTL_DIRECTION 1
#define _POSIX_INTERRUPT_CONTROL 1
#define _POSIX_ADVISORY_INFO 1
/* UNIX98 added some new pthread mutex attributes */
#define _UNIX98_THREAD_MUTEX_ATTRIBUTES 1
/* POSIX 1003.26-2003 defined device control method */
#define _POSIX_26_VERSION 200312L
#endif
/* XMK loosely adheres to POSIX -- 1003.1 */
#ifdef __XMK__
#define _POSIX_THREADS 1
#define _POSIX_THREAD_PRIORITY_SCHEDULING 1
#endif
#ifdef __svr4__
# define _POSIX_JOB_CONTROL 1
# define _POSIX_SAVED_IDS 1
# define _POSIX_VERSION 199009L
#endif
#ifdef __CYGWIN__
#if __POSIX_VISIBLE >= 200809
#define _POSIX_VERSION 200809L
#define _POSIX2_VERSION 200809L
#elif __POSIX_VISIBLE >= 200112
#define _POSIX_VERSION 200112L
#define _POSIX2_VERSION 200112L
#elif __POSIX_VISIBLE >= 199506
#define _POSIX_VERSION 199506L
#define _POSIX2_VERSION 199506L
#elif __POSIX_VISIBLE >= 199309
#define _POSIX_VERSION 199309L
#define _POSIX2_VERSION 199209L
#elif __POSIX_VISIBLE >= 199209
#define _POSIX_VERSION 199009L
#define _POSIX2_VERSION 199209L
#elif __POSIX_VISIBLE
#define _POSIX_VERSION 199009L
#endif
#if __XSI_VISIBLE >= 4
#define _XOPEN_VERSION __XSI_VISIBLE
#endif
#define _POSIX_ADVISORY_INFO 200809L
#define _POSIX_ASYNCHRONOUS_IO 200809L
#define _POSIX_BARRIERS 200809L
#define _POSIX_CHOWN_RESTRICTED 1
#define _POSIX_CLOCK_SELECTION 200809L
#define _POSIX_CPUTIME 200809L
#define _POSIX_FSYNC 200809L
#define _POSIX_IPV6 200809L
#define _POSIX_JOB_CONTROL 1
#define _POSIX_MAPPED_FILES 200809L
/* #define _POSIX_MEMLOCK -1 */
#define _POSIX_MEMLOCK_RANGE 200809L
#define _POSIX_MEMORY_PROTECTION 200809L
#define _POSIX_MESSAGE_PASSING 200809L
#define _POSIX_MONOTONIC_CLOCK 200809L
#define _POSIX_NO_TRUNC 1
/* #define _POSIX_PRIORITIZED_IO -1 */
#define _POSIX_PRIORITY_SCHEDULING 200809L
#define _POSIX_RAW_SOCKETS 200809L
#define _POSIX_READER_WRITER_LOCKS 200809L
#define _POSIX_REALTIME_SIGNALS 200809L
#define _POSIX_REGEXP 1
#define _POSIX_SAVED_IDS 1
#define _POSIX_SEMAPHORES 200809L
#define _POSIX_SHARED_MEMORY_OBJECTS 200809L
#define _POSIX_SHELL 1
#define _POSIX_SPAWN 200809L
#define _POSIX_SPIN_LOCKS 200809L
/* #define _POSIX_SPORADIC_SERVER -1 */
#define _POSIX_SYNCHRONIZED_IO 200809L
#define _POSIX_THREAD_ATTR_STACKADDR 200809L
#define _POSIX_THREAD_ATTR_STACKSIZE 200809L
#define _POSIX_THREAD_CPUTIME 200809L
/* #define _POSIX_THREAD_PRIO_INHERIT -1 */
/* #define _POSIX_THREAD_PRIO_PROTECT -1 */
#define _POSIX_THREAD_PRIORITY_SCHEDULING 200809L
#define _POSIX_THREAD_PROCESS_SHARED 200809L
#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L
/* #define _POSIX_THREAD_SPORADIC_SERVER -1 */
#define _POSIX_THREADS 200809L
#define _POSIX_TIMEOUTS 200809L
#define _POSIX_TIMERS 200809L
/* #define _POSIX_TRACE -1 */
/* #define _POSIX_TRACE_EVENT_FILTER -1 */
/* #define _POSIX_TRACE_INHERIT -1 */
/* #define _POSIX_TRACE_LOG -1 */
/* #define _POSIX_TYPED_MEMORY_OBJECTS -1 */
#define _POSIX_VDISABLE '\0'
#if __POSIX_VISIBLE >= 2
#define _POSIX2_C_VERSION _POSIX2_VERSION
#define _POSIX2_C_BIND _POSIX2_VERSION
#define _POSIX2_C_DEV _POSIX2_VERSION
#define _POSIX2_CHAR_TERM _POSIX2_VERSION
/* #define _POSIX2_FORT_DEV -1 */
/* #define _POSIX2_FORT_RUN -1 */
/* #define _POSIX2_LOCALEDEF -1 */
/* #define _POSIX2_PBS -1 */
/* #define _POSIX2_PBS_ACCOUNTING -1 */
/* #define _POSIX2_PBS_CHECKPOINT -1 */
/* #define _POSIX2_PBS_LOCATE -1 */
/* #define _POSIX2_PBS_MESSAGE -1 */
/* #define _POSIX2_PBS_TRACK -1 */
#define _POSIX2_SW_DEV _POSIX2_VERSION
#define _POSIX2_UPE _POSIX2_VERSION
#endif /* __POSIX_VISIBLE >= 2 */
#define _POSIX_V6_ILP32_OFF32 -1
#ifdef __LP64__
#define _POSIX_V6_ILP32_OFFBIG -1
#define _POSIX_V6_LP64_OFF64 1
#define _POSIX_V6_LPBIG_OFFBIG 1
#else
#define _POSIX_V6_ILP32_OFFBIG 1
#define _POSIX_V6_LP64_OFF64 -1
#define _POSIX_V6_LPBIG_OFFBIG -1
#endif
#define _POSIX_V7_ILP32_OFF32 _POSIX_V6_ILP32_OFF32
#define _POSIX_V7_ILP32_OFFBIG _POSIX_V6_ILP32_OFFBIG
#define _POSIX_V7_LP64_OFF64 _POSIX_V6_LP64_OFF64
#define _POSIX_V7_LPBIG_OFFBIG _POSIX_V6_LPBIG_OFFBIG
#define _XBS5_ILP32_OFF32 _POSIX_V6_ILP32_OFF32
#define _XBS5_ILP32_OFFBIG _POSIX_V6_ILP32_OFFBIG
#define _XBS5_LP64_OFF64 _POSIX_V6_LP64_OFF64
#define _XBS5_LPBIG_OFFBIG _POSIX_V6_LPBIG_OFFBIG
#if __XSI_VISIBLE
#define _XOPEN_CRYPT 1
#define _XOPEN_ENH_I18N 1
/* #define _XOPEN_LEGACY -1 */
/* #define _XOPEN_REALTIME -1 */
/* #define _XOPEN_REALTIME_THREADS -1 */
#define _XOPEN_SHM 1
/* #define _XOPEN_STREAMS -1 */
/* #define _XOPEN_UNIX -1 */
#endif /* __XSI_VISIBLE */
/* The value corresponds to UNICODE version 5.2, which is the current
state of newlib's wide char conversion functions. */
#define __STDC_ISO_10646__ 200910L
#endif /* __CYGWIN__ */
#ifdef __cplusplus
}
#endif
#endif /* _SYS_FEATURES_H */

69
src/include/sys/lock.h Executable file
View File

@ -0,0 +1,69 @@
#ifndef __SYS_LOCK_H__
#define __SYS_LOCK_H__
/* dummy lock routines for single-threaded aps */
#include <newlib.h>
#include <_ansi.h>
#if !defined(_RETARGETABLE_LOCKING)
typedef int _LOCK_T;
typedef int _LOCK_RECURSIVE_T;
#define __LOCK_INIT(class,lock) static int lock = 0;
#define __LOCK_INIT_RECURSIVE(class,lock) static int lock = 0;
#define __lock_init(lock) ((void) 0)
#define __lock_init_recursive(lock) ((void) 0)
#define __lock_close(lock) ((void) 0)
#define __lock_close_recursive(lock) ((void) 0)
#define __lock_acquire(lock) ((void) 0)
#define __lock_acquire_recursive(lock) ((void) 0)
#define __lock_try_acquire(lock) ((void) 0)
#define __lock_try_acquire_recursive(lock) ((void) 0)
#define __lock_release(lock) ((void) 0)
#define __lock_release_recursive(lock) ((void) 0)
#else
#ifdef __cplusplus
extern "C" {
#endif
struct __lock;
typedef struct __lock * _LOCK_T;
#define _LOCK_RECURSIVE_T _LOCK_T
#define __LOCK_INIT(class,lock) extern struct __lock __lock_ ## lock; \
class _LOCK_T lock = &__lock_ ## lock
#define __LOCK_INIT_RECURSIVE(class,lock) __LOCK_INIT(class,lock)
extern void __retarget_lock_init(_LOCK_T *lock);
#define __lock_init(lock) __retarget_lock_init(&lock)
extern void __retarget_lock_init_recursive(_LOCK_T *lock);
#define __lock_init_recursive(lock) __retarget_lock_init_recursive(&lock)
extern void __retarget_lock_close(_LOCK_T lock);
#define __lock_close(lock) __retarget_lock_close(lock)
extern void __retarget_lock_close_recursive(_LOCK_T lock);
#define __lock_close_recursive(lock) __retarget_lock_close_recursive(lock)
extern void __retarget_lock_acquire(_LOCK_T lock);
#define __lock_acquire(lock) __retarget_lock_acquire(lock)
extern void __retarget_lock_acquire_recursive(_LOCK_T lock);
#define __lock_acquire_recursive(lock) __retarget_lock_acquire_recursive(lock)
extern int __retarget_lock_try_acquire(_LOCK_T lock);
#define __lock_try_acquire(lock) __retarget_lock_try_acquire(lock)
extern int __retarget_lock_try_acquire_recursive(_LOCK_T lock);
#define __lock_try_acquire_recursive(lock) \
__retarget_lock_try_acquire_recursive(lock)
extern void __retarget_lock_release(_LOCK_T lock);
#define __lock_release(lock) __retarget_lock_release(lock)
extern void __retarget_lock_release_recursive(_LOCK_T lock);
#define __lock_release_recursive(lock) __retarget_lock_release_recursive(lock)
#ifdef __cplusplus
}
#endif
#endif /* !defined(_RETARGETABLE_LOCKING) */
#endif /* __SYS_LOCK_H__ */

842
src/include/sys/reent.h Executable file
View File

@ -0,0 +1,842 @@
/* This header file provides the reentrancy. */
/* WARNING: All identifiers here must begin with an underscore. This file is
included by stdio.h and others and we therefore must only use identifiers
in the namespace allotted to us. */
#ifndef _SYS_REENT_H_
#ifdef __cplusplus
extern "C" {
#endif
#define _SYS_REENT_H_
#include <_ansi.h>
#include <stddef.h>
#include <sys/_types.h>
#define _NULL 0
#ifndef __Long
#if __LONG_MAX__ == 2147483647L
#define __Long long
typedef unsigned __Long __ULong;
#elif __INT_MAX__ == 2147483647
#define __Long int
typedef unsigned __Long __ULong;
#endif
#endif
#if !defined( __Long)
#include <sys/types.h>
#endif
#ifndef __Long
#define __Long __int32_t
typedef __uint32_t __ULong;
#endif
struct _reent;
struct __locale_t;
/*
* If _REENT_SMALL is defined, we make struct _reent as small as possible,
* by having nearly everything possible allocated at first use.
*/
struct _Bigint
{
struct _Bigint *_next;
int _k, _maxwds, _sign, _wds;
__ULong _x[1];
};
/* needed by reentrant structure */
struct __tm
{
int __tm_sec;
int __tm_min;
int __tm_hour;
int __tm_mday;
int __tm_mon;
int __tm_year;
int __tm_wday;
int __tm_yday;
int __tm_isdst;
};
/*
* atexit() support.
*/
#define _ATEXIT_SIZE 32 /* must be at least 32 to guarantee ANSI conformance */
struct _on_exit_args {
void * _fnargs[_ATEXIT_SIZE]; /* user fn args */
void * _dso_handle[_ATEXIT_SIZE];
/* Bitmask is set if user function takes arguments. */
__ULong _fntypes; /* type of exit routine -
Must have at least _ATEXIT_SIZE bits */
/* Bitmask is set if function was registered via __cxa_atexit. */
__ULong _is_cxa;
};
#ifdef _REENT_SMALL
struct _atexit {
struct _atexit *_next; /* next in list */
int _ind; /* next index in this table */
void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */
struct _on_exit_args * _on_exit_args_ptr;
};
# define _ATEXIT_INIT {_NULL, 0, {_NULL}, _NULL}
#else
struct _atexit {
struct _atexit *_next; /* next in list */
int _ind; /* next index in this table */
/* Some entries may already have been called, and will be NULL. */
void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */
struct _on_exit_args _on_exit_args;
};
# define _ATEXIT_INIT {_NULL, 0, {_NULL}, {{_NULL}, {_NULL}, 0, 0}}
#endif
#ifdef _REENT_GLOBAL_ATEXIT
# define _REENT_INIT_ATEXIT
#else
# define _REENT_INIT_ATEXIT \
_NULL, _ATEXIT_INIT,
#endif
/*
* Stdio buffers.
*
* This and __FILE are defined here because we need them for struct _reent,
* but we don't want stdio.h included when stdlib.h is.
*/
struct __sbuf {
unsigned char *_base;
int _size;
};
/*
* Stdio state variables.
*
* The following always hold:
*
* if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
* _lbfsize is -_bf._size, else _lbfsize is 0
* if _flags&__SRD, _w is 0
* if _flags&__SWR, _r is 0
*
* This ensures that the getc and putc macros (or inline functions) never
* try to write or read from a file that is in `read' or `write' mode.
* (Moreover, they can, and do, automatically switch from read mode to
* write mode, and back, on "r+" and "w+" files.)
*
* _lbfsize is used only to make the inline line-buffered output stream
* code as compact as possible.
*
* _ub, _up, and _ur are used when ungetc() pushes back more characters
* than fit in the current _bf, or when ungetc() pushes back a character
* that does not match the previous one in _bf. When this happens,
* _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
* _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
*/
#if defined(_REENT_SMALL) && !defined(_REENT_GLOBAL_STDIO_STREAMS)
/*
* struct __sFILE_fake is the start of a struct __sFILE, with only the
* minimal fields allocated. In __sinit() we really allocate the 3
* standard streams, etc., and point away from this fake.
*/
struct __sFILE_fake {
unsigned char *_p; /* current position in (some) buffer */
int _r; /* read space left for getc() */
int _w; /* write space left for putc() */
short _flags; /* flags, below; this FILE is free if 0 */
short _file; /* fileno, if Unix descriptor, else -1 */
struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
int _lbfsize; /* 0 or -_bf._size, for inline putc */
struct _reent *_data;
};
/* Following is needed both in libc/stdio and libc/stdlib so we put it
* here instead of libc/stdio/local.h where it was previously. */
extern void __sinit (struct _reent *);
# define _REENT_SMALL_CHECK_INIT(ptr) \
do \
{ \
if ((ptr) && !(ptr)->__sdidinit) \
__sinit (ptr); \
} \
while (0)
#else /* _REENT_SMALL && !_REENT_GLOBAL_STDIO_STREAMS */
# define _REENT_SMALL_CHECK_INIT(ptr) /* nothing */
#endif /* _REENT_SMALL && !_REENT_GLOBAL_STDIO_STREAMS */
struct __sFILE {
unsigned char *_p; /* current position in (some) buffer */
int _r; /* read space left for getc() */
int _w; /* write space left for putc() */
short _flags; /* flags, below; this FILE is free if 0 */
short _file; /* fileno, if Unix descriptor, else -1 */
struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
int _lbfsize; /* 0 or -_bf._size, for inline putc */
#ifdef _REENT_SMALL
struct _reent *_data;
#endif
/* operations */
void * _cookie; /* cookie passed to io functions */
_READ_WRITE_RETURN_TYPE (*_read) (struct _reent *, void *,
char *, _READ_WRITE_BUFSIZE_TYPE);
_READ_WRITE_RETURN_TYPE (*_write) (struct _reent *, void *,
const char *,
_READ_WRITE_BUFSIZE_TYPE);
_fpos_t (*_seek) (struct _reent *, void *, _fpos_t, int);
int (*_close) (struct _reent *, void *);
/* separate buffer for long sequences of ungetc() */
struct __sbuf _ub; /* ungetc buffer */
unsigned char *_up; /* saved _p when _p is doing ungetc data */
int _ur; /* saved _r when _r is counting ungetc data */
/* tricks to meet minimum requirements even when malloc() fails */
unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
unsigned char _nbuf[1]; /* guarantee a getc() buffer */
/* separate buffer for fgetline() when line crosses buffer boundary */
struct __sbuf _lb; /* buffer for fgetline() */
/* Unix stdio files get aligned to block boundaries on fseek() */
int _blksize; /* stat.st_blksize (may be != _bf._size) */
_off_t _offset; /* current lseek offset */
#ifndef _REENT_SMALL
struct _reent *_data; /* Here for binary compatibility? Remove? */
#endif
#ifndef __SINGLE_THREAD__
_flock_t _lock; /* for thread-safety locking */
#endif
_mbstate_t _mbstate; /* for wide char stdio functions. */
int _flags2; /* for future use */
};
#ifdef __CUSTOM_FILE_IO__
/* Get custom _FILE definition. */
#include <sys/custom_file.h>
#else /* !__CUSTOM_FILE_IO__ */
#ifdef __LARGE64_FILES
struct __sFILE64 {
unsigned char *_p; /* current position in (some) buffer */
int _r; /* read space left for getc() */
int _w; /* write space left for putc() */
short _flags; /* flags, below; this FILE is free if 0 */
short _file; /* fileno, if Unix descriptor, else -1 */
struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
int _lbfsize; /* 0 or -_bf._size, for inline putc */
struct _reent *_data;
/* operations */
void * _cookie; /* cookie passed to io functions */
_READ_WRITE_RETURN_TYPE (*_read) (struct _reent *, void *,
char *, _READ_WRITE_BUFSIZE_TYPE);
_READ_WRITE_RETURN_TYPE (*_write) (struct _reent *, void *,
const char *,
_READ_WRITE_BUFSIZE_TYPE);
_fpos_t (*_seek) (struct _reent *, void *, _fpos_t, int);
int (*_close) (struct _reent *, void *);
/* separate buffer for long sequences of ungetc() */
struct __sbuf _ub; /* ungetc buffer */
unsigned char *_up; /* saved _p when _p is doing ungetc data */
int _ur; /* saved _r when _r is counting ungetc data */
/* tricks to meet minimum requirements even when malloc() fails */
unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
unsigned char _nbuf[1]; /* guarantee a getc() buffer */
/* separate buffer for fgetline() when line crosses buffer boundary */
struct __sbuf _lb; /* buffer for fgetline() */
/* Unix stdio files get aligned to block boundaries on fseek() */
int _blksize; /* stat.st_blksize (may be != _bf._size) */
int _flags2; /* for future use */
_off64_t _offset; /* current lseek offset */
_fpos64_t (*_seek64) (struct _reent *, void *, _fpos64_t, int);
#ifndef __SINGLE_THREAD__
_flock_t _lock; /* for thread-safety locking */
#endif
_mbstate_t _mbstate; /* for wide char stdio functions. */
};
typedef struct __sFILE64 __FILE;
#else
typedef struct __sFILE __FILE;
#endif /* __LARGE64_FILES */
#endif /* !__CUSTOM_FILE_IO__ */
struct _glue
{
struct _glue *_next;
int _niobs;
__FILE *_iobs;
};
/*
* rand48 family support
*
* Copyright (c) 1993 Martin Birgmeier
* All rights reserved.
*
* You may redistribute unmodified or modified versions of this source
* code provided that the above copyright notice and this and the
* following conditions are retained.
*
* This software is provided ``as is'', and comes with no warranties
* of any kind. I shall in no event be liable for anything that happens
* to anyone/anything when using this software.
*/
#define _RAND48_SEED_0 (0x330e)
#define _RAND48_SEED_1 (0xabcd)
#define _RAND48_SEED_2 (0x1234)
#define _RAND48_MULT_0 (0xe66d)
#define _RAND48_MULT_1 (0xdeec)
#define _RAND48_MULT_2 (0x0005)
#define _RAND48_ADD (0x000b)
struct _rand48 {
unsigned short _seed[3];
unsigned short _mult[3];
unsigned short _add;
#ifdef _REENT_SMALL
/* Put this in here as well, for good luck. */
__extension__ unsigned long long _rand_next;
#endif
};
/* How big the some arrays are. */
#define _REENT_EMERGENCY_SIZE 25
#define _REENT_ASCTIME_SIZE 26
#define _REENT_SIGNAL_SIZE 24
/*
* struct _reent
*
* This structure contains *all* globals needed by the library.
* It's raison d'etre is to facilitate threads by making all library routines
* reentrant. IE: All state information is contained here.
*/
#ifdef _REENT_SMALL
struct _mprec
{
/* used by mprec routines */
struct _Bigint *_result;
int _result_k;
struct _Bigint *_p5s;
struct _Bigint **_freelist;
};
struct _misc_reent
{
/* miscellaneous reentrant data */
char *_strtok_last;
_mbstate_t _mblen_state;
_mbstate_t _wctomb_state;
_mbstate_t _mbtowc_state;
char _l64a_buf[8];
int _getdate_err;
_mbstate_t _mbrlen_state;
_mbstate_t _mbrtowc_state;
_mbstate_t _mbsrtowcs_state;
_mbstate_t _wcrtomb_state;
_mbstate_t _wcsrtombs_state;
};
/* This version of _reent is laid out with "int"s in pairs, to help
* ports with 16-bit int's but 32-bit pointers, align nicely. */
struct _reent
{
/* As an exception to the above put _errno first for binary
compatibility with non _REENT_SMALL targets. */
int _errno; /* local copy of errno */
/* FILE is a big struct and may change over time. To try to achieve binary
compatibility with future versions, put stdin,stdout,stderr here.
These are pointers into member __sf defined below. */
__FILE *_stdin, *_stdout, *_stderr; /* XXX */
int _inc; /* used by tmpnam */
char *_emergency;
int __sdidinit; /* 1 means stdio has been init'd */
int _unspecified_locale_info; /* unused, reserved for locale stuff */
struct __locale_t *_locale;/* per-thread locale */
struct _mprec *_mp;
void (*__cleanup) (struct _reent *);
int _gamma_signgam;
/* used by some fp conversion routines */
int _cvtlen; /* should be size_t */
char *_cvtbuf;
struct _rand48 *_r48;
struct __tm *_localtime_buf;
char *_asctime_buf;
/* signal info */
void (**(_sig_func))(int);
# ifndef _REENT_GLOBAL_ATEXIT
/* atexit stuff */
struct _atexit *_atexit;
struct _atexit _atexit0;
# endif
struct _glue __sglue; /* root of glue chain */
__FILE *__sf; /* file descriptors */
struct _misc_reent *_misc; /* strtok, multibyte states */
char *_signal_buf; /* strsignal */
};
#ifdef _REENT_GLOBAL_STDIO_STREAMS
extern __FILE __sf[3];
# define _REENT_INIT(var) \
{ 0, \
&__sf[0], \
&__sf[1], \
&__sf[2], \
0, \
_NULL, \
0, \
0, \
_NULL, \
_NULL, \
_NULL, \
0, \
0, \
_NULL, \
_NULL, \
_NULL, \
_NULL, \
_NULL, \
_REENT_INIT_ATEXIT \
{_NULL, 0, _NULL}, \
_NULL, \
_NULL, \
_NULL \
}
#define _REENT_INIT_PTR_ZEROED(var) \
{ (var)->_stdin = &__sf[0]; \
(var)->_stdout = &__sf[1]; \
(var)->_stderr = &__sf[2]; \
}
#else /* _REENT_GLOBAL_STDIO_STREAMS */
extern const struct __sFILE_fake __sf_fake_stdin;
extern const struct __sFILE_fake __sf_fake_stdout;
extern const struct __sFILE_fake __sf_fake_stderr;
# define _REENT_INIT(var) \
{ 0, \
(__FILE *)&__sf_fake_stdin, \
(__FILE *)&__sf_fake_stdout, \
(__FILE *)&__sf_fake_stderr, \
0, \
_NULL, \
0, \
0, \
_NULL, \
_NULL, \
_NULL, \
0, \
0, \
_NULL, \
_NULL, \
_NULL, \
_NULL, \
_NULL, \
_REENT_INIT_ATEXIT \
{_NULL, 0, _NULL}, \
_NULL, \
_NULL, \
_NULL \
}
#define _REENT_INIT_PTR_ZEROED(var) \
{ (var)->_stdin = (__FILE *)&__sf_fake_stdin; \
(var)->_stdout = (__FILE *)&__sf_fake_stdout; \
(var)->_stderr = (__FILE *)&__sf_fake_stderr; \
}
#endif /* _REENT_GLOBAL_STDIO_STREAMS */
/* Only add assert() calls if we are specified to debug. */
#ifdef _REENT_CHECK_DEBUG
#include <assert.h>
#define __reent_assert(x) assert(x)
#else
#define __reent_assert(x) ((void)0)
#endif
#ifdef __CUSTOM_FILE_IO__
#error Custom FILE I/O and _REENT_SMALL not currently supported.
#endif
/* Generic _REENT check macro. */
#define _REENT_CHECK(var, what, type, size, init) do { \
struct _reent *_r = (var); \
if (_r->what == NULL) { \
_r->what = (type)malloc(size); \
__reent_assert(_r->what); \
init; \
} \
} while (0)
#define _REENT_CHECK_TM(var) \
_REENT_CHECK(var, _localtime_buf, struct __tm *, sizeof *((var)->_localtime_buf), \
/* nothing */)
#define _REENT_CHECK_ASCTIME_BUF(var) \
_REENT_CHECK(var, _asctime_buf, char *, _REENT_ASCTIME_SIZE, \
memset((var)->_asctime_buf, 0, _REENT_ASCTIME_SIZE))
/* Handle the dynamically allocated rand48 structure. */
#define _REENT_INIT_RAND48(var) do { \
struct _reent *_r = (var); \
_r->_r48->_seed[0] = _RAND48_SEED_0; \
_r->_r48->_seed[1] = _RAND48_SEED_1; \
_r->_r48->_seed[2] = _RAND48_SEED_2; \
_r->_r48->_mult[0] = _RAND48_MULT_0; \
_r->_r48->_mult[1] = _RAND48_MULT_1; \
_r->_r48->_mult[2] = _RAND48_MULT_2; \
_r->_r48->_add = _RAND48_ADD; \
_r->_r48->_rand_next = 1; \
} while (0)
#define _REENT_CHECK_RAND48(var) \
_REENT_CHECK(var, _r48, struct _rand48 *, sizeof *((var)->_r48), _REENT_INIT_RAND48((var)))
#define _REENT_INIT_MP(var) do { \
struct _reent *_r = (var); \
_r->_mp->_result_k = 0; \
_r->_mp->_result = _r->_mp->_p5s = _NULL; \
_r->_mp->_freelist = _NULL; \
} while (0)
#define _REENT_CHECK_MP(var) \
_REENT_CHECK(var, _mp, struct _mprec *, sizeof *((var)->_mp), _REENT_INIT_MP(var))
#define _REENT_CHECK_EMERGENCY(var) \
_REENT_CHECK(var, _emergency, char *, _REENT_EMERGENCY_SIZE, /* nothing */)
#define _REENT_INIT_MISC(var) do { \
struct _reent *_r = (var); \
_r->_misc->_strtok_last = _NULL; \
_r->_misc->_mblen_state.__count = 0; \
_r->_misc->_mblen_state.__value.__wch = 0; \
_r->_misc->_wctomb_state.__count = 0; \
_r->_misc->_wctomb_state.__value.__wch = 0; \
_r->_misc->_mbtowc_state.__count = 0; \
_r->_misc->_mbtowc_state.__value.__wch = 0; \
_r->_misc->_mbrlen_state.__count = 0; \
_r->_misc->_mbrlen_state.__value.__wch = 0; \
_r->_misc->_mbrtowc_state.__count = 0; \
_r->_misc->_mbrtowc_state.__value.__wch = 0; \
_r->_misc->_mbsrtowcs_state.__count = 0; \
_r->_misc->_mbsrtowcs_state.__value.__wch = 0; \
_r->_misc->_wcrtomb_state.__count = 0; \
_r->_misc->_wcrtomb_state.__value.__wch = 0; \
_r->_misc->_wcsrtombs_state.__count = 0; \
_r->_misc->_wcsrtombs_state.__value.__wch = 0; \
_r->_misc->_l64a_buf[0] = '\0'; \
_r->_misc->_getdate_err = 0; \
} while (0)
#define _REENT_CHECK_MISC(var) \
_REENT_CHECK(var, _misc, struct _misc_reent *, sizeof *((var)->_misc), _REENT_INIT_MISC(var))
#define _REENT_CHECK_SIGNAL_BUF(var) \
_REENT_CHECK(var, _signal_buf, char *, _REENT_SIGNAL_SIZE, /* nothing */)
#define _REENT_SIGNGAM(ptr) ((ptr)->_gamma_signgam)
#define _REENT_RAND_NEXT(ptr) ((ptr)->_r48->_rand_next)
#define _REENT_RAND48_SEED(ptr) ((ptr)->_r48->_seed)
#define _REENT_RAND48_MULT(ptr) ((ptr)->_r48->_mult)
#define _REENT_RAND48_ADD(ptr) ((ptr)->_r48->_add)
#define _REENT_MP_RESULT(ptr) ((ptr)->_mp->_result)
#define _REENT_MP_RESULT_K(ptr) ((ptr)->_mp->_result_k)
#define _REENT_MP_P5S(ptr) ((ptr)->_mp->_p5s)
#define _REENT_MP_FREELIST(ptr) ((ptr)->_mp->_freelist)
#define _REENT_ASCTIME_BUF(ptr) ((ptr)->_asctime_buf)
#define _REENT_TM(ptr) ((ptr)->_localtime_buf)
#define _REENT_EMERGENCY(ptr) ((ptr)->_emergency)
#define _REENT_STRTOK_LAST(ptr) ((ptr)->_misc->_strtok_last)
#define _REENT_MBLEN_STATE(ptr) ((ptr)->_misc->_mblen_state)
#define _REENT_MBTOWC_STATE(ptr)((ptr)->_misc->_mbtowc_state)
#define _REENT_WCTOMB_STATE(ptr)((ptr)->_misc->_wctomb_state)
#define _REENT_MBRLEN_STATE(ptr) ((ptr)->_misc->_mbrlen_state)
#define _REENT_MBRTOWC_STATE(ptr) ((ptr)->_misc->_mbrtowc_state)
#define _REENT_MBSRTOWCS_STATE(ptr) ((ptr)->_misc->_mbsrtowcs_state)
#define _REENT_WCRTOMB_STATE(ptr) ((ptr)->_misc->_wcrtomb_state)
#define _REENT_WCSRTOMBS_STATE(ptr) ((ptr)->_misc->_wcsrtombs_state)
#define _REENT_L64A_BUF(ptr) ((ptr)->_misc->_l64a_buf)
#define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_misc->_getdate_err))
#define _REENT_SIGNAL_BUF(ptr) ((ptr)->_signal_buf)
#else /* !_REENT_SMALL */
struct _reent
{
int _errno; /* local copy of errno */
/* FILE is a big struct and may change over time. To try to achieve binary
compatibility with future versions, put stdin,stdout,stderr here.
These are pointers into member __sf defined below. */
__FILE *_stdin, *_stdout, *_stderr;
int _inc; /* used by tmpnam */
char _emergency[_REENT_EMERGENCY_SIZE];
/* TODO */
int _unspecified_locale_info; /* unused, reserved for locale stuff */
struct __locale_t *_locale;/* per-thread locale */
int __sdidinit; /* 1 means stdio has been init'd */
void (*__cleanup) (struct _reent *);
/* used by mprec routines */
struct _Bigint *_result;
int _result_k;
struct _Bigint *_p5s;
struct _Bigint **_freelist;
/* used by some fp conversion routines */
int _cvtlen; /* should be size_t */
char *_cvtbuf;
union
{
struct
{
unsigned int _unused_rand;
char * _strtok_last;
char _asctime_buf[_REENT_ASCTIME_SIZE];
struct __tm _localtime_buf;
int _gamma_signgam;
__extension__ unsigned long long _rand_next;
struct _rand48 _r48;
_mbstate_t _mblen_state;
_mbstate_t _mbtowc_state;
_mbstate_t _wctomb_state;
char _l64a_buf[8];
char _signal_buf[_REENT_SIGNAL_SIZE];
int _getdate_err;
_mbstate_t _mbrlen_state;
_mbstate_t _mbrtowc_state;
_mbstate_t _mbsrtowcs_state;
_mbstate_t _wcrtomb_state;
_mbstate_t _wcsrtombs_state;
int _h_errno;
} _reent;
/* Two next two fields were once used by malloc. They are no longer
used. They are used to preserve the space used before so as to
allow addition of new reent fields and keep binary compatibility. */
struct
{
#define _N_LISTS 30
unsigned char * _nextf[_N_LISTS];
unsigned int _nmalloc[_N_LISTS];
} _unused;
} _new;
# ifndef _REENT_GLOBAL_ATEXIT
/* atexit stuff */
struct _atexit *_atexit; /* points to head of LIFO stack */
struct _atexit _atexit0; /* one guaranteed table, required by ANSI */
# endif
/* signal info */
void (**(_sig_func))(int);
/* These are here last so that __FILE can grow without changing the offsets
of the above members (on the off chance that future binary compatibility
would be broken otherwise). */
struct _glue __sglue; /* root of glue chain */
# ifndef _REENT_GLOBAL_STDIO_STREAMS
__FILE __sf[3]; /* first three file descriptors */
# endif
};
#ifdef _REENT_GLOBAL_STDIO_STREAMS
extern __FILE __sf[3];
#define _REENT_STDIO_STREAM(var, index) &__sf[index]
#else
#define _REENT_STDIO_STREAM(var, index) &(var)->__sf[index]
#endif
#define _REENT_INIT(var) \
{ 0, \
_REENT_STDIO_STREAM(&(var), 0), \
_REENT_STDIO_STREAM(&(var), 1), \
_REENT_STDIO_STREAM(&(var), 2), \
0, \
"", \
0, \
_NULL, \
0, \
_NULL, \
_NULL, \
0, \
_NULL, \
_NULL, \
0, \
_NULL, \
{ \
{ \
0, \
_NULL, \
"", \
{0, 0, 0, 0, 0, 0, 0, 0, 0}, \
0, \
1, \
{ \
{_RAND48_SEED_0, _RAND48_SEED_1, _RAND48_SEED_2}, \
{_RAND48_MULT_0, _RAND48_MULT_1, _RAND48_MULT_2}, \
_RAND48_ADD \
}, \
{0, {0}}, \
{0, {0}}, \
{0, {0}}, \
"", \
"", \
0, \
{0, {0}}, \
{0, {0}}, \
{0, {0}}, \
{0, {0}}, \
{0, {0}} \
} \
}, \
_REENT_INIT_ATEXIT \
_NULL, \
{_NULL, 0, _NULL} \
}
#define _REENT_INIT_PTR_ZEROED(var) \
{ (var)->_stdin = _REENT_STDIO_STREAM(var, 0); \
(var)->_stdout = _REENT_STDIO_STREAM(var, 1); \
(var)->_stderr = _REENT_STDIO_STREAM(var, 2); \
(var)->_new._reent._rand_next = 1; \
(var)->_new._reent._r48._seed[0] = _RAND48_SEED_0; \
(var)->_new._reent._r48._seed[1] = _RAND48_SEED_1; \
(var)->_new._reent._r48._seed[2] = _RAND48_SEED_2; \
(var)->_new._reent._r48._mult[0] = _RAND48_MULT_0; \
(var)->_new._reent._r48._mult[1] = _RAND48_MULT_1; \
(var)->_new._reent._r48._mult[2] = _RAND48_MULT_2; \
(var)->_new._reent._r48._add = _RAND48_ADD; \
}
#define _REENT_CHECK_RAND48(ptr) /* nothing */
#define _REENT_CHECK_MP(ptr) /* nothing */
#define _REENT_CHECK_TM(ptr) /* nothing */
#define _REENT_CHECK_ASCTIME_BUF(ptr) /* nothing */
#define _REENT_CHECK_EMERGENCY(ptr) /* nothing */
#define _REENT_CHECK_MISC(ptr) /* nothing */
#define _REENT_CHECK_SIGNAL_BUF(ptr) /* nothing */
#define _REENT_SIGNGAM(ptr) ((ptr)->_new._reent._gamma_signgam)
#define _REENT_RAND_NEXT(ptr) ((ptr)->_new._reent._rand_next)
#define _REENT_RAND48_SEED(ptr) ((ptr)->_new._reent._r48._seed)
#define _REENT_RAND48_MULT(ptr) ((ptr)->_new._reent._r48._mult)
#define _REENT_RAND48_ADD(ptr) ((ptr)->_new._reent._r48._add)
#define _REENT_MP_RESULT(ptr) ((ptr)->_result)
#define _REENT_MP_RESULT_K(ptr) ((ptr)->_result_k)
#define _REENT_MP_P5S(ptr) ((ptr)->_p5s)
#define _REENT_MP_FREELIST(ptr) ((ptr)->_freelist)
#define _REENT_ASCTIME_BUF(ptr) ((ptr)->_new._reent._asctime_buf)
#define _REENT_TM(ptr) (&(ptr)->_new._reent._localtime_buf)
#define _REENT_EMERGENCY(ptr) ((ptr)->_emergency)
#define _REENT_STRTOK_LAST(ptr) ((ptr)->_new._reent._strtok_last)
#define _REENT_MBLEN_STATE(ptr) ((ptr)->_new._reent._mblen_state)
#define _REENT_MBTOWC_STATE(ptr)((ptr)->_new._reent._mbtowc_state)
#define _REENT_WCTOMB_STATE(ptr)((ptr)->_new._reent._wctomb_state)
#define _REENT_MBRLEN_STATE(ptr)((ptr)->_new._reent._mbrlen_state)
#define _REENT_MBRTOWC_STATE(ptr)((ptr)->_new._reent._mbrtowc_state)
#define _REENT_MBSRTOWCS_STATE(ptr)((ptr)->_new._reent._mbsrtowcs_state)
#define _REENT_WCRTOMB_STATE(ptr)((ptr)->_new._reent._wcrtomb_state)
#define _REENT_WCSRTOMBS_STATE(ptr)((ptr)->_new._reent._wcsrtombs_state)
#define _REENT_L64A_BUF(ptr) ((ptr)->_new._reent._l64a_buf)
#define _REENT_SIGNAL_BUF(ptr) ((ptr)->_new._reent._signal_buf)
#define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_new._reent._getdate_err))
#endif /* !_REENT_SMALL */
#define _REENT_INIT_PTR(var) \
{ memset((var), 0, sizeof(*(var))); \
_REENT_INIT_PTR_ZEROED(var); \
}
/* This value is used in stdlib/misc.c. reent/reent.c has to know it
as well to make sure the freelist is correctly free'd. Therefore
we define it here, rather than in stdlib/misc.c, as before. */
#define _Kmax (sizeof (size_t) << 3)
/*
* All references to struct _reent are via this pointer.
* Internally, newlib routines that need to reference it should use _REENT.
*/
#ifndef __ATTRIBUTE_IMPURE_PTR__
#define __ATTRIBUTE_IMPURE_PTR__
#endif
extern struct _reent *_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
extern struct _reent *const _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
void _reclaim_reent (struct _reent *);
/* #define _REENT_ONLY define this to get only reentrant routines */
#if defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__)
#ifndef __getreent
struct _reent * __getreent (void);
#endif
# define _REENT (__getreent())
#else /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */
# define _REENT _impure_ptr
#endif /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */
#define _GLOBAL_REENT _global_impure_ptr
#ifdef _REENT_GLOBAL_ATEXIT
extern struct _atexit *_global_atexit; /* points to head of LIFO stack */
# define _GLOBAL_ATEXIT _global_atexit
#else
# define _GLOBAL_ATEXIT (_GLOBAL_REENT->_atexit)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _SYS_REENT_H_ */

69
src/include/sys/sched.h Executable file
View File

@ -0,0 +1,69 @@
/*
* Written by Joel Sherrill <joel@OARcorp.com>.
*
* COPYRIGHT (c) 1989-2010.
* On-Line Applications Research Corporation (OAR).
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION
* OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
* SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
* $Id$
*/
#ifndef _SYS_SCHED_H_
#define _SYS_SCHED_H_
#include <sys/_timespec.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Scheduling Policies */
/* Open Group Specifications Issue 6 */
#if defined(__CYGWIN__)
#define SCHED_OTHER 3
#else
#define SCHED_OTHER 0
#endif
#define SCHED_FIFO 1
#define SCHED_RR 2
#if defined(_POSIX_SPORADIC_SERVER)
#define SCHED_SPORADIC 4
#endif
/* Scheduling Parameters */
/* Open Group Specifications Issue 6 */
struct sched_param {
int sched_priority; /* Process execution scheduling priority */
#if defined(_POSIX_SPORADIC_SERVER) || defined(_POSIX_THREAD_SPORADIC_SERVER)
int sched_ss_low_priority; /* Low scheduling priority for sporadic */
/* server */
struct timespec sched_ss_repl_period;
/* Replenishment period for sporadic server */
struct timespec sched_ss_init_budget;
/* Initial budget for sporadic server */
int sched_ss_max_repl; /* Maximum pending replenishments for */
/* sporadic server */
#endif
};
#ifdef __cplusplus
}
#endif
#endif
/* end of include file */

76
src/include/sys/select.h Executable file
View File

@ -0,0 +1,76 @@
#ifndef _SYS_SELECT_H
#define _SYS_SELECT_H
/* We don't define fd_set and friends if we are compiling POSIX
source, or if we have included (or may include as indicated
by __USE_W32_SOCKETS) the W32api winsock[2].h header which
defines Windows versions of them. Note that a program which
includes the W32api winsock[2].h header must know what it is doing;
it must not call the Cygwin select function.
*/
# if !(defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS))
#include <sys/cdefs.h>
#include <sys/_sigset.h>
#include <sys/_timeval.h>
#include <sys/timespec.h>
#if !defined(_SIGSET_T_DECLARED)
#define _SIGSET_T_DECLARED
typedef __sigset_t sigset_t;
#endif
# define _SYS_TYPES_FD_SET
/*
* Select uses bit masks of file descriptors in longs.
* These macros manipulate such bit fields (the filesystem macros use chars).
* FD_SETSIZE may be defined by the user, but the default here
* should be >= NOFILE (param.h).
*/
# ifndef FD_SETSIZE
# define FD_SETSIZE 64
# endif
typedef unsigned long fd_mask;
# define NFDBITS (sizeof (fd_mask) * 8) /* bits per mask */
# ifndef _howmany
# define _howmany(x,y) (((x)+((y)-1))/(y))
# endif
/* We use a macro for fd_set so that including Sockets.h afterwards
can work. */
typedef struct _types_fd_set {
fd_mask fds_bits[_howmany(FD_SETSIZE, NFDBITS)];
} _types_fd_set;
#define fd_set _types_fd_set
# define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1L << ((n) % NFDBITS)))
# define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1L << ((n) % NFDBITS)))
# define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % NFDBITS)))
# define FD_ZERO(p) (__extension__ (void)({ \
size_t __i; \
char *__tmp = (char *)p; \
for (__i = 0; __i < sizeof (*(p)); ++__i) \
*__tmp++ = 0; \
}))
#if !defined (__INSIDE_CYGWIN_NET__)
__BEGIN_DECLS
int select __P ((int __n, fd_set *__readfds, fd_set *__writefds,
fd_set *__exceptfds, struct timeval *__timeout));
#if __POSIX_VISIBLE >= 200112
int pselect __P ((int __n, fd_set *__readfds, fd_set *__writefds,
fd_set *__exceptfds, const struct timespec *__timeout,
const sigset_t *__set));
#endif
__END_DECLS
#endif /* !__INSIDE_CYGWIN_NET__ */
#endif /* !(_WINSOCK_H || _WINSOCKAPI_ || __USE_W32_SOCKETS) */
#endif /* sys/select.h */

27
src/include/sys/stdio.h Executable file
View File

@ -0,0 +1,27 @@
#ifndef _NEWLIB_STDIO_H
#define _NEWLIB_STDIO_H
#include <sys/lock.h>
#include <sys/reent.h>
/* Internal locking macros, used to protect stdio functions. In the
general case, expand to nothing. Use __SSTR flag in FILE _flags to
detect if FILE is private to sprintf/sscanf class of functions; if
set then do nothing as lock is not initialised. */
#if !defined(_flockfile)
#ifndef __SINGLE_THREAD__
# define _flockfile(fp) (((fp)->_flags & __SSTR) ? 0 : __lock_acquire_recursive((fp)->_lock))
#else
# define _flockfile(fp) ((void) 0)
#endif
#endif
#if !defined(_funlockfile)
#ifndef __SINGLE_THREAD__
# define _funlockfile(fp) (((fp)->_flags & __SSTR) ? 0 : __lock_release_recursive((fp)->_lock))
#else
# define _funlockfile(fp) ((void) 0)
#endif
#endif
#endif /* _NEWLIB_STDIO_H */

2
src/include/sys/string.h Executable file
View File

@ -0,0 +1,2 @@
/* This is a dummy <sys/string.h> used as a placeholder for
systems that need to have a special header file. */

63
src/include/sys/timespec.h Executable file
View File

@ -0,0 +1,63 @@
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
* from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp
* $FreeBSD$
*/
#ifndef _SYS_TIMESPEC_H_
#define _SYS_TIMESPEC_H_
#include <sys/cdefs.h>
#include <sys/_timespec.h>
#if __BSD_VISIBLE
#define TIMEVAL_TO_TIMESPEC(tv, ts) \
do { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
} while (0)
#define TIMESPEC_TO_TIMEVAL(tv, ts) \
do { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
} while (0)
#endif /* __BSD_VISIBLE */
/*
* Structure defined by POSIX.1b to be like a itimerval, but with
* timespecs. Used in the timer_*() system calls.
*/
struct itimerspec {
struct timespec it_interval;
struct timespec it_value;
};
#endif /* _SYS_TIMESPEC_H_ */

246
src/include/sys/types.h Executable file
View File

@ -0,0 +1,246 @@
/* unified sys/types.h:
start with sef's sysvi386 version.
merge go32 version -- a few ifdefs.
h8300hms, h8300xray, and sysvnecv70 disagree on the following types:
typedef int gid_t;
typedef int uid_t;
typedef int dev_t;
typedef int ino_t;
typedef int mode_t;
typedef int caddr_t;
however, these aren't "reasonable" values, the sysvi386 ones make far
more sense, and should work sufficiently well (in particular, h8300
doesn't have a stat, and the necv70 doesn't matter.) -- eichin
*/
#ifndef _SYS_TYPES_H
#include <_ansi.h>
#include <sys/cdefs.h>
#include <machine/_types.h>
/* BSD types permitted by POSIX and always exposed as in Glibc. Only provided
for backward compatibility with BSD code. The uintN_t standard types should
be preferred in new code. */
#if ___int8_t_defined
typedef __uint8_t u_int8_t;
#endif
#if ___int16_t_defined
typedef __uint16_t u_int16_t;
#endif
#if ___int32_t_defined
typedef __uint32_t u_int32_t;
#endif
#if ___int64_t_defined
typedef __uint64_t u_int64_t;
#endif
typedef int register_t;
#define __BIT_TYPES_DEFINED__ 1
#if defined(__rtems__) || defined(__XMK__)
/*
* The following section is RTEMS specific and is needed to more
* closely match the types defined in the BSD sys/types.h.
* This is needed to let the RTEMS/BSD TCP/IP stack compile.
*/
/* deprecated */
#if ___int64_t_defined
typedef __uint64_t u_quad_t;
typedef __int64_t quad_t;
typedef quad_t * qaddr_t;
#endif
#endif /* __rtems__ || __XMK__ */
#ifndef __need_inttypes
#define _SYS_TYPES_H
/* <stddef.h> must be before <sys/_types.h> for __size_t considerations */
#include <stddef.h>
#include <sys/_types.h>
#include <sys/_stdint.h>
#if __BSD_VISIBLE
#include <machine/endian.h>
#include <sys/select.h>
# define physadr physadr_t
# define quad quad_t
#ifndef _IN_ADDR_T_DECLARED
typedef __uint32_t in_addr_t; /* base type for internet address */
#define _IN_ADDR_T_DECLARED
#endif
#ifndef _IN_PORT_T_DECLARED
typedef __uint16_t in_port_t;
#define _IN_PORT_T_DECLARED
#endif
#endif /* __BSD_VISIBLE */
#if __MISC_VISIBLE
#ifndef _BSDTYPES_DEFINED
/* also defined in mingw/gmon.h and in w32api/winsock[2].h */
#ifndef __u_char_defined
typedef unsigned char u_char;
#define __u_char_defined
#endif
#ifndef __u_short_defined
typedef unsigned short u_short;
#define __u_short_defined
#endif
#ifndef __u_int_defined
typedef unsigned int u_int;
#define __u_int_defined
#endif
#ifndef __u_long_defined
typedef unsigned long u_long;
#define __u_long_defined
#endif
#define _BSDTYPES_DEFINED
#endif
#endif /*__BSD_VISIBLE || __CYGWIN__ */
#if __MISC_VISIBLE
typedef unsigned short ushort; /* System V compatibility */
typedef unsigned int uint; /* System V compatibility */
typedef unsigned long ulong; /* System V compatibility */
#endif
#ifndef _BLKCNT_T_DECLARED
typedef __blkcnt_t blkcnt_t;
#define _BLKCNT_T_DECLARED
#endif
#ifndef _BLKSIZE_T_DECLARED
typedef __blksize_t blksize_t;
#define _BLKSIZE_T_DECLARED
#endif
#if !defined(__clock_t_defined) && !defined(_CLOCK_T_DECLARED)
typedef _CLOCK_T_ clock_t;
#define __clock_t_defined
#define _CLOCK_T_DECLARED
#endif
#if !defined(__time_t_defined) && !defined(_TIME_T_DECLARED)
typedef _TIME_T_ time_t;
#define __time_t_defined
#define _TIME_T_DECLARED
#endif
#ifndef __daddr_t_defined
typedef long daddr_t;
#define __daddr_t_defined
#endif
#ifndef __caddr_t_defined
typedef char * caddr_t;
#define __caddr_t_defined
#endif
#ifndef _FSBLKCNT_T_DECLARED /* for statvfs() */
typedef __fsblkcnt_t fsblkcnt_t;
typedef __fsfilcnt_t fsfilcnt_t;
#define _FSBLKCNT_T_DECLARED
#endif
#ifndef _ID_T_DECLARED
typedef __id_t id_t; /* can hold a uid_t or pid_t */
#define _ID_T_DECLARED
#endif
#ifndef _INO_T_DECLARED
typedef __ino_t ino_t; /* inode number */
#define _INO_T_DECLARED
#endif
#if defined(__i386__) && (defined(GO32) || defined(__MSDOS__))
typedef char * addr_t;
typedef unsigned long vm_offset_t;
typedef unsigned long vm_size_t;
#endif /* __i386__ && (GO32 || __MSDOS__) */
/*
* All these should be machine specific - right now they are all broken.
* However, for all of Cygnus' embedded targets, we want them to all be
* the same. Otherwise things like sizeof (struct stat) might depend on
* how the file was compiled (e.g. -mint16 vs -mint32, etc.).
*/
#ifndef _OFF_T_DECLARED
typedef __off_t off_t; /* file offset */
#define _OFF_T_DECLARED
#endif
#ifndef _DEV_T_DECLARED
typedef __dev_t dev_t; /* device number or struct cdev */
#define _DEV_T_DECLARED
#endif
#ifndef _UID_T_DECLARED
typedef __uid_t uid_t; /* user id */
#define _UID_T_DECLARED
#endif
#ifndef _GID_T_DECLARED
typedef __gid_t gid_t; /* group id */
#define _GID_T_DECLARED
#endif
#ifndef _PID_T_DECLARED
typedef __pid_t pid_t; /* process id */
#define _PID_T_DECLARED
#endif
#ifndef _KEY_T_DECLARED
typedef __key_t key_t; /* IPC key */
#define _KEY_T_DECLARED
#endif
#ifndef _SSIZE_T_DECLARED
typedef _ssize_t ssize_t;
#define _SSIZE_T_DECLARED
#endif
#ifndef _MODE_T_DECLARED
typedef __mode_t mode_t; /* permissions */
#define _MODE_T_DECLARED
#endif
#ifndef _NLINK_T_DECLARED
typedef __nlink_t nlink_t; /* link count */
#define _NLINK_T_DECLARED
#endif
#if !defined(__clockid_t_defined) && !defined(_CLOCKID_T_DECLARED)
typedef __clockid_t clockid_t;
#define __clockid_t_defined
#define _CLOCKID_T_DECLARED
#endif
#if !defined(__timer_t_defined) && !defined(_TIMER_T_DECLARED)
typedef __timer_t timer_t;
#define __timer_t_defined
#define _TIMER_T_DECLARED
#endif
#ifndef _USECONDS_T_DECLARED
typedef __useconds_t useconds_t; /* microseconds (unsigned) */
#define _USECONDS_T_DECLARED
#endif
#ifndef _SUSECONDS_T_DECLARED
typedef __suseconds_t suseconds_t;
#define _SUSECONDS_T_DECLARED
#endif
typedef __int64_t sbintime_t;
#include <sys/features.h>
#include <sys/_pthreadtypes.h>
#include <machine/types.h>
#endif /* !__need_inttypes */
#undef __need_inttypes
#endif /* _SYS_TYPES_H */

599
src/include/sys/unistd.h Executable file
View File

@ -0,0 +1,599 @@
#ifndef _SYS_UNISTD_H
#define _SYS_UNISTD_H
#ifdef __cplusplus
extern "C" {
#endif
#include <_ansi.h>
#define __need_size_t
#define __need_ptrdiff_t
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/_types.h>
#include <stddef.h>
extern char **environ;
void _exit (int __status) _ATTRIBUTE ((__noreturn__));
int access (const char *__path, int __amode);
unsigned alarm (unsigned __secs);
int chdir (const char *__path);
int chmod (const char *__path, mode_t __mode);
#if !defined(__INSIDE_CYGWIN__)
int chown (const char *__path, uid_t __owner, gid_t __group);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112)
int chroot (const char *__path);
#endif
int close (int __fildes);
#if __POSIX_VISIBLE >= 199209
size_t confstr (int __name, char *__buf, size_t __len);
#endif
#if __XSI_VISIBLE
char * crypt (const char *__key, const char *__salt);
#endif
#if __XSI_VISIBLE && __XSI_VISIBLE < 700
char * ctermid (char *__s);
#endif
#if __XSI_VISIBLE && __XSI_VISIBLE < 600
char * cuserid (char *__s);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500)
int daemon (int nochdir, int noclose);
#endif
int dup (int __fildes);
int dup2 (int __fildes, int __fildes2);
#if __GNU_VISIBLE
int dup3 (int __fildes, int __fildes2, int flags);
int eaccess (const char *__path, int __mode);
#endif
#if __XSI_VISIBLE
void encrypt (char *__block, int __edflag);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500)
void endusershell (void);
#endif
#if __GNU_VISIBLE
int euidaccess (const char *__path, int __mode);
#endif
int execl (const char *__path, const char *, ...);
int execle (const char *__path, const char *, ...);
int execlp (const char *__file, const char *, ...);
#if __MISC_VISIBLE
int execlpe (const char *__file, const char *, ...);
#endif
int execv (const char *__path, char * const __argv[]);
int execve (const char *__path, char * const __argv[], char * const __envp[]);
int execvp (const char *__file, char * const __argv[]);
#if __GNU_VISIBLE
int execvpe (const char *__file, char * const __argv[], char * const __envp[]);
#endif
#if __ATFILE_VISIBLE
int faccessat (int __dirfd, const char *__path, int __mode, int __flags);
#endif
#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809
int fchdir (int __fildes);
#endif
#if __POSIX_VISIBLE >= 199309
int fchmod (int __fildes, mode_t __mode);
#endif
#if !defined(__INSIDE_CYGWIN__)
#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809
int fchown (int __fildes, uid_t __owner, gid_t __group);
#endif
#endif
#if __ATFILE_VISIBLE
int fchownat (int __dirfd, const char *__path, uid_t __owner, gid_t __group, int __flags);
#endif
#if __POSIX_VISIBLE >= 200809
int fexecve (int __fd, char * const __argv[], char * const __envp[]);
#endif
pid_t fork (void);
long fpathconf (int __fd, int __name);
int fsync (int __fd);
#if __POSIX_VISIBLE >= 199309
int fdatasync (int __fd);
#endif
#if __GNU_VISIBLE
char * get_current_dir_name (void);
#endif
char * getcwd (char *__buf, size_t __size);
#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500)
int getdomainname (char *__name, size_t __len);
#endif
#if __BSD_VISIBLE
int getentropy (void *, size_t);
#endif
#if !defined(__INSIDE_CYGWIN__)
gid_t getegid (void);
uid_t geteuid (void);
gid_t getgid (void);
#endif
int getgroups (int __gidsetsize, gid_t __grouplist[]);
#if __BSD_VISIBLE || __XSI_VISIBLE >= 4
long gethostid (void);
#endif
char * getlogin (void);
#if defined(_POSIX_THREAD_SAFE_FUNCTIONS)
int getlogin_r (char *name, size_t namesize) ;
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE && __POSIX_VISIBLE < 200112)
char * getpass (const char *__prompt);
int getpagesize (void);
#endif
#if __BSD_VISIBLE
int getpeereid (int, uid_t *, gid_t *);
#endif
#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 4
pid_t getpgid (pid_t);
#endif
pid_t getpgrp (void);
pid_t getpid (void);
pid_t getppid (void);
#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 4
pid_t getsid (pid_t);
#endif
#if !defined(__INSIDE_CYGWIN__)
uid_t getuid (void);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500)
char * getusershell (void);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200809)
char * getwd (char *__buf);
#endif
#if __BSD_VISIBLE
int iruserok (unsigned long raddr, int superuser, const char *ruser, const char *luser);
#endif
int isatty (int __fildes);
#if __BSD_VISIBLE
int issetugid (void);
#endif
#if !defined(__INSIDE_CYGWIN__)
#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809
int lchown (const char *__path, uid_t __owner, gid_t __group);
#endif
#endif
int link (const char *__path1, const char *__path2);
#if __ATFILE_VISIBLE
int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char *__path2, int __flags);
#endif
#if __MISC_VISIBLE || __XSI_VISIBLE
int nice (int __nice_value);
#endif
#if !defined(__INSIDE_CYGWIN__)
off_t lseek (int __fildes, off_t __offset, int __whence);
#endif
#if __MISC_VISIBLE || __XSI_VISIBLE >= 4
#define F_ULOCK 0
#define F_LOCK 1
#define F_TLOCK 2
#define F_TEST 3
int lockf (int __fd, int __cmd, off_t __len);
#endif
long pathconf (const char *__path, int __name);
int pause (void);
#if __POSIX_VISIBLE >= 199506
int pthread_atfork (void (*)(void), void (*)(void), void (*)(void));
#endif
int pipe (int __fildes[2]);
#if __GNU_VISIBLE
int pipe2 (int __fildes[2], int flags);
#endif
#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500
ssize_t pread (int __fd, void *__buf, size_t __nbytes, off_t __offset);
ssize_t pwrite (int __fd, const void *__buf, size_t __nbytes, off_t __offset);
#endif
_READ_WRITE_RETURN_TYPE read (int __fd, void *__buf, size_t __nbyte);
#if __BSD_VISIBLE
int rresvport (int *__alport);
int revoke (char *__path);
#endif
int rmdir (const char *__path);
#if __BSD_VISIBLE
int ruserok (const char *rhost, int superuser, const char *ruser, const char *luser);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112)
void * sbrk (ptrdiff_t __incr);
#endif
#if !defined(__INSIDE_CYGWIN__)
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112
int setegid (gid_t __gid);
int seteuid (uid_t __uid);
#endif
int setgid (gid_t __gid);
#endif
#if __BSD_VISIBLE
int setgroups (int ngroups, const gid_t *grouplist);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500)
int sethostname (const char *, size_t);
#endif
int setpgid (pid_t __pid, pid_t __pgid);
#if __SVID_VISIBLE || __XSI_VISIBLE >= 500
int setpgrp (void);
#endif
#if (__BSD_VISIBLE || __XSI_VISIBLE >= 4) && !defined(__INSIDE_CYGWIN__)
int setregid (gid_t __rgid, gid_t __egid);
int setreuid (uid_t __ruid, uid_t __euid);
#endif
pid_t setsid (void);
#if !defined(__INSIDE_CYGWIN__)
int setuid (uid_t __uid);
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500)
void setusershell (void);
#endif
unsigned sleep (unsigned int __seconds);
#if __XSI_VISIBLE
void swab (const void *__restrict, void *__restrict, ssize_t);
#endif
long sysconf (int __name);
pid_t tcgetpgrp (int __fildes);
int tcsetpgrp (int __fildes, pid_t __pgrp_id);
char * ttyname (int __fildes);
int ttyname_r (int, char *, size_t);
int unlink (const char *__path);
#if __XSI_VISIBLE >= 500 && __POSIX_VISIBLE < 200809 || __BSD_VISIBLE
int usleep (useconds_t __useconds);
#endif
#if __BSD_VISIBLE
int vhangup (void);
#endif
_READ_WRITE_RETURN_TYPE write (int __fd, const void *__buf, size_t __nbyte);
#ifdef __CYGWIN__
# define __UNISTD_GETOPT__
# include <getopt.h>
# undef __UNISTD_GETOPT__
#else
extern char *optarg; /* getopt(3) external variables */
extern int optind, opterr, optopt;
int getopt(int, char * const [], const char *);
extern int optreset; /* getopt(3) external variable */
#endif
#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200809)
pid_t vfork (void);
#endif
#ifdef _COMPILING_NEWLIB
/* Provide prototypes for most of the _<systemcall> names that are
provided in newlib for some compilers. */
int _close (int __fildes);
pid_t _fork (void);
pid_t _getpid (void);
int _isatty (int __fildes);
int _link (const char *__path1, const char *__path2);
_off_t _lseek (int __fildes, _off_t __offset, int __whence);
#ifdef __LARGE64_FILES
_off64_t _lseek64 (int __filedes, _off64_t __offset, int __whence);
#endif
_READ_WRITE_RETURN_TYPE _read (int __fd, void *__buf, size_t __nbyte);
void * _sbrk (ptrdiff_t __incr);
int _unlink (const char *__path);
_READ_WRITE_RETURN_TYPE _write (int __fd, const void *__buf, size_t __nbyte);
int _execve (const char *__path, char * const __argv[], char * const __envp[]);
#endif
#if !defined(__INSIDE_CYGWIN__)
#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500
int ftruncate (int __fd, off_t __length);
#endif
#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500
int truncate (const char *, off_t __length);
#endif
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE < 200112
int getdtablesize (void);
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500
useconds_t ualarm (useconds_t __useconds, useconds_t __interval);
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500
#if !(defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS))
/* winsock[2].h defines as __stdcall, and with int as 2nd arg */
int gethostname (char *__name, size_t __len);
#endif
#endif
#if __MISC_VISIBLE
int setdtablesize (int);
#endif
#if __BSD_VISIBLE || __XSI_VISIBLE >= 500
void sync (void);
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 4
ssize_t readlink (const char *__restrict __path,
char *__restrict __buf, size_t __buflen);
int symlink (const char *__name1, const char *__name2);
#endif
#if __ATFILE_VISIBLE
ssize_t readlinkat (int __dirfd1, const char *__restrict __path,
char *__restrict __buf, size_t __buflen);
int symlinkat (const char *, int, const char *);
int unlinkat (int, const char *, int);
#endif
#define F_OK 0
#define R_OK 4
#define W_OK 2
#define X_OK 1
# define SEEK_SET 0
# define SEEK_CUR 1
# define SEEK_END 2
#include <sys/features.h>
#define STDIN_FILENO 0 /* standard input file descriptor */
#define STDOUT_FILENO 1 /* standard output file descriptor */
#define STDERR_FILENO 2 /* standard error file descriptor */
/*
* sysconf values per IEEE Std 1003.1, 2008 Edition
*/
#define _SC_ARG_MAX 0
#define _SC_CHILD_MAX 1
#define _SC_CLK_TCK 2
#define _SC_NGROUPS_MAX 3
#define _SC_OPEN_MAX 4
#define _SC_JOB_CONTROL 5
#define _SC_SAVED_IDS 6
#define _SC_VERSION 7
#define _SC_PAGESIZE 8
#define _SC_PAGE_SIZE _SC_PAGESIZE
/* These are non-POSIX values we accidentally introduced in 2000 without
guarding them. Keeping them unguarded for backward compatibility. */
#define _SC_NPROCESSORS_CONF 9
#define _SC_NPROCESSORS_ONLN 10
#define _SC_PHYS_PAGES 11
#define _SC_AVPHYS_PAGES 12
/* End of non-POSIX values. */
#define _SC_MQ_OPEN_MAX 13
#define _SC_MQ_PRIO_MAX 14
#define _SC_RTSIG_MAX 15
#define _SC_SEM_NSEMS_MAX 16
#define _SC_SEM_VALUE_MAX 17
#define _SC_SIGQUEUE_MAX 18
#define _SC_TIMER_MAX 19
#define _SC_TZNAME_MAX 20
#define _SC_ASYNCHRONOUS_IO 21
#define _SC_FSYNC 22
#define _SC_MAPPED_FILES 23
#define _SC_MEMLOCK 24
#define _SC_MEMLOCK_RANGE 25
#define _SC_MEMORY_PROTECTION 26
#define _SC_MESSAGE_PASSING 27
#define _SC_PRIORITIZED_IO 28
#define _SC_REALTIME_SIGNALS 29
#define _SC_SEMAPHORES 30
#define _SC_SHARED_MEMORY_OBJECTS 31
#define _SC_SYNCHRONIZED_IO 32
#define _SC_TIMERS 33
#define _SC_AIO_LISTIO_MAX 34
#define _SC_AIO_MAX 35
#define _SC_AIO_PRIO_DELTA_MAX 36
#define _SC_DELAYTIMER_MAX 37
#define _SC_THREAD_KEYS_MAX 38
#define _SC_THREAD_STACK_MIN 39
#define _SC_THREAD_THREADS_MAX 40
#define _SC_TTY_NAME_MAX 41
#define _SC_THREADS 42
#define _SC_THREAD_ATTR_STACKADDR 43
#define _SC_THREAD_ATTR_STACKSIZE 44
#define _SC_THREAD_PRIORITY_SCHEDULING 45
#define _SC_THREAD_PRIO_INHERIT 46
/* _SC_THREAD_PRIO_PROTECT was _SC_THREAD_PRIO_CEILING in early drafts */
#define _SC_THREAD_PRIO_PROTECT 47
#define _SC_THREAD_PRIO_CEILING _SC_THREAD_PRIO_PROTECT
#define _SC_THREAD_PROCESS_SHARED 48
#define _SC_THREAD_SAFE_FUNCTIONS 49
#define _SC_GETGR_R_SIZE_MAX 50
#define _SC_GETPW_R_SIZE_MAX 51
#define _SC_LOGIN_NAME_MAX 52
#define _SC_THREAD_DESTRUCTOR_ITERATIONS 53
#define _SC_ADVISORY_INFO 54
#define _SC_ATEXIT_MAX 55
#define _SC_BARRIERS 56
#define _SC_BC_BASE_MAX 57
#define _SC_BC_DIM_MAX 58
#define _SC_BC_SCALE_MAX 59
#define _SC_BC_STRING_MAX 60
#define _SC_CLOCK_SELECTION 61
#define _SC_COLL_WEIGHTS_MAX 62
#define _SC_CPUTIME 63
#define _SC_EXPR_NEST_MAX 64
#define _SC_HOST_NAME_MAX 65
#define _SC_IOV_MAX 66
#define _SC_IPV6 67
#define _SC_LINE_MAX 68
#define _SC_MONOTONIC_CLOCK 69
#define _SC_RAW_SOCKETS 70
#define _SC_READER_WRITER_LOCKS 71
#define _SC_REGEXP 72
#define _SC_RE_DUP_MAX 73
#define _SC_SHELL 74
#define _SC_SPAWN 75
#define _SC_SPIN_LOCKS 76
#define _SC_SPORADIC_SERVER 77
#define _SC_SS_REPL_MAX 78
#define _SC_SYMLOOP_MAX 79
#define _SC_THREAD_CPUTIME 80
#define _SC_THREAD_SPORADIC_SERVER 81
#define _SC_TIMEOUTS 82
#define _SC_TRACE 83
#define _SC_TRACE_EVENT_FILTER 84
#define _SC_TRACE_EVENT_NAME_MAX 85
#define _SC_TRACE_INHERIT 86
#define _SC_TRACE_LOG 87
#define _SC_TRACE_NAME_MAX 88
#define _SC_TRACE_SYS_MAX 89
#define _SC_TRACE_USER_EVENT_MAX 90
#define _SC_TYPED_MEMORY_OBJECTS 91
#define _SC_V7_ILP32_OFF32 92
#define _SC_V6_ILP32_OFF32 _SC_V7_ILP32_OFF32
#define _SC_XBS5_ILP32_OFF32 _SC_V7_ILP32_OFF32
#define _SC_V7_ILP32_OFFBIG 93
#define _SC_V6_ILP32_OFFBIG _SC_V7_ILP32_OFFBIG
#define _SC_XBS5_ILP32_OFFBIG _SC_V7_ILP32_OFFBIG
#define _SC_V7_LP64_OFF64 94
#define _SC_V6_LP64_OFF64 _SC_V7_LP64_OFF64
#define _SC_XBS5_LP64_OFF64 _SC_V7_LP64_OFF64
#define _SC_V7_LPBIG_OFFBIG 95
#define _SC_V6_LPBIG_OFFBIG _SC_V7_LPBIG_OFFBIG
#define _SC_XBS5_LPBIG_OFFBIG _SC_V7_LPBIG_OFFBIG
#define _SC_XOPEN_CRYPT 96
#define _SC_XOPEN_ENH_I18N 97
#define _SC_XOPEN_LEGACY 98
#define _SC_XOPEN_REALTIME 99
#define _SC_STREAM_MAX 100
#define _SC_PRIORITY_SCHEDULING 101
#define _SC_XOPEN_REALTIME_THREADS 102
#define _SC_XOPEN_SHM 103
#define _SC_XOPEN_STREAMS 104
#define _SC_XOPEN_UNIX 105
#define _SC_XOPEN_VERSION 106
#define _SC_2_CHAR_TERM 107
#define _SC_2_C_BIND 108
#define _SC_2_C_DEV 109
#define _SC_2_FORT_DEV 110
#define _SC_2_FORT_RUN 111
#define _SC_2_LOCALEDEF 112
#define _SC_2_PBS 113
#define _SC_2_PBS_ACCOUNTING 114
#define _SC_2_PBS_CHECKPOINT 115
#define _SC_2_PBS_LOCATE 116
#define _SC_2_PBS_MESSAGE 117
#define _SC_2_PBS_TRACK 118
#define _SC_2_SW_DEV 119
#define _SC_2_UPE 120
#define _SC_2_VERSION 121
#define _SC_THREAD_ROBUST_PRIO_INHERIT 122
#define _SC_THREAD_ROBUST_PRIO_PROTECT 123
#define _SC_XOPEN_UUCP 124
#define _SC_LEVEL1_ICACHE_SIZE 125
#define _SC_LEVEL1_ICACHE_ASSOC 126
#define _SC_LEVEL1_ICACHE_LINESIZE 127
#define _SC_LEVEL1_DCACHE_SIZE 128
#define _SC_LEVEL1_DCACHE_ASSOC 129
#define _SC_LEVEL1_DCACHE_LINESIZE 130
#define _SC_LEVEL2_CACHE_SIZE 131
#define _SC_LEVEL2_CACHE_ASSOC 132
#define _SC_LEVEL2_CACHE_LINESIZE 133
#define _SC_LEVEL3_CACHE_SIZE 134
#define _SC_LEVEL3_CACHE_ASSOC 135
#define _SC_LEVEL3_CACHE_LINESIZE 136
#define _SC_LEVEL4_CACHE_SIZE 137
#define _SC_LEVEL4_CACHE_ASSOC 138
#define _SC_LEVEL4_CACHE_LINESIZE 139
#define _SC_POSIX_26_VERSION 140
/*
* pathconf values per IEEE Std 1003.1, 2008 Edition
*/
#define _PC_LINK_MAX 0
#define _PC_MAX_CANON 1
#define _PC_MAX_INPUT 2
#define _PC_NAME_MAX 3
#define _PC_PATH_MAX 4
#define _PC_PIPE_BUF 5
#define _PC_CHOWN_RESTRICTED 6
#define _PC_NO_TRUNC 7
#define _PC_VDISABLE 8
#define _PC_ASYNC_IO 9
#define _PC_PRIO_IO 10
#define _PC_SYNC_IO 11
#define _PC_FILESIZEBITS 12
#define _PC_2_SYMLINKS 13
#define _PC_SYMLINK_MAX 14
#define _PC_ALLOC_SIZE_MIN 15
#define _PC_REC_INCR_XFER_SIZE 16
#define _PC_REC_MAX_XFER_SIZE 17
#define _PC_REC_MIN_XFER_SIZE 18
#define _PC_REC_XFER_ALIGN 19
#define _PC_TIMESTAMP_RESOLUTION 20
#ifdef __CYGWIN__
/* Ask for POSIX permission bits support. */
#define _PC_POSIX_PERMISSIONS 90
/* Ask for full POSIX permission support including uid/gid settings. */
#define _PC_POSIX_SECURITY 91
#define _PC_CASE_INSENSITIVE 92
#endif
/*
* confstr values per IEEE Std 1003.1, 2004 Edition
*/
#ifdef __CYGWIN__ /* Only defined on Cygwin for now. */
#define _CS_PATH 0
#define _CS_POSIX_V7_ILP32_OFF32_CFLAGS 1
#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS _CS_POSIX_V7_ILP32_OFF32_CFLAGS
#define _CS_XBS5_ILP32_OFF32_CFLAGS _CS_POSIX_V7_ILP32_OFF32_CFLAGS
#define _CS_POSIX_V7_ILP32_OFF32_LDFLAGS 2
#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS _CS_POSIX_V7_ILP32_OFF32_LDFLAGS
#define _CS_XBS5_ILP32_OFF32_LDFLAGS _CS_POSIX_V7_ILP32_OFF32_LDFLAGS
#define _CS_POSIX_V7_ILP32_OFF32_LIBS 3
#define _CS_POSIX_V6_ILP32_OFF32_LIBS _CS_POSIX_V7_ILP32_OFF32_LIBS
#define _CS_XBS5_ILP32_OFF32_LIBS _CS_POSIX_V7_ILP32_OFF32_LIBS
#define _CS_XBS5_ILP32_OFF32_LINTFLAGS 4
#define _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS 5
#define _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS
#define _CS_XBS5_ILP32_OFFBIG_CFLAGS _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS
#define _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS 6
#define _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS
#define _CS_XBS5_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS
#define _CS_POSIX_V7_ILP32_OFFBIG_LIBS 7
#define _CS_POSIX_V6_ILP32_OFFBIG_LIBS _CS_POSIX_V7_ILP32_OFFBIG_LIBS
#define _CS_XBS5_ILP32_OFFBIG_LIBS _CS_POSIX_V7_ILP32_OFFBIG_LIBS
#define _CS_XBS5_ILP32_OFFBIG_LINTFLAGS 8
#define _CS_POSIX_V7_LP64_OFF64_CFLAGS 9
#define _CS_POSIX_V6_LP64_OFF64_CFLAGS _CS_POSIX_V7_LP64_OFF64_CFLAGS
#define _CS_XBS5_LP64_OFF64_CFLAGS _CS_POSIX_V7_LP64_OFF64_CFLAGS
#define _CS_POSIX_V7_LP64_OFF64_LDFLAGS 10
#define _CS_POSIX_V6_LP64_OFF64_LDFLAGS _CS_POSIX_V7_LP64_OFF64_LDFLAGS
#define _CS_XBS5_LP64_OFF64_LDFLAGS _CS_POSIX_V7_LP64_OFF64_LDFLAGS
#define _CS_POSIX_V7_LP64_OFF64_LIBS 11
#define _CS_POSIX_V6_LP64_OFF64_LIBS _CS_POSIX_V7_LP64_OFF64_LIBS
#define _CS_XBS5_LP64_OFF64_LIBS _CS_POSIX_V7_LP64_OFF64_LIBS
#define _CS_XBS5_LP64_OFF64_LINTFLAGS 12
#define _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS 13
#define _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS
#define _CS_XBS5_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS
#define _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS 14
#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS
#define _CS_XBS5_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS
#define _CS_POSIX_V7_LPBIG_OFFBIG_LIBS 15
#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS _CS_POSIX_V7_LPBIG_OFFBIG_LIBS
#define _CS_XBS5_LPBIG_OFFBIG_LIBS _CS_POSIX_V7_LPBIG_OFFBIG_LIBS
#define _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS 16
#define _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS 17
#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS
#define _CS_XBS5_WIDTH_RESTRICTED_ENVS _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS
#define _CS_POSIX_V7_THREADS_CFLAGS 18
#define _CS_POSIX_V7_THREADS_LDFLAGS 19
#define _CS_V7_ENV 20
#define _CS_V6_ENV _CS_V7_ENV
#define _CS_LFS_CFLAGS 21
#define _CS_LFS_LDFLAGS 22
#define _CS_LFS_LIBS 23
#define _CS_LFS_LINTFLAGS 24
#endif
#ifdef __cplusplus
}
#endif
#if __SSP_FORTIFY_LEVEL > 0
#include <ssp/unistd.h>
#endif
#endif /* _SYS_UNISTD_H */

6
src/include/unistd.h Executable file
View File

@ -0,0 +1,6 @@
#ifndef _UNISTD_H_
#define _UNISTD_H_
# include <sys/unistd.h>
#endif /* _UNISTD_H_ */

12
src/include/xlocale.h Executable file
View File

@ -0,0 +1,12 @@
/* Definition of opaque POSIX-1.2008 type locale_t for userspace. */
#ifndef _XLOCALE_H
#define _XLOCALE_H
#include <newlib.h>
#include <sys/config.h>
struct __locale_t;
typedef struct __locale_t *locale_t;
#endif /* _XLOCALE_H */

9
src/libc/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "libc"
version = "0.1.0"
authors = ["pca006132 <john.lck40@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

7
src/libc/src/lib.rs Normal file
View File

@ -0,0 +1,7 @@
// Helper crate for dealing with libc dependencies, which only requires these
// definitions...
#![allow(non_camel_case_types)]
#![no_std]
pub type c_int = i32;
pub type uintptr_t = usize;
pub type c_void = core::ffi::c_void;

17
src/libdwarf/Cargo.toml Normal file
View File

@ -0,0 +1,17 @@
[package]
# This package is orignally panic_unwind, but is adapted as a dwarf parser
authors = ["The Rust Project Developers"]
name = "dwarf"
version = "0.0.0"
edition = "2018"
[lib]
test = false
bench = false
doc = false
[dependencies]
libc = { path = "../libc" }
unwind = { path = "../libunwind" }
compiler_builtins = "0.1.0"
cfg-if = "0.1.8"

200
src/libdwarf/src/eh.rs Normal file
View File

@ -0,0 +1,200 @@
//! Parsing of GCC-style Language-Specific Data Area (LSDA)
//! For details see:
//! http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
//! http://mentorembedded.github.io/cxx-abi/exceptions.pdf
//! http://www.airs.com/blog/archives/460
//! http://www.airs.com/blog/archives/464
//!
//! A reference implementation may be found in the GCC source tree
//! (`<root>/libgcc/unwind-c.c` as of this writing).
#![allow(non_upper_case_globals)]
#![allow(unused)]
use crate::DwarfReader;
use core::mem;
pub const DW_EH_PE_omit: u8 = 0xFF;
pub const DW_EH_PE_absptr: u8 = 0x00;
pub const DW_EH_PE_uleb128: u8 = 0x01;
pub const DW_EH_PE_udata2: u8 = 0x02;
pub const DW_EH_PE_udata4: u8 = 0x03;
pub const DW_EH_PE_udata8: u8 = 0x04;
pub const DW_EH_PE_sleb128: u8 = 0x09;
pub const DW_EH_PE_sdata2: u8 = 0x0A;
pub const DW_EH_PE_sdata4: u8 = 0x0B;
pub const DW_EH_PE_sdata8: u8 = 0x0C;
pub const DW_EH_PE_pcrel: u8 = 0x10;
pub const DW_EH_PE_textrel: u8 = 0x20;
pub const DW_EH_PE_datarel: u8 = 0x30;
pub const DW_EH_PE_funcrel: u8 = 0x40;
pub const DW_EH_PE_aligned: u8 = 0x50;
pub const DW_EH_PE_indirect: u8 = 0x80;
#[derive(Copy, Clone)]
pub struct EHContext<'a> {
pub ip: usize, // Current instruction pointer
pub func_start: usize, // Address of the current function
pub get_text_start: &'a dyn Fn() -> usize, // Get address of the code section
pub get_data_start: &'a dyn Fn() -> usize, // Get address of the data section
}
pub enum EHAction {
None,
Cleanup(usize),
Catch(usize),
Terminate,
}
pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm"));
pub unsafe fn find_eh_action(
lsda: *const u8,
context: &EHContext<'_>,
foreign_exception: bool,
) -> Result<EHAction, ()> {
if lsda.is_null() {
return Ok(EHAction::None);
}
let func_start = context.func_start;
let mut reader = DwarfReader::new(lsda);
let start_encoding = reader.read::<u8>();
// base address for landing pad offsets
let lpad_base = if start_encoding != DW_EH_PE_omit {
read_encoded_pointer(&mut reader, context, start_encoding)?
} else {
func_start
};
let ttype_encoding = reader.read::<u8>();
if ttype_encoding != DW_EH_PE_omit {
// Rust doesn't analyze exception types, so we don't care about the type table
reader.read_uleb128();
}
let call_site_encoding = reader.read::<u8>();
let call_site_table_length = reader.read_uleb128();
let action_table = reader.ptr.offset(call_site_table_length as isize);
let ip = context.ip;
if !USING_SJLJ_EXCEPTIONS {
while reader.ptr < action_table {
let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
let cs_action = reader.read_uleb128();
// Callsite table is sorted by cs_start, so if we've passed the ip, we
// may stop searching.
if ip < func_start + cs_start {
break;
}
if ip < func_start + cs_start + cs_len {
if cs_lpad == 0 {
return Ok(EHAction::None);
} else {
let lpad = lpad_base + cs_lpad;
return Ok(interpret_cs_action(cs_action, lpad, foreign_exception));
}
}
}
// Ip is not present in the table. This should not happen... but it does: issue #35011.
// So rather than returning EHAction::Terminate, we do this.
Ok(EHAction::None)
} else {
// SjLj version:
// The "IP" is an index into the call-site table, with two exceptions:
// -1 means 'no-action', and 0 means 'terminate'.
match ip as isize {
-1 => return Ok(EHAction::None),
0 => return Ok(EHAction::Terminate),
_ => (),
}
let mut idx = ip;
loop {
let cs_lpad = reader.read_uleb128();
let cs_action = reader.read_uleb128();
idx -= 1;
if idx == 0 {
// Can never have null landing pad for sjlj -- that would have
// been indicated by a -1 call site index.
let lpad = (cs_lpad + 1) as usize;
return Ok(interpret_cs_action(cs_action, lpad, foreign_exception));
}
}
}
}
fn interpret_cs_action(cs_action: u64, lpad: usize, foreign_exception: bool) -> EHAction {
if cs_action == 0 {
// If cs_action is 0 then this is a cleanup (Drop::drop). We run these
// for both Rust panics and foreign exceptions.
EHAction::Cleanup(lpad)
} else if foreign_exception {
// catch_unwind should not catch foreign exceptions, only Rust panics.
// Instead just continue unwinding.
EHAction::None
} else {
// Stop unwinding Rust panics at catch_unwind.
EHAction::Catch(lpad)
}
}
#[inline]
fn round_up(unrounded: usize, align: usize) -> Result<usize, ()> {
if align.is_power_of_two() { Ok((unrounded + align - 1) & !(align - 1)) } else { Err(()) }
}
unsafe fn read_encoded_pointer(
reader: &mut DwarfReader,
context: &EHContext<'_>,
encoding: u8,
) -> Result<usize, ()> {
if encoding == DW_EH_PE_omit {
return Err(());
}
// DW_EH_PE_aligned implies it's an absolute pointer value
if encoding == DW_EH_PE_aligned {
reader.ptr = round_up(reader.ptr as usize, mem::size_of::<usize>())? as *const u8;
return Ok(reader.read::<usize>());
}
let mut result = match encoding & 0x0F {
DW_EH_PE_absptr => reader.read::<usize>(),
DW_EH_PE_uleb128 => reader.read_uleb128() as usize,
DW_EH_PE_udata2 => reader.read::<u16>() as usize,
DW_EH_PE_udata4 => reader.read::<u32>() as usize,
DW_EH_PE_udata8 => reader.read::<u64>() as usize,
DW_EH_PE_sleb128 => reader.read_sleb128() as usize,
DW_EH_PE_sdata2 => reader.read::<i16>() as usize,
DW_EH_PE_sdata4 => reader.read::<i32>() as usize,
DW_EH_PE_sdata8 => reader.read::<i64>() as usize,
_ => return Err(()),
};
result += match encoding & 0x70 {
DW_EH_PE_absptr => 0,
// relative to address of the encoded value, despite the name
DW_EH_PE_pcrel => reader.ptr as usize,
DW_EH_PE_funcrel => {
if context.func_start == 0 {
return Err(());
}
context.func_start
}
DW_EH_PE_textrel => (*context.get_text_start)(),
DW_EH_PE_datarel => (*context.get_data_start)(),
_ => return Err(()),
};
if encoding & DW_EH_PE_indirect != 0 {
result = *(result as *const usize);
}
Ok(result)
}

74
src/libdwarf/src/lib.rs Normal file
View File

@ -0,0 +1,74 @@
//! Utilities for parsing DWARF-encoded data streams.
//! See <http://www.dwarfstd.org>,
//! DWARF-4 standard, Section 7 - "Data Representation"
#![no_std]
// This module is used only by x86_64-pc-windows-gnu for now, but we
// are compiling it everywhere to avoid regressions.
#![allow(unused)]
#[cfg(test)]
mod tests;
pub mod eh;
use core::mem;
pub struct DwarfReader {
pub ptr: *const u8,
}
#[repr(C, packed)]
struct Unaligned<T>(T);
impl DwarfReader {
pub fn new(ptr: *const u8) -> DwarfReader {
DwarfReader { ptr }
}
// DWARF streams are packed, so e.g., a u32 would not necessarily be aligned
// on a 4-byte boundary. This may cause problems on platforms with strict
// alignment requirements. By wrapping data in a "packed" struct, we are
// telling the backend to generate "misalignment-safe" code.
pub unsafe fn read<T: Copy>(&mut self) -> T {
let Unaligned(result) = *(self.ptr as *const Unaligned<T>);
self.ptr = self.ptr.add(mem::size_of::<T>());
result
}
// ULEB128 and SLEB128 encodings are defined in Section 7.6 - "Variable
// Length Data".
pub unsafe fn read_uleb128(&mut self) -> u64 {
let mut shift: usize = 0;
let mut result: u64 = 0;
let mut byte: u8;
loop {
byte = self.read::<u8>();
result |= ((byte & 0x7F) as u64) << shift;
shift += 7;
if byte & 0x80 == 0 {
break;
}
}
result
}
pub unsafe fn read_sleb128(&mut self) -> i64 {
let mut shift: usize = 0;
let mut result: u64 = 0;
let mut byte: u8;
loop {
byte = self.read::<u8>();
result |= ((byte & 0x7F) as u64) << shift;
shift += 7;
if byte & 0x80 == 0 {
break;
}
}
// sign-extend
if shift < 8 * mem::size_of::<u64>() && (byte & 0x40) != 0 {
result |= (!0 as u64) << shift;
}
result as i64
}
}

19
src/libdwarf/src/tests.rs Normal file
View File

@ -0,0 +1,19 @@
use super::*;
#[test]
fn dwarf_reader() {
let encoded: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 0xE5, 0x8E, 0x26, 0x9B, 0xF1, 0x59, 0xFF, 0xFF];
let mut reader = DwarfReader::new(encoded.as_ptr());
unsafe {
assert!(reader.read::<u8>() == u8::to_be(1u8));
assert!(reader.read::<u16>() == u16::to_be(0x0203));
assert!(reader.read::<u32>() == u32::to_be(0x04050607));
assert!(reader.read_uleb128() == 624485);
assert!(reader.read_sleb128() == -624485);
assert!(reader.read::<i8>() == i8::to_be(-1));
}
}

View File

@ -3,7 +3,7 @@
extern crate alloc;
extern crate log;
use core::{ops::Range, convert, fmt, str};
use core::{convert, fmt, str};
use alloc::string::String;
use log::{debug, trace};
use elf::*;
@ -57,10 +57,43 @@ fn elf_hash(name: &[u8]) -> u32 {
h
}
// linker symbols
extern "C" {
#[no_mangle]
static __text_start: u32;
#[no_mangle]
static __text_end: u32;
#[no_mangle]
static __exidx_start: u32;
#[no_mangle]
static __exidx_end: u32;
}
static mut KERNEL_EXIDX_START: u32 = 0;
static mut KERNEL_EXIDX_END: u32 = 0;
#[no_mangle]
extern fn dl_unwind_find_exidx(pc: u32, len_ptr: *mut u32) -> u32 {
let length: u32;
let start: u32;
unsafe {
if (&__text_start as *const u32 as u32) <= pc && pc < (&__text_end as *const u32 as u32) {
length = (&__exidx_end - &__exidx_start) as u32;
start = &__exidx_start as *const u32 as u32;
} else {
// make sure that the kernel is loaded
assert_ne!(KERNEL_EXIDX_START, 0);
length = (KERNEL_EXIDX_END - KERNEL_EXIDX_START) / core::mem::size_of::<u32>() as u32;
start = KERNEL_EXIDX_START;
}
*len_ptr = length;
}
start
}
pub struct Library {
pub image: Image,
dyn_section: DynamicSection,
exidx: Range<usize>,
}
impl Library {
@ -130,10 +163,6 @@ impl Library {
Ok(self.strtab().get(offset..offset + size)
.ok_or("cannot read symbol name")?)
}
pub fn exidx(&self) -> &[usize] {
self.image.get_ref_slice_unchecked(&self.exidx)
}
}
pub fn load(
@ -169,7 +198,6 @@ pub fn load(
.map_err(|_| "cannot allocate target image")?;
debug!("ELF target: {} bytes, align to {:X}, allocated at {:08X}", image_size, image_align, image.ptr() as usize);
let mut exidx = None;
// LOAD
for phdr in file.program_headers() {
let phdr = phdr.ok_or("cannot read program header")?;
@ -188,8 +216,13 @@ pub fn load(
dst.copy_from_slice(src);
}
PT_ARM_EXIDX => {
exidx = Some(phdr.p_vaddr as usize..
(phdr.p_vaddr + phdr.p_filesz) as usize);
let range = image.get(phdr.p_vaddr as usize..
(phdr.p_vaddr + phdr.p_filesz) as usize)
.ok_or("program header requests and out of bounds load (in target)")?;
unsafe {
KERNEL_EXIDX_START = range.as_ptr() as u32;
KERNEL_EXIDX_END = range.as_ptr().add(range.len()) as u32;
}
}
_ => {}
}
@ -203,8 +236,7 @@ pub fn load(
dyn_section.rela.len(), dyn_section.rel.len(), dyn_section.pltrel.len());
let lib = Library {
image,
dyn_section,
exidx: exidx.ok_or("missing EXIDX program header")?,
dyn_section
};
for rela in lib.rela() {

27
src/libunwind/Cargo.toml Normal file
View File

@ -0,0 +1,27 @@
[package]
authors = ["The Rust Project Developers"]
name = "unwind"
version = "0.0.0"
build = "build.rs"
edition = "2018"
include = [
'/libunwind/*',
]
[lib]
name = "unwind"
path = "lib.rs"
test = false
bench = false
doc = false
[dependencies]
compiler_builtins = "0.1.0"
cfg-if = "0.1.8"
libc = { path = "../libc" }
[build-dependencies]
cc = { version = "1.0.1" }
[features]
llvm-libunwind = []

View File

@ -0,0 +1,41 @@
use libc::{c_void, c_int};
use crate::libunwind as uw;
const UW_REG_SP: c_int = 13;
pub fn backtrace<F>(f: F) -> Result<(), uw::_Unwind_Reason_Code>
where F: FnMut(usize) -> ()
{
struct TraceContext<F> {
step_fn: F,
prev_sp: uw::_Unwind_Word
}
extern fn trace<F>(context: *mut uw::_Unwind_Context, arg: *mut c_void)
-> uw::_Unwind_Reason_Code
where F: FnMut(usize) -> ()
{
unsafe {
let trace_context = &mut *(arg as *mut TraceContext<F>);
// Detect the root of a libfringe thread
let cur_sp = uw::_Unwind_GetGR(context, UW_REG_SP);
if cur_sp == trace_context.prev_sp {
return uw::_URC_END_OF_STACK
} else {
trace_context.prev_sp = cur_sp;
}
(trace_context.step_fn)(uw::_Unwind_GetIP(context));
uw::_URC_NO_REASON
}
}
unsafe {
let mut trace_context = TraceContext { step_fn: f, prev_sp: 0 };
match uw::_Unwind_Backtrace(trace::<F>, &mut trace_context as *mut _ as *mut c_void) {
uw::_URC_NO_REASON => Ok(()),
err => Err(err)
}
}
}

63
src/libunwind/build.rs Normal file
View File

@ -0,0 +1,63 @@
fn main() {
println!("cargo:rerun-if-changed=build.rs");
llvm_libunwind::compile();
}
mod llvm_libunwind {
use std::path::Path;
/// Compile the libunwind C/C++ source code.
pub fn compile() {
let cfg = &mut cc::Build::new();
cfg.cpp(true);
cfg.cpp_set_stdlib(None);
cfg.warnings(false);
// libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
cfg.define("__LITTLE_ENDIAN__", Some("1"));
// still have problem compiling the libunwind
cfg.flag("-nostdlib");
cfg.flag("-ffreestanding");
cfg.flag("-fno-PIC");
cfg.flag("-Isrc");
cfg.flag("-isystem../include");
cfg.flag("-fno-stack-protector");
cfg.flag("--target=armv7-none-eabihf");
cfg.define("_LIBUNWIND_IS_BAREMETAL", Some("1"));
cfg.define("_LIBUNWIND_NO_HEAP", Some("1"));
cfg.define("_LIBUNWIND_HAS_NO_THREADS", Some("1"));
cfg.define("NDEBUG", Some("1"));
cfg.flag("-std=c99");
cfg.flag("-std=c++11");
cfg.flag("-nostdinc++");
cfg.flag("-fno-exceptions");
cfg.flag("-fno-rtti");
cfg.flag("-fstrict-aliasing");
cfg.flag("-funwind-tables");
cfg.flag("-fvisibility=hidden");
cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
let unwind_sources = vec![
"Unwind-EHABI.cpp",
"Unwind-seh.cpp",
"Unwind-sjlj.c",
"UnwindLevel1-gcc-ext.c",
"UnwindLevel1.c",
"UnwindRegistersRestore.S",
"UnwindRegistersSave.S",
"libunwind.cpp",
"printf.c",
];
let root = Path::new("../llvm_libunwind");
cfg.include(root.join("include"));
for src in unwind_sources {
println!("cargo:rerun-if-changed={}", src);
cfg.file(root.join("src").join(src));
}
cfg.compile("unwind");
}
}

33
src/libunwind/lib.rs Normal file
View File

@ -0,0 +1,33 @@
#![no_std]
#![feature(link_cfg)]
#![feature(nll)]
#![feature(unwind_attributes)]
#![feature(static_nobundle)]
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
cfg_if::cfg_if! {
if #[cfg(target_env = "msvc")] {
// no extra unwinder support needed
} else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
// no unwinder on the system!
} else {
mod libunwind;
pub use libunwind::*;
mod backtrace;
pub use backtrace::backtrace;
}
}
#[cfg(target_env = "musl")]
#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern "C" {}
#[cfg(target_os = "redox")]
#[link(name = "gcc_eh", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern "C" {}
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
#[link(name = "unwind", kind = "static-nobundle")]
extern "C" {}

285
src/libunwind/libunwind.rs Normal file
View File

@ -0,0 +1,285 @@
#![allow(nonstandard_style)]
use libc::{c_int, c_void, uintptr_t};
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum _Unwind_Reason_Code {
_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,
_URC_FAILURE = 9, // used only by ARM EHABI
}
pub use _Unwind_Reason_Code::*;
pub type _Unwind_Exception_Class = u64;
pub type _Unwind_Word = uintptr_t;
pub type _Unwind_Ptr = uintptr_t;
pub type _Unwind_Trace_Fn =
extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;
#[cfg(target_arch = "x86")]
pub const unwinder_private_data_size: usize = 5;
#[cfg(target_arch = "x86_64")]
pub const unwinder_private_data_size: usize = 6;
#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
pub const unwinder_private_data_size: usize = 20;
#[cfg(all(target_arch = "arm", target_os = "ios"))]
pub const unwinder_private_data_size: usize = 5;
#[cfg(target_arch = "aarch64")]
pub const unwinder_private_data_size: usize = 2;
#[cfg(target_arch = "mips")]
pub const unwinder_private_data_size: usize = 2;
#[cfg(target_arch = "mips64")]
pub const unwinder_private_data_size: usize = 2;
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
pub const unwinder_private_data_size: usize = 2;
#[cfg(target_arch = "s390x")]
pub const unwinder_private_data_size: usize = 2;
#[cfg(target_arch = "sparc64")]
pub const unwinder_private_data_size: usize = 2;
#[cfg(target_arch = "riscv64")]
pub const unwinder_private_data_size: usize = 2;
#[cfg(target_os = "emscripten")]
pub const unwinder_private_data_size: usize = 20;
#[cfg(all(target_arch = "hexagon", target_os = "linux"))]
pub const unwinder_private_data_size: usize = 35;
#[repr(C)]
pub struct _Unwind_Exception {
pub exception_class: _Unwind_Exception_Class,
pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
pub private: [_Unwind_Word; unwinder_private_data_size],
}
pub enum _Unwind_Context {}
pub type _Unwind_Exception_Cleanup_Fn =
extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
#[cfg_attr(
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
link(name = "unwind", kind = "static")
)]
extern "C" {
#[unwind(allowed)]
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
}
cfg_if::cfg_if! {
if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm"))))] {
// Not ARM EHABI
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]
pub enum _Unwind_Action {
_UA_SEARCH_PHASE = 1,
_UA_CLEANUP_PHASE = 2,
_UA_HANDLER_FRAME = 4,
_UA_FORCE_UNWIND = 8,
_UA_END_OF_STACK = 16,
}
pub use _Unwind_Action::*;
#[cfg_attr(all(feature = "llvm-libunwind",
any(target_os = "fuchsia", target_os = "linux")),
link(name = "unwind", kind = "static"))]
extern "C" {
pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word;
pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word);
pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int)
-> _Unwind_Word;
pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
}
} else {
// ARM EHABI
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]
pub enum _Unwind_State {
_US_VIRTUAL_UNWIND_FRAME = 0,
_US_UNWIND_FRAME_STARTING = 1,
_US_UNWIND_FRAME_RESUME = 2,
_US_ACTION_MASK = 3,
_US_FORCE_UNWIND = 8,
_US_END_OF_STACK = 16,
}
pub use _Unwind_State::*;
#[repr(C)]
enum _Unwind_VRS_Result {
_UVRSR_OK = 0,
_UVRSR_NOT_IMPLEMENTED = 1,
_UVRSR_FAILED = 2,
}
#[repr(C)]
enum _Unwind_VRS_RegClass {
_UVRSC_CORE = 0,
_UVRSC_VFP = 1,
_UVRSC_FPA = 2,
_UVRSC_WMMXD = 3,
_UVRSC_WMMXC = 4,
}
use _Unwind_VRS_RegClass::*;
#[repr(C)]
enum _Unwind_VRS_DataRepresentation {
_UVRSD_UINT32 = 0,
_UVRSD_VFPX = 1,
_UVRSD_FPAX = 2,
_UVRSD_UINT64 = 3,
_UVRSD_FLOAT = 4,
_UVRSD_DOUBLE = 5,
}
use _Unwind_VRS_DataRepresentation::*;
pub const UNWIND_POINTER_REG: c_int = 12;
pub const UNWIND_SP_REG: c_int = 13;
pub const UNWIND_IP_REG: c_int = 15;
#[cfg_attr(all(feature = "llvm-libunwind",
any(target_os = "fuchsia", target_os = "linux")),
link(name = "unwind", kind = "static"))]
extern "C" {
fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
regclass: _Unwind_VRS_RegClass,
regno: _Unwind_Word,
repr: _Unwind_VRS_DataRepresentation,
data: *mut c_void)
-> _Unwind_VRS_Result;
fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
regclass: _Unwind_VRS_RegClass,
regno: _Unwind_Word,
repr: _Unwind_VRS_DataRepresentation,
data: *mut c_void)
-> _Unwind_VRS_Result;
}
// On Android or ARM/Linux, these are implemented as macros:
pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
let mut val: _Unwind_Word = 0;
_Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
&mut val as *mut _ as *mut c_void);
val
}
pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
let mut value = value;
_Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
&mut value as *mut _ as *mut c_void);
}
pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
-> _Unwind_Word {
let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
(val & !1) as _Unwind_Word
}
pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
value: _Unwind_Word) {
// Propagate thumb bit to instruction pointer
let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
let value = value | thumb_state;
_Unwind_SetGR(ctx, UNWIND_IP_REG, value);
}
pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
ip_before_insn: *mut c_int)
-> _Unwind_Word {
*ip_before_insn = 0;
_Unwind_GetIP(ctx)
}
// This function also doesn't exist on Android or ARM/Linux, so make it a no-op
pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
pc
}
}
} // cfg_if!
cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
// Not 32-bit iOS
#[cfg_attr(all(feature = "llvm-libunwind",
any(target_os = "fuchsia", target_os = "linux")),
link(name = "unwind", kind = "static"))]
extern "C" {
#[unwind(allowed)]
pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
trace_argument: *mut c_void)
-> _Unwind_Reason_Code;
}
} else {
// 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
#[cfg_attr(all(feature = "llvm-libunwind",
any(target_os = "fuchsia", target_os = "linux")),
link(name = "unwind", kind = "static"))]
extern "C" {
#[unwind(allowed)]
pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
}
#[inline]
pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
_Unwind_SjLj_RaiseException(exc)
}
}
} // cfg_if!
cfg_if::cfg_if! {
if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
// We declare these as opaque types. This is fine since you just need to
// pass them to _GCC_specific_handler and forget about them.
pub enum EXCEPTION_RECORD {}
pub type LPVOID = *mut c_void;
pub enum CONTEXT {}
pub enum DISPATCHER_CONTEXT {}
pub type EXCEPTION_DISPOSITION = c_int;
type PersonalityFn = unsafe extern "C" fn(version: c_int,
actions: _Unwind_Action,
exception_class: _Unwind_Exception_Class,
exception_object: *mut _Unwind_Exception,
context: *mut _Unwind_Context)
-> _Unwind_Reason_Code;
extern "C" {
pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD,
establisherFrame: LPVOID,
contextRecord: *mut CONTEXT,
dispatcherContext: *mut DISPATCHER_CONTEXT,
personality: PersonalityFn)
-> EXCEPTION_DISPOSITION;
}
}
} // cfg_if!
#[no_mangle]
extern fn abort() {
panic!("Abort!");
}

View File

@ -0,0 +1,4 @@
{
"repository.callsign" : "UNW",
"conduit_uri" : "https://reviews.llvm.org/"
}

View File

@ -0,0 +1,2 @@
BasedOnStyle: LLVM

View File

@ -0,0 +1,372 @@
#===============================================================================
# Setup Project
#===============================================================================
cmake_minimum_required(VERSION 3.4.3)
if (POLICY CMP0042)
cmake_policy(SET CMP0042 NEW) # Set MACOSX_RPATH=YES by default
endif()
# Add path for custom modules
set(CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
${CMAKE_MODULE_PATH}
)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBUNWIND_STANDALONE_BUILD)
project(libunwind)
# Rely on llvm-config.
set(CONFIG_OUTPUT)
if(NOT LLVM_CONFIG_PATH)
find_program(LLVM_CONFIG_PATH "llvm-config")
endif()
if (DEFINED LLVM_PATH)
set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include")
set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree")
set(LLVM_MAIN_SRC_DIR ${LLVM_PATH})
set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules")
elseif(LLVM_CONFIG_PATH)
message(STATUS "Found LLVM_CONFIG_PATH as ${LLVM_CONFIG_PATH}")
set(CONFIG_COMMAND ${LLVM_CONFIG_PATH} "--includedir" "--prefix" "--src-root")
execute_process(COMMAND ${CONFIG_COMMAND}
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE CONFIG_OUTPUT)
if (NOT HAD_ERROR)
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";"
CONFIG_OUTPUT ${CONFIG_OUTPUT})
else()
string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}")
message(STATUS "${CONFIG_COMMAND_STR}")
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
endif()
list(GET CONFIG_OUTPUT 0 INCLUDE_DIR)
list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT)
list(GET CONFIG_OUTPUT 2 MAIN_SRC_DIR)
set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include")
set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree")
set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
set(LLVM_LIT_PATH "${LLVM_PATH}/utils/lit/lit.py")
# --cmakedir is supported since llvm r291218 (4.0 release)
execute_process(
COMMAND ${LLVM_CONFIG_PATH} --cmakedir
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE CONFIG_OUTPUT
ERROR_QUIET)
if(NOT HAD_ERROR)
string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG)
file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH)
else()
file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE)
set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
endif()
else()
message(WARNING "UNSUPPORTED LIBUNWIND CONFIGURATION DETECTED: "
"llvm-config not found and LLVM_MAIN_SRC_DIR not defined. "
"Reconfigure with -DLLVM_CONFIG=path/to/llvm-config "
"or -DLLVM_PATH=path/to/llvm-source-root.")
endif()
if (EXISTS ${LLVM_CMAKE_PATH})
# Enable warnings, otherwise -w gets added to the cflags by HandleLLVMOptions.
set(LLVM_ENABLE_WARNINGS ON)
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
include("${LLVM_CMAKE_PATH}/AddLLVM.cmake")
include("${LLVM_CMAKE_PATH}/HandleLLVMOptions.cmake")
else()
message(WARNING "Not found: ${LLVM_CMAKE_PATH}")
endif()
set(PACKAGE_NAME libunwind)
set(PACKAGE_VERSION 10.0.0svn)
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
if (EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
else()
# Seek installed Lit.
find_program(LLVM_LIT "lit.py" ${LLVM_MAIN_SRC_DIR}/utils/lit
DOC "Path to lit.py")
endif()
if (LLVM_LIT)
# Define the default arguments to use with 'lit', and an option for the user
# to override.
set(LIT_ARGS_DEFAULT "-sv")
if (MSVC OR XCODE)
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
endif()
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
# On Win32 hosts, provide an option to specify the path to the GnuWin32 tools.
if (WIN32 AND NOT CYGWIN)
set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
endif()
else()
set(LLVM_INCLUDE_TESTS OFF)
endif()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
else()
set(LLVM_LIT "${CMAKE_SOURCE_DIR}/utils/lit/lit.py")
endif()
#===============================================================================
# Setup CMake Options
#===============================================================================
include(CMakeDependentOption)
include(HandleCompilerRT)
# Define options.
option(LIBUNWIND_BUILD_32_BITS "Build 32 bit libunwind" ${LLVM_BUILD_32_BITS})
option(LIBUNWIND_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON)
option(LIBUNWIND_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
option(LIBUNWIND_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
option(LIBUNWIND_ENABLE_SHARED "Build libunwind as a shared library." ON)
option(LIBUNWIND_ENABLE_STATIC "Build libunwind as a static library." ON)
option(LIBUNWIND_ENABLE_CROSS_UNWINDING "Enable cross-platform unwinding support." OFF)
option(LIBUNWIND_ENABLE_ARM_WMMX "Enable unwinding support for ARM WMMX registers." OFF)
option(LIBUNWIND_ENABLE_THREADS "Build libunwind with threading support." ON)
option(LIBUNWIND_WEAK_PTHREAD_LIB "Use weak references to refer to pthread functions." OFF)
option(LIBUNWIND_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF)
option(LIBUNWIND_INCLUDE_DOCS "Build the libunwind documentation." ${LLVM_INCLUDE_DOCS})
set(LIBUNWIND_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
"Define suffix of library directory name (32/64)")
option(LIBUNWIND_INSTALL_LIBRARY "Install the libunwind library." ON)
cmake_dependent_option(LIBUNWIND_INSTALL_STATIC_LIBRARY
"Install the static libunwind library." ON
"LIBUNWIND_ENABLE_STATIC;LIBUNWIND_INSTALL_LIBRARY" OFF)
cmake_dependent_option(LIBUNWIND_INSTALL_SHARED_LIBRARY
"Install the shared libunwind library." ON
"LIBUNWIND_ENABLE_SHARED;LIBUNWIND_INSTALL_LIBRARY" OFF)
set(LIBUNWIND_TARGET_TRIPLE "" CACHE STRING "Target triple for cross compiling.")
set(LIBUNWIND_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.")
set(LIBUNWIND_SYSROOT "" CACHE PATH "Sysroot for cross compiling.")
set(LIBUNWIND_TEST_LINKER_FLAGS "" CACHE STRING
"Additional linker flags for test programs.")
set(LIBUNWIND_TEST_COMPILER_FLAGS "" CACHE STRING
"Additional compiler flags for test programs.")
if (NOT LIBUNWIND_ENABLE_SHARED AND NOT LIBUNWIND_ENABLE_STATIC)
message(FATAL_ERROR "libunwind must be built as either a shared or static library.")
endif()
# Check that we can build with 32 bits if requested.
if (CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32)
if (LIBUNWIND_BUILD_32_BITS AND NOT LLVM_BUILD_32_BITS) # Don't duplicate the output from LLVM
message(STATUS "Building 32 bits executables and libraries.")
endif()
elseif(LIBUNWIND_BUILD_32_BITS)
message(FATAL_ERROR "LIBUNWIND_BUILD_32_BITS=ON is not supported on this platform.")
endif()
option(LIBUNWIND_HERMETIC_STATIC_LIBRARY
"Do not export any symbols from the static library." OFF)
#===============================================================================
# Configure System
#===============================================================================
# Add path for custom modules
set(CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
${CMAKE_MODULE_PATH})
set(LIBUNWIND_COMPILER ${CMAKE_CXX_COMPILER})
set(LIBUNWIND_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBUNWIND_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
${PACKAGE_VERSION})
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
if(LIBCXX_LIBDIR_SUBDIR)
string(APPEND LIBUNWIND_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR})
string(APPEND LIBUNWIND_INSTALL_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR})
endif()
elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX})
else()
set(LIBUNWIND_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBUNWIND_LIBDIR_SUFFIX})
set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX})
endif()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR})
set(LIBUNWIND_INSTALL_PREFIX "" CACHE STRING "Define libunwind destination prefix.")
set(LIBUNWIND_C_FLAGS "")
set(LIBUNWIND_CXX_FLAGS "")
set(LIBUNWIND_COMPILE_FLAGS "")
set(LIBUNWIND_LINK_FLAGS "")
# Include macros for adding and removing libunwind flags.
include(HandleLibunwindFlags)
#===============================================================================
# Setup Compiler Flags
#===============================================================================
# Get required flags.
add_target_flags_if(LIBUNWIND_BUILD_32_BITS "-m32")
if(LIBUNWIND_TARGET_TRIPLE)
add_target_flags("--target=${LIBUNWIND_TARGET_TRIPLE}")
elseif(CMAKE_CXX_COMPILER_TARGET)
set(LIBUNWIND_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}")
endif()
if(LIBUNWIND_GCC_TOOLCHAIN)
add_target_flags("--gcc-toolchain=${LIBUNWIND_GCC_TOOLCHAIN}")
elseif(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN)
set(LIBUNWIND_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}")
endif()
if(LIBUNWIND_SYSROOT)
add_target_flags("--sysroot=${LIBUNWIND_SYSROOT}")
elseif(CMAKE_SYSROOT)
set(LIBUNWIND_SYSROOT "${CMAKE_SYSROOT}")
endif()
if (LIBUNWIND_TARGET_TRIPLE)
set(TARGET_TRIPLE "${LIBUNWIND_TARGET_TRIPLE}")
endif()
# Configure compiler.
include(config-ix)
if (LIBUNWIND_USE_COMPILER_RT AND NOT LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
list(APPEND LIBUNWIND_LINK_FLAGS "-rtlib=compiler-rt")
endif()
add_compile_flags_if_supported(-Werror=return-type)
# Get warning flags
add_compile_flags_if_supported(-W)
add_compile_flags_if_supported(-Wall)
add_compile_flags_if_supported(-Wchar-subscripts)
add_compile_flags_if_supported(-Wconversion)
add_compile_flags_if_supported(-Wmismatched-tags)
add_compile_flags_if_supported(-Wmissing-braces)
add_compile_flags_if_supported(-Wnewline-eof)
add_compile_flags_if_supported(-Wno-unused-function)
add_compile_flags_if_supported(-Wshadow)
add_compile_flags_if_supported(-Wshorten-64-to-32)
add_compile_flags_if_supported(-Wsign-compare)
add_compile_flags_if_supported(-Wsign-conversion)
add_compile_flags_if_supported(-Wstrict-aliasing=2)
add_compile_flags_if_supported(-Wstrict-overflow=4)
add_compile_flags_if_supported(-Wunused-parameter)
add_compile_flags_if_supported(-Wunused-variable)
add_compile_flags_if_supported(-Wwrite-strings)
add_compile_flags_if_supported(-Wundef)
if (LIBUNWIND_ENABLE_WERROR)
add_compile_flags_if_supported(-Werror)
add_compile_flags_if_supported(-WX)
else()
add_compile_flags_if_supported(-Wno-error)
add_compile_flags_if_supported(-WX-)
endif()
if (LIBUNWIND_ENABLE_PEDANTIC)
add_compile_flags_if_supported(-pedantic)
endif()
# Get feature flags.
# Exceptions
# Catches C++ exceptions only and tells the compiler to assume that extern C
# functions never throw a C++ exception.
add_cxx_compile_flags_if_supported(-fstrict-aliasing)
add_cxx_compile_flags_if_supported(-EHsc)
add_compile_flags_if_supported(-funwind-tables)
add_cxx_compile_flags_if_supported(-fno-exceptions)
add_cxx_compile_flags_if_supported(-fno-rtti)
# Ensure that we don't depend on C++ standard library.
if (LIBUNWIND_HAS_NOSTDINCXX_FLAG)
list(APPEND LIBUNWIND_COMPILE_FLAGS -nostdinc++)
# Remove -stdlib flags to prevent them from causing an unused flag warning.
string(REPLACE "-stdlib=libc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "-stdlib=libstdc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
# Assert
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
if (LIBUNWIND_ENABLE_ASSERTIONS)
# MSVC doesn't like _DEBUG on release builds. See PR 4379.
if (NOT MSVC)
add_compile_flags(-D_DEBUG)
endif()
# On Release builds cmake automatically defines NDEBUG, so we
# explicitly undefine it:
if (uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
add_compile_flags(-UNDEBUG)
endif()
else()
if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
add_compile_flags(-DNDEBUG)
endif()
endif()
# Cross-unwinding
if (NOT LIBUNWIND_ENABLE_CROSS_UNWINDING)
add_compile_flags(-D_LIBUNWIND_IS_NATIVE_ONLY)
endif()
# Threading-support
if (NOT LIBUNWIND_ENABLE_THREADS)
add_compile_flags(-D_LIBUNWIND_HAS_NO_THREADS)
endif()
# ARM WMMX register support
if (LIBUNWIND_ENABLE_ARM_WMMX)
# __ARM_WMMX is a compiler pre-define (as per the ACLE 2.0). Clang does not
# define this macro for any supported target at present. Therefore, here we
# provide the option to explicitly enable support for WMMX registers in the
# unwinder.
add_compile_flags(-D__ARM_WMMX)
endif()
# This is the _ONLY_ place where add_definitions is called.
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
# Disable DLL annotations on Windows for static builds.
if (WIN32 AND LIBUNWIND_ENABLE_STATIC AND NOT LIBUNWIND_ENABLE_SHARED)
add_definitions(-D_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
endif()
if (LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
add_definitions(-D_LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
endif()
#===============================================================================
# Setup Source Code
#===============================================================================
include_directories(include)
add_subdirectory(src)
if (LIBUNWIND_INCLUDE_DOCS)
add_subdirectory(docs)
endif()
if (EXISTS ${LLVM_CMAKE_PATH})
add_subdirectory(test)
endif()

View File

@ -0,0 +1,311 @@
==============================================================================
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
==============================================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---- LLVM Exceptions to the Apache 2.0 License ----
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into an Object form of such source code, you
may redistribute such embedded portions in such Object form without complying
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 ("Combined Software") and if a
court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of
the License, but only in their entirety and only with respect to the Combined
Software.
==============================================================================
Software from third parties included in the LLVM Project:
==============================================================================
The LLVM Project contains third party software which is under different license
terms. All such code will be identified clearly using at least one of two
mechanisms:
1) It will be in a separate directory tree with its own `LICENSE.txt` or
`LICENSE` file at the top containing the specific license and restrictions
which apply to that software, or
2) It will contain specific license and restriction terms at the top of every
file.
==============================================================================
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
==============================================================================
The libunwind library is dual licensed under both the University of Illinois
"BSD-Like" license and the MIT license. As a user of this code you may choose
to use it under either license. As a contributor, you agree to allow your code
to be used under both.
Full text of the relevant licenses is included below.
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
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:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
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
CONTRIBUTORS 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 WITH THE
SOFTWARE.
==============================================================================
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,64 @@
function(find_compiler_rt_library name dest)
if (NOT DEFINED LIBUNWIND_COMPILE_FLAGS)
message(FATAL_ERROR "LIBUNWIND_COMPILE_FLAGS must be defined when using this function")
endif()
set(dest "" PARENT_SCOPE)
set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBUNWIND_COMPILE_FLAGS}
"--rtlib=compiler-rt" "--print-libgcc-file-name")
if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_CXX_COMPILER_TARGET)
list(APPEND CLANG_COMMAND "--target=${CMAKE_CXX_COMPILER_TARGET}")
endif()
get_property(LIBUNWIND_CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE)
string(REPLACE " " ";" LIBUNWIND_CXX_FLAGS "${LIBUNWIND_CXX_FLAGS}")
list(APPEND CLANG_COMMAND ${LIBUNWIND_CXX_FLAGS})
execute_process(
COMMAND ${CLANG_COMMAND}
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE LIBRARY_FILE
)
string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}")
if (NOT HAD_ERROR AND EXISTS "${LIBRARY_FILE}")
message(STATUS "Found compiler-rt library: ${LIBRARY_FILE}")
set(${dest} "${LIBRARY_FILE}" PARENT_SCOPE)
else()
message(STATUS "Failed to find compiler-rt library")
endif()
endfunction()
function(find_compiler_rt_dir dest)
if (NOT DEFINED LIBUNWIND_COMPILE_FLAGS)
message(FATAL_ERROR "LIBUNWIND_COMPILE_FLAGS must be defined when using this function")
endif()
set(dest "" PARENT_SCOPE)
if (APPLE)
set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBUNWIND_COMPILE_FLAGS}
"-print-file-name=lib")
execute_process(
COMMAND ${CLANG_COMMAND}
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE LIBRARY_DIR
)
string(STRIP "${LIBRARY_DIR}" LIBRARY_DIR)
file(TO_CMAKE_PATH "${LIBRARY_DIR}" LIBRARY_DIR)
set(LIBRARY_DIR "${LIBRARY_DIR}/darwin")
else()
set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBUNWIND_COMPILE_FLAGS}
"--rtlib=compiler-rt" "--print-libgcc-file-name")
execute_process(
COMMAND ${CLANG_COMMAND}
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE LIBRARY_FILE
)
string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
get_filename_component(LIBRARY_DIR "${LIBRARY_FILE}" DIRECTORY)
endif()
if (NOT HAD_ERROR AND EXISTS "${LIBRARY_DIR}")
message(STATUS "Found compiler-rt directory: ${LIBRARY_DIR}")
set(${dest} "${LIBRARY_DIR}" PARENT_SCOPE)
else()
message(STATUS "Failed to find compiler-rt directory")
endif()
endfunction()

View File

@ -0,0 +1,272 @@
# HandleLibcxxFlags - A set of macros used to setup the flags used to compile
# and link libc++abi. These macros add flags to the following CMake variables.
# - LIBUNWIND_COMPILE_FLAGS: flags used to compile libunwind
# - LIBUNWIND_LINK_FLAGS: flags used to link libunwind
# - LIBUNWIND_LIBRARIES: libraries to link libunwind to.
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
unset(add_flag_if_supported)
# Mangle the name of a compiler flag into a valid CMake identifier.
# Ex: --std=c++11 -> STD_EQ_CXX11
macro(mangle_name str output)
string(STRIP "${str}" strippedStr)
string(REGEX REPLACE "^/" "" strippedStr "${strippedStr}")
string(REGEX REPLACE "^-+" "" strippedStr "${strippedStr}")
string(REGEX REPLACE "-+$" "" strippedStr "${strippedStr}")
string(REPLACE "-" "_" strippedStr "${strippedStr}")
string(REPLACE "=" "_EQ_" strippedStr "${strippedStr}")
string(REPLACE "+" "X" strippedStr "${strippedStr}")
string(TOUPPER "${strippedStr}" ${output})
endmacro()
# Remove a list of flags from all CMake variables that affect compile flags.
# This can be used to remove unwanted flags specified on the command line
# or added in other parts of LLVM's cmake configuration.
macro(remove_flags)
foreach(var ${ARGN})
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "${var}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REPLACE "${var}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
string(REPLACE "${var}" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
string(REPLACE "${var}" "" CMAKE_SHARED_MODULE_FLAGS "${CMAKE_SHARED_MODULE_FLAGS}")
remove_definitions(${var})
endforeach()
endmacro(remove_flags)
macro(check_flag_supported flag)
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
endmacro()
macro(append_flags DEST)
foreach(value ${ARGN})
list(APPEND ${DEST} ${value})
list(APPEND ${DEST} ${value})
endforeach()
endmacro()
# If the specified 'condition' is true then append the specified list of flags to DEST
macro(append_flags_if condition DEST)
if (${condition})
list(APPEND ${DEST} ${ARGN})
endif()
endmacro()
# Add each flag in the list specified by DEST if that flag is supported by the current compiler.
macro(append_flags_if_supported DEST)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
append_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${DEST} ${flag})
endforeach()
endmacro()
# Add a macro definition if condition is true.
macro(define_if condition def)
if (${condition})
add_definitions(${def})
endif()
endmacro()
# Add a macro definition if condition is not true.
macro(define_if_not condition def)
if (NOT ${condition})
add_definitions(${def})
endif()
endmacro()
# Add a macro definition to the __config_site file if the specified condition
# is 'true'. Note that '-D${def}' is not added. Instead it is expected that
# the build include the '__config_site' header.
macro(config_define_if condition def)
if (${condition})
set(${def} ON)
set(LIBUNWIND_NEEDS_SITE_CONFIG ON)
endif()
endmacro()
macro(config_define_if_not condition def)
if (NOT ${condition})
set(${def} ON)
set(LIBUNWIND_NEEDS_SITE_CONFIG ON)
endif()
endmacro()
macro(config_define value def)
set(${def} ${value})
set(LIBUNWIND_NEEDS_SITE_CONFIG ON)
endmacro()
# Add a list of flags to all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS',
# 'LIBUNWIND_COMPILE_FLAGS' and 'LIBUNWIND_LINK_FLAGS'.
macro(add_target_flags)
foreach(value ${ARGN})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${value}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${value}")
list(APPEND LIBUNWIND_COMPILE_FLAGS ${value})
list(APPEND LIBUNWIND_LINK_FLAGS ${value})
endforeach()
endmacro()
# If the specified 'condition' is true then add a list of flags to
# all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBUNWIND_COMPILE_FLAGS'
# and 'LIBUNWIND_LINK_FLAGS'.
macro(add_target_flags_if condition)
if (${condition})
add_target_flags(${ARGN})
endif()
endmacro()
# Add a specified list of flags to both 'LIBUNWIND_COMPILE_FLAGS' and
# 'LIBUNWIND_LINK_FLAGS'.
macro(add_flags)
foreach(value ${ARGN})
list(APPEND LIBUNWIND_COMPILE_FLAGS ${value})
list(APPEND LIBUNWIND_LINK_FLAGS ${value})
endforeach()
endmacro()
# If the specified 'condition' is true then add a list of flags to both
# 'LIBUNWIND_COMPILE_FLAGS' and 'LIBUNWIND_LINK_FLAGS'.
macro(add_flags_if condition)
if (${condition})
add_flags(${ARGN})
endif()
endmacro()
# Add each flag in the list to LIBUNWIND_COMPILE_FLAGS and LIBUNWIND_LINK_FLAGS
# if that flag is supported by the current compiler.
macro(add_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
add_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
# Add a list of flags to 'LIBUNWIND_COMPILE_FLAGS'.
macro(add_compile_flags)
foreach(f ${ARGN})
list(APPEND LIBUNWIND_COMPILE_FLAGS ${f})
endforeach()
endmacro()
# If 'condition' is true then add the specified list of flags to
# 'LIBUNWIND_COMPILE_FLAGS'
macro(add_compile_flags_if condition)
if (${condition})
add_compile_flags(${ARGN})
endif()
endmacro()
# For each specified flag, add that flag to 'LIBUNWIND_COMPILE_FLAGS' if the
# flag is supported by the C++ compiler.
macro(add_compile_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
add_compile_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
# Add a list of flags to 'LIBUNWIND_C_FLAGS'.
macro(add_c_flags)
foreach(f ${ARGN})
list(APPEND LIBUNWIND_C_FLAGS ${f})
endforeach()
endmacro()
# If 'condition' is true then add the specified list of flags to
# 'LIBUNWIND_C_FLAGS'
macro(add_c_flags_if condition)
if (${condition})
add_c_flags(${ARGN})
endif()
endmacro()
# For each specified flag, add that flag to 'LIBUNWIND_C_FLAGS' if the
# flag is supported by the C compiler.
macro(add_c_compile_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_c_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
add_c_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
# Add a list of flags to 'LIBUNWIND_CXX_FLAGS'.
macro(add_cxx_flags)
foreach(f ${ARGN})
list(APPEND LIBUNWIND_CXX_FLAGS ${f})
endforeach()
endmacro()
# If 'condition' is true then add the specified list of flags to
# 'LIBUNWIND_CXX_FLAGS'
macro(add_cxx_flags_if condition)
if (${condition})
add_cxx_flags(${ARGN})
endif()
endmacro()
# For each specified flag, add that flag to 'LIBUNWIND_CXX_FLAGS' if the
# flag is supported by the C compiler.
macro(add_cxx_compile_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
add_cxx_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
# Add a list of flags to 'LIBUNWIND_LINK_FLAGS'.
macro(add_link_flags)
foreach(f ${ARGN})
list(APPEND LIBUNWIND_LINK_FLAGS ${f})
endforeach()
endmacro()
# If 'condition' is true then add the specified list of flags to
# 'LIBUNWIND_LINK_FLAGS'
macro(add_link_flags_if condition)
if (${condition})
add_link_flags(${ARGN})
endif()
endmacro()
# For each specified flag, add that flag to 'LIBUNWIND_LINK_FLAGS' if the
# flag is supported by the C++ compiler.
macro(add_link_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
add_link_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
# Add a list of libraries or link flags to 'LIBUNWIND_LIBRARIES'.
macro(add_library_flags)
foreach(lib ${ARGN})
list(APPEND LIBUNWIND_LIBRARIES ${lib})
endforeach()
endmacro()
# if 'condition' is true then add the specified list of libraries and flags
# to 'LIBUNWIND_LIBRARIES'.
macro(add_library_flags_if condition)
if(${condition})
add_library_flags(${ARGN})
endif()
endmacro()
# Turn a comma separated CMake list into a space separated string.
macro(split_list listname)
string(REPLACE ";" " " ${listname} "${${listname}}")
endmacro()

View File

@ -0,0 +1,75 @@
include(CMakePushCheckState)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
include(CheckLibraryExists)
include(CheckCSourceCompiles)
check_library_exists(c fopen "" LIBUNWIND_HAS_C_LIB)
if (NOT LIBUNWIND_USE_COMPILER_RT)
check_library_exists(gcc_s __gcc_personality_v0 "" LIBUNWIND_HAS_GCC_S_LIB)
check_library_exists(gcc __absvdi2 "" LIBUNWIND_HAS_GCC_LIB)
endif()
# libunwind is built with -nodefaultlibs, so we want all our checks to also
# use this option, otherwise we may end up with an inconsistency between
# the flags we think we require during configuration (if the checks are
# performed without -nodefaultlibs) and the flags that are actually
# required during compilation (which has the -nodefaultlibs). libc is
# required for the link to go through. We remove sanitizers from the
# configuration checks to avoid spurious link errors.
check_c_compiler_flag(-nodefaultlibs LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
if (LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
if (LIBUNWIND_HAS_C_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES c)
endif ()
if (LIBUNWIND_USE_COMPILER_RT)
find_compiler_rt_library(builtins LIBUNWIND_BUILTINS_LIBRARY)
list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBUNWIND_BUILTINS_LIBRARY}")
else ()
if (LIBUNWIND_HAS_GCC_S_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s)
endif ()
if (LIBUNWIND_HAS_GCC_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES gcc)
endif ()
endif ()
if (MINGW)
# Mingw64 requires quite a few "C" runtime libraries in order for basic
# programs to link successfully with -nodefaultlibs.
if (LIBUNWIND_USE_COMPILER_RT)
set(MINGW_RUNTIME ${LIBUNWIND_BUILTINS_LIBRARY})
else ()
set(MINGW_RUNTIME gcc_s gcc)
endif()
set(MINGW_LIBRARIES mingw32 ${MINGW_RUNTIME} moldname mingwex msvcrt advapi32
shell32 user32 kernel32 mingw32 ${MINGW_RUNTIME}
moldname mingwex msvcrt)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES})
endif()
if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all")
endif ()
if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters")
endif ()
endif ()
# Check compiler pragmas
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unknown-pragmas")
check_c_source_compiles("
#pragma comment(lib, \"c\")
int main() { return 0; }
" LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
cmake_pop_check_state()
endif()
# Check compiler flags
check_cxx_compiler_flag(-nostdinc++ LIBUNWIND_HAS_NOSTDINCXX_FLAG)
# Check libraries
check_library_exists(dl dladdr "" LIBUNWIND_HAS_DL_LIB)
check_library_exists(pthread pthread_once "" LIBUNWIND_HAS_PTHREAD_LIB)

View File

@ -0,0 +1,161 @@
.. _BuildingLibunwind:
==================
Building libunwind
==================
.. contents::
:local:
.. _build instructions:
Getting Started
===============
On Mac OS, the easiest way to get this library is to link with -lSystem.
However if you want to build tip-of-trunk from here (getting the bleeding
edge), read on.
The basic steps needed to build libc++ are:
#. Checkout LLVM, libunwind, and related projects:
* ``cd where-you-want-llvm-to-live``
* ``git clone https://github.com/llvm/llvm-project.git``
#. Configure and build libunwind:
CMake is the only supported configuration system.
Clang is the preferred compiler when building and using libunwind.
* ``cd where you want to build llvm``
* ``mkdir build``
* ``cd build``
* ``cmake -G <generator> -DLLVM_ENABLE_PROJECTS=libunwind [options] <path to llvm sources>``
For more information about configuring libunwind see :ref:`CMake Options`.
* ``make unwind`` --- will build libunwind.
* ``make check-unwind`` --- will run the test suite.
Shared and static libraries for libunwind should now be present in llvm/build/lib.
#. **Optional**: Install libunwind
If your system already provides an unwinder, it is important to be careful
not to replace it. Remember Use the CMake option ``CMAKE_INSTALL_PREFIX`` to
select a safe place to install libunwind.
* ``make install-unwind`` --- Will install the libraries and the headers
It is sometimes beneficial to build outside of the LLVM tree. An out-of-tree
build would look like this:
.. code-block:: bash
$ cd where-you-want-libunwind-to-live
$ # Check out llvm, and libunwind
$ ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm``
$ ``svn co http://llvm.org/svn/llvm-project/libunwind/trunk libunwind``
$ cd where-you-want-to-build
$ mkdir build && cd build
$ export CC=clang CXX=clang++
$ cmake -DLLVM_PATH=path/to/llvm \
path/to/libunwind
$ make
.. _CMake Options:
CMake Options
=============
Here are some of the CMake variables that are used often, along with a
brief explanation and LLVM-specific notes. For full documentation, check the
CMake docs or execute ``cmake --help-variable VARIABLE_NAME``.
**CMAKE_BUILD_TYPE**:STRING
Sets the build type for ``make`` based generators. Possible values are
Release, Debug, RelWithDebInfo and MinSizeRel. On systems like Visual Studio
the user sets the build type with the IDE settings.
**CMAKE_INSTALL_PREFIX**:PATH
Path where LLVM will be installed if "make install" is invoked or the
"INSTALL" target is built.
**CMAKE_CXX_COMPILER**:STRING
The C++ compiler to use when building and testing libunwind.
.. _libunwind-specific options:
libunwind specific options
--------------------------
.. option:: LIBUNWIND_BUILD_32_BITS:BOOL
**Default**: Same as LLVM_BUILD_32_BITS
Toggle whether libunwind should be built with -m32.
.. option:: LIBUNWIND_ENABLE_ASSERTIONS:BOOL
**Default**: ``ON``
Toggle assertions independent of the build mode.
.. option:: LIBUNWIND_ENABLE_PEDANTIC:BOOL
**Default**: ``ON``
Compile with -Wpedantic.
.. option:: LIBUNWIND_ENABLE_WERROR:BOOL
**Default**: ``ON``
Compile with -Werror
.. option:: LIBUNWIND_ENABLE_SHARED:BOOL
**Default**: ``ON``
Build libunwind as a shared library.
.. option:: LIBUNWIND_ENABLE_STATIC:BOOL
**Default**: ``ON``
Build libunwind as a static archive.
.. option:: LIBUNWIND_ENABLE_CROSS_UNWINDING:BOOL
**Default**: ``OFF``
Enable cross-platform unwinding support.
.. option:: LIBUNWIND_ENABLE_ARM_WMMX:BOOL
**Default**: ``OFF``
Enable unwinding support for ARM WMMX registers.
.. option:: LIBUNWIND_ENABLE_THREADS:BOOL
**Default**: ``ON``
Build libunwind with threading support.
.. option:: LIBUNWIND_TARGET_TRIPLE:STRING
Target triple for cross compiling
.. option:: LIBUNWIND_GCC_TOOLCHAIN:PATH
GCC toolchain for cross compiling
.. option:: LIBUNWIND_SYSROOT
Sysroot for cross compiling

View File

@ -0,0 +1,7 @@
include(FindSphinx)
if (SPHINX_FOUND)
include(AddSphinxTarget)
if (${SPHINX_OUTPUT_HTML})
add_sphinx_target(html libunwind)
endif()
endif()

View File

@ -0,0 +1,13 @@
libunwind Documentation
====================
The libunwind documentation is written using the Sphinx documentation generator. It is
currently tested with Sphinx 1.1.3.
To build the documents into html configure libunwind with the following cmake options:
* -DLLVM_ENABLE_SPHINX=ON
* -DLIBUNWIND_INCLUDE_DOCS=ON
After configuring libunwind with these options the make rule `docs-libunwind-html`
should be available.

View File

@ -0,0 +1,252 @@
# -*- coding: utf-8 -*-
#
# libunwind documentation build configuration file.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
from datetime import date
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'libunwind'
copyright = u'2011-%d, LLVM Project' % date.today().year
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '10.0'
# The full version, including alpha/beta/rc tags.
release = '10.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
today_fmt = '%Y-%m-%d'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'friendly'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'haiku'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'libunwinddoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('contents', 'libunwind.tex', u'libunwind Documentation',
u'LLVM project', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('contents', 'libunwind', u'libunwind Documentation',
[u'LLVM project'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('contents', 'libunwind', u'libunwind Documentation',
u'LLVM project', 'libunwind', 'LLVM Unwinder',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# FIXME: Define intersphinx configration.
intersphinx_mapping = {}
# -- Options for extensions ----------------------------------------------------
# Enable this if you want TODOs to show up in the generated documentation.
todo_include_todos = True

View File

@ -0,0 +1,104 @@
.. _index:
=======================
libunwind LLVM Unwinder
=======================
Overview
========
libunwind is an implementation of the interface defined by the HP libunwind
project. It was contributed by Apple as a way to enable clang++ to port to
platforms that do not have a system unwinder. It is intended to be a small and
fast implementation of the ABI, leaving off some features of HP's libunwind
that never materialized (e.g. remote unwinding).
The unwinder has two levels of API. The high level APIs are the `_Unwind_*`
functions which implement functionality required by `__cxa_*` exception
functions. The low level APIs are the `unw_*` functions which are an interface
defined by the old HP libunwind project.
Getting Started with libunwind
------------------------------
.. toctree::
:maxdepth: 2
BuildingLibunwind
Current Status
--------------
libunwind is a production-quality unwinder, with platform support for DWARF
unwind info, SjLj, and ARM EHABI.
The low level libunwind API was designed to work either in-process (aka local)
or to operate on another process (aka remote), but only the local path has been
implemented. Remote unwinding remains as future work.
Platform and Compiler Support
-----------------------------
libunwind is known to work on the following platforms:
============ ======================== ============ ========================
OS Arch Compilers Unwind Info
============ ======================== ============ ========================
Any i386, x86_64, ARM Clang SjLj
Bare Metal ARM Clang, GCC EHABI
FreeBSD i386, x86_64, ARM64 Clang DWARF CFI
iOS ARM Clang SjLj
Linux ARM Clang, GCC EHABI
Linux i386, x86_64, ARM64 Clang, GCC DWARF CFI
macOS i386, x86_64 Clang, GCC DWARF CFI
NetBSD x86_64 Clang, GCC DWARF CFI
Windows i386, x86_64, ARM, ARM64 Clang DWARF CFI
============ ======================== ============ ========================
The following minimum compiler versions are strongly recommended.
* Clang 3.5 and above
* GCC 4.7 and above.
Anything older *may* work.
Notes and Known Issues
----------------------
* TODO
Getting Involved
================
First please review our `Developer's Policy <http://llvm.org/docs/DeveloperPolicy.html>`__
and `Getting started with LLVM <http://llvm.org/docs/GettingStarted.html>`__.
**Bug Reports**
If you think you've found a bug in libunwind, please report it using
the `LLVM Bugzilla`_. If you're not sure, you
can post a message to the `cfe-dev mailing list`_ or on IRC.
Please include "libunwind" in your subject.
**Patches**
If you want to contribute a patch to libunwind, the best place for that is
`Phabricator <http://llvm.org/docs/Phabricator.html>`_. Please include [libunwind] in the subject and
add `cfe-commits` as a subscriber. Also make sure you are subscribed to the
`cfe-commits mailing list <http://lists.llvm.org/mailman/listinfo/cfe-commits>`_.
**Discussion and Questions**
Send discussions and questions to the
`cfe-dev mailing list <http://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
Please include [libunwind] in the subject.
Quick Links
===========
* `LLVM Homepage <http://llvm.org/>`_
* `LLVM Bugzilla <https://bugs.llvm.org/>`_
* `cfe-commits Mailing List`_
* `cfe-dev Mailing List`_
* `Browse libunwind Sources <https://github.com/llvm/llvm-project/blob/master/libunwind/>`_

View File

@ -0,0 +1,140 @@
//===------------------------- __libunwind_config.h -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef ____LIBUNWIND_CONFIG_H__
#define ____LIBUNWIND_CONFIG_H__
#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
!defined(__ARM_DWARF_EH__)
#define _LIBUNWIND_ARM_EHABI
#endif
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 116
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
# if defined(__i386__)
# define _LIBUNWIND_TARGET_I386
# define _LIBUNWIND_CONTEXT_SIZE 8
# define _LIBUNWIND_CURSOR_SIZE 15
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86
# elif defined(__x86_64__)
# define _LIBUNWIND_TARGET_X86_64 1
# if defined(_WIN64)
# define _LIBUNWIND_CONTEXT_SIZE 54
# ifdef __SEH__
# define _LIBUNWIND_CURSOR_SIZE 204
# else
# define _LIBUNWIND_CURSOR_SIZE 66
# endif
# else
# define _LIBUNWIND_CONTEXT_SIZE 21
# define _LIBUNWIND_CURSOR_SIZE 33
# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64
# elif defined(__powerpc64__)
# define _LIBUNWIND_TARGET_PPC64 1
# define _LIBUNWIND_CONTEXT_SIZE 167
# define _LIBUNWIND_CURSOR_SIZE 179
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64
# elif defined(__ppc__)
# define _LIBUNWIND_TARGET_PPC 1
# define _LIBUNWIND_CONTEXT_SIZE 117
# define _LIBUNWIND_CURSOR_SIZE 124
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC
# elif defined(__aarch64__)
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_CONTEXT_SIZE 66
# if defined(__SEH__)
# define _LIBUNWIND_CURSOR_SIZE 164
# else
# define _LIBUNWIND_CURSOR_SIZE 78
# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
# elif defined(__arm__)
# define _LIBUNWIND_TARGET_ARM 1
# if defined(__SEH__)
# define _LIBUNWIND_CONTEXT_SIZE 42
# define _LIBUNWIND_CURSOR_SIZE 80
# elif defined(__ARM_WMMX)
# define _LIBUNWIND_CONTEXT_SIZE 61
# define _LIBUNWIND_CURSOR_SIZE 68
# else
# define _LIBUNWIND_CONTEXT_SIZE 42
# define _LIBUNWIND_CURSOR_SIZE 49
# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM
# elif defined(__or1k__)
# define _LIBUNWIND_TARGET_OR1K 1
# define _LIBUNWIND_CONTEXT_SIZE 16
# define _LIBUNWIND_CURSOR_SIZE 24
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K
# elif defined(__mips__)
# if defined(_ABIO32) && _MIPS_SIM == _ABIO32
# define _LIBUNWIND_TARGET_MIPS_O32 1
# if defined(__mips_hard_float)
# define _LIBUNWIND_CONTEXT_SIZE 50
# define _LIBUNWIND_CURSOR_SIZE 57
# else
# define _LIBUNWIND_CONTEXT_SIZE 18
# define _LIBUNWIND_CURSOR_SIZE 24
# endif
# elif defined(_ABIN32) && _MIPS_SIM == _ABIN32
# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
# if defined(__mips_hard_float)
# define _LIBUNWIND_CONTEXT_SIZE 67
# define _LIBUNWIND_CURSOR_SIZE 74
# else
# define _LIBUNWIND_CONTEXT_SIZE 35
# define _LIBUNWIND_CURSOR_SIZE 42
# endif
# elif defined(_ABI64) && _MIPS_SIM == _ABI64
# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
# if defined(__mips_hard_float)
# define _LIBUNWIND_CONTEXT_SIZE 67
# define _LIBUNWIND_CURSOR_SIZE 79
# else
# define _LIBUNWIND_CONTEXT_SIZE 35
# define _LIBUNWIND_CURSOR_SIZE 47
# endif
# else
# error "Unsupported MIPS ABI and/or environment"
# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
# elif defined(__sparc__)
#define _LIBUNWIND_TARGET_SPARC 1
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
#define _LIBUNWIND_CONTEXT_SIZE 16
#define _LIBUNWIND_CURSOR_SIZE 23
# else
# error "Unsupported architecture."
# endif
#else // !_LIBUNWIND_IS_NATIVE_ONLY
# define _LIBUNWIND_TARGET_I386
# define _LIBUNWIND_TARGET_X86_64 1
# define _LIBUNWIND_TARGET_PPC 1
# define _LIBUNWIND_TARGET_PPC64 1
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_TARGET_ARM 1
# define _LIBUNWIND_TARGET_OR1K 1
# define _LIBUNWIND_TARGET_MIPS_O32 1
# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
# define _LIBUNWIND_TARGET_SPARC 1
# define _LIBUNWIND_CONTEXT_SIZE 167
# define _LIBUNWIND_CURSOR_SIZE 179
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
#endif // _LIBUNWIND_IS_NATIVE_ONLY
#endif // ____LIBUNWIND_CONFIG_H__

View File

@ -0,0 +1,835 @@
//===---------------------------- libunwind.h -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Compatible with libunwind API documented at:
// http://www.nongnu.org/libunwind/man/libunwind(3).html
//
//===----------------------------------------------------------------------===//
#ifndef __LIBUNWIND__
#define __LIBUNWIND__
#include <__libunwind_config.h>
#include <stdint.h>
#include <stddef.h>
#ifdef __APPLE__
#if __clang__
#if __has_include(<Availability.h>)
#include <Availability.h>
#endif
#elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
#include <Availability.h>
#endif
#ifdef __arm__
#define LIBUNWIND_AVAIL __attribute__((unavailable))
#elif defined(__OSX_AVAILABLE_STARTING)
#define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0)
#else
#include <AvailabilityMacros.h>
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#define LIBUNWIND_AVAIL AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#else
#define LIBUNWIND_AVAIL __attribute__((unavailable))
#endif
#endif
#else
#define LIBUNWIND_AVAIL
#endif
/* error codes */
enum {
UNW_ESUCCESS = 0, /* no error */
UNW_EUNSPEC = -6540, /* unspecified (general) error */
UNW_ENOMEM = -6541, /* out of memory */
UNW_EBADREG = -6542, /* bad register number */
UNW_EREADONLYREG = -6543, /* attempt to write read-only register */
UNW_ESTOPUNWIND = -6544, /* stop unwinding */
UNW_EINVALIDIP = -6545, /* invalid IP */
UNW_EBADFRAME = -6546, /* bad frame */
UNW_EINVAL = -6547, /* unsupported operation or bad value */
UNW_EBADVERSION = -6548, /* unwind info has unsupported version */
UNW_ENOINFO = -6549 /* no unwind info found */
#if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY)
, UNW_ECROSSRASIGNING = -6550 /* cross unwind with return address signing */
#endif
};
struct unw_context_t {
uint64_t data[_LIBUNWIND_CONTEXT_SIZE];
};
typedef struct unw_context_t unw_context_t;
struct unw_cursor_t {
uint64_t data[_LIBUNWIND_CURSOR_SIZE];
};
typedef struct unw_cursor_t unw_cursor_t;
typedef struct unw_addr_space *unw_addr_space_t;
typedef int unw_regnum_t;
typedef uintptr_t unw_word_t;
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
typedef uint64_t unw_fpreg_t;
#else
typedef double unw_fpreg_t;
#endif
struct unw_proc_info_t {
unw_word_t start_ip; /* start address of function */
unw_word_t end_ip; /* address after end of function */
unw_word_t lsda; /* address of language specific data area, */
/* or zero if not used */
unw_word_t handler; /* personality routine, or zero if not used */
unw_word_t gp; /* not used */
unw_word_t flags; /* not used */
uint32_t format; /* compact unwind encoding, or zero if none */
uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */
unw_word_t unwind_info; /* address of DWARF unwind info, or zero */
unw_word_t extra; /* mach_header of mach-o image containing func */
};
typedef struct unw_proc_info_t unw_proc_info_t;
#ifdef __cplusplus
extern "C" {
#endif
extern int unw_getcontext(unw_context_t *) LIBUNWIND_AVAIL;
extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL;
extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL;
extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL;
extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL;
extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL;
extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL;
extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL;
#ifdef __arm__
/* Save VFP registers in FSTMX format (instead of FSTMD). */
extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL;
#endif
extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL;
extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL;
extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL;
//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*);
extern unw_addr_space_t unw_local_addr_space;
#ifdef __cplusplus
}
#endif
// architecture independent register numbers
enum {
UNW_REG_IP = -1, // instruction pointer
UNW_REG_SP = -2, // stack pointer
};
// 32-bit x86 registers
enum {
UNW_X86_EAX = 0,
UNW_X86_ECX = 1,
UNW_X86_EDX = 2,
UNW_X86_EBX = 3,
UNW_X86_EBP = 4,
UNW_X86_ESP = 5,
UNW_X86_ESI = 6,
UNW_X86_EDI = 7
};
// 64-bit x86_64 registers
enum {
UNW_X86_64_RAX = 0,
UNW_X86_64_RDX = 1,
UNW_X86_64_RCX = 2,
UNW_X86_64_RBX = 3,
UNW_X86_64_RSI = 4,
UNW_X86_64_RDI = 5,
UNW_X86_64_RBP = 6,
UNW_X86_64_RSP = 7,
UNW_X86_64_R8 = 8,
UNW_X86_64_R9 = 9,
UNW_X86_64_R10 = 10,
UNW_X86_64_R11 = 11,
UNW_X86_64_R12 = 12,
UNW_X86_64_R13 = 13,
UNW_X86_64_R14 = 14,
UNW_X86_64_R15 = 15,
UNW_X86_64_RIP = 16,
UNW_X86_64_XMM0 = 17,
UNW_X86_64_XMM1 = 18,
UNW_X86_64_XMM2 = 19,
UNW_X86_64_XMM3 = 20,
UNW_X86_64_XMM4 = 21,
UNW_X86_64_XMM5 = 22,
UNW_X86_64_XMM6 = 23,
UNW_X86_64_XMM7 = 24,
UNW_X86_64_XMM8 = 25,
UNW_X86_64_XMM9 = 26,
UNW_X86_64_XMM10 = 27,
UNW_X86_64_XMM11 = 28,
UNW_X86_64_XMM12 = 29,
UNW_X86_64_XMM13 = 30,
UNW_X86_64_XMM14 = 31,
UNW_X86_64_XMM15 = 32,
};
// 32-bit ppc register numbers
enum {
UNW_PPC_R0 = 0,
UNW_PPC_R1 = 1,
UNW_PPC_R2 = 2,
UNW_PPC_R3 = 3,
UNW_PPC_R4 = 4,
UNW_PPC_R5 = 5,
UNW_PPC_R6 = 6,
UNW_PPC_R7 = 7,
UNW_PPC_R8 = 8,
UNW_PPC_R9 = 9,
UNW_PPC_R10 = 10,
UNW_PPC_R11 = 11,
UNW_PPC_R12 = 12,
UNW_PPC_R13 = 13,
UNW_PPC_R14 = 14,
UNW_PPC_R15 = 15,
UNW_PPC_R16 = 16,
UNW_PPC_R17 = 17,
UNW_PPC_R18 = 18,
UNW_PPC_R19 = 19,
UNW_PPC_R20 = 20,
UNW_PPC_R21 = 21,
UNW_PPC_R22 = 22,
UNW_PPC_R23 = 23,
UNW_PPC_R24 = 24,
UNW_PPC_R25 = 25,
UNW_PPC_R26 = 26,
UNW_PPC_R27 = 27,
UNW_PPC_R28 = 28,
UNW_PPC_R29 = 29,
UNW_PPC_R30 = 30,
UNW_PPC_R31 = 31,
UNW_PPC_F0 = 32,
UNW_PPC_F1 = 33,
UNW_PPC_F2 = 34,
UNW_PPC_F3 = 35,
UNW_PPC_F4 = 36,
UNW_PPC_F5 = 37,
UNW_PPC_F6 = 38,
UNW_PPC_F7 = 39,
UNW_PPC_F8 = 40,
UNW_PPC_F9 = 41,
UNW_PPC_F10 = 42,
UNW_PPC_F11 = 43,
UNW_PPC_F12 = 44,
UNW_PPC_F13 = 45,
UNW_PPC_F14 = 46,
UNW_PPC_F15 = 47,
UNW_PPC_F16 = 48,
UNW_PPC_F17 = 49,
UNW_PPC_F18 = 50,
UNW_PPC_F19 = 51,
UNW_PPC_F20 = 52,
UNW_PPC_F21 = 53,
UNW_PPC_F22 = 54,
UNW_PPC_F23 = 55,
UNW_PPC_F24 = 56,
UNW_PPC_F25 = 57,
UNW_PPC_F26 = 58,
UNW_PPC_F27 = 59,
UNW_PPC_F28 = 60,
UNW_PPC_F29 = 61,
UNW_PPC_F30 = 62,
UNW_PPC_F31 = 63,
UNW_PPC_MQ = 64,
UNW_PPC_LR = 65,
UNW_PPC_CTR = 66,
UNW_PPC_AP = 67,
UNW_PPC_CR0 = 68,
UNW_PPC_CR1 = 69,
UNW_PPC_CR2 = 70,
UNW_PPC_CR3 = 71,
UNW_PPC_CR4 = 72,
UNW_PPC_CR5 = 73,
UNW_PPC_CR6 = 74,
UNW_PPC_CR7 = 75,
UNW_PPC_XER = 76,
UNW_PPC_V0 = 77,
UNW_PPC_V1 = 78,
UNW_PPC_V2 = 79,
UNW_PPC_V3 = 80,
UNW_PPC_V4 = 81,
UNW_PPC_V5 = 82,
UNW_PPC_V6 = 83,
UNW_PPC_V7 = 84,
UNW_PPC_V8 = 85,
UNW_PPC_V9 = 86,
UNW_PPC_V10 = 87,
UNW_PPC_V11 = 88,
UNW_PPC_V12 = 89,
UNW_PPC_V13 = 90,
UNW_PPC_V14 = 91,
UNW_PPC_V15 = 92,
UNW_PPC_V16 = 93,
UNW_PPC_V17 = 94,
UNW_PPC_V18 = 95,
UNW_PPC_V19 = 96,
UNW_PPC_V20 = 97,
UNW_PPC_V21 = 98,
UNW_PPC_V22 = 99,
UNW_PPC_V23 = 100,
UNW_PPC_V24 = 101,
UNW_PPC_V25 = 102,
UNW_PPC_V26 = 103,
UNW_PPC_V27 = 104,
UNW_PPC_V28 = 105,
UNW_PPC_V29 = 106,
UNW_PPC_V30 = 107,
UNW_PPC_V31 = 108,
UNW_PPC_VRSAVE = 109,
UNW_PPC_VSCR = 110,
UNW_PPC_SPE_ACC = 111,
UNW_PPC_SPEFSCR = 112
};
// 64-bit ppc register numbers
enum {
UNW_PPC64_R0 = 0,
UNW_PPC64_R1 = 1,
UNW_PPC64_R2 = 2,
UNW_PPC64_R3 = 3,
UNW_PPC64_R4 = 4,
UNW_PPC64_R5 = 5,
UNW_PPC64_R6 = 6,
UNW_PPC64_R7 = 7,
UNW_PPC64_R8 = 8,
UNW_PPC64_R9 = 9,
UNW_PPC64_R10 = 10,
UNW_PPC64_R11 = 11,
UNW_PPC64_R12 = 12,
UNW_PPC64_R13 = 13,
UNW_PPC64_R14 = 14,
UNW_PPC64_R15 = 15,
UNW_PPC64_R16 = 16,
UNW_PPC64_R17 = 17,
UNW_PPC64_R18 = 18,
UNW_PPC64_R19 = 19,
UNW_PPC64_R20 = 20,
UNW_PPC64_R21 = 21,
UNW_PPC64_R22 = 22,
UNW_PPC64_R23 = 23,
UNW_PPC64_R24 = 24,
UNW_PPC64_R25 = 25,
UNW_PPC64_R26 = 26,
UNW_PPC64_R27 = 27,
UNW_PPC64_R28 = 28,
UNW_PPC64_R29 = 29,
UNW_PPC64_R30 = 30,
UNW_PPC64_R31 = 31,
UNW_PPC64_F0 = 32,
UNW_PPC64_F1 = 33,
UNW_PPC64_F2 = 34,
UNW_PPC64_F3 = 35,
UNW_PPC64_F4 = 36,
UNW_PPC64_F5 = 37,
UNW_PPC64_F6 = 38,
UNW_PPC64_F7 = 39,
UNW_PPC64_F8 = 40,
UNW_PPC64_F9 = 41,
UNW_PPC64_F10 = 42,
UNW_PPC64_F11 = 43,
UNW_PPC64_F12 = 44,
UNW_PPC64_F13 = 45,
UNW_PPC64_F14 = 46,
UNW_PPC64_F15 = 47,
UNW_PPC64_F16 = 48,
UNW_PPC64_F17 = 49,
UNW_PPC64_F18 = 50,
UNW_PPC64_F19 = 51,
UNW_PPC64_F20 = 52,
UNW_PPC64_F21 = 53,
UNW_PPC64_F22 = 54,
UNW_PPC64_F23 = 55,
UNW_PPC64_F24 = 56,
UNW_PPC64_F25 = 57,
UNW_PPC64_F26 = 58,
UNW_PPC64_F27 = 59,
UNW_PPC64_F28 = 60,
UNW_PPC64_F29 = 61,
UNW_PPC64_F30 = 62,
UNW_PPC64_F31 = 63,
// 64: reserved
UNW_PPC64_LR = 65,
UNW_PPC64_CTR = 66,
// 67: reserved
UNW_PPC64_CR0 = 68,
UNW_PPC64_CR1 = 69,
UNW_PPC64_CR2 = 70,
UNW_PPC64_CR3 = 71,
UNW_PPC64_CR4 = 72,
UNW_PPC64_CR5 = 73,
UNW_PPC64_CR6 = 74,
UNW_PPC64_CR7 = 75,
UNW_PPC64_XER = 76,
UNW_PPC64_V0 = 77,
UNW_PPC64_V1 = 78,
UNW_PPC64_V2 = 79,
UNW_PPC64_V3 = 80,
UNW_PPC64_V4 = 81,
UNW_PPC64_V5 = 82,
UNW_PPC64_V6 = 83,
UNW_PPC64_V7 = 84,
UNW_PPC64_V8 = 85,
UNW_PPC64_V9 = 86,
UNW_PPC64_V10 = 87,
UNW_PPC64_V11 = 88,
UNW_PPC64_V12 = 89,
UNW_PPC64_V13 = 90,
UNW_PPC64_V14 = 91,
UNW_PPC64_V15 = 92,
UNW_PPC64_V16 = 93,
UNW_PPC64_V17 = 94,
UNW_PPC64_V18 = 95,
UNW_PPC64_V19 = 96,
UNW_PPC64_V20 = 97,
UNW_PPC64_V21 = 98,
UNW_PPC64_V22 = 99,
UNW_PPC64_V23 = 100,
UNW_PPC64_V24 = 101,
UNW_PPC64_V25 = 102,
UNW_PPC64_V26 = 103,
UNW_PPC64_V27 = 104,
UNW_PPC64_V28 = 105,
UNW_PPC64_V29 = 106,
UNW_PPC64_V30 = 107,
UNW_PPC64_V31 = 108,
// 109, 111-113: OpenPOWER ELF V2 ABI: reserved
// Borrowing VRSAVE number from PPC32.
UNW_PPC64_VRSAVE = 109,
UNW_PPC64_VSCR = 110,
UNW_PPC64_TFHAR = 114,
UNW_PPC64_TFIAR = 115,
UNW_PPC64_TEXASR = 116,
UNW_PPC64_VS0 = UNW_PPC64_F0,
UNW_PPC64_VS1 = UNW_PPC64_F1,
UNW_PPC64_VS2 = UNW_PPC64_F2,
UNW_PPC64_VS3 = UNW_PPC64_F3,
UNW_PPC64_VS4 = UNW_PPC64_F4,
UNW_PPC64_VS5 = UNW_PPC64_F5,
UNW_PPC64_VS6 = UNW_PPC64_F6,
UNW_PPC64_VS7 = UNW_PPC64_F7,
UNW_PPC64_VS8 = UNW_PPC64_F8,
UNW_PPC64_VS9 = UNW_PPC64_F9,
UNW_PPC64_VS10 = UNW_PPC64_F10,
UNW_PPC64_VS11 = UNW_PPC64_F11,
UNW_PPC64_VS12 = UNW_PPC64_F12,
UNW_PPC64_VS13 = UNW_PPC64_F13,
UNW_PPC64_VS14 = UNW_PPC64_F14,
UNW_PPC64_VS15 = UNW_PPC64_F15,
UNW_PPC64_VS16 = UNW_PPC64_F16,
UNW_PPC64_VS17 = UNW_PPC64_F17,
UNW_PPC64_VS18 = UNW_PPC64_F18,
UNW_PPC64_VS19 = UNW_PPC64_F19,
UNW_PPC64_VS20 = UNW_PPC64_F20,
UNW_PPC64_VS21 = UNW_PPC64_F21,
UNW_PPC64_VS22 = UNW_PPC64_F22,
UNW_PPC64_VS23 = UNW_PPC64_F23,
UNW_PPC64_VS24 = UNW_PPC64_F24,
UNW_PPC64_VS25 = UNW_PPC64_F25,
UNW_PPC64_VS26 = UNW_PPC64_F26,
UNW_PPC64_VS27 = UNW_PPC64_F27,
UNW_PPC64_VS28 = UNW_PPC64_F28,
UNW_PPC64_VS29 = UNW_PPC64_F29,
UNW_PPC64_VS30 = UNW_PPC64_F30,
UNW_PPC64_VS31 = UNW_PPC64_F31,
UNW_PPC64_VS32 = UNW_PPC64_V0,
UNW_PPC64_VS33 = UNW_PPC64_V1,
UNW_PPC64_VS34 = UNW_PPC64_V2,
UNW_PPC64_VS35 = UNW_PPC64_V3,
UNW_PPC64_VS36 = UNW_PPC64_V4,
UNW_PPC64_VS37 = UNW_PPC64_V5,
UNW_PPC64_VS38 = UNW_PPC64_V6,
UNW_PPC64_VS39 = UNW_PPC64_V7,
UNW_PPC64_VS40 = UNW_PPC64_V8,
UNW_PPC64_VS41 = UNW_PPC64_V9,
UNW_PPC64_VS42 = UNW_PPC64_V10,
UNW_PPC64_VS43 = UNW_PPC64_V11,
UNW_PPC64_VS44 = UNW_PPC64_V12,
UNW_PPC64_VS45 = UNW_PPC64_V13,
UNW_PPC64_VS46 = UNW_PPC64_V14,
UNW_PPC64_VS47 = UNW_PPC64_V15,
UNW_PPC64_VS48 = UNW_PPC64_V16,
UNW_PPC64_VS49 = UNW_PPC64_V17,
UNW_PPC64_VS50 = UNW_PPC64_V18,
UNW_PPC64_VS51 = UNW_PPC64_V19,
UNW_PPC64_VS52 = UNW_PPC64_V20,
UNW_PPC64_VS53 = UNW_PPC64_V21,
UNW_PPC64_VS54 = UNW_PPC64_V22,
UNW_PPC64_VS55 = UNW_PPC64_V23,
UNW_PPC64_VS56 = UNW_PPC64_V24,
UNW_PPC64_VS57 = UNW_PPC64_V25,
UNW_PPC64_VS58 = UNW_PPC64_V26,
UNW_PPC64_VS59 = UNW_PPC64_V27,
UNW_PPC64_VS60 = UNW_PPC64_V28,
UNW_PPC64_VS61 = UNW_PPC64_V29,
UNW_PPC64_VS62 = UNW_PPC64_V30,
UNW_PPC64_VS63 = UNW_PPC64_V31
};
// 64-bit ARM64 registers
enum {
UNW_ARM64_X0 = 0,
UNW_ARM64_X1 = 1,
UNW_ARM64_X2 = 2,
UNW_ARM64_X3 = 3,
UNW_ARM64_X4 = 4,
UNW_ARM64_X5 = 5,
UNW_ARM64_X6 = 6,
UNW_ARM64_X7 = 7,
UNW_ARM64_X8 = 8,
UNW_ARM64_X9 = 9,
UNW_ARM64_X10 = 10,
UNW_ARM64_X11 = 11,
UNW_ARM64_X12 = 12,
UNW_ARM64_X13 = 13,
UNW_ARM64_X14 = 14,
UNW_ARM64_X15 = 15,
UNW_ARM64_X16 = 16,
UNW_ARM64_X17 = 17,
UNW_ARM64_X18 = 18,
UNW_ARM64_X19 = 19,
UNW_ARM64_X20 = 20,
UNW_ARM64_X21 = 21,
UNW_ARM64_X22 = 22,
UNW_ARM64_X23 = 23,
UNW_ARM64_X24 = 24,
UNW_ARM64_X25 = 25,
UNW_ARM64_X26 = 26,
UNW_ARM64_X27 = 27,
UNW_ARM64_X28 = 28,
UNW_ARM64_X29 = 29,
UNW_ARM64_FP = 29,
UNW_ARM64_X30 = 30,
UNW_ARM64_LR = 30,
UNW_ARM64_X31 = 31,
UNW_ARM64_SP = 31,
// reserved block
UNW_ARM64_RA_SIGN_STATE = 34,
// reserved block
UNW_ARM64_D0 = 64,
UNW_ARM64_D1 = 65,
UNW_ARM64_D2 = 66,
UNW_ARM64_D3 = 67,
UNW_ARM64_D4 = 68,
UNW_ARM64_D5 = 69,
UNW_ARM64_D6 = 70,
UNW_ARM64_D7 = 71,
UNW_ARM64_D8 = 72,
UNW_ARM64_D9 = 73,
UNW_ARM64_D10 = 74,
UNW_ARM64_D11 = 75,
UNW_ARM64_D12 = 76,
UNW_ARM64_D13 = 77,
UNW_ARM64_D14 = 78,
UNW_ARM64_D15 = 79,
UNW_ARM64_D16 = 80,
UNW_ARM64_D17 = 81,
UNW_ARM64_D18 = 82,
UNW_ARM64_D19 = 83,
UNW_ARM64_D20 = 84,
UNW_ARM64_D21 = 85,
UNW_ARM64_D22 = 86,
UNW_ARM64_D23 = 87,
UNW_ARM64_D24 = 88,
UNW_ARM64_D25 = 89,
UNW_ARM64_D26 = 90,
UNW_ARM64_D27 = 91,
UNW_ARM64_D28 = 92,
UNW_ARM64_D29 = 93,
UNW_ARM64_D30 = 94,
UNW_ARM64_D31 = 95,
};
// 32-bit ARM registers. Numbers match DWARF for ARM spec #3.1 Table 1.
// Naming scheme uses recommendations given in Note 4 for VFP-v2 and VFP-v3.
// In this scheme, even though the 64-bit floating point registers D0-D31
// overlap physically with the 32-bit floating pointer registers S0-S31,
// they are given a non-overlapping range of register numbers.
//
// Commented out ranges are not preserved during unwinding.
enum {
UNW_ARM_R0 = 0,
UNW_ARM_R1 = 1,
UNW_ARM_R2 = 2,
UNW_ARM_R3 = 3,
UNW_ARM_R4 = 4,
UNW_ARM_R5 = 5,
UNW_ARM_R6 = 6,
UNW_ARM_R7 = 7,
UNW_ARM_R8 = 8,
UNW_ARM_R9 = 9,
UNW_ARM_R10 = 10,
UNW_ARM_R11 = 11,
UNW_ARM_R12 = 12,
UNW_ARM_SP = 13, // Logical alias for UNW_REG_SP
UNW_ARM_R13 = 13,
UNW_ARM_LR = 14,
UNW_ARM_R14 = 14,
UNW_ARM_IP = 15, // Logical alias for UNW_REG_IP
UNW_ARM_R15 = 15,
// 16-63 -- OBSOLETE. Used in VFP1 to represent both S0-S31 and D0-D31.
UNW_ARM_S0 = 64,
UNW_ARM_S1 = 65,
UNW_ARM_S2 = 66,
UNW_ARM_S3 = 67,
UNW_ARM_S4 = 68,
UNW_ARM_S5 = 69,
UNW_ARM_S6 = 70,
UNW_ARM_S7 = 71,
UNW_ARM_S8 = 72,
UNW_ARM_S9 = 73,
UNW_ARM_S10 = 74,
UNW_ARM_S11 = 75,
UNW_ARM_S12 = 76,
UNW_ARM_S13 = 77,
UNW_ARM_S14 = 78,
UNW_ARM_S15 = 79,
UNW_ARM_S16 = 80,
UNW_ARM_S17 = 81,
UNW_ARM_S18 = 82,
UNW_ARM_S19 = 83,
UNW_ARM_S20 = 84,
UNW_ARM_S21 = 85,
UNW_ARM_S22 = 86,
UNW_ARM_S23 = 87,
UNW_ARM_S24 = 88,
UNW_ARM_S25 = 89,
UNW_ARM_S26 = 90,
UNW_ARM_S27 = 91,
UNW_ARM_S28 = 92,
UNW_ARM_S29 = 93,
UNW_ARM_S30 = 94,
UNW_ARM_S31 = 95,
// 96-103 -- OBSOLETE. F0-F7. Used by the FPA system. Superseded by VFP.
// 104-111 -- wCGR0-wCGR7, ACC0-ACC7 (Intel wireless MMX)
UNW_ARM_WR0 = 112,
UNW_ARM_WR1 = 113,
UNW_ARM_WR2 = 114,
UNW_ARM_WR3 = 115,
UNW_ARM_WR4 = 116,
UNW_ARM_WR5 = 117,
UNW_ARM_WR6 = 118,
UNW_ARM_WR7 = 119,
UNW_ARM_WR8 = 120,
UNW_ARM_WR9 = 121,
UNW_ARM_WR10 = 122,
UNW_ARM_WR11 = 123,
UNW_ARM_WR12 = 124,
UNW_ARM_WR13 = 125,
UNW_ARM_WR14 = 126,
UNW_ARM_WR15 = 127,
// 128-133 -- SPSR, SPSR_{FIQ|IRQ|ABT|UND|SVC}
// 134-143 -- Reserved
// 144-150 -- R8_USR-R14_USR
// 151-157 -- R8_FIQ-R14_FIQ
// 158-159 -- R13_IRQ-R14_IRQ
// 160-161 -- R13_ABT-R14_ABT
// 162-163 -- R13_UND-R14_UND
// 164-165 -- R13_SVC-R14_SVC
// 166-191 -- Reserved
UNW_ARM_WC0 = 192,
UNW_ARM_WC1 = 193,
UNW_ARM_WC2 = 194,
UNW_ARM_WC3 = 195,
// 196-199 -- wC4-wC7 (Intel wireless MMX control)
// 200-255 -- Reserved
UNW_ARM_D0 = 256,
UNW_ARM_D1 = 257,
UNW_ARM_D2 = 258,
UNW_ARM_D3 = 259,
UNW_ARM_D4 = 260,
UNW_ARM_D5 = 261,
UNW_ARM_D6 = 262,
UNW_ARM_D7 = 263,
UNW_ARM_D8 = 264,
UNW_ARM_D9 = 265,
UNW_ARM_D10 = 266,
UNW_ARM_D11 = 267,
UNW_ARM_D12 = 268,
UNW_ARM_D13 = 269,
UNW_ARM_D14 = 270,
UNW_ARM_D15 = 271,
UNW_ARM_D16 = 272,
UNW_ARM_D17 = 273,
UNW_ARM_D18 = 274,
UNW_ARM_D19 = 275,
UNW_ARM_D20 = 276,
UNW_ARM_D21 = 277,
UNW_ARM_D22 = 278,
UNW_ARM_D23 = 279,
UNW_ARM_D24 = 280,
UNW_ARM_D25 = 281,
UNW_ARM_D26 = 282,
UNW_ARM_D27 = 283,
UNW_ARM_D28 = 284,
UNW_ARM_D29 = 285,
UNW_ARM_D30 = 286,
UNW_ARM_D31 = 287,
// 288-319 -- Reserved for VFP/Neon
// 320-8191 -- Reserved
// 8192-16383 -- Unspecified vendor co-processor register.
};
// OpenRISC1000 register numbers
enum {
UNW_OR1K_R0 = 0,
UNW_OR1K_R1 = 1,
UNW_OR1K_R2 = 2,
UNW_OR1K_R3 = 3,
UNW_OR1K_R4 = 4,
UNW_OR1K_R5 = 5,
UNW_OR1K_R6 = 6,
UNW_OR1K_R7 = 7,
UNW_OR1K_R8 = 8,
UNW_OR1K_R9 = 9,
UNW_OR1K_R10 = 10,
UNW_OR1K_R11 = 11,
UNW_OR1K_R12 = 12,
UNW_OR1K_R13 = 13,
UNW_OR1K_R14 = 14,
UNW_OR1K_R15 = 15,
UNW_OR1K_R16 = 16,
UNW_OR1K_R17 = 17,
UNW_OR1K_R18 = 18,
UNW_OR1K_R19 = 19,
UNW_OR1K_R20 = 20,
UNW_OR1K_R21 = 21,
UNW_OR1K_R22 = 22,
UNW_OR1K_R23 = 23,
UNW_OR1K_R24 = 24,
UNW_OR1K_R25 = 25,
UNW_OR1K_R26 = 26,
UNW_OR1K_R27 = 27,
UNW_OR1K_R28 = 28,
UNW_OR1K_R29 = 29,
UNW_OR1K_R30 = 30,
UNW_OR1K_R31 = 31,
UNW_OR1K_EPCR = 32,
};
// MIPS registers
enum {
UNW_MIPS_R0 = 0,
UNW_MIPS_R1 = 1,
UNW_MIPS_R2 = 2,
UNW_MIPS_R3 = 3,
UNW_MIPS_R4 = 4,
UNW_MIPS_R5 = 5,
UNW_MIPS_R6 = 6,
UNW_MIPS_R7 = 7,
UNW_MIPS_R8 = 8,
UNW_MIPS_R9 = 9,
UNW_MIPS_R10 = 10,
UNW_MIPS_R11 = 11,
UNW_MIPS_R12 = 12,
UNW_MIPS_R13 = 13,
UNW_MIPS_R14 = 14,
UNW_MIPS_R15 = 15,
UNW_MIPS_R16 = 16,
UNW_MIPS_R17 = 17,
UNW_MIPS_R18 = 18,
UNW_MIPS_R19 = 19,
UNW_MIPS_R20 = 20,
UNW_MIPS_R21 = 21,
UNW_MIPS_R22 = 22,
UNW_MIPS_R23 = 23,
UNW_MIPS_R24 = 24,
UNW_MIPS_R25 = 25,
UNW_MIPS_R26 = 26,
UNW_MIPS_R27 = 27,
UNW_MIPS_R28 = 28,
UNW_MIPS_R29 = 29,
UNW_MIPS_R30 = 30,
UNW_MIPS_R31 = 31,
UNW_MIPS_F0 = 32,
UNW_MIPS_F1 = 33,
UNW_MIPS_F2 = 34,
UNW_MIPS_F3 = 35,
UNW_MIPS_F4 = 36,
UNW_MIPS_F5 = 37,
UNW_MIPS_F6 = 38,
UNW_MIPS_F7 = 39,
UNW_MIPS_F8 = 40,
UNW_MIPS_F9 = 41,
UNW_MIPS_F10 = 42,
UNW_MIPS_F11 = 43,
UNW_MIPS_F12 = 44,
UNW_MIPS_F13 = 45,
UNW_MIPS_F14 = 46,
UNW_MIPS_F15 = 47,
UNW_MIPS_F16 = 48,
UNW_MIPS_F17 = 49,
UNW_MIPS_F18 = 50,
UNW_MIPS_F19 = 51,
UNW_MIPS_F20 = 52,
UNW_MIPS_F21 = 53,
UNW_MIPS_F22 = 54,
UNW_MIPS_F23 = 55,
UNW_MIPS_F24 = 56,
UNW_MIPS_F25 = 57,
UNW_MIPS_F26 = 58,
UNW_MIPS_F27 = 59,
UNW_MIPS_F28 = 60,
UNW_MIPS_F29 = 61,
UNW_MIPS_F30 = 62,
UNW_MIPS_F31 = 63,
UNW_MIPS_HI = 64,
UNW_MIPS_LO = 65,
};
// SPARC registers
enum {
UNW_SPARC_G0 = 0,
UNW_SPARC_G1 = 1,
UNW_SPARC_G2 = 2,
UNW_SPARC_G3 = 3,
UNW_SPARC_G4 = 4,
UNW_SPARC_G5 = 5,
UNW_SPARC_G6 = 6,
UNW_SPARC_G7 = 7,
UNW_SPARC_O0 = 8,
UNW_SPARC_O1 = 9,
UNW_SPARC_O2 = 10,
UNW_SPARC_O3 = 11,
UNW_SPARC_O4 = 12,
UNW_SPARC_O5 = 13,
UNW_SPARC_O6 = 14,
UNW_SPARC_O7 = 15,
UNW_SPARC_L0 = 16,
UNW_SPARC_L1 = 17,
UNW_SPARC_L2 = 18,
UNW_SPARC_L3 = 19,
UNW_SPARC_L4 = 20,
UNW_SPARC_L5 = 21,
UNW_SPARC_L6 = 22,
UNW_SPARC_L7 = 23,
UNW_SPARC_I0 = 24,
UNW_SPARC_I1 = 25,
UNW_SPARC_I2 = 26,
UNW_SPARC_I3 = 27,
UNW_SPARC_I4 = 28,
UNW_SPARC_I5 = 29,
UNW_SPARC_I6 = 30,
UNW_SPARC_I7 = 31,
};
#endif

View File

@ -0,0 +1,477 @@
//===------------------ mach-o/compact_unwind_encoding.h ------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Darwin's alternative to DWARF based unwind encodings.
//
//===----------------------------------------------------------------------===//
#ifndef __COMPACT_UNWIND_ENCODING__
#define __COMPACT_UNWIND_ENCODING__
#include <stdint.h>
//
// Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section
// of object files. Or compilers can emit compact unwind information in
// the __LD,__compact_unwind section.
//
// When the linker creates a final linked image, it will create a
// __TEXT,__unwind_info section. This section is a small and fast way for the
// runtime to access unwind info for any given function. If the compiler
// emitted compact unwind info for the function, that compact unwind info will
// be encoded in the __TEXT,__unwind_info section. If the compiler emitted
// DWARF unwind info, the __TEXT,__unwind_info section will contain the offset
// of the FDE in the __TEXT,__eh_frame section in the final linked image.
//
// Note: Previously, the linker would transform some DWARF unwind infos into
// compact unwind info. But that is fragile and no longer done.
//
// The compact unwind endoding is a 32-bit value which encoded in an
// architecture specific way, which registers to restore from where, and how
// to unwind out of the function.
//
typedef uint32_t compact_unwind_encoding_t;
// architecture independent bits
enum {
UNWIND_IS_NOT_FUNCTION_START = 0x80000000,
UNWIND_HAS_LSDA = 0x40000000,
UNWIND_PERSONALITY_MASK = 0x30000000,
};
//
// x86
//
// 1-bit: start
// 1-bit: has lsda
// 2-bit: personality index
//
// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF
// ebp based:
// 15-bits (5*3-bits per reg) register permutation
// 8-bits for stack offset
// frameless:
// 8-bits stack size
// 3-bits stack adjust
// 3-bits register count
// 10-bits register permutation
//
enum {
UNWIND_X86_MODE_MASK = 0x0F000000,
UNWIND_X86_MODE_EBP_FRAME = 0x01000000,
UNWIND_X86_MODE_STACK_IMMD = 0x02000000,
UNWIND_X86_MODE_STACK_IND = 0x03000000,
UNWIND_X86_MODE_DWARF = 0x04000000,
UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF,
UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000,
UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000,
UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000,
UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF,
};
enum {
UNWIND_X86_REG_NONE = 0,
UNWIND_X86_REG_EBX = 1,
UNWIND_X86_REG_ECX = 2,
UNWIND_X86_REG_EDX = 3,
UNWIND_X86_REG_EDI = 4,
UNWIND_X86_REG_ESI = 5,
UNWIND_X86_REG_EBP = 6,
};
//
// For x86 there are four modes for the compact unwind encoding:
// UNWIND_X86_MODE_EBP_FRAME:
// EBP based frame where EBP is push on stack immediately after return address,
// then ESP is moved to EBP. Thus, to unwind ESP is restored with the current
// EPB value, then EBP is restored by popping off the stack, and the return
// is done by popping the stack once more into the pc.
// All non-volatile registers that need to be restored must have been saved
// in a small range in the stack that starts EBP-4 to EBP-1020. The offset/4
// is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved
// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
// Each entry contains which register to restore.
// UNWIND_X86_MODE_STACK_IMMD:
// A "frameless" (EBP not used as frame pointer) function with a small
// constant stack size. To return, a constant (encoded in the compact
// unwind encoding) is added to the ESP. Then the return is done by
// popping the stack into the pc.
// All non-volatile registers that need to be restored must have been saved
// on the stack immediately after the return address. The stack_size/4 is
// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
// saved and their order.
// UNWIND_X86_MODE_STACK_IND:
// A "frameless" (EBP not used as frame pointer) function large constant
// stack size. This case is like the previous, except the stack size is too
// large to encode in the compact unwind encoding. Instead it requires that
// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact
// encoding contains the offset to the nnnnnnnn value in the function in
// UNWIND_X86_FRAMELESS_STACK_SIZE.
// UNWIND_X86_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
// linker in final linked images which have only DWARF unwind info for a
// function.
//
// The permutation encoding is a Lehmer code sequence encoded into a
// single variable-base number so we can encode the ordering of up to
// six registers in a 10-bit space.
//
// The following is the algorithm used to create the permutation encoding used
// with frameless stacks. It is passed the number of registers to be saved and
// an array of the register numbers saved.
//
//uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6])
//{
// uint32_t renumregs[6];
// for (int i=6-registerCount; i < 6; ++i) {
// int countless = 0;
// for (int j=6-registerCount; j < i; ++j) {
// if ( registers[j] < registers[i] )
// ++countless;
// }
// renumregs[i] = registers[i] - countless -1;
// }
// uint32_t permutationEncoding = 0;
// switch ( registerCount ) {
// case 6:
// permutationEncoding |= (120*renumregs[0] + 24*renumregs[1]
// + 6*renumregs[2] + 2*renumregs[3]
// + renumregs[4]);
// break;
// case 5:
// permutationEncoding |= (120*renumregs[1] + 24*renumregs[2]
// + 6*renumregs[3] + 2*renumregs[4]
// + renumregs[5]);
// break;
// case 4:
// permutationEncoding |= (60*renumregs[2] + 12*renumregs[3]
// + 3*renumregs[4] + renumregs[5]);
// break;
// case 3:
// permutationEncoding |= (20*renumregs[3] + 4*renumregs[4]
// + renumregs[5]);
// break;
// case 2:
// permutationEncoding |= (5*renumregs[4] + renumregs[5]);
// break;
// case 1:
// permutationEncoding |= (renumregs[5]);
// break;
// }
// return permutationEncoding;
//}
//
//
// x86_64
//
// 1-bit: start
// 1-bit: has lsda
// 2-bit: personality index
//
// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF
// rbp based:
// 15-bits (5*3-bits per reg) register permutation
// 8-bits for stack offset
// frameless:
// 8-bits stack size
// 3-bits stack adjust
// 3-bits register count
// 10-bits register permutation
//
enum {
UNWIND_X86_64_MODE_MASK = 0x0F000000,
UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
UNWIND_X86_64_MODE_DWARF = 0x04000000,
UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF,
UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000,
UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000,
UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000,
UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
};
enum {
UNWIND_X86_64_REG_NONE = 0,
UNWIND_X86_64_REG_RBX = 1,
UNWIND_X86_64_REG_R12 = 2,
UNWIND_X86_64_REG_R13 = 3,
UNWIND_X86_64_REG_R14 = 4,
UNWIND_X86_64_REG_R15 = 5,
UNWIND_X86_64_REG_RBP = 6,
};
//
// For x86_64 there are four modes for the compact unwind encoding:
// UNWIND_X86_64_MODE_RBP_FRAME:
// RBP based frame where RBP is push on stack immediately after return address,
// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
// EPB value, then RBP is restored by popping off the stack, and the return
// is done by popping the stack once more into the pc.
// All non-volatile registers that need to be restored must have been saved
// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8
// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved
// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
// Each entry contains which register to restore.
// UNWIND_X86_64_MODE_STACK_IMMD:
// A "frameless" (RBP not used as frame pointer) function with a small
// constant stack size. To return, a constant (encoded in the compact
// unwind encoding) is added to the RSP. Then the return is done by
// popping the stack into the pc.
// All non-volatile registers that need to be restored must have been saved
// on the stack immediately after the return address. The stack_size/8 is
// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
// saved and their order.
// UNWIND_X86_64_MODE_STACK_IND:
// A "frameless" (RBP not used as frame pointer) function large constant
// stack size. This case is like the previous, except the stack size is too
// large to encode in the compact unwind encoding. Instead it requires that
// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
// encoding contains the offset to the nnnnnnnn value in the function in
// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
// UNWIND_X86_64_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
// linker in final linked images which have only DWARF unwind info for a
// function.
//
// ARM64
//
// 1-bit: start
// 1-bit: has lsda
// 2-bit: personality index
//
// 4-bits: 4=frame-based, 3=DWARF, 2=frameless
// frameless:
// 12-bits of stack size
// frame-based:
// 4-bits D reg pairs saved
// 5-bits X reg pairs saved
// DWARF:
// 24-bits offset of DWARF FDE in __eh_frame section
//
enum {
UNWIND_ARM64_MODE_MASK = 0x0F000000,
UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
UNWIND_ARM64_MODE_DWARF = 0x03000000,
UNWIND_ARM64_MODE_FRAME = 0x04000000,
UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800,
UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000,
UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
};
// For arm64 there are three modes for the compact unwind encoding:
// UNWIND_ARM64_MODE_FRAME:
// This is a standard arm64 prolog where FP/LR are immediately pushed on the
// stack, then SP is copied to FP. If there are any non-volatile registers
// saved, then are copied into the stack frame in pairs in a contiguous
// range right below the saved FP/LR pair. Any subset of the five X pairs
// and four D pairs can be saved, but the memory layout must be in register
// number order.
// UNWIND_ARM64_MODE_FRAMELESS:
// A "frameless" leaf function, where FP/LR are not saved. The return address
// remains in LR throughout the function. If any non-volatile registers
// are saved, they must be pushed onto the stack before any stack space is
// allocated for local variables. The stack sized (including any saved
// non-volatile registers) divided by 16 is encoded in the bits
// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
// UNWIND_ARM64_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
// linker in final linked images which have only DWARF unwind info for a
// function.
//
////////////////////////////////////////////////////////////////////////////////
//
// Relocatable Object Files: __LD,__compact_unwind
//
////////////////////////////////////////////////////////////////////////////////
//
// A compiler can generated compact unwind information for a function by adding
// a "row" to the __LD,__compact_unwind section. This section has the
// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
// It is removed by the new linker, so never ends up in final executables.
// This section is a table, initially with one row per function (that needs
// unwind info). The table columns and some conceptual entries are:
//
// range-start pointer to start of function/range
// range-length
// compact-unwind-encoding 32-bit encoding
// personality-function or zero if no personality function
// lsda or zero if no LSDA data
//
// The length and encoding fields are 32-bits. The other are all pointer sized.
//
// In x86_64 assembly, these entry would look like:
//
// .section __LD,__compact_unwind,regular,debug
//
// #compact unwind for _foo
// .quad _foo
// .set L1,LfooEnd-_foo
// .long L1
// .long 0x01010001
// .quad 0
// .quad 0
//
// #compact unwind for _bar
// .quad _bar
// .set L2,LbarEnd-_bar
// .long L2
// .long 0x01020011
// .quad __gxx_personality
// .quad except_tab1
//
//
// Notes: There is no need for any labels in the the __compact_unwind section.
// The use of the .set directive is to force the evaluation of the
// range-length at assembly time, instead of generating relocations.
//
// To support future compiler optimizations where which non-volatile registers
// are saved changes within a function (e.g. delay saving non-volatiles until
// necessary), there can by multiple lines in the __compact_unwind table for one
// function, each with a different (non-overlapping) range and each with
// different compact unwind encodings that correspond to the non-volatiles
// saved at that range of the function.
//
// If a particular function is so wacky that there is no compact unwind way
// to encode it, then the compiler can emit traditional DWARF unwind info.
// The runtime will use which ever is available.
//
// Runtime support for compact unwind encodings are only available on 10.6
// and later. So, the compiler should not generate it when targeting pre-10.6.
////////////////////////////////////////////////////////////////////////////////
//
// Final Linked Images: __TEXT,__unwind_info
//
////////////////////////////////////////////////////////////////////////////////
//
// The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
// The header of the section contains a coarse index that maps function address
// to the page (4096 byte block) containing the unwind info for that function.
//
#define UNWIND_SECTION_VERSION 1
struct unwind_info_section_header
{
uint32_t version; // UNWIND_SECTION_VERSION
uint32_t commonEncodingsArraySectionOffset;
uint32_t commonEncodingsArrayCount;
uint32_t personalityArraySectionOffset;
uint32_t personalityArrayCount;
uint32_t indexSectionOffset;
uint32_t indexCount;
// compact_unwind_encoding_t[]
// uint32_t personalities[]
// unwind_info_section_header_index_entry[]
// unwind_info_section_header_lsda_index_entry[]
};
struct unwind_info_section_header_index_entry
{
uint32_t functionOffset;
uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page
uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range
};
struct unwind_info_section_header_lsda_index_entry
{
uint32_t functionOffset;
uint32_t lsdaOffset;
};
//
// There are two kinds of second level index pages: regular and compressed.
// A compressed page can hold up to 1021 entries, but it cannot be used
// if too many different encoding types are used. The regular page holds
// 511 entries.
//
struct unwind_info_regular_second_level_entry
{
uint32_t functionOffset;
compact_unwind_encoding_t encoding;
};
#define UNWIND_SECOND_LEVEL_REGULAR 2
struct unwind_info_regular_second_level_page_header
{
uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR
uint16_t entryPageOffset;
uint16_t entryCount;
// entry array
};
#define UNWIND_SECOND_LEVEL_COMPRESSED 3
struct unwind_info_compressed_second_level_page_header
{
uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED
uint16_t entryPageOffset;
uint16_t entryCount;
uint16_t encodingsPageOffset;
uint16_t encodingsCount;
// 32-bit entry array
// encodings array
};
#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF)
#endif

View File

@ -0,0 +1,400 @@
//===------------------------------- unwind.h -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// C++ ABI Level 1 ABI documented at:
// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
//
//===----------------------------------------------------------------------===//
#ifndef __UNWIND_H__
#define __UNWIND_H__
#include <__libunwind_config.h>
#include <stdint.h>
#include <stddef.h>
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) && defined(_WIN32)
#include <windows.h>
#include <ntverp.h>
#endif
#if defined(__APPLE__)
#define LIBUNWIND_UNAVAIL __attribute__ (( unavailable ))
#else
#define LIBUNWIND_UNAVAIL
#endif
typedef enum {
_URC_NO_REASON = 0,
_URC_OK = 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,
#if defined(_LIBUNWIND_ARM_EHABI)
_URC_FAILURE = 9
#endif
} _Unwind_Reason_Code;
typedef enum {
_UA_SEARCH_PHASE = 1,
_UA_CLEANUP_PHASE = 2,
_UA_HANDLER_FRAME = 4,
_UA_FORCE_UNWIND = 8,
_UA_END_OF_STACK = 16 // gcc extension to C++ ABI
} _Unwind_Action;
typedef struct _Unwind_Context _Unwind_Context; // opaque
#if defined(_LIBUNWIND_ARM_EHABI)
typedef uint32_t _Unwind_State;
static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0;
static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1;
static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2;
static const _Unwind_State _US_ACTION_MASK = 3;
/* Undocumented flag for force unwinding. */
static const _Unwind_State _US_FORCE_UNWIND = 8;
typedef uint32_t _Unwind_EHT_Header;
struct _Unwind_Control_Block;
typedef struct _Unwind_Control_Block _Unwind_Control_Block;
typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */
struct _Unwind_Control_Block {
uint64_t exception_class;
void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*);
/* Unwinder cache, private fields for the unwinder's use */
struct {
uint32_t reserved1; /* init reserved1 to 0, then don't touch */
uint32_t reserved2;
uint32_t reserved3;
uint32_t reserved4;
uint32_t reserved5;
} unwinder_cache;
/* Propagation barrier cache (valid after phase 1): */
struct {
uint32_t sp;
uint32_t bitpattern[5];
} barrier_cache;
/* Cleanup cache (preserved over cleanup): */
struct {
uint32_t bitpattern[4];
} cleanup_cache;
/* Pr cache (for pr's benefit): */
struct {
uint32_t fnstart; /* function start address */
_Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */
uint32_t additional;
uint32_t reserved1;
} pr_cache;
long long int :0; /* Enforce the 8-byte alignment */
} __attribute__((__aligned__(8)));
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
(_Unwind_State state,
_Unwind_Exception* exceptionObject,
struct _Unwind_Context* context);
typedef _Unwind_Reason_Code (*__personality_routine)
(_Unwind_State state,
_Unwind_Exception* exceptionObject,
struct _Unwind_Context* context);
#else
struct _Unwind_Context; // opaque
struct _Unwind_Exception; // forward declaration
typedef struct _Unwind_Exception _Unwind_Exception;
struct _Unwind_Exception {
uint64_t exception_class;
void (*exception_cleanup)(_Unwind_Reason_Code reason,
_Unwind_Exception *exc);
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
uintptr_t private_[6];
#else
uintptr_t private_1; // non-zero means forced unwind
uintptr_t private_2; // holds sp that phase1 found for phase2 to use
#endif
#if __SIZEOF_POINTER__ == 4
// The implementation of _Unwind_Exception uses an attribute mode on the
// above fields which has the side effect of causing this whole struct to
// round up to 32 bytes in size (48 with SEH). To be more explicit, we add
// pad fields added for binary compatibility.
uint32_t reserved[3];
#endif
// The Itanium ABI requires that _Unwind_Exception objects are "double-word
// aligned". GCC has interpreted this to mean "use the maximum useful
// alignment for the target"; so do we.
} __attribute__((__aligned__));
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
(int version,
_Unwind_Action actions,
uint64_t exceptionClass,
_Unwind_Exception* exceptionObject,
struct _Unwind_Context* context,
void* stop_parameter );
typedef _Unwind_Reason_Code (*__personality_routine)
(int version,
_Unwind_Action actions,
uint64_t exceptionClass,
_Unwind_Exception* exceptionObject,
struct _Unwind_Context* context);
#endif
#ifdef __cplusplus
extern "C" {
#endif
//
// The following are the base functions documented by the C++ ABI
//
#ifdef __USING_SJLJ_EXCEPTIONS__
extern _Unwind_Reason_Code
_Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object);
extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object);
#else
extern _Unwind_Reason_Code
_Unwind_RaiseException(_Unwind_Exception *exception_object);
extern void _Unwind_Resume(_Unwind_Exception *exception_object);
#endif
extern void _Unwind_DeleteException(_Unwind_Exception *exception_object);
#if defined(_LIBUNWIND_ARM_EHABI)
typedef enum {
_UVRSC_CORE = 0, /* integer register */
_UVRSC_VFP = 1, /* vfp */
_UVRSC_WMMXD = 3, /* Intel WMMX data register */
_UVRSC_WMMXC = 4 /* Intel WMMX control register */
} _Unwind_VRS_RegClass;
typedef enum {
_UVRSD_UINT32 = 0,
_UVRSD_VFPX = 1,
_UVRSD_UINT64 = 3,
_UVRSD_FLOAT = 4,
_UVRSD_DOUBLE = 5
} _Unwind_VRS_DataRepresentation;
typedef enum {
_UVRSR_OK = 0,
_UVRSR_NOT_IMPLEMENTED = 1,
_UVRSR_FAILED = 2
} _Unwind_VRS_Result;
extern void _Unwind_Complete(_Unwind_Exception* exception_object);
extern _Unwind_VRS_Result
_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
uint32_t regno, _Unwind_VRS_DataRepresentation representation,
void *valuep);
extern _Unwind_VRS_Result
_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
uint32_t regno, _Unwind_VRS_DataRepresentation representation,
void *valuep);
extern _Unwind_VRS_Result
_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
uint32_t discriminator,
_Unwind_VRS_DataRepresentation representation);
#endif
#if !defined(_LIBUNWIND_ARM_EHABI)
extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value);
extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
#else // defined(_LIBUNWIND_ARM_EHABI)
#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern
#else
#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__
#endif
// These are de facto helper functions for ARM, which delegate the function
// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI
// specification, thus these function MUST be inlined. Please don't replace
// these with the "extern" function declaration; otherwise, the program
// including this <unwind.h> header won't be ABI compatible and will result in
// link error when we are linking the program with libgcc.
_LIBUNWIND_EXPORT_UNWIND_LEVEL1
uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
uintptr_t value = 0;
_Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
return value;
}
_LIBUNWIND_EXPORT_UNWIND_LEVEL1
void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t value) {
_Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
}
_LIBUNWIND_EXPORT_UNWIND_LEVEL1
uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
// remove the thumb-bit before returning
return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1);
}
_LIBUNWIND_EXPORT_UNWIND_LEVEL1
void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) {
uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
_Unwind_SetGR(context, 15, value | thumb_bit);
}
#endif // defined(_LIBUNWIND_ARM_EHABI)
extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context);
extern uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context);
#ifdef __USING_SJLJ_EXCEPTIONS__
extern _Unwind_Reason_Code
_Unwind_SjLj_ForcedUnwind(_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter);
#else
extern _Unwind_Reason_Code
_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter);
#endif
#ifdef __USING_SJLJ_EXCEPTIONS__
typedef struct _Unwind_FunctionContext *_Unwind_FunctionContext_t;
extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc);
extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc);
#endif
//
// The following are semi-suppoted extensions to the C++ ABI
//
//
// called by __cxa_rethrow().
//
#ifdef __USING_SJLJ_EXCEPTIONS__
extern _Unwind_Reason_Code
_Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *exception_object);
#else
extern _Unwind_Reason_Code
_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object);
#endif
// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the
// _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack
// or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON.
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
void *);
extern _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void *);
// _Unwind_GetCFA is a gcc extension that can be called from within a
// personality handler to get the CFA (stack pointer before call) of
// current frame.
extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context *);
// _Unwind_GetIPInfo is a gcc extension that can be called from within a
// personality handler. Similar to _Unwind_GetIP() but also returns in
// *ipBefore a non-zero value if the instruction pointer is at or before the
// instruction causing the unwind. Normally, in a function call, the IP returned
// is the return address which is after the call instruction and may be past the
// end of the function containing the call instruction.
extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
int *ipBefore);
// __register_frame() is used with dynamically generated code to register the
// FDE for a generated (JIT) code. The FDE must use pc-rel addressing to point
// to its function and optional LSDA.
// __register_frame() has existed in all versions of Mac OS X, but in 10.4 and
// 10.5 it was buggy and did not actually register the FDE with the unwinder.
// In 10.6 and later it does register properly.
extern void __register_frame(const void *fde);
extern void __deregister_frame(const void *fde);
// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has
// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind
// info" which the runtime uses in preference to DWARF unwind info. This
// function will only work if the target function has an FDE but no compact
// unwind info.
struct dwarf_eh_bases {
uintptr_t tbase;
uintptr_t dbase;
uintptr_t func;
};
extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *);
// This function attempts to find the start (address of first instruction) of
// a function given an address inside the function. It only works if the
// function has an FDE (DWARF unwind info).
// This function is unimplemented on Mac OS X 10.6 and later. Instead, use
// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result.
extern void *_Unwind_FindEnclosingFunction(void *pc);
// Mac OS X does not support text-rel and data-rel addressing so these functions
// are unimplemented
extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context)
LIBUNWIND_UNAVAIL;
extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context)
LIBUNWIND_UNAVAIL;
// Mac OS X 10.4 and 10.5 had implementations of these functions in
// libgcc_s.dylib, but they never worked.
/// These functions are no longer available on Mac OS X.
extern void __register_frame_info_bases(const void *fde, void *ob, void *tb,
void *db) LIBUNWIND_UNAVAIL;
extern void __register_frame_info(const void *fde, void *ob)
LIBUNWIND_UNAVAIL;
extern void __register_frame_info_table_bases(const void *fde, void *ob,
void *tb, void *db)
LIBUNWIND_UNAVAIL;
extern void __register_frame_info_table(const void *fde, void *ob)
LIBUNWIND_UNAVAIL;
extern void __register_frame_table(const void *fde)
LIBUNWIND_UNAVAIL;
extern void *__deregister_frame_info(const void *fde)
LIBUNWIND_UNAVAIL;
extern void *__deregister_frame_info_bases(const void *fde)
LIBUNWIND_UNAVAIL;
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
#ifndef _WIN32
typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
typedef struct _CONTEXT CONTEXT;
typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT;
#elif !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT;
#endif
// This is the common wrapper for GCC-style personality functions with SEH.
extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc,
void *frame,
CONTEXT *ctx,
DISPATCHER_CONTEXT *disp,
__personality_routine pers);
#endif
#ifdef __cplusplus
}
#endif
#endif // __UNWIND_H__

View File

@ -0,0 +1,633 @@
//===------------------------- AddressSpace.hpp ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Abstracts accessing local vs remote address spaces.
//
//===----------------------------------------------------------------------===//
#ifndef __ADDRESSSPACE_HPP__
#define __ADDRESSSPACE_HPP__
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _LIBUNWIND_USE_DLADDR
#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
#define _LIBUNWIND_USE_DLADDR 1
#else
#define _LIBUNWIND_USE_DLADDR 0
#endif
#endif
#if _LIBUNWIND_USE_DLADDR
#include <dlfcn.h>
#if defined(__unix__) && defined(__ELF__) && defined(_LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
#pragma comment(lib, "dl")
#endif
#endif
#if defined(_LIBUNWIND_ARM_EHABI)
struct EHABIIndexEntry {
uint32_t functionOffset;
uint32_t data;
};
#endif
#ifdef __APPLE__
#include <mach-o/getsect.h>
namespace libunwind {
bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
}
#endif
#include "libunwind.h"
#include "config.h"
#include "dwarf2.h"
#include "EHHeaderParser.hpp"
#include "Registers.hpp"
#ifdef __APPLE__
struct dyld_unwind_sections
{
const struct mach_header* mh;
const void* dwarf_section;
uintptr_t dwarf_section_length;
const void* compact_unwind_section;
uintptr_t compact_unwind_section_length;
};
#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
&& (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
// In 10.7.0 or later, libSystem.dylib implements this function.
extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
#else
// In 10.6.x and earlier, we need to implement this functionality. Note
// that this requires a newer version of libmacho (from cctools) than is
// present in libSystem on 10.6.x (for getsectiondata).
static inline bool _dyld_find_unwind_sections(void* addr,
dyld_unwind_sections* info) {
// Find mach-o image containing address.
Dl_info dlinfo;
if (!dladdr(addr, &dlinfo))
return false;
#if __LP64__
const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
#else
const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
#endif
// Initialize the return struct
info->mh = (const struct mach_header *)mh;
info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
if (!info->dwarf_section) {
info->dwarf_section_length = 0;
}
if (!info->compact_unwind_section) {
info->compact_unwind_section_length = 0;
}
return true;
}
#endif
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
// When statically linked on bare-metal, the symbols for the EH table are looked
// up without going through the dynamic loader.
// The following linker script may be used to produce the necessary sections and symbols.
// Unless the --eh-frame-hdr linker option is provided, the section is not generated
// and does not take space in the output file.
//
// .eh_frame :
// {
// __eh_frame_start = .;
// KEEP(*(.eh_frame))
// __eh_frame_end = .;
// }
//
// .eh_frame_hdr :
// {
// KEEP(*(.eh_frame_hdr))
// }
//
// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
extern char __eh_frame_start;
extern char __eh_frame_end;
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
extern char __eh_frame_hdr_start;
extern char __eh_frame_hdr_end;
#endif
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
// When statically linked on bare-metal, the symbols for the EH table are looked
// up without going through the dynamic loader.
extern char __exidx_start;
extern char __exidx_end;
#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
// ELF-based systems may use dl_iterate_phdr() to access sections
// containing unwinding information. The ElfW() macro for pointer-size
// independent ELF header traversal is not provided by <link.h> on some
// systems (e.g., FreeBSD). On these systems the data structures are
// just called Elf_XXX. Define ElfW() locally.
#ifndef _WIN32
#include <link.h>
#else
#include <windows.h>
#include <psapi.h>
#endif
#if !defined(ElfW)
#define ElfW(type) Elf_##type
#endif
#endif
namespace libunwind {
/// Used by findUnwindSections() to return info about needed sections.
struct UnwindInfoSections {
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
// No dso_base for SEH or ARM EHABI.
uintptr_t dso_base;
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
uintptr_t dwarf_section;
uintptr_t dwarf_section_length;
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
uintptr_t dwarf_index_section;
uintptr_t dwarf_index_section_length;
#endif
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
uintptr_t compact_unwind_section;
uintptr_t compact_unwind_section_length;
#endif
#if defined(_LIBUNWIND_ARM_EHABI)
uintptr_t arm_section;
uintptr_t arm_section_length;
#endif
};
/// LocalAddressSpace is used as a template parameter to UnwindCursor when
/// unwinding a thread in the same process. The wrappers compile away,
/// making local unwinds fast.
class _LIBUNWIND_HIDDEN LocalAddressSpace {
public:
typedef uintptr_t pint_t;
typedef intptr_t sint_t;
uint8_t get8(pint_t addr) {
uint8_t val;
memcpy(&val, (void *)addr, sizeof(val));
return val;
}
uint16_t get16(pint_t addr) {
uint16_t val;
memcpy(&val, (void *)addr, sizeof(val));
return val;
}
uint32_t get32(pint_t addr) {
uint32_t val;
memcpy(&val, (void *)addr, sizeof(val));
return val;
}
uint64_t get64(pint_t addr) {
uint64_t val;
memcpy(&val, (void *)addr, sizeof(val));
return val;
}
double getDouble(pint_t addr) {
double val;
memcpy(&val, (void *)addr, sizeof(val));
return val;
}
v128 getVector(pint_t addr) {
v128 val;
memcpy(&val, (void *)addr, sizeof(val));
return val;
}
uintptr_t getP(pint_t addr);
uint64_t getRegister(pint_t addr);
static uint64_t getULEB128(pint_t &addr, pint_t end);
static int64_t getSLEB128(pint_t &addr, pint_t end);
pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
pint_t datarelBase = 0);
bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
unw_word_t *offset);
bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
bool findOtherFDE(pint_t targetAddr, pint_t &fde);
static LocalAddressSpace sThisAddressSpace;
};
inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
#if __SIZEOF_POINTER__ == 8
return get64(addr);
#else
return get32(addr);
#endif
}
inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
return get64(addr);
#else
return get32(addr);
#endif
}
/// Read a ULEB128 into a 64-bit word.
inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
const uint8_t *p = (uint8_t *)addr;
const uint8_t *pend = (uint8_t *)end;
uint64_t result = 0;
int bit = 0;
do {
uint64_t b;
if (p == pend)
_LIBUNWIND_ABORT("truncated uleb128 expression");
b = *p & 0x7f;
if (bit >= 64 || b << bit >> bit != b) {
_LIBUNWIND_ABORT("malformed uleb128 expression");
} else {
result |= b << bit;
bit += 7;
}
} while (*p++ >= 0x80);
addr = (pint_t) p;
return result;
}
/// Read a SLEB128 into a 64-bit word.
inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
const uint8_t *p = (uint8_t *)addr;
const uint8_t *pend = (uint8_t *)end;
int64_t result = 0;
int bit = 0;
uint8_t byte;
do {
if (p == pend)
_LIBUNWIND_ABORT("truncated sleb128 expression");
byte = *p++;
result |= ((byte & 0x7f) << bit);
bit += 7;
} while (byte & 0x80);
// sign extend negative numbers
if ((byte & 0x40) != 0)
result |= (-1ULL) << bit;
addr = (pint_t) p;
return result;
}
inline LocalAddressSpace::pint_t
LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
pint_t datarelBase) {
pint_t startAddr = addr;
const uint8_t *p = (uint8_t *)addr;
pint_t result;
// first get value
switch (encoding & 0x0F) {
case DW_EH_PE_ptr:
result = getP(addr);
p += sizeof(pint_t);
addr = (pint_t) p;
break;
case DW_EH_PE_uleb128:
result = (pint_t)getULEB128(addr, end);
break;
case DW_EH_PE_udata2:
result = get16(addr);
p += 2;
addr = (pint_t) p;
break;
case DW_EH_PE_udata4:
result = get32(addr);
p += 4;
addr = (pint_t) p;
break;
case DW_EH_PE_udata8:
result = (pint_t)get64(addr);
p += 8;
addr = (pint_t) p;
break;
case DW_EH_PE_sleb128:
result = (pint_t)getSLEB128(addr, end);
break;
case DW_EH_PE_sdata2:
// Sign extend from signed 16-bit value.
result = (pint_t)(int16_t)get16(addr);
p += 2;
addr = (pint_t) p;
break;
case DW_EH_PE_sdata4:
// Sign extend from signed 32-bit value.
result = (pint_t)(int32_t)get32(addr);
p += 4;
addr = (pint_t) p;
break;
case DW_EH_PE_sdata8:
result = (pint_t)get64(addr);
p += 8;
addr = (pint_t) p;
break;
default:
_LIBUNWIND_ABORT("unknown pointer encoding");
}
// then add relative offset
switch (encoding & 0x70) {
case DW_EH_PE_absptr:
// do nothing
break;
case DW_EH_PE_pcrel:
result += startAddr;
break;
case DW_EH_PE_textrel:
_LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
break;
case DW_EH_PE_datarel:
// DW_EH_PE_datarel is only valid in a few places, so the parameter has a
// default value of 0, and we abort in the event that someone calls this
// function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
if (datarelBase == 0)
_LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
result += datarelBase;
break;
case DW_EH_PE_funcrel:
_LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
break;
case DW_EH_PE_aligned:
_LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
break;
default:
_LIBUNWIND_ABORT("unknown pointer encoding");
break;
}
if (encoding & DW_EH_PE_indirect)
result = getP(result);
return result;
}
extern "C" {
uintptr_t dl_unwind_find_exidx(uintptr_t pc, int *length);
}
inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
UnwindInfoSections &info) {
#ifdef __APPLE__
dyld_unwind_sections dyldInfo;
if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
info.dso_base = (uintptr_t)dyldInfo.mh;
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
info.dwarf_section_length = dyldInfo.dwarf_section_length;
#endif
info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section;
info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
return true;
}
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
// Bare metal is statically linked, so no need to ask the dynamic loader
info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
info.dwarf_section = (uintptr_t)(&__eh_frame_start);
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
(void *)info.dwarf_section, (void *)info.dwarf_section_length);
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
(void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
#endif
if (info.dwarf_section_length)
return true;
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
// patched as our baremetal solution has a dynamic loader...
int length = 0;
info.arm_section =
(uintptr_t)dl_unwind_find_exidx((uintptr_t)targetAddr, &length);
info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry);
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
(void *)info.arm_section, (void *)info.arm_section_length);
if (info.arm_section && info.arm_section_length)
return true;
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
HMODULE mods[1024];
HANDLE process = GetCurrentProcess();
DWORD needed;
if (!EnumProcessModules(process, mods, sizeof(mods), &needed))
return false;
for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
bool found_obj = false;
bool found_hdr = false;
info.dso_base = (uintptr_t)mods[i];
for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
uintptr_t end = begin + pish->Misc.VirtualSize;
if (!strncmp((const char *)pish->Name, ".text",
IMAGE_SIZEOF_SHORT_NAME)) {
if (targetAddr >= begin && targetAddr < end)
found_obj = true;
} else if (!strncmp((const char *)pish->Name, ".eh_frame",
IMAGE_SIZEOF_SHORT_NAME)) {
info.dwarf_section = begin;
info.dwarf_section_length = pish->Misc.VirtualSize;
found_hdr = true;
}
if (found_obj && found_hdr)
return true;
}
}
return false;
#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
// Don't even bother, since Windows has functions that do all this stuff
// for us.
(void)targetAddr;
(void)info;
return true;
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__)
// For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After
// API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster.
int length = 0;
info.arm_section =
(uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry);
if (info.arm_section && info.arm_section_length)
return true;
#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
struct dl_iterate_cb_data {
LocalAddressSpace *addressSpace;
UnwindInfoSections *sects;
uintptr_t targetAddr;
};
dl_iterate_cb_data cb_data = {this, &info, targetAddr};
int found = dl_iterate_phdr(
[](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
auto cbdata = static_cast<dl_iterate_cb_data *>(data);
bool found_obj = false;
bool found_hdr = false;
assert(cbdata);
assert(cbdata->sects);
if (cbdata->targetAddr < pinfo->dlpi_addr) {
return false;
}
#if !defined(Elf_Half)
typedef ElfW(Half) Elf_Half;
#endif
#if !defined(Elf_Phdr)
typedef ElfW(Phdr) Elf_Phdr;
#endif
#if !defined(Elf_Addr)
typedef ElfW(Addr) Elf_Addr;
#endif
Elf_Addr image_base = pinfo->dlpi_addr;
#if defined(__ANDROID__) && __ANDROID_API__ < 18
if (image_base == 0) {
// Normally, an image base of 0 indicates a non-PIE executable. On
// versions of Android prior to API 18, the dynamic linker reported a
// dlpi_addr of 0 for PIE executables. Compute the true image base
// using the PT_PHDR segment.
// See https://github.com/android/ndk/issues/505.
for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
if (phdr->p_type == PT_PHDR) {
image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
phdr->p_vaddr;
break;
}
}
}
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
#endif
size_t object_length;
for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
if (phdr->p_type == PT_LOAD) {
uintptr_t begin = image_base + phdr->p_vaddr;
uintptr_t end = begin + phdr->p_memsz;
if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
cbdata->sects->dso_base = begin;
object_length = phdr->p_memsz;
found_obj = true;
}
} else if (phdr->p_type == PT_GNU_EH_FRAME) {
EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr;
cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
*cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
hdrInfo);
if (found_hdr)
cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
}
}
if (found_obj && found_hdr) {
cbdata->sects->dwarf_section_length = object_length;
return true;
} else {
return false;
}
#else // defined(_LIBUNWIND_ARM_EHABI)
for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
if (phdr->p_type == PT_LOAD) {
uintptr_t begin = image_base + phdr->p_vaddr;
uintptr_t end = begin + phdr->p_memsz;
if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
found_obj = true;
} else if (phdr->p_type == PT_ARM_EXIDX) {
uintptr_t exidx_start = image_base + phdr->p_vaddr;
cbdata->sects->arm_section = exidx_start;
cbdata->sects->arm_section_length = phdr->p_memsz;
found_hdr = true;
}
}
return found_obj && found_hdr;
#endif
},
&cb_data);
return static_cast<bool>(found);
#endif
return false;
}
inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
#ifdef __APPLE__
return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
#else
// TO DO: if OS has way to dynamically register FDEs, check that.
(void)targetAddr;
(void)fde;
return false;
#endif
}
inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
size_t bufLen,
unw_word_t *offset) {
#if _LIBUNWIND_USE_DLADDR
Dl_info dyldInfo;
if (dladdr((void *)addr, &dyldInfo)) {
if (dyldInfo.dli_sname != NULL) {
snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
*offset = (addr - (pint_t) dyldInfo.dli_saddr);
return true;
}
}
#else
(void)addr;
(void)buf;
(void)bufLen;
(void)offset;
#endif
return false;
}
} // namespace libunwind
#endif // __ADDRESSSPACE_HPP__

View File

@ -0,0 +1,195 @@
# Get sources
set(LIBUNWIND_CXX_SOURCES
libunwind.cpp
Unwind-EHABI.cpp
Unwind-seh.cpp
)
if(APPLE)
list(APPEND LIBUNWIND_CXX_SOURCES
Unwind_AppleExtras.cpp
)
endif()
set(LIBUNWIND_C_SOURCES
UnwindLevel1.c
UnwindLevel1-gcc-ext.c
Unwind-sjlj.c
)
set_source_files_properties(${LIBUNWIND_C_SOURCES}
PROPERTIES
COMPILE_FLAGS "-std=c99")
set(LIBUNWIND_ASM_SOURCES
UnwindRegistersRestore.S
UnwindRegistersSave.S
)
set_source_files_properties(${LIBUNWIND_ASM_SOURCES}
PROPERTIES
LANGUAGE C)
set(LIBUNWIND_HEADERS
AddressSpace.hpp
assembly.h
CompactUnwinder.hpp
config.h
dwarf2.h
DwarfInstructions.hpp
DwarfParser.hpp
libunwind_ext.h
Registers.hpp
RWMutex.hpp
UnwindCursor.hpp
../include/libunwind.h
../include/unwind.h
)
if(APPLE)
list(APPEND LIBUNWIND_HEADERS
../include/mach-o/compact_unwind_encoding.h
)
endif()
if (MSVC_IDE)
# Force them all into the headers dir on MSVC, otherwise they end up at
# project scope because they don't have extensions.
source_group("Header Files" FILES ${LIBUNWIND_HEADERS})
endif()
set(LIBUNWIND_SOURCES
${LIBUNWIND_CXX_SOURCES}
${LIBUNWIND_C_SOURCES}
${LIBUNWIND_ASM_SOURCES})
# Generate library list.
add_library_flags_if(LIBUNWIND_HAS_C_LIB c)
if (LIBUNWIND_USE_COMPILER_RT)
add_library_flags("${LIBUNWIND_BUILTINS_LIBRARY}")
else()
add_library_flags_if(LIBUNWIND_HAS_GCC_S_LIB gcc_s)
add_library_flags_if(LIBUNWIND_HAS_GCC_LIB gcc)
endif()
add_library_flags_if(LIBUNWIND_HAS_DL_LIB dl)
if (LIBUNWIND_ENABLE_THREADS)
add_library_flags_if(LIBUNWIND_HAS_PTHREAD_LIB pthread)
add_compile_flags_if(LIBUNWIND_WEAK_PTHREAD_LIB -DLIBUNWIND_USE_WEAK_PTHREAD=1)
endif()
# Setup flags.
add_link_flags_if_supported(-nodefaultlibs)
# MINGW_LIBRARIES is defined in config-ix.cmake
add_library_flags_if(MINGW "${MINGW_LIBRARIES}")
if (LIBUNWIND_ENABLE_SHARED AND
NOT (LIBUNWIND_SUPPORTS_FNO_EXCEPTIONS_FLAG AND
LIBUNWIND_SUPPORTS_FUNWIND_TABLES_FLAG))
message(FATAL_ERROR
"Compiler doesn't support generation of unwind tables if exception "
"support is disabled. Building libunwind DSO with runtime dependency "
"on C++ ABI library is not supported.")
endif()
if (APPLE)
add_compile_flags("-U__STRICT_ANSI__")
add_link_flags("-compatibility_version 1" "-install_name /usr/lib/libunwind.1.dylib")
if (CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.6")
add_link_flags("-current_version ${LIBUNWIND_VERSION}" "/usr/lib/libSystem.B.dylib")
endif ()
endif ()
string(REPLACE ";" " " LIBUNWIND_COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}")
string(REPLACE ";" " " LIBUNWIND_CXX_FLAGS "${LIBUNWIND_CXX_FLAGS}")
string(REPLACE ";" " " LIBUNWIND_C_FLAGS "${LIBUNWIND_C_FLAGS}")
string(REPLACE ";" " " LIBUNWIND_LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}")
set_property(SOURCE ${LIBUNWIND_CXX_SOURCES}
APPEND_STRING PROPERTY COMPILE_FLAGS " ${LIBUNWIND_CXX_FLAGS}")
set_property(SOURCE ${LIBUNWIND_C_SOURCES}
APPEND_STRING PROPERTY COMPILE_FLAGS " ${LIBUNWIND_C_FLAGS}")
# Build the shared library.
if (LIBUNWIND_ENABLE_SHARED)
add_library(unwind_shared SHARED ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
if(COMMAND llvm_setup_rpath)
llvm_setup_rpath(unwind_shared)
endif()
target_link_libraries(unwind_shared PRIVATE ${LIBUNWIND_LIBRARIES})
set_target_properties(unwind_shared
PROPERTIES
CXX_EXTENSIONS
OFF
CXX_STANDARD
11
CXX_STANDARD_REQUIRED
ON
COMPILE_FLAGS
"${LIBUNWIND_COMPILE_FLAGS}"
LINK_FLAGS
"${LIBUNWIND_LINK_FLAGS}"
OUTPUT_NAME
"unwind"
VERSION
"1.0"
SOVERSION
"1")
list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_shared")
if (LIBUNWIND_INSTALL_SHARED_LIBRARY)
list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared")
endif()
endif()
# Build the static library.
if (LIBUNWIND_ENABLE_STATIC)
add_library(unwind_static STATIC ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
target_link_libraries(unwind_static PRIVATE ${LIBUNWIND_LIBRARIES})
set_target_properties(unwind_static
PROPERTIES
CXX_EXTENSIONS
OFF
CXX_STANDARD
11
CXX_STANDARD_REQUIRED
ON
COMPILE_FLAGS
"${LIBUNWIND_COMPILE_FLAGS}"
LINK_FLAGS
"${LIBUNWIND_LINK_FLAGS}"
OUTPUT_NAME
"unwind")
if(LIBUNWIND_HERMETIC_STATIC_LIBRARY)
append_flags_if_supported(UNWIND_STATIC_LIBRARY_FLAGS -fvisibility=hidden)
append_flags_if_supported(UNWIND_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden)
target_compile_options(unwind_static PRIVATE ${UNWIND_STATIC_LIBRARY_FLAGS})
target_compile_definitions(unwind_static PRIVATE _LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
endif()
list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_static")
if (LIBUNWIND_INSTALL_STATIC_LIBRARY)
list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static")
endif()
endif()
# Add a meta-target for both libraries.
add_custom_target(unwind DEPENDS ${LIBUNWIND_BUILD_TARGETS})
if (LIBUNWIND_INSTALL_LIBRARY)
install(TARGETS ${LIBUNWIND_INSTALL_TARGETS}
LIBRARY DESTINATION ${LIBUNWIND_INSTALL_PREFIX}${LIBUNWIND_INSTALL_LIBRARY_DIR} COMPONENT unwind
ARCHIVE DESTINATION ${LIBUNWIND_INSTALL_PREFIX}${LIBUNWIND_INSTALL_LIBRARY_DIR} COMPONENT unwind)
endif()
if (NOT CMAKE_CONFIGURATION_TYPES AND LIBUNWIND_INSTALL_LIBRARY)
add_custom_target(install-unwind
DEPENDS unwind
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=unwind
-P "${LIBUNWIND_BINARY_DIR}/cmake_install.cmake")
add_custom_target(install-unwind-stripped
DEPENDS unwind
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=unwind
-DCMAKE_INSTALL_DO_STRIP=1
-P "${LIBUNWIND_BINARY_DIR}/cmake_install.cmake")
endif()

View File

@ -0,0 +1,697 @@
//===-------------------------- CompactUnwinder.hpp -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Does runtime stack unwinding using compact unwind encodings.
//
//===----------------------------------------------------------------------===//
#ifndef __COMPACT_UNWINDER_HPP__
#define __COMPACT_UNWINDER_HPP__
#include <stdint.h>
#include <stdlib.h>
#include <libunwind.h>
#include <mach-o/compact_unwind_encoding.h>
#include "Registers.hpp"
#define EXTRACT_BITS(value, mask) \
((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1))
namespace libunwind {
#if defined(_LIBUNWIND_TARGET_I386)
/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_x86 register set
template <typename A>
class CompactUnwinder_x86 {
public:
static int stepWithCompactEncoding(compact_unwind_encoding_t info,
uint32_t functionStart, A &addressSpace,
Registers_x86 &registers);
private:
typename A::pint_t pint_t;
static void frameUnwind(A &addressSpace, Registers_x86 &registers);
static void framelessUnwind(A &addressSpace,
typename A::pint_t returnAddressLocation,
Registers_x86 &registers);
static int
stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding,
uint32_t functionStart, A &addressSpace,
Registers_x86 &registers);
static int stepWithCompactEncodingFrameless(
compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
A &addressSpace, Registers_x86 &registers, bool indirectStackSize);
};
template <typename A>
int CompactUnwinder_x86<A>::stepWithCompactEncoding(
compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
A &addressSpace, Registers_x86 &registers) {
switch (compactEncoding & UNWIND_X86_MODE_MASK) {
case UNWIND_X86_MODE_EBP_FRAME:
return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart,
addressSpace, registers);
case UNWIND_X86_MODE_STACK_IMMD:
return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
addressSpace, registers, false);
case UNWIND_X86_MODE_STACK_IND:
return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
addressSpace, registers, true);
}
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
template <typename A>
int CompactUnwinder_x86<A>::stepWithCompactEncodingEBPFrame(
compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
A &addressSpace, Registers_x86 &registers) {
uint32_t savedRegistersOffset =
EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET);
uint32_t savedRegistersLocations =
EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS);
uint32_t savedRegisters = registers.getEBP() - 4 * savedRegistersOffset;
for (int i = 0; i < 5; ++i) {
switch (savedRegistersLocations & 0x7) {
case UNWIND_X86_REG_NONE:
// no register saved in this slot
break;
case UNWIND_X86_REG_EBX:
registers.setEBX(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_ECX:
registers.setECX(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_EDX:
registers.setEDX(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_EDI:
registers.setEDI(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_ESI:
registers.setESI(addressSpace.get32(savedRegisters));
break;
default:
(void)functionStart;
_LIBUNWIND_DEBUG_LOG("bad register for EBP frame, encoding=%08X for "
"function starting at 0x%X",
compactEncoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
savedRegisters += 4;
savedRegistersLocations = (savedRegistersLocations >> 3);
}
frameUnwind(addressSpace, registers);
return UNW_STEP_SUCCESS;
}
template <typename A>
int CompactUnwinder_x86<A>::stepWithCompactEncodingFrameless(
compact_unwind_encoding_t encoding, uint32_t functionStart,
A &addressSpace, Registers_x86 &registers, bool indirectStackSize) {
uint32_t stackSizeEncoded =
EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
uint32_t stackAdjust =
EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST);
uint32_t regCount =
EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT);
uint32_t permutation =
EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION);
uint32_t stackSize = stackSizeEncoded * 4;
if (indirectStackSize) {
// stack size is encoded in subl $xxx,%esp instruction
uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded);
stackSize = subl + 4 * stackAdjust;
}
// decompress permutation
uint32_t permunreg[6];
switch (regCount) {
case 6:
permunreg[0] = permutation / 120;
permutation -= (permunreg[0] * 120);
permunreg[1] = permutation / 24;
permutation -= (permunreg[1] * 24);
permunreg[2] = permutation / 6;
permutation -= (permunreg[2] * 6);
permunreg[3] = permutation / 2;
permutation -= (permunreg[3] * 2);
permunreg[4] = permutation;
permunreg[5] = 0;
break;
case 5:
permunreg[0] = permutation / 120;
permutation -= (permunreg[0] * 120);
permunreg[1] = permutation / 24;
permutation -= (permunreg[1] * 24);
permunreg[2] = permutation / 6;
permutation -= (permunreg[2] * 6);
permunreg[3] = permutation / 2;
permutation -= (permunreg[3] * 2);
permunreg[4] = permutation;
break;
case 4:
permunreg[0] = permutation / 60;
permutation -= (permunreg[0] * 60);
permunreg[1] = permutation / 12;
permutation -= (permunreg[1] * 12);
permunreg[2] = permutation / 3;
permutation -= (permunreg[2] * 3);
permunreg[3] = permutation;
break;
case 3:
permunreg[0] = permutation / 20;
permutation -= (permunreg[0] * 20);
permunreg[1] = permutation / 4;
permutation -= (permunreg[1] * 4);
permunreg[2] = permutation;
break;
case 2:
permunreg[0] = permutation / 5;
permutation -= (permunreg[0] * 5);
permunreg[1] = permutation;
break;
case 1:
permunreg[0] = permutation;
break;
}
// re-number registers back to standard numbers
int registersSaved[6];
bool used[7] = { false, false, false, false, false, false, false };
for (uint32_t i = 0; i < regCount; ++i) {
uint32_t renum = 0;
for (int u = 1; u < 7; ++u) {
if (!used[u]) {
if (renum == permunreg[i]) {
registersSaved[i] = u;
used[u] = true;
break;
}
++renum;
}
}
}
uint32_t savedRegisters = registers.getSP() + stackSize - 4 - 4 * regCount;
for (uint32_t i = 0; i < regCount; ++i) {
switch (registersSaved[i]) {
case UNWIND_X86_REG_EBX:
registers.setEBX(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_ECX:
registers.setECX(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_EDX:
registers.setEDX(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_EDI:
registers.setEDI(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_ESI:
registers.setESI(addressSpace.get32(savedRegisters));
break;
case UNWIND_X86_REG_EBP:
registers.setEBP(addressSpace.get32(savedRegisters));
break;
default:
_LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
"function starting at 0x%X",
encoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
savedRegisters += 4;
}
framelessUnwind(addressSpace, savedRegisters, registers);
return UNW_STEP_SUCCESS;
}
template <typename A>
void CompactUnwinder_x86<A>::frameUnwind(A &addressSpace,
Registers_x86 &registers) {
typename A::pint_t bp = registers.getEBP();
// ebp points to old ebp
registers.setEBP(addressSpace.get32(bp));
// old esp is ebp less saved ebp and return address
registers.setSP((uint32_t)bp + 8);
// pop return address into eip
registers.setIP(addressSpace.get32(bp + 4));
}
template <typename A>
void CompactUnwinder_x86<A>::framelessUnwind(
A &addressSpace, typename A::pint_t returnAddressLocation,
Registers_x86 &registers) {
// return address is on stack after last saved register
registers.setIP(addressSpace.get32(returnAddressLocation));
// old esp is before return address
registers.setSP((uint32_t)returnAddressLocation + 4);
}
#endif // _LIBUNWIND_TARGET_I386
#if defined(_LIBUNWIND_TARGET_X86_64)
/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_x86_64 register set
template <typename A>
class CompactUnwinder_x86_64 {
public:
static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding,
uint64_t functionStart, A &addressSpace,
Registers_x86_64 &registers);
private:
typename A::pint_t pint_t;
static void frameUnwind(A &addressSpace, Registers_x86_64 &registers);
static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation,
Registers_x86_64 &registers);
static int
stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding,
uint64_t functionStart, A &addressSpace,
Registers_x86_64 &registers);
static int stepWithCompactEncodingFrameless(
compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
A &addressSpace, Registers_x86_64 &registers, bool indirectStackSize);
};
template <typename A>
int CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
A &addressSpace, Registers_x86_64 &registers) {
switch (compactEncoding & UNWIND_X86_64_MODE_MASK) {
case UNWIND_X86_64_MODE_RBP_FRAME:
return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart,
addressSpace, registers);
case UNWIND_X86_64_MODE_STACK_IMMD:
return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
addressSpace, registers, false);
case UNWIND_X86_64_MODE_STACK_IND:
return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
addressSpace, registers, true);
}
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
template <typename A>
int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(
compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
A &addressSpace, Registers_x86_64 &registers) {
uint32_t savedRegistersOffset =
EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
uint32_t savedRegistersLocations =
EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset;
for (int i = 0; i < 5; ++i) {
switch (savedRegistersLocations & 0x7) {
case UNWIND_X86_64_REG_NONE:
// no register saved in this slot
break;
case UNWIND_X86_64_REG_RBX:
registers.setRBX(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_R12:
registers.setR12(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_R13:
registers.setR13(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_R14:
registers.setR14(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_R15:
registers.setR15(addressSpace.get64(savedRegisters));
break;
default:
(void)functionStart;
_LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for "
"function starting at 0x%llX",
compactEncoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
savedRegisters += 8;
savedRegistersLocations = (savedRegistersLocations >> 3);
}
frameUnwind(addressSpace, registers);
return UNW_STEP_SUCCESS;
}
template <typename A>
int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(
compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace,
Registers_x86_64 &registers, bool indirectStackSize) {
uint32_t stackSizeEncoded =
EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
uint32_t stackAdjust =
EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
uint32_t regCount =
EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
uint32_t permutation =
EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
uint32_t stackSize = stackSizeEncoded * 8;
if (indirectStackSize) {
// stack size is encoded in subl $xxx,%esp instruction
uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded);
stackSize = subl + 8 * stackAdjust;
}
// decompress permutation
uint32_t permunreg[6];
switch (regCount) {
case 6:
permunreg[0] = permutation / 120;
permutation -= (permunreg[0] * 120);
permunreg[1] = permutation / 24;
permutation -= (permunreg[1] * 24);
permunreg[2] = permutation / 6;
permutation -= (permunreg[2] * 6);
permunreg[3] = permutation / 2;
permutation -= (permunreg[3] * 2);
permunreg[4] = permutation;
permunreg[5] = 0;
break;
case 5:
permunreg[0] = permutation / 120;
permutation -= (permunreg[0] * 120);
permunreg[1] = permutation / 24;
permutation -= (permunreg[1] * 24);
permunreg[2] = permutation / 6;
permutation -= (permunreg[2] * 6);
permunreg[3] = permutation / 2;
permutation -= (permunreg[3] * 2);
permunreg[4] = permutation;
break;
case 4:
permunreg[0] = permutation / 60;
permutation -= (permunreg[0] * 60);
permunreg[1] = permutation / 12;
permutation -= (permunreg[1] * 12);
permunreg[2] = permutation / 3;
permutation -= (permunreg[2] * 3);
permunreg[3] = permutation;
break;
case 3:
permunreg[0] = permutation / 20;
permutation -= (permunreg[0] * 20);
permunreg[1] = permutation / 4;
permutation -= (permunreg[1] * 4);
permunreg[2] = permutation;
break;
case 2:
permunreg[0] = permutation / 5;
permutation -= (permunreg[0] * 5);
permunreg[1] = permutation;
break;
case 1:
permunreg[0] = permutation;
break;
}
// re-number registers back to standard numbers
int registersSaved[6];
bool used[7] = { false, false, false, false, false, false, false };
for (uint32_t i = 0; i < regCount; ++i) {
uint32_t renum = 0;
for (int u = 1; u < 7; ++u) {
if (!used[u]) {
if (renum == permunreg[i]) {
registersSaved[i] = u;
used[u] = true;
break;
}
++renum;
}
}
}
uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount;
for (uint32_t i = 0; i < regCount; ++i) {
switch (registersSaved[i]) {
case UNWIND_X86_64_REG_RBX:
registers.setRBX(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_R12:
registers.setR12(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_R13:
registers.setR13(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_R14:
registers.setR14(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_R15:
registers.setR15(addressSpace.get64(savedRegisters));
break;
case UNWIND_X86_64_REG_RBP:
registers.setRBP(addressSpace.get64(savedRegisters));
break;
default:
_LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
"function starting at 0x%llX",
encoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
savedRegisters += 8;
}
framelessUnwind(addressSpace, savedRegisters, registers);
return UNW_STEP_SUCCESS;
}
template <typename A>
void CompactUnwinder_x86_64<A>::frameUnwind(A &addressSpace,
Registers_x86_64 &registers) {
uint64_t rbp = registers.getRBP();
// ebp points to old ebp
registers.setRBP(addressSpace.get64(rbp));
// old esp is ebp less saved ebp and return address
registers.setSP(rbp + 16);
// pop return address into eip
registers.setIP(addressSpace.get64(rbp + 8));
}
template <typename A>
void CompactUnwinder_x86_64<A>::framelessUnwind(A &addressSpace,
uint64_t returnAddressLocation,
Registers_x86_64 &registers) {
// return address is on stack after last saved register
registers.setIP(addressSpace.get64(returnAddressLocation));
// old esp is before return address
registers.setSP(returnAddressLocation + 8);
}
#endif // _LIBUNWIND_TARGET_X86_64
#if defined(_LIBUNWIND_TARGET_AARCH64)
/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_arm64 register set
template <typename A>
class CompactUnwinder_arm64 {
public:
static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding,
uint64_t functionStart, A &addressSpace,
Registers_arm64 &registers);
private:
typename A::pint_t pint_t;
static int
stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding,
uint64_t functionStart, A &addressSpace,
Registers_arm64 &registers);
static int stepWithCompactEncodingFrameless(
compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
A &addressSpace, Registers_arm64 &registers);
};
template <typename A>
int CompactUnwinder_arm64<A>::stepWithCompactEncoding(
compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
A &addressSpace, Registers_arm64 &registers) {
switch (compactEncoding & UNWIND_ARM64_MODE_MASK) {
case UNWIND_ARM64_MODE_FRAME:
return stepWithCompactEncodingFrame(compactEncoding, functionStart,
addressSpace, registers);
case UNWIND_ARM64_MODE_FRAMELESS:
return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
addressSpace, registers);
}
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
template <typename A>
int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless(
compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,
Registers_arm64 &registers) {
uint32_t stackSize =
16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK);
uint64_t savedRegisterLoc = registers.getSP() + stackSize;
if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
registers.setFloatRegister(UNW_ARM64_D8,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setFloatRegister(UNW_ARM64_D9,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
registers.setFloatRegister(UNW_ARM64_D10,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setFloatRegister(UNW_ARM64_D11,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
registers.setFloatRegister(UNW_ARM64_D12,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setFloatRegister(UNW_ARM64_D13,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
registers.setFloatRegister(UNW_ARM64_D14,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setFloatRegister(UNW_ARM64_D15,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
// subtract stack size off of sp
registers.setSP(savedRegisterLoc);
// set pc to be value in lr
registers.setIP(registers.getRegister(UNW_ARM64_LR));
return UNW_STEP_SUCCESS;
}
template <typename A>
int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,
Registers_arm64 &registers) {
uint64_t savedRegisterLoc = registers.getFP() - 8;
if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
registers.setFloatRegister(UNW_ARM64_D8,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setFloatRegister(UNW_ARM64_D9,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
registers.setFloatRegister(UNW_ARM64_D10,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setFloatRegister(UNW_ARM64_D11,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
registers.setFloatRegister(UNW_ARM64_D12,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setFloatRegister(UNW_ARM64_D13,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
registers.setFloatRegister(UNW_ARM64_D14,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
registers.setFloatRegister(UNW_ARM64_D15,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
uint64_t fp = registers.getFP();
// fp points to old fp
registers.setFP(addressSpace.get64(fp));
// old sp is fp less saved fp and lr
registers.setSP(fp + 16);
// pop return address into pc
registers.setIP(addressSpace.get64(fp + 8));
return UNW_STEP_SUCCESS;
}
#endif // _LIBUNWIND_TARGET_AARCH64
} // namespace libunwind
#endif // __COMPACT_UNWINDER_HPP__

View File

@ -0,0 +1,818 @@
//===-------------------------- DwarfInstructions.hpp ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Processor specific interpretation of DWARF unwind info.
//
//===----------------------------------------------------------------------===//
#ifndef __DWARF_INSTRUCTIONS_HPP__
#define __DWARF_INSTRUCTIONS_HPP__
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "dwarf2.h"
#include "Registers.hpp"
#include "DwarfParser.hpp"
#include "config.h"
namespace libunwind {
/// DwarfInstructions maps abtract DWARF unwind instructions to a particular
/// architecture
template <typename A, typename R>
class DwarfInstructions {
public:
typedef typename A::pint_t pint_t;
typedef typename A::sint_t sint_t;
static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
R &registers);
private:
enum {
DW_X86_64_RET_ADDR = 16
};
enum {
DW_X86_RET_ADDR = 8
};
typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation;
typedef typename CFI_Parser<A>::PrologInfo PrologInfo;
typedef typename CFI_Parser<A>::FDE_Info FDE_Info;
typedef typename CFI_Parser<A>::CIE_Info CIE_Info;
static pint_t evaluateExpression(pint_t expression, A &addressSpace,
const R &registers,
pint_t initialStackValue);
static pint_t getSavedRegister(A &addressSpace, const R &registers,
pint_t cfa, const RegisterLocation &savedReg);
static double getSavedFloatRegister(A &addressSpace, const R &registers,
pint_t cfa, const RegisterLocation &savedReg);
static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
pint_t cfa, const RegisterLocation &savedReg);
static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
const R &registers) {
if (prolog.cfaRegister != 0)
return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
prolog.cfaRegisterOffset);
if (prolog.cfaExpression != 0)
return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
registers, 0);
assert(0 && "getCFA(): unknown location");
__builtin_unreachable();
}
};
template <typename A, typename R>
typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
A &addressSpace, const R &registers, pint_t cfa,
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
return (pint_t)addressSpace.getRegister(evaluateExpression(
(pint_t)savedReg.value, addressSpace, registers, cfa));
case CFI_Parser<A>::kRegisterIsExpression:
return evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa);
case CFI_Parser<A>::kRegisterInRegister:
return registers.getRegister((int)savedReg.value);
case CFI_Parser<A>::kRegisterUnused:
case CFI_Parser<A>::kRegisterOffsetFromCFA:
// FIX ME
break;
}
_LIBUNWIND_ABORT("unsupported restore location for register");
}
template <typename A, typename R>
double DwarfInstructions<A, R>::getSavedFloatRegister(
A &addressSpace, const R &registers, pint_t cfa,
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
return addressSpace.getDouble(
evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa));
case CFI_Parser<A>::kRegisterIsExpression:
case CFI_Parser<A>::kRegisterUnused:
case CFI_Parser<A>::kRegisterOffsetFromCFA:
case CFI_Parser<A>::kRegisterInRegister:
// FIX ME
break;
}
_LIBUNWIND_ABORT("unsupported restore location for float register");
}
template <typename A, typename R>
v128 DwarfInstructions<A, R>::getSavedVectorRegister(
A &addressSpace, const R &registers, pint_t cfa,
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
return addressSpace.getVector(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
return addressSpace.getVector(
evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa));
case CFI_Parser<A>::kRegisterIsExpression:
case CFI_Parser<A>::kRegisterUnused:
case CFI_Parser<A>::kRegisterOffsetFromCFA:
case CFI_Parser<A>::kRegisterInRegister:
// FIX ME
break;
}
_LIBUNWIND_ABORT("unsupported restore location for vector register");
}
template <typename A, typename R>
int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
pint_t fdeStart, R &registers) {
FDE_Info fdeInfo;
CIE_Info cieInfo;
if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
&cieInfo) == NULL) {
PrologInfo prolog;
if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
R::getArch(), &prolog)) {
// get pointer to cfa (architecture specific)
pint_t cfa = getCFA(addressSpace, prolog, registers);
// restore registers that DWARF says were saved
R newRegisters = registers;
pint_t returnAddress = 0;
const int lastReg = R::lastDwarfRegNum();
assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
"register range too large");
assert(lastReg >= (int)cieInfo.returnAddressRegister &&
"register range does not contain return address register");
for (int i = 0; i <= lastReg; ++i) {
if (prolog.savedRegisters[i].location !=
CFI_Parser<A>::kRegisterUnused) {
if (registers.validFloatRegister(i))
newRegisters.setFloatRegister(
i, getSavedFloatRegister(addressSpace, registers, cfa,
prolog.savedRegisters[i]));
else if (registers.validVectorRegister(i))
newRegisters.setVectorRegister(
i, getSavedVectorRegister(addressSpace, registers, cfa,
prolog.savedRegisters[i]));
else if (i == (int)cieInfo.returnAddressRegister)
returnAddress = getSavedRegister(addressSpace, registers, cfa,
prolog.savedRegisters[i]);
else if (registers.validRegister(i))
newRegisters.setRegister(
i, getSavedRegister(addressSpace, registers, cfa,
prolog.savedRegisters[i]));
else
return UNW_EBADREG;
}
}
// By definition, the CFA is the stack pointer at the call site, so
// restoring SP means setting it to CFA.
newRegisters.setSP(cfa);
#if defined(_LIBUNWIND_TARGET_AARCH64)
// If the target is aarch64 then the return address may have been signed
// using the v8.3 pointer authentication extensions. The original
// return address needs to be authenticated before the return address is
// restored. autia1716 is used instead of autia as autia1716 assembles
// to a NOP on pre-v8.3a architectures.
if ((R::getArch() == REGISTERS_ARM64) &&
prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {
#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
return UNW_ECROSSRASIGNING;
#else
register unsigned long long x17 __asm("x17") = returnAddress;
register unsigned long long x16 __asm("x16") = cfa;
// These are the autia1716/autib1716 instructions. The hint instructions
// are used here as gcc does not assemble autia1716/autib1716 for pre
// armv8.3a targets.
if (cieInfo.addressesSignedWithBKey)
asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
else
asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
returnAddress = x17;
#endif
}
#endif
#if defined(_LIBUNWIND_TARGET_SPARC)
if (R::getArch() == REGISTERS_SPARC) {
// Skip call site instruction and delay slot
returnAddress += 8;
// Skip unimp instruction if function returns a struct
if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
returnAddress += 4;
}
#endif
#if defined(_LIBUNWIND_TARGET_PPC64)
#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
#define PPC64_ELFV1_R2_OFFSET 40
#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
#define PPC64_ELFV2_R2_OFFSET 24
// If the instruction at return address is a TOC (r2) restore,
// then r2 was saved and needs to be restored.
// ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
// while in ELFv1 ABI it is saved at SP + 40.
if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {
pint_t sp = newRegisters.getRegister(UNW_REG_SP);
pint_t r2 = 0;
switch (addressSpace.get32(returnAddress)) {
case PPC64_ELFV1_R2_LOAD_INST_ENCODING:
r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);
break;
case PPC64_ELFV2_R2_LOAD_INST_ENCODING:
r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
break;
}
if (r2)
newRegisters.setRegister(UNW_PPC64_R2, r2);
}
#endif
// Return address is address after call site instruction, so setting IP to
// that does simualates a return.
newRegisters.setIP(returnAddress);
// Simulate the step by replacing the register set with the new ones.
registers = newRegisters;
return UNW_STEP_SUCCESS;
}
}
return UNW_EBADFRAME;
}
template <typename A, typename R>
typename A::pint_t
DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
const R &registers,
pint_t initialStackValue) {
const bool log = false;
pint_t p = expression;
pint_t expressionEnd = expression + 20; // temp, until len read
pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
expressionEnd = p + length;
if (log)
fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
(uint64_t)length);
pint_t stack[100];
pint_t *sp = stack;
*(++sp) = initialStackValue;
while (p < expressionEnd) {
if (log) {
for (pint_t *t = sp; t > stack; --t) {
fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
}
}
uint8_t opcode = addressSpace.get8(p++);
sint_t svalue, svalue2;
pint_t value;
uint32_t reg;
switch (opcode) {
case DW_OP_addr:
// push immediate address sized value
value = addressSpace.getP(p);
p += sizeof(pint_t);
*(++sp) = value;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_deref:
// pop stack, dereference, push result
value = *sp--;
*(++sp) = addressSpace.getP(value);
if (log)
fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_const1u:
// push immediate 1 byte value
value = addressSpace.get8(p);
p += 1;
*(++sp) = value;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_const1s:
// push immediate 1 byte signed value
svalue = (int8_t) addressSpace.get8(p);
p += 1;
*(++sp) = (pint_t)svalue;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
break;
case DW_OP_const2u:
// push immediate 2 byte value
value = addressSpace.get16(p);
p += 2;
*(++sp) = value;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_const2s:
// push immediate 2 byte signed value
svalue = (int16_t) addressSpace.get16(p);
p += 2;
*(++sp) = (pint_t)svalue;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
break;
case DW_OP_const4u:
// push immediate 4 byte value
value = addressSpace.get32(p);
p += 4;
*(++sp) = value;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_const4s:
// push immediate 4 byte signed value
svalue = (int32_t)addressSpace.get32(p);
p += 4;
*(++sp) = (pint_t)svalue;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
break;
case DW_OP_const8u:
// push immediate 8 byte value
value = (pint_t)addressSpace.get64(p);
p += 8;
*(++sp) = value;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_const8s:
// push immediate 8 byte signed value
value = (pint_t)addressSpace.get64(p);
p += 8;
*(++sp) = value;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_constu:
// push immediate ULEB128 value
value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
*(++sp) = value;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_consts:
// push immediate SLEB128 value
svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
*(++sp) = (pint_t)svalue;
if (log)
fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
break;
case DW_OP_dup:
// push top of stack
value = *sp;
*(++sp) = value;
if (log)
fprintf(stderr, "duplicate top of stack\n");
break;
case DW_OP_drop:
// pop
--sp;
if (log)
fprintf(stderr, "pop top of stack\n");
break;
case DW_OP_over:
// dup second
value = sp[-1];
*(++sp) = value;
if (log)
fprintf(stderr, "duplicate second in stack\n");
break;
case DW_OP_pick:
// pick from
reg = addressSpace.get8(p);
p += 1;
value = sp[-reg];
*(++sp) = value;
if (log)
fprintf(stderr, "duplicate %d in stack\n", reg);
break;
case DW_OP_swap:
// swap top two
value = sp[0];
sp[0] = sp[-1];
sp[-1] = value;
if (log)
fprintf(stderr, "swap top of stack\n");
break;
case DW_OP_rot:
// rotate top three
value = sp[0];
sp[0] = sp[-1];
sp[-1] = sp[-2];
sp[-2] = value;
if (log)
fprintf(stderr, "rotate top three of stack\n");
break;
case DW_OP_xderef:
// pop stack, dereference, push result
value = *sp--;
*sp = *((pint_t*)value);
if (log)
fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_abs:
svalue = (sint_t)*sp;
if (svalue < 0)
*sp = (pint_t)(-svalue);
if (log)
fprintf(stderr, "abs\n");
break;
case DW_OP_and:
value = *sp--;
*sp &= value;
if (log)
fprintf(stderr, "and\n");
break;
case DW_OP_div:
svalue = (sint_t)(*sp--);
svalue2 = (sint_t)*sp;
*sp = (pint_t)(svalue2 / svalue);
if (log)
fprintf(stderr, "div\n");
break;
case DW_OP_minus:
value = *sp--;
*sp = *sp - value;
if (log)
fprintf(stderr, "minus\n");
break;
case DW_OP_mod:
svalue = (sint_t)(*sp--);
svalue2 = (sint_t)*sp;
*sp = (pint_t)(svalue2 % svalue);
if (log)
fprintf(stderr, "module\n");
break;
case DW_OP_mul:
svalue = (sint_t)(*sp--);
svalue2 = (sint_t)*sp;
*sp = (pint_t)(svalue2 * svalue);
if (log)
fprintf(stderr, "mul\n");
break;
case DW_OP_neg:
*sp = 0 - *sp;
if (log)
fprintf(stderr, "neg\n");
break;
case DW_OP_not:
svalue = (sint_t)(*sp);
*sp = (pint_t)(~svalue);
if (log)
fprintf(stderr, "not\n");
break;
case DW_OP_or:
value = *sp--;
*sp |= value;
if (log)
fprintf(stderr, "or\n");
break;
case DW_OP_plus:
value = *sp--;
*sp += value;
if (log)
fprintf(stderr, "plus\n");
break;
case DW_OP_plus_uconst:
// pop stack, add uelb128 constant, push result
*sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
if (log)
fprintf(stderr, "add constant\n");
break;
case DW_OP_shl:
value = *sp--;
*sp = *sp << value;
if (log)
fprintf(stderr, "shift left\n");
break;
case DW_OP_shr:
value = *sp--;
*sp = *sp >> value;
if (log)
fprintf(stderr, "shift left\n");
break;
case DW_OP_shra:
value = *sp--;
svalue = (sint_t)*sp;
*sp = (pint_t)(svalue >> value);
if (log)
fprintf(stderr, "shift left arithmetric\n");
break;
case DW_OP_xor:
value = *sp--;
*sp ^= value;
if (log)
fprintf(stderr, "xor\n");
break;
case DW_OP_skip:
svalue = (int16_t) addressSpace.get16(p);
p += 2;
p = (pint_t)((sint_t)p + svalue);
if (log)
fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
break;
case DW_OP_bra:
svalue = (int16_t) addressSpace.get16(p);
p += 2;
if (*sp--)
p = (pint_t)((sint_t)p + svalue);
if (log)
fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
break;
case DW_OP_eq:
value = *sp--;
*sp = (*sp == value);
if (log)
fprintf(stderr, "eq\n");
break;
case DW_OP_ge:
value = *sp--;
*sp = (*sp >= value);
if (log)
fprintf(stderr, "ge\n");
break;
case DW_OP_gt:
value = *sp--;
*sp = (*sp > value);
if (log)
fprintf(stderr, "gt\n");
break;
case DW_OP_le:
value = *sp--;
*sp = (*sp <= value);
if (log)
fprintf(stderr, "le\n");
break;
case DW_OP_lt:
value = *sp--;
*sp = (*sp < value);
if (log)
fprintf(stderr, "lt\n");
break;
case DW_OP_ne:
value = *sp--;
*sp = (*sp != value);
if (log)
fprintf(stderr, "ne\n");
break;
case DW_OP_lit0:
case DW_OP_lit1:
case DW_OP_lit2:
case DW_OP_lit3:
case DW_OP_lit4:
case DW_OP_lit5:
case DW_OP_lit6:
case DW_OP_lit7:
case DW_OP_lit8:
case DW_OP_lit9:
case DW_OP_lit10:
case DW_OP_lit11:
case DW_OP_lit12:
case DW_OP_lit13:
case DW_OP_lit14:
case DW_OP_lit15:
case DW_OP_lit16:
case DW_OP_lit17:
case DW_OP_lit18:
case DW_OP_lit19:
case DW_OP_lit20:
case DW_OP_lit21:
case DW_OP_lit22:
case DW_OP_lit23:
case DW_OP_lit24:
case DW_OP_lit25:
case DW_OP_lit26:
case DW_OP_lit27:
case DW_OP_lit28:
case DW_OP_lit29:
case DW_OP_lit30:
case DW_OP_lit31:
value = static_cast<pint_t>(opcode - DW_OP_lit0);
*(++sp) = value;
if (log)
fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_reg0:
case DW_OP_reg1:
case DW_OP_reg2:
case DW_OP_reg3:
case DW_OP_reg4:
case DW_OP_reg5:
case DW_OP_reg6:
case DW_OP_reg7:
case DW_OP_reg8:
case DW_OP_reg9:
case DW_OP_reg10:
case DW_OP_reg11:
case DW_OP_reg12:
case DW_OP_reg13:
case DW_OP_reg14:
case DW_OP_reg15:
case DW_OP_reg16:
case DW_OP_reg17:
case DW_OP_reg18:
case DW_OP_reg19:
case DW_OP_reg20:
case DW_OP_reg21:
case DW_OP_reg22:
case DW_OP_reg23:
case DW_OP_reg24:
case DW_OP_reg25:
case DW_OP_reg26:
case DW_OP_reg27:
case DW_OP_reg28:
case DW_OP_reg29:
case DW_OP_reg30:
case DW_OP_reg31:
reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
*(++sp) = registers.getRegister((int)reg);
if (log)
fprintf(stderr, "push reg %d\n", reg);
break;
case DW_OP_regx:
reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
*(++sp) = registers.getRegister((int)reg);
if (log)
fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
break;
case DW_OP_breg0:
case DW_OP_breg1:
case DW_OP_breg2:
case DW_OP_breg3:
case DW_OP_breg4:
case DW_OP_breg5:
case DW_OP_breg6:
case DW_OP_breg7:
case DW_OP_breg8:
case DW_OP_breg9:
case DW_OP_breg10:
case DW_OP_breg11:
case DW_OP_breg12:
case DW_OP_breg13:
case DW_OP_breg14:
case DW_OP_breg15:
case DW_OP_breg16:
case DW_OP_breg17:
case DW_OP_breg18:
case DW_OP_breg19:
case DW_OP_breg20:
case DW_OP_breg21:
case DW_OP_breg22:
case DW_OP_breg23:
case DW_OP_breg24:
case DW_OP_breg25:
case DW_OP_breg26:
case DW_OP_breg27:
case DW_OP_breg28:
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31:
reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
svalue += static_cast<sint_t>(registers.getRegister((int)reg));
*(++sp) = (pint_t)(svalue);
if (log)
fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
break;
case DW_OP_bregx:
reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
svalue += static_cast<sint_t>(registers.getRegister((int)reg));
*(++sp) = (pint_t)(svalue);
if (log)
fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
break;
case DW_OP_fbreg:
_LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
break;
case DW_OP_piece:
_LIBUNWIND_ABORT("DW_OP_piece not implemented");
break;
case DW_OP_deref_size:
// pop stack, dereference, push result
value = *sp--;
switch (addressSpace.get8(p++)) {
case 1:
value = addressSpace.get8(value);
break;
case 2:
value = addressSpace.get16(value);
break;
case 4:
value = addressSpace.get32(value);
break;
case 8:
value = (pint_t)addressSpace.get64(value);
break;
default:
_LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
}
*(++sp) = value;
if (log)
fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
break;
case DW_OP_xderef_size:
case DW_OP_nop:
case DW_OP_push_object_addres:
case DW_OP_call2:
case DW_OP_call4:
case DW_OP_call_ref:
default:
_LIBUNWIND_ABORT("DWARF opcode not implemented");
}
}
if (log)
fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
return *sp;
}
} // namespace libunwind
#endif // __DWARF_INSTRUCTIONS_HPP__

View File

@ -0,0 +1,765 @@
//===--------------------------- DwarfParser.hpp --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Parses DWARF CFIs (FDEs and CIEs).
//
//===----------------------------------------------------------------------===//
#ifndef __DWARF_PARSER_HPP__
#define __DWARF_PARSER_HPP__
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "libunwind.h"
#include "dwarf2.h"
#include "Registers.hpp"
#include "config.h"
namespace libunwind {
/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
/// See DWARF Spec for details:
/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
///
template <typename A>
class CFI_Parser {
public:
typedef typename A::pint_t pint_t;
/// Information encoded in a CIE (Common Information Entry)
struct CIE_Info {
pint_t cieStart;
pint_t cieLength;
pint_t cieInstructions;
uint8_t pointerEncoding;
uint8_t lsdaEncoding;
uint8_t personalityEncoding;
uint8_t personalityOffsetInCIE;
pint_t personality;
uint32_t codeAlignFactor;
int dataAlignFactor;
bool isSignalFrame;
bool fdesHaveAugmentationData;
uint8_t returnAddressRegister;
#if defined(_LIBUNWIND_TARGET_AARCH64)
bool addressesSignedWithBKey;
#endif
};
/// Information about an FDE (Frame Description Entry)
struct FDE_Info {
pint_t fdeStart;
pint_t fdeLength;
pint_t fdeInstructions;
pint_t pcStart;
pint_t pcEnd;
pint_t lsda;
};
enum {
kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER
};
enum RegisterSavedWhere {
kRegisterUnused,
kRegisterInCFA,
kRegisterOffsetFromCFA,
kRegisterInRegister,
kRegisterAtExpression,
kRegisterIsExpression
};
struct RegisterLocation {
RegisterSavedWhere location;
int64_t value;
};
/// Information about a frame layout and registers saved determined
/// by "running" the DWARF FDE "instructions"
struct PrologInfo {
uint32_t cfaRegister;
int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
int64_t cfaExpression; // CFA = expression
uint32_t spExtraArgSize;
uint32_t codeOffsetAtStackDecrement;
bool registersInOtherRegisters;
bool sameValueUsed;
RegisterLocation savedRegisters[kMaxRegisterNumber + 1];
};
struct PrologInfoStackEntry {
PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
: next(n), info(i) {}
PrologInfoStackEntry *next;
PrologInfo info;
};
static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
CIE_Info *cieInfo);
static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
FDE_Info *fdeInfo, CIE_Info *cieInfo);
static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
const CIE_Info &cieInfo, pint_t upToPC,
int arch, PrologInfo *results);
static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
private:
static bool parseInstructions(A &addressSpace, pint_t instructions,
pint_t instructionsEnd, const CIE_Info &cieInfo,
pint_t pcoffset,
PrologInfoStackEntry *&rememberStack, int arch,
PrologInfo *results);
};
/// Parse a FDE into a CIE_Info and an FDE_Info
template <typename A>
const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
FDE_Info *fdeInfo, CIE_Info *cieInfo) {
pint_t p = fdeStart;
pint_t cfiLength = (pint_t)addressSpace.get32(p);
p += 4;
if (cfiLength == 0xffffffff) {
// 0xffffffff means length is really next 8 bytes
cfiLength = (pint_t)addressSpace.get64(p);
p += 8;
}
if (cfiLength == 0)
return "FDE has zero length"; // end marker
uint32_t ciePointer = addressSpace.get32(p);
if (ciePointer == 0)
return "FDE is really a CIE"; // this is a CIE not an FDE
pint_t nextCFI = p + cfiLength;
pint_t cieStart = p - ciePointer;
const char *err = parseCIE(addressSpace, cieStart, cieInfo);
if (err != NULL)
return err;
p += 4;
// Parse pc begin and range.
pint_t pcStart =
addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
pint_t pcRange =
addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
// Parse rest of info.
fdeInfo->lsda = 0;
// Check for augmentation length.
if (cieInfo->fdesHaveAugmentationData) {
pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
pint_t endOfAug = p + augLen;
if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
// Peek at value (without indirection). Zero means no LSDA.
pint_t lsdaStart = p;
if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
0) {
// Reset pointer and re-parse LSDA address.
p = lsdaStart;
fdeInfo->lsda =
addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
}
}
p = endOfAug;
}
fdeInfo->fdeStart = fdeStart;
fdeInfo->fdeLength = nextCFI - fdeStart;
fdeInfo->fdeInstructions = p;
fdeInfo->pcStart = pcStart;
fdeInfo->pcEnd = pcStart + pcRange;
return NULL; // success
}
/// Scan an eh_frame section to find an FDE for a pc
template <typename A>
bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
uint32_t sectionLength, pint_t fdeHint,
FDE_Info *fdeInfo, CIE_Info *cieInfo) {
//fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
const pint_t ehSectionEnd = p + sectionLength;
while (p < ehSectionEnd) {
pint_t currentCFI = p;
//fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
pint_t cfiLength = addressSpace.get32(p);
p += 4;
if (cfiLength == 0xffffffff) {
// 0xffffffff means length is really next 8 bytes
cfiLength = (pint_t)addressSpace.get64(p);
p += 8;
}
if (cfiLength == 0)
return false; // end marker
uint32_t id = addressSpace.get32(p);
if (id == 0) {
// Skip over CIEs.
p += cfiLength;
} else {
// Process FDE to see if it covers pc.
pint_t nextCFI = p + cfiLength;
uint32_t ciePointer = addressSpace.get32(p);
pint_t cieStart = p - ciePointer;
// Validate pointer to CIE is within section.
if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
p += 4;
// Parse pc begin and range.
pint_t pcStart =
addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
pint_t pcRange = addressSpace.getEncodedP(
p, nextCFI, cieInfo->pointerEncoding & 0x0F);
// Test if pc is within the function this FDE covers.
if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
// parse rest of info
fdeInfo->lsda = 0;
// check for augmentation length
if (cieInfo->fdesHaveAugmentationData) {
pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
pint_t endOfAug = p + augLen;
if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
// Peek at value (without indirection). Zero means no LSDA.
pint_t lsdaStart = p;
if (addressSpace.getEncodedP(
p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
// Reset pointer and re-parse LSDA address.
p = lsdaStart;
fdeInfo->lsda = addressSpace
.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
}
}
p = endOfAug;
}
fdeInfo->fdeStart = currentCFI;
fdeInfo->fdeLength = nextCFI - currentCFI;
fdeInfo->fdeInstructions = p;
fdeInfo->pcStart = pcStart;
fdeInfo->pcEnd = pcStart + pcRange;
return true;
} else {
// pc is not in begin/range, skip this FDE
}
} else {
// Malformed CIE, now augmentation describing pc range encoding.
}
} else {
// malformed FDE. CIE is bad
}
p = nextCFI;
}
}
return false;
}
/// Extract info from a CIE
template <typename A>
const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
CIE_Info *cieInfo) {
cieInfo->pointerEncoding = 0;
cieInfo->lsdaEncoding = DW_EH_PE_omit;
cieInfo->personalityEncoding = 0;
cieInfo->personalityOffsetInCIE = 0;
cieInfo->personality = 0;
cieInfo->codeAlignFactor = 0;
cieInfo->dataAlignFactor = 0;
cieInfo->isSignalFrame = false;
cieInfo->fdesHaveAugmentationData = false;
#if defined(_LIBUNWIND_TARGET_AARCH64)
cieInfo->addressesSignedWithBKey = false;
#endif
cieInfo->cieStart = cie;
pint_t p = cie;
pint_t cieLength = (pint_t)addressSpace.get32(p);
p += 4;
pint_t cieContentEnd = p + cieLength;
if (cieLength == 0xffffffff) {
// 0xffffffff means length is really next 8 bytes
cieLength = (pint_t)addressSpace.get64(p);
p += 8;
cieContentEnd = p + cieLength;
}
if (cieLength == 0)
return NULL;
// CIE ID is always 0
if (addressSpace.get32(p) != 0)
return "CIE ID is not zero";
p += 4;
// Version is always 1 or 3
uint8_t version = addressSpace.get8(p);
if ((version != 1) && (version != 3))
return "CIE version is not 1 or 3";
++p;
// save start of augmentation string and find end
pint_t strStart = p;
while (addressSpace.get8(p) != 0)
++p;
++p;
// parse code aligment factor
cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
// parse data alignment factor
cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
// parse return address register
uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
assert(raReg < 255 && "return address register too large");
cieInfo->returnAddressRegister = (uint8_t)raReg;
// parse augmentation data based on augmentation string
const char *result = NULL;
if (addressSpace.get8(strStart) == 'z') {
// parse augmentation data length
addressSpace.getULEB128(p, cieContentEnd);
for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
switch (addressSpace.get8(s)) {
case 'z':
cieInfo->fdesHaveAugmentationData = true;
break;
case 'P':
cieInfo->personalityEncoding = addressSpace.get8(p);
++p;
cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
cieInfo->personality = addressSpace
.getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
break;
case 'L':
cieInfo->lsdaEncoding = addressSpace.get8(p);
++p;
break;
case 'R':
cieInfo->pointerEncoding = addressSpace.get8(p);
++p;
break;
case 'S':
cieInfo->isSignalFrame = true;
break;
#if defined(_LIBUNWIND_TARGET_AARCH64)
case 'B':
cieInfo->addressesSignedWithBKey = true;
break;
#endif
default:
// ignore unknown letters
break;
}
}
}
cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
cieInfo->cieInstructions = p;
return result;
}
/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE
template <typename A>
bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
const FDE_Info &fdeInfo,
const CIE_Info &cieInfo, pint_t upToPC,
int arch, PrologInfo *results) {
// clear results
memset(results, '\0', sizeof(PrologInfo));
PrologInfoStackEntry *rememberStack = NULL;
// parse CIE then FDE instructions
return parseInstructions(addressSpace, cieInfo.cieInstructions,
cieInfo.cieStart + cieInfo.cieLength, cieInfo,
(pint_t)(-1), rememberStack, arch, results) &&
parseInstructions(addressSpace, fdeInfo.fdeInstructions,
fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
upToPC - fdeInfo.pcStart, rememberStack, arch,
results);
}
/// "run" the DWARF instructions
template <typename A>
bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
pint_t instructionsEnd,
const CIE_Info &cieInfo, pint_t pcoffset,
PrologInfoStackEntry *&rememberStack,
int arch, PrologInfo *results) {
pint_t p = instructions;
pint_t codeOffset = 0;
PrologInfo initialState = *results;
_LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n",
static_cast<uint64_t>(instructionsEnd));
// see DWARF Spec, section 6.4.2 for details on unwind opcodes
while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
uint64_t reg;
uint64_t reg2;
int64_t offset;
uint64_t length;
uint8_t opcode = addressSpace.get8(p);
uint8_t operand;
#if !defined(_LIBUNWIND_NO_HEAP)
PrologInfoStackEntry *entry;
#endif
++p;
switch (opcode) {
case DW_CFA_nop:
_LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
break;
case DW_CFA_set_loc:
codeOffset =
addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
_LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
break;
case DW_CFA_advance_loc1:
codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
p += 1;
_LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
static_cast<uint64_t>(codeOffset));
break;
case DW_CFA_advance_loc2:
codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
p += 2;
_LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
static_cast<uint64_t>(codeOffset));
break;
case DW_CFA_advance_loc4:
codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
p += 4;
_LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
static_cast<uint64_t>(codeOffset));
break;
case DW_CFA_offset_extended:
reg = addressSpace.getULEB128(p, instructionsEnd);
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
* cieInfo.dataAlignFactor;
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_offset_extended DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value = offset;
_LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", "
"offset=%" PRId64 ")\n",
reg, offset);
break;
case DW_CFA_restore_extended:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_restore_extended DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg] = initialState.savedRegisters[reg];
_LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg);
break;
case DW_CFA_undefined:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_undefined DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg].location = kRegisterUnused;
_LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
break;
case DW_CFA_same_value:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_same_value DWARF unwind, reg too big");
return false;
}
// <rdar://problem/8456377> DW_CFA_same_value unsupported
// "same value" means register was stored in frame, but its current
// value has not changed, so no need to restore from frame.
// We model this as if the register was never saved.
results->savedRegisters[reg].location = kRegisterUnused;
// set flag to disable conversion to compact unwind
results->sameValueUsed = true;
_LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
break;
case DW_CFA_register:
reg = addressSpace.getULEB128(p, instructionsEnd);
reg2 = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_register DWARF unwind, reg too big");
return false;
}
if (reg2 > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_register DWARF unwind, reg2 too big");
return false;
}
results->savedRegisters[reg].location = kRegisterInRegister;
results->savedRegisters[reg].value = (int64_t)reg2;
// set flag to disable conversion to compact unwind
results->registersInOtherRegisters = true;
_LIBUNWIND_TRACE_DWARF(
"DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
break;
#if !defined(_LIBUNWIND_NO_HEAP)
case DW_CFA_remember_state:
// avoid operator new, because that would be an upward dependency
entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
if (entry != NULL) {
entry->next = rememberStack;
entry->info = *results;
rememberStack = entry;
} else {
return false;
}
_LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
break;
case DW_CFA_restore_state:
if (rememberStack != NULL) {
PrologInfoStackEntry *top = rememberStack;
*results = top->info;
rememberStack = top->next;
free((char *)top);
} else {
return false;
}
_LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
break;
#endif
case DW_CFA_def_cfa:
reg = addressSpace.getULEB128(p, instructionsEnd);
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
return false;
}
results->cfaRegister = (uint32_t)reg;
results->cfaRegisterOffset = (int32_t)offset;
_LIBUNWIND_TRACE_DWARF(
"DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset);
break;
case DW_CFA_def_cfa_register:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
return false;
}
results->cfaRegister = (uint32_t)reg;
_LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
break;
case DW_CFA_def_cfa_offset:
results->cfaRegisterOffset = (int32_t)
addressSpace.getULEB128(p, instructionsEnd);
results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
_LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
results->cfaRegisterOffset);
break;
case DW_CFA_def_cfa_expression:
results->cfaRegister = 0;
results->cfaExpression = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
assert(length < static_cast<pint_t>(~0) && "pointer overflow");
p += static_cast<pint_t>(length);
_LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
", length=%" PRIu64 ")\n",
results->cfaExpression, length);
break;
case DW_CFA_expression:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_expression DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg].location = kRegisterAtExpression;
results->savedRegisters[reg].value = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
assert(length < static_cast<pint_t>(~0) && "pointer overflow");
p += static_cast<pint_t>(length);
_LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", "
"expression=0x%" PRIx64 ", "
"length=%" PRIu64 ")\n",
reg, results->savedRegisters[reg].value, length);
break;
case DW_CFA_offset_extended_sf:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
return false;
}
offset =
addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value = offset;
_LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", "
"offset=%" PRId64 ")\n",
reg, offset);
break;
case DW_CFA_def_cfa_sf:
reg = addressSpace.getULEB128(p, instructionsEnd);
offset =
addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
return false;
}
results->cfaRegister = (uint32_t)reg;
results->cfaRegisterOffset = (int32_t)offset;
_LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", "
"offset=%" PRId64 ")\n",
reg, offset);
break;
case DW_CFA_def_cfa_offset_sf:
results->cfaRegisterOffset = (int32_t)
(addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
_LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
results->cfaRegisterOffset);
break;
case DW_CFA_val_offset:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG(
"malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
") out of range\n",
reg);
return false;
}
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
* cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
results->savedRegisters[reg].value = offset;
_LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", "
"offset=%" PRId64 "\n",
reg, offset);
break;
case DW_CFA_val_offset_sf:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
return false;
}
offset =
addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
results->savedRegisters[reg].value = offset;
_LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", "
"offset=%" PRId64 "\n",
reg, offset);
break;
case DW_CFA_val_expression:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0(
"malformed DW_CFA_val_expression DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg].location = kRegisterIsExpression;
results->savedRegisters[reg].value = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
assert(length < static_cast<pint_t>(~0) && "pointer overflow");
p += static_cast<pint_t>(length);
_LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", "
"expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
reg, results->savedRegisters[reg].value, length);
break;
case DW_CFA_GNU_args_size:
length = addressSpace.getULEB128(p, instructionsEnd);
results->spExtraArgSize = (uint32_t)length;
_LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
break;
case DW_CFA_GNU_negative_offset_extended:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
"unwind, reg too big");
return false;
}
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
* cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value = -offset;
_LIBUNWIND_TRACE_DWARF(
"DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
break;
#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC)
// The same constant is used to represent different instructions on
// AArch64 (negate_ra_state) and SPARC (window_save).
static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
"uses the same constant");
case DW_CFA_AARCH64_negate_ra_state:
switch (arch) {
#if defined(_LIBUNWIND_TARGET_AARCH64)
case REGISTERS_ARM64:
results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1;
_LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
break;
#endif
#if defined(_LIBUNWIND_TARGET_SPARC)
// case DW_CFA_GNU_window_save:
case REGISTERS_SPARC:
_LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) {
results->savedRegisters[reg].location = kRegisterInRegister;
results->savedRegisters[reg].value =
((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0;
}
for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value =
((int64_t)reg - UNW_SPARC_L0) * 4;
}
break;
#endif
}
break;
#else
(void)arch;
#endif
default:
operand = opcode & 0x3F;
switch (opcode & 0xC0) {
case DW_CFA_offset:
reg = operand;
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
") out of range",
reg);
return false;
}
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
* cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value = offset;
_LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
operand, offset);
break;
case DW_CFA_advance_loc:
codeOffset += operand * cieInfo.codeAlignFactor;
_LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
static_cast<uint64_t>(codeOffset));
break;
case DW_CFA_restore:
reg = operand;
if (reg > kMaxRegisterNumber) {
_LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
") out of range",
reg);
return false;
}
results->savedRegisters[reg] = initialState.savedRegisters[reg];
_LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
static_cast<uint64_t>(operand));
break;
default:
_LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
return false;
}
}
}
return true;
}
} // namespace libunwind
#endif // __DWARF_PARSER_HPP__

View File

@ -0,0 +1,167 @@
//===------------------------- EHHeaderParser.hpp -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Parses ELF .eh_frame_hdr sections.
//
//===----------------------------------------------------------------------===//
#ifndef __EHHEADERPARSER_HPP__
#define __EHHEADERPARSER_HPP__
#include "libunwind.h"
#include "DwarfParser.hpp"
namespace libunwind {
/// \brief EHHeaderParser does basic parsing of an ELF .eh_frame_hdr section.
///
/// See DWARF spec for details:
/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
///
template <typename A> class EHHeaderParser {
public:
typedef typename A::pint_t pint_t;
/// Information encoded in the EH frame header.
struct EHHeaderInfo {
pint_t eh_frame_ptr;
size_t fde_count;
pint_t table;
uint8_t table_enc;
};
static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
EHHeaderInfo &ehHdrInfo);
static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
uint32_t sectionLength,
typename CFI_Parser<A>::FDE_Info *fdeInfo,
typename CFI_Parser<A>::CIE_Info *cieInfo);
private:
static bool decodeTableEntry(A &addressSpace, pint_t &tableEntry,
pint_t ehHdrStart, pint_t ehHdrEnd,
uint8_t tableEnc,
typename CFI_Parser<A>::FDE_Info *fdeInfo,
typename CFI_Parser<A>::CIE_Info *cieInfo);
static size_t getTableEntrySize(uint8_t tableEnc);
};
template <typename A>
bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
pint_t p = ehHdrStart;
uint8_t version = addressSpace.get8(p++);
if (version != 1) {
_LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version");
return false;
}
uint8_t eh_frame_ptr_enc = addressSpace.get8(p++);
uint8_t fde_count_enc = addressSpace.get8(p++);
ehHdrInfo.table_enc = addressSpace.get8(p++);
ehHdrInfo.eh_frame_ptr =
addressSpace.getEncodedP(p, ehHdrEnd, eh_frame_ptr_enc, ehHdrStart);
ehHdrInfo.fde_count =
fde_count_enc == DW_EH_PE_omit
? 0
: addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart);
ehHdrInfo.table = p;
return true;
}
template <typename A>
bool EHHeaderParser<A>::decodeTableEntry(
A &addressSpace, pint_t &tableEntry, pint_t ehHdrStart, pint_t ehHdrEnd,
uint8_t tableEnc, typename CFI_Parser<A>::FDE_Info *fdeInfo,
typename CFI_Parser<A>::CIE_Info *cieInfo) {
// Have to decode the whole FDE for the PC range anyway, so just throw away
// the PC start.
addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart);
pint_t fde =
addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart);
const char *message =
CFI_Parser<A>::decodeFDE(addressSpace, fde, fdeInfo, cieInfo);
if (message != NULL) {
_LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s",
message);
return false;
}
return true;
}
template <typename A>
bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
uint32_t sectionLength,
typename CFI_Parser<A>::FDE_Info *fdeInfo,
typename CFI_Parser<A>::CIE_Info *cieInfo) {
pint_t ehHdrEnd = ehHdrStart + sectionLength;
EHHeaderParser<A>::EHHeaderInfo hdrInfo;
if (!EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd,
hdrInfo))
return false;
size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc);
pint_t tableEntry;
size_t low = 0;
for (size_t len = hdrInfo.fde_count; len > 1;) {
size_t mid = low + (len / 2);
tableEntry = hdrInfo.table + mid * tableEntrySize;
pint_t start = addressSpace.getEncodedP(tableEntry, ehHdrEnd,
hdrInfo.table_enc, ehHdrStart);
if (start == pc) {
low = mid;
break;
} else if (start < pc) {
low = mid;
len -= (len / 2);
} else {
len /= 2;
}
}
tableEntry = hdrInfo.table + low * tableEntrySize;
if (decodeTableEntry(addressSpace, tableEntry, ehHdrStart, ehHdrEnd,
hdrInfo.table_enc, fdeInfo, cieInfo)) {
if (pc >= fdeInfo->pcStart && pc < fdeInfo->pcEnd)
return true;
}
return false;
}
template <typename A>
size_t EHHeaderParser<A>::getTableEntrySize(uint8_t tableEnc) {
switch (tableEnc & 0x0f) {
case DW_EH_PE_sdata2:
case DW_EH_PE_udata2:
return 4;
case DW_EH_PE_sdata4:
case DW_EH_PE_udata4:
return 8;
case DW_EH_PE_sdata8:
case DW_EH_PE_udata8:
return 16;
case DW_EH_PE_sleb128:
case DW_EH_PE_uleb128:
_LIBUNWIND_ABORT("Can't binary search on variable length encoded data.");
case DW_EH_PE_omit:
return 0;
default:
_LIBUNWIND_ABORT("Unknown DWARF encoding for search table.");
}
}
}
#endif

View File

@ -0,0 +1,114 @@
//===----------------------------- Registers.hpp --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Abstract interface to shared reader/writer log, hiding platform and
// configuration differences.
//
//===----------------------------------------------------------------------===//
#ifndef __RWMUTEX_HPP__
#define __RWMUTEX_HPP__
#if defined(_WIN32)
#include <windows.h>
#elif !defined(_LIBUNWIND_HAS_NO_THREADS)
#include <pthread.h>
#if defined(__unix__) && !defined(__ANDROID__) && defined(__ELF__) && defined(_LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
#pragma comment(lib, "pthread")
#endif
#endif
namespace libunwind {
#if defined(_LIBUNWIND_HAS_NO_THREADS)
class _LIBUNWIND_HIDDEN RWMutex {
public:
bool lock_shared() { return true; }
bool unlock_shared() { return true; }
bool lock() { return true; }
bool unlock() { return true; }
};
#elif defined(_WIN32)
class _LIBUNWIND_HIDDEN RWMutex {
public:
bool lock_shared() {
AcquireSRWLockShared(&_lock);
return true;
}
bool unlock_shared() {
ReleaseSRWLockShared(&_lock);
return true;
}
bool lock() {
AcquireSRWLockExclusive(&_lock);
return true;
}
bool unlock() {
ReleaseSRWLockExclusive(&_lock);
return true;
}
private:
SRWLOCK _lock = SRWLOCK_INIT;
};
#elif !defined(LIBUNWIND_USE_WEAK_PTHREAD)
class _LIBUNWIND_HIDDEN RWMutex {
public:
bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0; }
bool unlock_shared() { return pthread_rwlock_unlock(&_lock) == 0; }
bool lock() { return pthread_rwlock_wrlock(&_lock) == 0; }
bool unlock() { return pthread_rwlock_unlock(&_lock) == 0; }
private:
pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER;
};
#else
extern "C" int __attribute__((weak))
pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
extern "C" int __attribute__((weak))
pthread_rwlock_rdlock(pthread_rwlock_t *lock);
extern "C" int __attribute__((weak))
pthread_rwlock_wrlock(pthread_rwlock_t *lock);
extern "C" int __attribute__((weak))
pthread_rwlock_unlock(pthread_rwlock_t *lock);
// Calls to the locking functions are gated on pthread_create, and not the
// functions themselves, because the data structure should only be locked if
// another thread has been created. This is what similar libraries do.
class _LIBUNWIND_HIDDEN RWMutex {
public:
bool lock_shared() {
return !pthread_create || (pthread_rwlock_rdlock(&_lock) == 0);
}
bool unlock_shared() {
return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0);
}
bool lock() {
return !pthread_create || (pthread_rwlock_wrlock(&_lock) == 0);
}
bool unlock() {
return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0);
}
private:
pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER;
};
#endif
} // namespace libunwind
#endif // __RWMUTEX_HPP__

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
//===------------------------- Unwind-EHABI.hpp ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
//===----------------------------------------------------------------------===//
#ifndef __UNWIND_EHABI_H__
#define __UNWIND_EHABI_H__
#include <__libunwind_config.h>
#if defined(_LIBUNWIND_ARM_EHABI)
#include <stdint.h>
#include <unwind.h>
// Unable to unwind in the ARM index table (section 5 EHABI).
#define UNW_EXIDX_CANTUNWIND 0x1
static inline uint32_t signExtendPrel31(uint32_t data) {
return data | ((data & 0x40000000u) << 1);
}
static inline uint32_t readPrel31(const uint32_t *data) {
return (((uint32_t)(uintptr_t)data) + signExtendPrel31(*data));
}
#if defined(__cplusplus)
extern "C" {
#endif
extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(
_Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(
_Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(
_Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // defined(_LIBUNWIND_ARM_EHABI)
#endif // __UNWIND_EHABI_H__

View File

@ -0,0 +1,501 @@
//===--------------------------- Unwind-seh.cpp ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Implements SEH-based Itanium C++ exceptions.
//
//===----------------------------------------------------------------------===//
#include "config.h"
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
#include <unwind.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <windef.h>
#include <excpt.h>
#include <winnt.h>
#include <ntstatus.h>
#include "libunwind_ext.h"
#include "UnwindCursor.hpp"
using namespace libunwind;
#define STATUS_USER_DEFINED (1u << 29)
#define STATUS_GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C')
#define MAKE_CUSTOM_STATUS(s, c) \
((NTSTATUS)(((s) << 30) | STATUS_USER_DEFINED | (c)))
#define MAKE_GCC_EXCEPTION(c) \
MAKE_CUSTOM_STATUS(STATUS_SEVERITY_SUCCESS, STATUS_GCC_MAGIC | ((c) << 24))
/// SEH exception raised by libunwind when the program calls
/// \c _Unwind_RaiseException.
#define STATUS_GCC_THROW MAKE_GCC_EXCEPTION(0) // 0x20474343
/// SEH exception raised by libunwind to initiate phase 2 of exception
/// handling.
#define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x21474343
/// Class of foreign exceptions based on unrecognized SEH exceptions.
static const uint64_t kSEHExceptionClass = 0x434C4E4753454800; // CLNGSEH\0
/// Exception cleanup routine used by \c _GCC_specific_handler to
/// free foreign exceptions.
static void seh_exc_cleanup(_Unwind_Reason_Code urc, _Unwind_Exception *exc) {
(void)urc;
if (exc->exception_class != kSEHExceptionClass)
_LIBUNWIND_ABORT("SEH cleanup called on non-SEH exception");
free(exc);
}
static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx);
static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor);
static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor,
DISPATCHER_CONTEXT *disp);
/// Common implementation of SEH-style handler functions used by Itanium-
/// style frames. Depending on how and why it was called, it may do one of:
/// a) Delegate to the given Itanium-style personality function; or
/// b) Initiate a collided unwind to halt unwinding.
_LIBUNWIND_EXPORT EXCEPTION_DISPOSITION
_GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
DISPATCHER_CONTEXT *disp, __personality_routine pers) {
unw_cursor_t cursor;
_Unwind_Exception *exc;
_Unwind_Action action;
struct _Unwind_Context *ctx = nullptr;
_Unwind_Reason_Code urc;
uintptr_t retval, target;
bool ours = false;
_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010lx(%lx), %p)",
ms_exc->ExceptionCode, ms_exc->ExceptionFlags,
(void *)frame);
if (ms_exc->ExceptionCode == STATUS_GCC_UNWIND) {
if (IS_TARGET_UNWIND(ms_exc->ExceptionFlags)) {
// Set up the upper return value (the lower one and the target PC
// were set in the call to RtlUnwindEx()) for the landing pad.
#ifdef __x86_64__
disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3];
#elif defined(__arm__)
disp->ContextRecord->R1 = ms_exc->ExceptionInformation[3];
#elif defined(__aarch64__)
disp->ContextRecord->X1 = ms_exc->ExceptionInformation[3];
#endif
}
// This is the collided unwind to the landing pad. Nothing to do.
return ExceptionContinueSearch;
}
if (ms_exc->ExceptionCode == STATUS_GCC_THROW) {
// This is (probably) a libunwind-controlled exception/unwind. Recover the
// parameters which we set below, and pass them to the personality function.
ours = true;
exc = (_Unwind_Exception *)ms_exc->ExceptionInformation[0];
if (!IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) {
ctx = (struct _Unwind_Context *)ms_exc->ExceptionInformation[1];
action = (_Unwind_Action)ms_exc->ExceptionInformation[2];
}
} else {
// Foreign exception.
exc = (_Unwind_Exception *)malloc(sizeof(_Unwind_Exception));
exc->exception_class = kSEHExceptionClass;
exc->exception_cleanup = seh_exc_cleanup;
memset(exc->private_, 0, sizeof(exc->private_));
}
if (!ctx) {
__unw_init_seh(&cursor, disp->ContextRecord);
__unw_seh_set_disp_ctx(&cursor, disp);
__unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc - 1);
ctx = (struct _Unwind_Context *)&cursor;
if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {
if (ours && ms_exc->NumberParameters > 1)
action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND);
else
action = _UA_SEARCH_PHASE;
} else {
if (ours && ms_exc->ExceptionInformation[1] == (ULONG_PTR)frame)
action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
else
action = _UA_CLEANUP_PHASE;
}
}
_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality "
"function %p(1, %d, %llx, %p, %p)",
(void *)pers, action, exc->exception_class,
(void *)exc, (void *)ctx);
urc = pers(1, action, exc->exception_class, exc, ctx);
_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() personality returned %d", urc);
switch (urc) {
case _URC_CONTINUE_UNWIND:
// If we're in phase 2, and the personality routine said to continue
// at the target frame, we're in real trouble.
if (action & _UA_HANDLER_FRAME)
_LIBUNWIND_ABORT("Personality continued unwind at the target frame!");
return ExceptionContinueSearch;
case _URC_HANDLER_FOUND:
// If we were called by __libunwind_seh_personality(), indicate that
// a handler was found; otherwise, initiate phase 2 by unwinding.
if (ours && ms_exc->NumberParameters > 1)
return 4 /* ExecptionExecuteHandler in mingw */;
// This should never happen in phase 2.
if (IS_UNWINDING(ms_exc->ExceptionFlags))
_LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");
exc->private_[1] = (ULONG_PTR)frame;
if (ours) {
ms_exc->NumberParameters = 4;
ms_exc->ExceptionInformation[1] = (ULONG_PTR)frame;
}
// FIXME: Indicate target frame in foreign case!
// phase 2: the clean up phase
RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, ms_ctx, disp->HistoryTable);
_LIBUNWIND_ABORT("RtlUnwindEx() failed");
case _URC_INSTALL_CONTEXT: {
// If we were called by __libunwind_seh_personality(), indicate that
// a handler was found; otherwise, it's time to initiate a collided
// unwind to the target.
if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)
return 4 /* ExecptionExecuteHandler in mingw */;
// This should never happen in phase 1.
if (!IS_UNWINDING(ms_exc->ExceptionFlags))
_LIBUNWIND_ABORT("Personality installed context during phase 1!");
#ifdef __x86_64__
exc->private_[2] = disp->TargetIp;
__unw_get_reg(&cursor, UNW_X86_64_RAX, &retval);
__unw_get_reg(&cursor, UNW_X86_64_RDX, &exc->private_[3]);
#elif defined(__arm__)
exc->private_[2] = disp->TargetPc;
__unw_get_reg(&cursor, UNW_ARM_R0, &retval);
__unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]);
#elif defined(__aarch64__)
exc->private_[2] = disp->TargetPc;
__unw_get_reg(&cursor, UNW_ARM64_X0, &retval);
__unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]);
#endif
__unw_get_reg(&cursor, UNW_REG_IP, &target);
ms_exc->ExceptionCode = STATUS_GCC_UNWIND;
#ifdef __x86_64__
ms_exc->ExceptionInformation[2] = disp->TargetIp;
#elif defined(__arm__) || defined(__aarch64__)
ms_exc->ExceptionInformation[2] = disp->TargetPc;
#endif
ms_exc->ExceptionInformation[3] = exc->private_[3];
// Give NTRTL some scratch space to keep track of the collided unwind.
// Don't use the one that was passed in; we don't want to overwrite the
// context in the DISPATCHER_CONTEXT.
CONTEXT new_ctx;
RtlUnwindEx(frame, (PVOID)target, ms_exc, (PVOID)retval, &new_ctx, disp->HistoryTable);
_LIBUNWIND_ABORT("RtlUnwindEx() failed");
}
// Anything else indicates a serious problem.
default: return ExceptionContinueExecution;
}
}
/// Personality function returned by \c __unw_get_proc_info() in SEH contexts.
/// This is a wrapper that calls the real SEH handler function, which in
/// turn (at least, for Itanium-style frames) calls the real Itanium
/// personality function (see \c _GCC_specific_handler()).
extern "C" _Unwind_Reason_Code
__libunwind_seh_personality(int version, _Unwind_Action state,
uint64_t klass, _Unwind_Exception *exc,
struct _Unwind_Context *context) {
(void)version;
(void)klass;
EXCEPTION_RECORD ms_exc;
bool phase2 = (state & (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)) == _UA_CLEANUP_PHASE;
ms_exc.ExceptionCode = STATUS_GCC_THROW;
ms_exc.ExceptionFlags = 0;
ms_exc.NumberParameters = 3;
ms_exc.ExceptionInformation[0] = (ULONG_PTR)exc;
ms_exc.ExceptionInformation[1] = (ULONG_PTR)context;
ms_exc.ExceptionInformation[2] = state;
DISPATCHER_CONTEXT *disp_ctx =
__unw_seh_get_disp_ctx((unw_cursor_t *)context);
EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,
(PVOID)disp_ctx->EstablisherFrame,
disp_ctx->ContextRecord,
disp_ctx);
switch (ms_act) {
case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
case 4 /*ExceptionExecuteHandler*/:
return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND;
default:
return phase2 ? _URC_FATAL_PHASE2_ERROR : _URC_FATAL_PHASE1_ERROR;
}
}
static _Unwind_Reason_Code
unwind_phase2_forced(unw_context_t *uc,
_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter) {
unw_cursor_t cursor2;
__unw_init_local(&cursor2, uc);
// Walk each frame until we reach where search phase said to stop
while (__unw_step(&cursor2) > 0) {
// Update info about this frame.
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step "
"failed => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((__unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64
", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64,
(void *)exception_object, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
// Call stop function at each frame.
_Unwind_Action action =
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
_Unwind_Reason_Code stopResult =
(*stop)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(&cursor2), stop_parameter);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
(void *)exception_object, stopResult);
if (stopResult != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
// If there is a personality routine, tell it we are unwinding.
if (frameInfo.handler != 0) {
__personality_routine p =
(__personality_routine)(intptr_t)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(&cursor2));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned "
"_URC_CONTINUE_UNWIND",
(void *)exception_object);
// Destructors called, continue unwinding
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned "
"_URC_INSTALL_CONTEXT",
(void *)exception_object);
// We may get control back if landing pad calls _Unwind_Resume().
__unw_resume(&cursor2);
break;
default:
// Personality routine returned an unknown result code.
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned %d, "
"_URC_FATAL_PHASE2_ERROR",
(void *)exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
}
}
// Call stop function one last time and tell it we've reached the end
// of the stack.
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
"function with _UA_END_OF_STACK",
(void *)exception_object);
_Unwind_Action lastAction =
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
(*stop)(1, lastAction, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(&cursor2), stop_parameter);
// Clean up phase did not resume at the frame that the search phase said it
// would.
return _URC_FATAL_PHASE2_ERROR;
}
/// Called by \c __cxa_throw(). Only returns if there is a fatal error.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
(void *)exception_object);
// Mark that this is a non-forced unwind, so _Unwind_Resume()
// can do the right thing.
memset(exception_object->private_, 0, sizeof(exception_object->private_));
// phase 1: the search phase
// We'll let the system do that for us.
RaiseException(STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exception_object);
// If we get here, either something went horribly wrong or we reached the
// top of the stack. Either way, let libc++abi call std::terminate().
return _URC_END_OF_STACK;
}
/// When \c _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame. The personality
/// may force a jump to a landing pad in that function; the landing
/// pad code may then call \c _Unwind_Resume() to continue with the
/// unwinding. Note: the call to \c _Unwind_Resume() is from compiler
/// geneated user code. All other \c _Unwind_* routines are called
/// by the C++ runtime \c __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
/// is implemented by having the code call \c __cxa_rethrow() which
/// in turn calls \c _Unwind_Resume_or_Rethrow().
_LIBUNWIND_EXPORT void
_Unwind_Resume(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
if (exception_object->private_[0] != 0) {
unw_context_t uc;
__unw_getcontext(&uc);
unwind_phase2_forced(&uc, exception_object,
(_Unwind_Stop_Fn) exception_object->private_[0],
(void *)exception_object->private_[4]);
} else {
// Recover the parameters for the unwind from the exception object
// so we can start unwinding again.
EXCEPTION_RECORD ms_exc;
CONTEXT ms_ctx;
UNWIND_HISTORY_TABLE hist;
memset(&ms_exc, 0, sizeof(ms_exc));
memset(&hist, 0, sizeof(hist));
ms_exc.ExceptionCode = STATUS_GCC_THROW;
ms_exc.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ms_exc.NumberParameters = 4;
ms_exc.ExceptionInformation[0] = (ULONG_PTR)exception_object;
ms_exc.ExceptionInformation[1] = exception_object->private_[1];
ms_exc.ExceptionInformation[2] = exception_object->private_[2];
ms_exc.ExceptionInformation[3] = exception_object->private_[3];
RtlUnwindEx((PVOID)exception_object->private_[1],
(PVOID)exception_object->private_[2], &ms_exc,
exception_object, &ms_ctx, &hist);
}
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
}
/// Not used by C++.
/// Unwinds stack, calling "stop" function at each frame.
/// Could be used to implement \c longjmp().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter) {
_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
(void *)exception_object, (void *)(uintptr_t)stop);
unw_context_t uc;
__unw_getcontext(&uc);
// Mark that this is a forced unwind, so _Unwind_Resume() can do
// the right thing.
exception_object->private_[0] = (uintptr_t) stop;
exception_object->private_[4] = (uintptr_t) stop_parameter;
// do it
return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
}
/// Called by personality handler during phase 2 to get LSDA for current frame.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
uintptr_t result =
(uintptr_t)__unw_seh_get_disp_ctx((unw_cursor_t *)context)->HandlerData;
_LIBUNWIND_TRACE_API(
"_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
return result;
}
/// Called by personality handler during phase 2 to find the start of the
/// function.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
DISPATCHER_CONTEXT *disp = __unw_seh_get_disp_ctx((unw_cursor_t *)context);
uintptr_t result = (uintptr_t)disp->FunctionEntry->BeginAddress + disp->ImageBase;
_LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
return result;
}
static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {
#ifdef _LIBUNWIND_TARGET_X86_64
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_x86_64>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
#elif defined(_LIBUNWIND_TARGET_ARM)
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_arm>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
#elif defined(_LIBUNWIND_TARGET_AARCH64)
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_arm64>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
#else
return UNW_EINVAL;
#endif
}
static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor) {
#ifdef _LIBUNWIND_TARGET_X86_64
return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->getDispatcherContext();
#elif defined(_LIBUNWIND_TARGET_ARM)
return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->getDispatcherContext();
#elif defined(_LIBUNWIND_TARGET_AARCH64)
return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->getDispatcherContext();
#else
return nullptr;
#endif
}
static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor,
DISPATCHER_CONTEXT *disp) {
#ifdef _LIBUNWIND_TARGET_X86_64
reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->setDispatcherContext(disp);
#elif defined(_LIBUNWIND_TARGET_ARM)
reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->setDispatcherContext(disp);
#elif defined(_LIBUNWIND_TARGET_AARCH64)
reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->setDispatcherContext(disp);
#endif
}
#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)

View File

@ -0,0 +1,516 @@
//===--------------------------- Unwind-sjlj.c ----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements setjump-longjump based C++ exceptions
//
//===----------------------------------------------------------------------===//
#include <unwind.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "config.h"
/// With SJLJ based exceptions, any function that has a catch clause or needs to
/// do any clean up when an exception propagates through it, needs to call
/// \c _Unwind_SjLj_Register at the start of the function and
/// \c _Unwind_SjLj_Unregister at the end. The register function is called with
/// the address of a block of memory in the function's stack frame. The runtime
/// keeps a linked list (stack) of these blocks - one per thread. The calling
/// function also sets the personality and lsda fields of the block.
#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
struct _Unwind_FunctionContext {
// next function in stack of handlers
struct _Unwind_FunctionContext *prev;
// set by calling function before registering to be the landing pad
uint32_t resumeLocation;
// set by personality handler to be parameters passed to landing pad function
uint32_t resumeParameters[4];
// set by calling function before registering
__personality_routine personality; // arm offset=24
uintptr_t lsda; // arm offset=28
// variable length array, contains registers to restore
// 0 = r7, 1 = pc, 2 = sp
void *jbuf[];
};
#if defined(_LIBUNWIND_HAS_NO_THREADS)
# define _LIBUNWIND_THREAD_LOCAL
#else
# if __STDC_VERSION__ >= 201112L
# define _LIBUNWIND_THREAD_LOCAL _Thread_local
# elif defined(_MSC_VER)
# define _LIBUNWIND_THREAD_LOCAL __declspec(thread)
# elif defined(__GNUC__) || defined(__clang__)
# define _LIBUNWIND_THREAD_LOCAL __thread
# else
# error Unable to create thread local storage
# endif
#endif
#if !defined(FOR_DYLD)
#if defined(__APPLE__)
#include <System/pthread_machdep.h>
#else
static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL;
#endif
static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
#if defined(__APPLE__)
return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
#else
return stack;
#endif
}
static void
__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
#if defined(__APPLE__)
_pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc);
#else
stack = fc;
#endif
}
#endif
/// Called at start of each function that catches exceptions
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) {
fc->prev = __Unwind_SjLj_GetTopOfFunctionStack();
__Unwind_SjLj_SetTopOfFunctionStack(fc);
}
/// Called at end of each function that catches exceptions
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) {
__Unwind_SjLj_SetTopOfFunctionStack(fc->prev);
}
static _Unwind_Reason_Code
unwind_phase1(struct _Unwind_Exception *exception_object) {
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p",
(void *)c);
// walk each frame looking for a place to stop
for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
// check for no more frames
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
}
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", (void *)c);
// if there is a personality routine, ask it if it will want to stop at this
// frame
if (c->personality != NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling "
"personality function %p",
(void *)exception_object,
(void *)c->personality);
_Unwind_Reason_Code personalityResult = (*c->personality)(
1, _UA_SEARCH_PHASE, exception_object->exception_class,
exception_object, (struct _Unwind_Context *)c);
switch (personalityResult) {
case _URC_HANDLER_FOUND:
// found a catch clause or locals that need destructing in this frame
// stop search and remember function context
handlerNotFound = false;
exception_object->private_2 = (uintptr_t) c;
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
"_URC_HANDLER_FOUND",
(void *)exception_object);
return _URC_NO_REASON;
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
"_URC_CONTINUE_UNWIND",
(void *)exception_object);
// continue unwinding
break;
default:
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
}
}
return _URC_NO_REASON;
}
static _Unwind_Reason_Code
unwind_phase2(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
(void *)exception_object);
// walk each frame until we reach where search phase said to stop
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
while (true) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p",
(void *)exception_object, (void *)c);
// check for no more frames
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): __unw_step() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
}
// if there is a personality routine, tell it we are unwinding
if (c->personality != NULL) {
_Unwind_Action action = _UA_CLEANUP_PHASE;
if ((uintptr_t) c == exception_object->private_2)
action = (_Unwind_Action)(
_UA_CLEANUP_PHASE |
_UA_HANDLER_FRAME); // tell personality this was the frame it marked
// in phase 1
_Unwind_Reason_Code personalityResult =
(*c->personality)(1, action, exception_object->exception_class,
exception_object, (struct _Unwind_Context *)c);
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
// continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
if ((uintptr_t) c == exception_object->private_2) {
// phase 1 said we would stop at this frame, but we did not...
_LIBUNWIND_ABORT("during phase1 personality function said it would "
"stop here, but now if phase2 it did not stop here");
}
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): "
"_URC_INSTALL_CONTEXT, will resume at "
"landing pad %p",
(void *)exception_object, c->jbuf[1]);
// personality routine says to transfer control to landing pad
// we may get control back if landing pad calls _Unwind_Resume()
__Unwind_SjLj_SetTopOfFunctionStack(c);
__builtin_longjmp(c->jbuf, 1);
// __unw_resume() only returns if there was an error
return _URC_FATAL_PHASE2_ERROR;
default:
// something went wrong
_LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
}
c = c->prev;
}
// clean up phase did not resume at the frame that the search phase said it
// would
return _URC_FATAL_PHASE2_ERROR;
}
static _Unwind_Reason_Code
unwind_phase2_forced(struct _Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter) {
// walk each frame until we reach where search phase said to stop
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
while (true) {
// get next frame (skip over first which is _Unwind_RaiseException)
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): __unw_step() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
}
// call stop function at each frame
_Unwind_Action action =
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
_Unwind_Reason_Code stopResult =
(*stop)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)c, stop_parameter);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"stop function returned %d",
(void *)exception_object, stopResult);
if (stopResult != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"stopped by stop function",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
// if there is a personality routine, tell it we are unwinding
if (c->personality != NULL) {
__personality_routine p = (__personality_routine) c->personality;
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"calling personality function %p",
(void *)exception_object, (void *)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)c);
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned _URC_CONTINUE_UNWIND",
(void *)exception_object);
// destructors called, continue unwinding
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned _URC_INSTALL_CONTEXT",
(void *)exception_object);
// we may get control back if landing pad calls _Unwind_Resume()
__Unwind_SjLj_SetTopOfFunctionStack(c);
__builtin_longjmp(c->jbuf, 1);
break;
default:
// something went wrong
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned %d, "
"_URC_FATAL_PHASE2_ERROR",
(void *)exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
}
c = c->prev;
}
// call stop function one last time and tell it we've reached the end of the
// stack
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
"function with _UA_END_OF_STACK",
(void *)exception_object);
_Unwind_Action lastAction =
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
(*stop)(1, lastAction, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)c, stop_parameter);
// clean up phase did not resume at the frame that the search phase said it
// would
return _URC_FATAL_PHASE2_ERROR;
}
/// Called by __cxa_throw. Only returns if there is a fatal error
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)",
(void *)exception_object);
// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
// thing
exception_object->private_1 = 0;
exception_object->private_2 = 0;
// phase 1: the search phase
_Unwind_Reason_Code phase1 = unwind_phase1(exception_object);
if (phase1 != _URC_NO_REASON)
return phase1;
// phase 2: the clean up phase
return unwind_phase2(exception_object);
}
/// When _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame. The personality
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding. Note: the call to _Unwind_Resume() is from compiler
/// geneated user code. All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Re-throwing an exception is implemented by having the code call
/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)",
(void *)exception_object);
if (exception_object->private_1 != 0)
unwind_phase2_forced(exception_object,
(_Unwind_Stop_Fn) exception_object->private_1,
(void *)exception_object->private_2);
else
unwind_phase2(exception_object);
// clients assume _Unwind_Resume() does not return, so all we can do is abort.
_LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return");
}
/// Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), "
"private_1=%" PRIuPTR,
(void *)exception_object, exception_object->private_1);
// If this is non-forced and a stopping place was found, then this is a
// re-throw.
// Call _Unwind_RaiseException() as if this was a new exception.
if (exception_object->private_1 == 0) {
return _Unwind_SjLj_RaiseException(exception_object);
// should return if there is no catch clause, so that __cxa_rethrow can call
// std::terminate()
}
// Call through to _Unwind_Resume() which distiguishes between forced and
// regular exceptions.
_Unwind_SjLj_Resume(exception_object);
_LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called "
"_Unwind_SjLj_Resume() which unexpectedly returned");
}
/// Called by personality handler during phase 2 to get LSDA for current frame.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
_LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) "
"=> 0x%" PRIuPTR,
(void *)context, ufc->lsda);
return ufc->lsda;
}
/// Called by personality handler during phase 2 to get register values.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
int index) {
_LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", (void *)context,
index);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
return ufc->resumeParameters[index];
}
/// Called by personality handler during phase 2 to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value) {
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR
")",
(void *)context, index, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeParameters[index] = new_value;
}
/// Called by personality handler during phase 2 to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32,
(void *)context, ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
/// Called by personality handler during phase 2 to get instruction pointer.
/// ipBefore is a boolean that says if IP is already adjusted to be the call
/// site address. Normally IP is the return address.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
int *ipBefore) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
*ipBefore = 0;
_LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32,
(void *)context, (void *)ipBefore,
ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
/// Called by personality handler during phase 2 to alter instruction pointer.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t new_value) {
_LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")",
(void *)context, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeLocation = new_value - 1;
}
/// Called by personality handler during phase 2 to find the start of the
/// function.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
// Not supported or needed for sjlj based unwinding
(void)context;
_LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", (void *)context);
return 0;
}
/// Called by personality handler during phase 2 if a foreign exception
/// is caught.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
(void *)exception_object);
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
exception_object);
}
/// Called by personality handler during phase 2 to get base address for data
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
// Not supported or needed for sjlj based unwinding
(void)context;
_LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
}
/// Called by personality handler during phase 2 to get base address for text
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
// Not supported or needed for sjlj based unwinding
(void)context;
_LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
}
/// Called by personality handler to get "Call Frame Area" for current frame.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
_LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", (void *)context);
if (context != NULL) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
// Setjmp/longjmp based exceptions don't have a true CFA.
// Instead, the SP in the jmpbuf is the closest approximation.
return (uintptr_t) ufc->jbuf[2];
}
return 0;
}
#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,319 @@
//===--------------------- UnwindLevel1-gcc-ext.c -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements gcc extensions to the C++ ABI Exception Handling Level 1.
//
//===----------------------------------------------------------------------===//
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "libunwind_ext.h"
#include "libunwind.h"
#include "Unwind-EHABI.h"
#include "unwind.h"
#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
#define private_1 private_[0]
#endif
/// Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
#if defined(_LIBUNWIND_ARM_EHABI)
_LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld",
(void *)exception_object,
(long)exception_object->unwinder_cache.reserved1);
#else
_LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR,
(void *)exception_object,
(intptr_t)exception_object->private_1);
#endif
#if defined(_LIBUNWIND_ARM_EHABI)
// _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
// which is in the same position as private_1 below.
return _Unwind_RaiseException(exception_object);
#else
// If this is non-forced and a stopping place was found, then this is a
// re-throw.
// Call _Unwind_RaiseException() as if this was a new exception
if (exception_object->private_1 == 0) {
return _Unwind_RaiseException(exception_object);
// Will return if there is no catch clause, so that __cxa_rethrow can call
// std::terminate().
}
// Call through to _Unwind_Resume() which distiguishes between forced and
// regular exceptions.
_Unwind_Resume(exception_object);
_LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()"
" which unexpectedly returned");
#endif
}
/// Called by personality handler during phase 2 to get base address for data
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
(void)context;
_LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
}
/// Called by personality handler during phase 2 to get base address for text
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
(void)context;
_LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
}
/// Scans unwind information to find the function that contains the
/// specified code address "pc".
_LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
_LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc);
// This is slow, but works.
// We create an unwind cursor then alter the IP to be pc
unw_cursor_t cursor;
unw_context_t uc;
unw_proc_info_t info;
__unw_getcontext(&uc);
__unw_init_local(&cursor, &uc);
__unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t)pc);
if (__unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS)
return (void *)(intptr_t) info.start_ip;
else
return NULL;
}
/// Walk every frame and call trace function at each one. If trace function
/// returns anything other than _URC_NO_REASON, then walk is terminated.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
unw_cursor_t cursor;
unw_context_t uc;
__unw_getcontext(&uc);
__unw_init_local(&cursor, &uc);
_LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)",
(void *)(uintptr_t)callback);
#if defined(_LIBUNWIND_ARM_EHABI)
// Create a mock exception object for force unwinding.
_Unwind_Exception ex;
memset(&ex, '\0', sizeof(ex));
ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0
#endif
// walk each frame
while (true) {
_Unwind_Reason_Code result;
#if !defined(_LIBUNWIND_ARM_EHABI)
// ask libunwind to get next frame (skip over first frame which is
// _Unwind_Backtrace())
if (__unw_step(&cursor) <= 0) {
_LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached "
"bottom of stack, returning %d",
_URC_END_OF_STACK);
return _URC_END_OF_STACK;
}
#else
// Get the information for this frame.
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) {
return _URC_END_OF_STACK;
}
// Update the pr_cache in the mock exception object.
const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info;
ex.pr_cache.fnstart = frameInfo.start_ip;
ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo;
ex.pr_cache.additional= frameInfo.flags;
struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor;
// Get and call the personality function to unwind the frame.
__personality_routine handler = (__personality_routine) frameInfo.handler;
if (handler == NULL) {
return _URC_END_OF_STACK;
}
if (handler(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) !=
_URC_CONTINUE_UNWIND) {
return _URC_END_OF_STACK;
}
#endif // defined(_LIBUNWIND_ARM_EHABI)
// debugging
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionName[512];
unw_proc_info_t frame;
unw_word_t offset;
__unw_get_proc_name(&cursor, functionName, 512, &offset);
__unw_get_proc_info(&cursor, &frame);
_LIBUNWIND_TRACE_UNWINDING(
" _backtrace: start_ip=0x%" PRIxPTR ", func=%s, lsda=0x%" PRIxPTR ", context=%p",
frame.start_ip, functionName, frame.lsda,
(void *)&cursor);
}
// call trace function with this frame
result = (*callback)((struct _Unwind_Context *)(&cursor), ref);
if (result != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING(
" _backtrace: ended because callback returned %d", result);
return result;
}
}
}
/// Find DWARF unwind info for an address 'pc' in some function.
_LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc,
struct dwarf_eh_bases *bases) {
// This is slow, but works.
// We create an unwind cursor then alter the IP to be pc
unw_cursor_t cursor;
unw_context_t uc;
unw_proc_info_t info;
__unw_getcontext(&uc);
__unw_init_local(&cursor, &uc);
__unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t)pc);
__unw_get_proc_info(&cursor, &info);
bases->tbase = (uintptr_t)info.extra;
bases->dbase = 0; // dbase not used on Mac OS X
bases->func = (uintptr_t)info.start_ip;
_LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc,
(void *)(intptr_t) info.unwind_info);
return (void *)(intptr_t) info.unwind_info;
}
/// Returns the CFA (call frame area, or stack pointer at start of function)
/// for the current context.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_word_t result;
__unw_get_reg(cursor, UNW_REG_SP, &result);
_LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
return (uintptr_t)result;
}
/// Called by personality handler during phase 2 to get instruction pointer.
/// ipBefore is a boolean that says if IP is already adjusted to be the call
/// site address. Normally IP is the return address.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
int *ipBefore) {
_LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)", (void *)context);
*ipBefore = 0;
return _Unwind_GetIP(context);
}
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
/// Called by programs with dynamic code generators that want
/// to register a dynamically generated FDE.
/// This function has existed on Mac OS X since 10.4, but
/// was broken until 10.6.
_LIBUNWIND_EXPORT void __register_frame(const void *fde) {
_LIBUNWIND_TRACE_API("__register_frame(%p)", fde);
__unw_add_dynamic_fde((unw_word_t)(uintptr_t)fde);
}
/// Called by programs with dynamic code generators that want
/// to unregister a dynamically generated FDE.
/// This function has existed on Mac OS X since 10.4, but
/// was broken until 10.6.
_LIBUNWIND_EXPORT void __deregister_frame(const void *fde) {
_LIBUNWIND_TRACE_API("__deregister_frame(%p)", fde);
__unw_remove_dynamic_fde((unw_word_t)(uintptr_t)fde);
}
// The following register/deregister functions are gcc extensions.
// They have existed on Mac OS X, but have never worked because Mac OS X
// before 10.6 used keymgr to track known FDEs, but these functions
// never got updated to use keymgr.
// For now, we implement these as do-nothing functions to keep any existing
// applications working. We also add the not in 10.6 symbol so that nwe
// application won't be able to use them.
#if defined(_LIBUNWIND_SUPPORT_FRAME_APIS)
_LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob,
void *tb, void *db) {
(void)fde;
(void)ob;
(void)tb;
(void)db;
_LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)",
fde, ob, tb, db);
// do nothing, this function never worked in Mac OS X
}
_LIBUNWIND_EXPORT void __register_frame_info(const void *fde, void *ob) {
(void)fde;
(void)ob;
_LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)", fde, ob);
// do nothing, this function never worked in Mac OS X
}
_LIBUNWIND_EXPORT void __register_frame_info_table_bases(const void *fde,
void *ob, void *tb,
void *db) {
(void)fde;
(void)ob;
(void)tb;
(void)db;
_LIBUNWIND_TRACE_API("__register_frame_info_table_bases"
"(%p,%p, %p, %p)", fde, ob, tb, db);
// do nothing, this function never worked in Mac OS X
}
_LIBUNWIND_EXPORT void __register_frame_info_table(const void *fde, void *ob) {
(void)fde;
(void)ob;
_LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)", fde, ob);
// do nothing, this function never worked in Mac OS X
}
_LIBUNWIND_EXPORT void __register_frame_table(const void *fde) {
(void)fde;
_LIBUNWIND_TRACE_API("__register_frame_table(%p)", fde);
// do nothing, this function never worked in Mac OS X
}
_LIBUNWIND_EXPORT void *__deregister_frame_info(const void *fde) {
(void)fde;
_LIBUNWIND_TRACE_API("__deregister_frame_info(%p)", fde);
// do nothing, this function never worked in Mac OS X
return NULL;
}
_LIBUNWIND_EXPORT void *__deregister_frame_info_bases(const void *fde) {
(void)fde;
_LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)", fde);
// do nothing, this function never worked in Mac OS X
return NULL;
}
#endif // defined(_LIBUNWIND_SUPPORT_FRAME_APIS)
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)

View File

@ -0,0 +1,515 @@
//===------------------------- UnwindLevel1.c -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements C++ ABI Exception Handling Level 1 as documented at:
// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
// using libunwind
//
//===----------------------------------------------------------------------===//
// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are
// defining inline functions to delegate the function calls to
// _Unwind_VRS_{Get,Set}(). However, some applications might declare the
// function protetype directly (instead of including <unwind.h>), thus we need
// to export these functions from libunwind.so as well.
#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "libunwind.h"
#include "libunwind_ext.h"
#include "unwind.h"
#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
static _Unwind_Reason_Code
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
__unw_init_local(cursor, uc);
// Walk each frame looking for a place to stop.
bool handlerNotFound = true;
while (handlerNotFound) {
// Ask libunwind to get next frame (skip over first which is
// _Unwind_RaiseException).
int stepResult = __unw_step(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): __unw_step() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): __unw_step failed => "
"_URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
// See if frame has code to run (has personality routine).
unw_proc_info_t frameInfo;
unw_word_t sp;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): __unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
unw_word_t pc;
__unw_get_reg(cursor, UNW_REG_IP, &pc);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR
", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",
(void *)exception_object, pc, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
// If there is a personality routine, ask it if it will want to stop at
// this frame.
if (frameInfo.handler != 0) {
__personality_routine p =
(__personality_routine)(uintptr_t)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
exception_object, (struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_HANDLER_FOUND:
// found a catch clause or locals that need destructing in this frame
// stop search and remember stack pointer at the frame
handlerNotFound = false;
__unw_get_reg(cursor, UNW_REG_SP, &sp);
exception_object->private_2 = (uintptr_t)sp;
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",
(void *)exception_object);
return _URC_NO_REASON;
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
// continue unwinding
break;
default:
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
}
}
return _URC_NO_REASON;
}
static _Unwind_Reason_Code
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
__unw_init_local(cursor, uc);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
(void *)exception_object);
// Walk each frame until we reach where search phase said to stop.
while (true) {
// Ask libunwind to get next frame (skip over first which is
// _Unwind_RaiseException).
int stepResult = __unw_step(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): __unw_step() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): __unw_step failed => "
"_URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
// Get info about this frame.
unw_word_t sp;
unw_proc_info_t frameInfo;
__unw_get_reg(cursor, UNW_REG_SP, &sp);
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): __unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR
", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR
", personality=0x%" PRIxPTR,
(void *)exception_object, frameInfo.start_ip,
functionName, sp, frameInfo.lsda,
frameInfo.handler);
}
// If there is a personality routine, tell it we are unwinding.
if (frameInfo.handler != 0) {
__personality_routine p =
(__personality_routine)(uintptr_t)(frameInfo.handler);
_Unwind_Action action = _UA_CLEANUP_PHASE;
if (sp == exception_object->private_2) {
// Tell personality this was the frame it marked in phase 1.
action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
}
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
// Continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
if (sp == exception_object->private_2) {
// Phase 1 said we would stop at this frame, but we did not...
_LIBUNWIND_ABORT("during phase1 personality function said it would "
"stop here, but now in phase2 it did not stop here");
}
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",
(void *)exception_object);
// Personality routine says to transfer control to landing pad.
// We may get control back if landing pad calls _Unwind_Resume().
if (_LIBUNWIND_TRACING_UNWINDING) {
unw_word_t pc;
__unw_get_reg(cursor, UNW_REG_IP, &pc);
__unw_get_reg(cursor, UNW_REG_SP, &sp);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
"user code with ip=0x%" PRIxPTR
", sp=0x%" PRIxPTR,
(void *)exception_object, pc, sp);
}
__unw_resume(cursor);
// __unw_resume() only returns if there was an error.
return _URC_FATAL_PHASE2_ERROR;
default:
// Personality routine returned an unknown result code.
_LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
}
}
// Clean up phase did not resume at the frame that the search phase
// said it would...
return _URC_FATAL_PHASE2_ERROR;
}
static _Unwind_Reason_Code
unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter) {
__unw_init_local(cursor, uc);
// Walk each frame until we reach where search phase said to stop
while (__unw_step(cursor) > 0) {
// Update info about this frame.
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step "
"failed => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
(void *)exception_object, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
// Call stop function at each frame.
_Unwind_Action action =
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
_Unwind_Reason_Code stopResult =
(*stop)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(cursor), stop_parameter);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
(void *)exception_object, stopResult);
if (stopResult != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
// If there is a personality routine, tell it we are unwinding.
if (frameInfo.handler != 0) {
__personality_routine p =
(__personality_routine)(intptr_t)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned "
"_URC_CONTINUE_UNWIND",
(void *)exception_object);
// Destructors called, continue unwinding
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned "
"_URC_INSTALL_CONTEXT",
(void *)exception_object);
// We may get control back if landing pad calls _Unwind_Resume().
__unw_resume(cursor);
break;
default:
// Personality routine returned an unknown result code.
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned %d, "
"_URC_FATAL_PHASE2_ERROR",
(void *)exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
}
}
// Call stop function one last time and tell it we've reached the end
// of the stack.
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
"function with _UA_END_OF_STACK",
(void *)exception_object);
_Unwind_Action lastAction =
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
(*stop)(1, lastAction, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(cursor), stop_parameter);
// Clean up phase did not resume at the frame that the search phase said it
// would.
return _URC_FATAL_PHASE2_ERROR;
}
/// Called by __cxa_throw. Only returns if there is a fatal error.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
(void *)exception_object);
unw_context_t uc;
unw_cursor_t cursor;
__unw_getcontext(&uc);
// Mark that this is a non-forced unwind, so _Unwind_Resume()
// can do the right thing.
exception_object->private_1 = 0;
exception_object->private_2 = 0;
// phase 1: the search phase
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
if (phase1 != _URC_NO_REASON)
return phase1;
// phase 2: the clean up phase
return unwind_phase2(&uc, &cursor, exception_object);
}
/// When _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame. The personality
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding. Note: the call to _Unwind_Resume() is from compiler
/// geneated user code. All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
/// is implemented by having the code call __cxa_rethrow() which
/// in turn calls _Unwind_Resume_or_Rethrow().
_LIBUNWIND_EXPORT void
_Unwind_Resume(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
unw_context_t uc;
unw_cursor_t cursor;
__unw_getcontext(&uc);
if (exception_object->private_1 != 0)
unwind_phase2_forced(&uc, &cursor, exception_object,
(_Unwind_Stop_Fn) exception_object->private_1,
(void *)exception_object->private_2);
else
unwind_phase2(&uc, &cursor, exception_object);
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
}
/// Not used by C++.
/// Unwinds stack, calling "stop" function at each frame.
/// Could be used to implement longjmp().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter) {
_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
(void *)exception_object, (void *)(uintptr_t)stop);
unw_context_t uc;
unw_cursor_t cursor;
__unw_getcontext(&uc);
// Mark that this is a forced unwind, so _Unwind_Resume() can do
// the right thing.
exception_object->private_1 = (uintptr_t) stop;
exception_object->private_2 = (uintptr_t) stop_parameter;
// do it
return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);
}
/// Called by personality handler during phase 2 to get LSDA for current frame.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_proc_info_t frameInfo;
uintptr_t result = 0;
if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
result = (uintptr_t)frameInfo.lsda;
_LIBUNWIND_TRACE_API(
"_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
if (result != 0) {
if (*((uint8_t *)result) != 0xFF)
_LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",
result);
}
return result;
}
/// Called by personality handler during phase 2 to find the start of the
/// function.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_proc_info_t frameInfo;
uintptr_t result = 0;
if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
result = (uintptr_t)frameInfo.start_ip;
_LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
return result;
}
#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND
/// Called by personality handler during phase 2 if a foreign exception
// is caught.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
(void *)exception_object);
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
exception_object);
}
/// Called by personality handler during phase 2 to get register values.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetGR(struct _Unwind_Context *context, int index) {
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_word_t result;
__unw_get_reg(cursor, index, &result);
_LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR,
(void *)context, index, result);
return (uintptr_t)result;
}
/// Called by personality handler during phase 2 to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t value) {
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR
")",
(void *)context, index, value);
unw_cursor_t *cursor = (unw_cursor_t *)context;
__unw_set_reg(cursor, index, value);
}
/// Called by personality handler during phase 2 to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_word_t result;
__unw_get_reg(cursor, UNW_REG_IP, &result);
_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
return (uintptr_t)result;
}
/// Called by personality handler during phase 2 to alter instruction pointer,
/// such as setting where the landing pad is, so _Unwind_Resume() will
/// start executing in the landing pad.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t value) {
_LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")",
(void *)context, value);
unw_cursor_t *cursor = (unw_cursor_t *)context;
__unw_set_reg(cursor, UNW_REG_IP, value);
}
#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,983 @@
//===------------------------ UnwindRegistersSave.S -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "assembly.h"
.text
#if !defined(__USING_SJLJ_EXCEPTIONS__)
#if defined(__i386__)
#
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# + +
# +-----------------------+
# + thread_state pointer +
# +-----------------------+
# + return address +
# +-----------------------+ <-- SP
# + +
#
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
push %eax
movl 8(%esp), %eax
movl %ebx, 4(%eax)
movl %ecx, 8(%eax)
movl %edx, 12(%eax)
movl %edi, 16(%eax)
movl %esi, 20(%eax)
movl %ebp, 24(%eax)
movl %esp, %edx
addl $8, %edx
movl %edx, 28(%eax) # store what sp was at call site as esp
# skip ss
# skip eflags
movl 4(%esp), %edx
movl %edx, 40(%eax) # store return address as eip
# skip cs
# skip ds
# skip es
# skip fs
# skip gs
movl (%esp), %edx
movl %edx, (%eax) # store original eax
popl %eax
xorl %eax, %eax # return UNW_ESUCCESS
ret
#elif defined(__x86_64__)
#
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in rdi
#
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
#if defined(_WIN64)
#define PTR %rcx
#define TMP %rdx
#else
#define PTR %rdi
#define TMP %rsi
#endif
movq %rax, (PTR)
movq %rbx, 8(PTR)
movq %rcx, 16(PTR)
movq %rdx, 24(PTR)
movq %rdi, 32(PTR)
movq %rsi, 40(PTR)
movq %rbp, 48(PTR)
movq %rsp, 56(PTR)
addq $8, 56(PTR)
movq %r8, 64(PTR)
movq %r9, 72(PTR)
movq %r10, 80(PTR)
movq %r11, 88(PTR)
movq %r12, 96(PTR)
movq %r13,104(PTR)
movq %r14,112(PTR)
movq %r15,120(PTR)
movq (%rsp),TMP
movq TMP,128(PTR) # store return address as rip
# skip rflags
# skip cs
# skip fs
# skip gs
#if defined(_WIN64)
movdqu %xmm0,176(PTR)
movdqu %xmm1,192(PTR)
movdqu %xmm2,208(PTR)
movdqu %xmm3,224(PTR)
movdqu %xmm4,240(PTR)
movdqu %xmm5,256(PTR)
movdqu %xmm6,272(PTR)
movdqu %xmm7,288(PTR)
movdqu %xmm8,304(PTR)
movdqu %xmm9,320(PTR)
movdqu %xmm10,336(PTR)
movdqu %xmm11,352(PTR)
movdqu %xmm12,368(PTR)
movdqu %xmm13,384(PTR)
movdqu %xmm14,400(PTR)
movdqu %xmm15,416(PTR)
#endif
xorl %eax, %eax # return UNW_ESUCCESS
ret
#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
#
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in a0 ($4)
#
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
.set push
.set noat
.set noreorder
.set nomacro
sw $1, (4 * 1)($4)
sw $2, (4 * 2)($4)
sw $3, (4 * 3)($4)
sw $4, (4 * 4)($4)
sw $5, (4 * 5)($4)
sw $6, (4 * 6)($4)
sw $7, (4 * 7)($4)
sw $8, (4 * 8)($4)
sw $9, (4 * 9)($4)
sw $10, (4 * 10)($4)
sw $11, (4 * 11)($4)
sw $12, (4 * 12)($4)
sw $13, (4 * 13)($4)
sw $14, (4 * 14)($4)
sw $15, (4 * 15)($4)
sw $16, (4 * 16)($4)
sw $17, (4 * 17)($4)
sw $18, (4 * 18)($4)
sw $19, (4 * 19)($4)
sw $20, (4 * 20)($4)
sw $21, (4 * 21)($4)
sw $22, (4 * 22)($4)
sw $23, (4 * 23)($4)
sw $24, (4 * 24)($4)
sw $25, (4 * 25)($4)
sw $26, (4 * 26)($4)
sw $27, (4 * 27)($4)
sw $28, (4 * 28)($4)
sw $29, (4 * 29)($4)
sw $30, (4 * 30)($4)
sw $31, (4 * 31)($4)
# Store return address to pc
sw $31, (4 * 32)($4)
# hi and lo
mfhi $8
sw $8, (4 * 33)($4)
mflo $8
sw $8, (4 * 34)($4)
#ifdef __mips_hard_float
#if __mips_fpr != 64
sdc1 $f0, (4 * 36 + 8 * 0)($4)
sdc1 $f2, (4 * 36 + 8 * 2)($4)
sdc1 $f4, (4 * 36 + 8 * 4)($4)
sdc1 $f6, (4 * 36 + 8 * 6)($4)
sdc1 $f8, (4 * 36 + 8 * 8)($4)
sdc1 $f10, (4 * 36 + 8 * 10)($4)
sdc1 $f12, (4 * 36 + 8 * 12)($4)
sdc1 $f14, (4 * 36 + 8 * 14)($4)
sdc1 $f16, (4 * 36 + 8 * 16)($4)
sdc1 $f18, (4 * 36 + 8 * 18)($4)
sdc1 $f20, (4 * 36 + 8 * 20)($4)
sdc1 $f22, (4 * 36 + 8 * 22)($4)
sdc1 $f24, (4 * 36 + 8 * 24)($4)
sdc1 $f26, (4 * 36 + 8 * 26)($4)
sdc1 $f28, (4 * 36 + 8 * 28)($4)
sdc1 $f30, (4 * 36 + 8 * 30)($4)
#else
sdc1 $f0, (4 * 36 + 8 * 0)($4)
sdc1 $f1, (4 * 36 + 8 * 1)($4)
sdc1 $f2, (4 * 36 + 8 * 2)($4)
sdc1 $f3, (4 * 36 + 8 * 3)($4)
sdc1 $f4, (4 * 36 + 8 * 4)($4)
sdc1 $f5, (4 * 36 + 8 * 5)($4)
sdc1 $f6, (4 * 36 + 8 * 6)($4)
sdc1 $f7, (4 * 36 + 8 * 7)($4)
sdc1 $f8, (4 * 36 + 8 * 8)($4)
sdc1 $f9, (4 * 36 + 8 * 9)($4)
sdc1 $f10, (4 * 36 + 8 * 10)($4)
sdc1 $f11, (4 * 36 + 8 * 11)($4)
sdc1 $f12, (4 * 36 + 8 * 12)($4)
sdc1 $f13, (4 * 36 + 8 * 13)($4)
sdc1 $f14, (4 * 36 + 8 * 14)($4)
sdc1 $f15, (4 * 36 + 8 * 15)($4)
sdc1 $f16, (4 * 36 + 8 * 16)($4)
sdc1 $f17, (4 * 36 + 8 * 17)($4)
sdc1 $f18, (4 * 36 + 8 * 18)($4)
sdc1 $f19, (4 * 36 + 8 * 19)($4)
sdc1 $f20, (4 * 36 + 8 * 20)($4)
sdc1 $f21, (4 * 36 + 8 * 21)($4)
sdc1 $f22, (4 * 36 + 8 * 22)($4)
sdc1 $f23, (4 * 36 + 8 * 23)($4)
sdc1 $f24, (4 * 36 + 8 * 24)($4)
sdc1 $f25, (4 * 36 + 8 * 25)($4)
sdc1 $f26, (4 * 36 + 8 * 26)($4)
sdc1 $f27, (4 * 36 + 8 * 27)($4)
sdc1 $f28, (4 * 36 + 8 * 28)($4)
sdc1 $f29, (4 * 36 + 8 * 29)($4)
sdc1 $f30, (4 * 36 + 8 * 30)($4)
sdc1 $f31, (4 * 36 + 8 * 31)($4)
#endif
#endif
jr $31
# return UNW_ESUCCESS
or $2, $0, $0
.set pop
#elif defined(__mips64)
#
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in a0 ($4)
#
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
.set push
.set noat
.set noreorder
.set nomacro
sd $1, (8 * 1)($4)
sd $2, (8 * 2)($4)
sd $3, (8 * 3)($4)
sd $4, (8 * 4)($4)
sd $5, (8 * 5)($4)
sd $6, (8 * 6)($4)
sd $7, (8 * 7)($4)
sd $8, (8 * 8)($4)
sd $9, (8 * 9)($4)
sd $10, (8 * 10)($4)
sd $11, (8 * 11)($4)
sd $12, (8 * 12)($4)
sd $13, (8 * 13)($4)
sd $14, (8 * 14)($4)
sd $15, (8 * 15)($4)
sd $16, (8 * 16)($4)
sd $17, (8 * 17)($4)
sd $18, (8 * 18)($4)
sd $19, (8 * 19)($4)
sd $20, (8 * 20)($4)
sd $21, (8 * 21)($4)
sd $22, (8 * 22)($4)
sd $23, (8 * 23)($4)
sd $24, (8 * 24)($4)
sd $25, (8 * 25)($4)
sd $26, (8 * 26)($4)
sd $27, (8 * 27)($4)
sd $28, (8 * 28)($4)
sd $29, (8 * 29)($4)
sd $30, (8 * 30)($4)
sd $31, (8 * 31)($4)
# Store return address to pc
sd $31, (8 * 32)($4)
# hi and lo
mfhi $8
sd $8, (8 * 33)($4)
mflo $8
sd $8, (8 * 34)($4)
#ifdef __mips_hard_float
sdc1 $f0, (8 * 35)($4)
sdc1 $f1, (8 * 36)($4)
sdc1 $f2, (8 * 37)($4)
sdc1 $f3, (8 * 38)($4)
sdc1 $f4, (8 * 39)($4)
sdc1 $f5, (8 * 40)($4)
sdc1 $f6, (8 * 41)($4)
sdc1 $f7, (8 * 42)($4)
sdc1 $f8, (8 * 43)($4)
sdc1 $f9, (8 * 44)($4)
sdc1 $f10, (8 * 45)($4)
sdc1 $f11, (8 * 46)($4)
sdc1 $f12, (8 * 47)($4)
sdc1 $f13, (8 * 48)($4)
sdc1 $f14, (8 * 49)($4)
sdc1 $f15, (8 * 50)($4)
sdc1 $f16, (8 * 51)($4)
sdc1 $f17, (8 * 52)($4)
sdc1 $f18, (8 * 53)($4)
sdc1 $f19, (8 * 54)($4)
sdc1 $f20, (8 * 55)($4)
sdc1 $f21, (8 * 56)($4)
sdc1 $f22, (8 * 57)($4)
sdc1 $f23, (8 * 58)($4)
sdc1 $f24, (8 * 59)($4)
sdc1 $f25, (8 * 60)($4)
sdc1 $f26, (8 * 61)($4)
sdc1 $f27, (8 * 62)($4)
sdc1 $f28, (8 * 63)($4)
sdc1 $f29, (8 * 64)($4)
sdc1 $f30, (8 * 65)($4)
sdc1 $f31, (8 * 66)($4)
#endif
jr $31
# return UNW_ESUCCESS
or $2, $0, $0
.set pop
# elif defined(__mips__)
#
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# Just trap for the time being.
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
teq $0, $0
#elif defined(__powerpc64__)
//
// extern int __unw_getcontext(unw_context_t* thread_state)
//
// On entry:
// thread_state pointer is in r3
//
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
// store register (GPR)
#define PPC64_STR(n) \
std %r##n, (8 * (n + 2))(%r3)
// save GPRs
PPC64_STR(0)
mflr %r0
std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0
PPC64_STR(1)
PPC64_STR(2)
PPC64_STR(3)
PPC64_STR(4)
PPC64_STR(5)
PPC64_STR(6)
PPC64_STR(7)
PPC64_STR(8)
PPC64_STR(9)
PPC64_STR(10)
PPC64_STR(11)
PPC64_STR(12)
PPC64_STR(13)
PPC64_STR(14)
PPC64_STR(15)
PPC64_STR(16)
PPC64_STR(17)
PPC64_STR(18)
PPC64_STR(19)
PPC64_STR(20)
PPC64_STR(21)
PPC64_STR(22)
PPC64_STR(23)
PPC64_STR(24)
PPC64_STR(25)
PPC64_STR(26)
PPC64_STR(27)
PPC64_STR(28)
PPC64_STR(29)
PPC64_STR(30)
PPC64_STR(31)
mfcr %r0
std %r0, PPC64_OFFS_CR(%r3)
mfxer %r0
std %r0, PPC64_OFFS_XER(%r3)
mflr %r0
std %r0, PPC64_OFFS_LR(%r3)
mfctr %r0
std %r0, PPC64_OFFS_CTR(%r3)
mfvrsave %r0
std %r0, PPC64_OFFS_VRSAVE(%r3)
#ifdef PPC64_HAS_VMX
// save VS registers
// (note that this also saves floating point registers and V registers,
// because part of VS is mapped to these registers)
addi %r4, %r3, PPC64_OFFS_FP
// store VS register
#define PPC64_STVS(n) \
stxvd2x %vs##n, 0, %r4 ;\
addi %r4, %r4, 16
PPC64_STVS(0)
PPC64_STVS(1)
PPC64_STVS(2)
PPC64_STVS(3)
PPC64_STVS(4)
PPC64_STVS(5)
PPC64_STVS(6)
PPC64_STVS(7)
PPC64_STVS(8)
PPC64_STVS(9)
PPC64_STVS(10)
PPC64_STVS(11)
PPC64_STVS(12)
PPC64_STVS(13)
PPC64_STVS(14)
PPC64_STVS(15)
PPC64_STVS(16)
PPC64_STVS(17)
PPC64_STVS(18)
PPC64_STVS(19)
PPC64_STVS(20)
PPC64_STVS(21)
PPC64_STVS(22)
PPC64_STVS(23)
PPC64_STVS(24)
PPC64_STVS(25)
PPC64_STVS(26)
PPC64_STVS(27)
PPC64_STVS(28)
PPC64_STVS(29)
PPC64_STVS(30)
PPC64_STVS(31)
PPC64_STVS(32)
PPC64_STVS(33)
PPC64_STVS(34)
PPC64_STVS(35)
PPC64_STVS(36)
PPC64_STVS(37)
PPC64_STVS(38)
PPC64_STVS(39)
PPC64_STVS(40)
PPC64_STVS(41)
PPC64_STVS(42)
PPC64_STVS(43)
PPC64_STVS(44)
PPC64_STVS(45)
PPC64_STVS(46)
PPC64_STVS(47)
PPC64_STVS(48)
PPC64_STVS(49)
PPC64_STVS(50)
PPC64_STVS(51)
PPC64_STVS(52)
PPC64_STVS(53)
PPC64_STVS(54)
PPC64_STVS(55)
PPC64_STVS(56)
PPC64_STVS(57)
PPC64_STVS(58)
PPC64_STVS(59)
PPC64_STVS(60)
PPC64_STVS(61)
PPC64_STVS(62)
PPC64_STVS(63)
#else
// store FP register
#define PPC64_STF(n) \
stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
// save float registers
PPC64_STF(0)
PPC64_STF(1)
PPC64_STF(2)
PPC64_STF(3)
PPC64_STF(4)
PPC64_STF(5)
PPC64_STF(6)
PPC64_STF(7)
PPC64_STF(8)
PPC64_STF(9)
PPC64_STF(10)
PPC64_STF(11)
PPC64_STF(12)
PPC64_STF(13)
PPC64_STF(14)
PPC64_STF(15)
PPC64_STF(16)
PPC64_STF(17)
PPC64_STF(18)
PPC64_STF(19)
PPC64_STF(20)
PPC64_STF(21)
PPC64_STF(22)
PPC64_STF(23)
PPC64_STF(24)
PPC64_STF(25)
PPC64_STF(26)
PPC64_STF(27)
PPC64_STF(28)
PPC64_STF(29)
PPC64_STF(30)
PPC64_STF(31)
// save vector registers
// Use 16-bytes below the stack pointer as an
// aligned buffer to save each vector register.
// Note that the stack pointer is always 16-byte aligned.
subi %r4, %r1, 16
#define PPC64_STV_UNALIGNED(n) \
stvx %v##n, 0, %r4 ;\
ld %r5, 0(%r4) ;\
std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\
ld %r5, 8(%r4) ;\
std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3)
PPC64_STV_UNALIGNED(0)
PPC64_STV_UNALIGNED(1)
PPC64_STV_UNALIGNED(2)
PPC64_STV_UNALIGNED(3)
PPC64_STV_UNALIGNED(4)
PPC64_STV_UNALIGNED(5)
PPC64_STV_UNALIGNED(6)
PPC64_STV_UNALIGNED(7)
PPC64_STV_UNALIGNED(8)
PPC64_STV_UNALIGNED(9)
PPC64_STV_UNALIGNED(10)
PPC64_STV_UNALIGNED(11)
PPC64_STV_UNALIGNED(12)
PPC64_STV_UNALIGNED(13)
PPC64_STV_UNALIGNED(14)
PPC64_STV_UNALIGNED(15)
PPC64_STV_UNALIGNED(16)
PPC64_STV_UNALIGNED(17)
PPC64_STV_UNALIGNED(18)
PPC64_STV_UNALIGNED(19)
PPC64_STV_UNALIGNED(20)
PPC64_STV_UNALIGNED(21)
PPC64_STV_UNALIGNED(22)
PPC64_STV_UNALIGNED(23)
PPC64_STV_UNALIGNED(24)
PPC64_STV_UNALIGNED(25)
PPC64_STV_UNALIGNED(26)
PPC64_STV_UNALIGNED(27)
PPC64_STV_UNALIGNED(28)
PPC64_STV_UNALIGNED(29)
PPC64_STV_UNALIGNED(30)
PPC64_STV_UNALIGNED(31)
#endif
li %r3, 0 // return UNW_ESUCCESS
blr
#elif defined(__ppc__)
//
// extern int unw_getcontext(unw_context_t* thread_state)
//
// On entry:
// thread_state pointer is in r3
//
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
stw %r0, 8(%r3)
mflr %r0
stw %r0, 0(%r3) // store lr as ssr0
stw %r1, 12(%r3)
stw %r2, 16(%r3)
stw %r3, 20(%r3)
stw %r4, 24(%r3)
stw %r5, 28(%r3)
stw %r6, 32(%r3)
stw %r7, 36(%r3)
stw %r8, 40(%r3)
stw %r9, 44(%r3)
stw %r10, 48(%r3)
stw %r11, 52(%r3)
stw %r12, 56(%r3)
stw %r13, 60(%r3)
stw %r14, 64(%r3)
stw %r15, 68(%r3)
stw %r16, 72(%r3)
stw %r17, 76(%r3)
stw %r18, 80(%r3)
stw %r19, 84(%r3)
stw %r20, 88(%r3)
stw %r21, 92(%r3)
stw %r22, 96(%r3)
stw %r23,100(%r3)
stw %r24,104(%r3)
stw %r25,108(%r3)
stw %r26,112(%r3)
stw %r27,116(%r3)
stw %r28,120(%r3)
stw %r29,124(%r3)
stw %r30,128(%r3)
stw %r31,132(%r3)
// save VRSave register
mfspr %r0, 256
stw %r0, 156(%r3)
// save CR registers
mfcr %r0
stw %r0, 136(%r3)
// save CTR register
mfctr %r0
stw %r0, 148(%r3)
// save float registers
stfd %f0, 160(%r3)
stfd %f1, 168(%r3)
stfd %f2, 176(%r3)
stfd %f3, 184(%r3)
stfd %f4, 192(%r3)
stfd %f5, 200(%r3)
stfd %f6, 208(%r3)
stfd %f7, 216(%r3)
stfd %f8, 224(%r3)
stfd %f9, 232(%r3)
stfd %f10,240(%r3)
stfd %f11,248(%r3)
stfd %f12,256(%r3)
stfd %f13,264(%r3)
stfd %f14,272(%r3)
stfd %f15,280(%r3)
stfd %f16,288(%r3)
stfd %f17,296(%r3)
stfd %f18,304(%r3)
stfd %f19,312(%r3)
stfd %f20,320(%r3)
stfd %f21,328(%r3)
stfd %f22,336(%r3)
stfd %f23,344(%r3)
stfd %f24,352(%r3)
stfd %f25,360(%r3)
stfd %f26,368(%r3)
stfd %f27,376(%r3)
stfd %f28,384(%r3)
stfd %f29,392(%r3)
stfd %f30,400(%r3)
stfd %f31,408(%r3)
// save vector registers
subi %r4, %r1, 16
rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits
// r4 is now a 16-byte aligned pointer into the red zone
#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
stvx _vec, 0, %r4 SEPARATOR \
lwz %r5, 0(%r4) SEPARATOR \
stw %r5, _offset(%r3) SEPARATOR \
lwz %r5, 4(%r4) SEPARATOR \
stw %r5, _offset+4(%r3) SEPARATOR \
lwz %r5, 8(%r4) SEPARATOR \
stw %r5, _offset+8(%r3) SEPARATOR \
lwz %r5, 12(%r4) SEPARATOR \
stw %r5, _offset+12(%r3)
SAVE_VECTOR_UNALIGNED( %v0, 424+0x000)
SAVE_VECTOR_UNALIGNED( %v1, 424+0x010)
SAVE_VECTOR_UNALIGNED( %v2, 424+0x020)
SAVE_VECTOR_UNALIGNED( %v3, 424+0x030)
SAVE_VECTOR_UNALIGNED( %v4, 424+0x040)
SAVE_VECTOR_UNALIGNED( %v5, 424+0x050)
SAVE_VECTOR_UNALIGNED( %v6, 424+0x060)
SAVE_VECTOR_UNALIGNED( %v7, 424+0x070)
SAVE_VECTOR_UNALIGNED( %v8, 424+0x080)
SAVE_VECTOR_UNALIGNED( %v9, 424+0x090)
SAVE_VECTOR_UNALIGNED(%v10, 424+0x0A0)
SAVE_VECTOR_UNALIGNED(%v11, 424+0x0B0)
SAVE_VECTOR_UNALIGNED(%v12, 424+0x0C0)
SAVE_VECTOR_UNALIGNED(%v13, 424+0x0D0)
SAVE_VECTOR_UNALIGNED(%v14, 424+0x0E0)
SAVE_VECTOR_UNALIGNED(%v15, 424+0x0F0)
SAVE_VECTOR_UNALIGNED(%v16, 424+0x100)
SAVE_VECTOR_UNALIGNED(%v17, 424+0x110)
SAVE_VECTOR_UNALIGNED(%v18, 424+0x120)
SAVE_VECTOR_UNALIGNED(%v19, 424+0x130)
SAVE_VECTOR_UNALIGNED(%v20, 424+0x140)
SAVE_VECTOR_UNALIGNED(%v21, 424+0x150)
SAVE_VECTOR_UNALIGNED(%v22, 424+0x160)
SAVE_VECTOR_UNALIGNED(%v23, 424+0x170)
SAVE_VECTOR_UNALIGNED(%v24, 424+0x180)
SAVE_VECTOR_UNALIGNED(%v25, 424+0x190)
SAVE_VECTOR_UNALIGNED(%v26, 424+0x1A0)
SAVE_VECTOR_UNALIGNED(%v27, 424+0x1B0)
SAVE_VECTOR_UNALIGNED(%v28, 424+0x1C0)
SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0)
SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0)
SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0)
li %r3, 0 // return UNW_ESUCCESS
blr
#elif defined(__arm64__) || defined(__aarch64__)
//
// extern int __unw_getcontext(unw_context_t* thread_state)
//
// On entry:
// thread_state pointer is in x0
//
.p2align 2
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
stp x0, x1, [x0, #0x000]
stp x2, x3, [x0, #0x010]
stp x4, x5, [x0, #0x020]
stp x6, x7, [x0, #0x030]
stp x8, x9, [x0, #0x040]
stp x10,x11, [x0, #0x050]
stp x12,x13, [x0, #0x060]
stp x14,x15, [x0, #0x070]
stp x16,x17, [x0, #0x080]
stp x18,x19, [x0, #0x090]
stp x20,x21, [x0, #0x0A0]
stp x22,x23, [x0, #0x0B0]
stp x24,x25, [x0, #0x0C0]
stp x26,x27, [x0, #0x0D0]
stp x28,x29, [x0, #0x0E0]
str x30, [x0, #0x0F0]
mov x1,sp
str x1, [x0, #0x0F8]
str x30, [x0, #0x100] // store return address as pc
// skip cpsr
stp d0, d1, [x0, #0x110]
stp d2, d3, [x0, #0x120]
stp d4, d5, [x0, #0x130]
stp d6, d7, [x0, #0x140]
stp d8, d9, [x0, #0x150]
stp d10,d11, [x0, #0x160]
stp d12,d13, [x0, #0x170]
stp d14,d15, [x0, #0x180]
stp d16,d17, [x0, #0x190]
stp d18,d19, [x0, #0x1A0]
stp d20,d21, [x0, #0x1B0]
stp d22,d23, [x0, #0x1C0]
stp d24,d25, [x0, #0x1D0]
stp d26,d27, [x0, #0x1E0]
stp d28,d29, [x0, #0x1F0]
str d30, [x0, #0x200]
str d31, [x0, #0x208]
mov x0, #0 // return UNW_ESUCCESS
ret
#elif defined(__arm__) && !defined(__APPLE__)
#if !defined(__ARM_ARCH_ISA_ARM)
#if (__ARM_ARCH_ISA_THUMB == 2)
.syntax unified
#endif
.thumb
#endif
@
@ extern int __unw_getcontext(unw_context_t* thread_state)
@
@ On entry:
@ thread_state pointer is in r0
@
@ Per EHABI #4.7 this only saves the core integer registers.
@ EHABI #7.4.5 notes that in general all VRS registers should be restored
@ however this is very hard to do for VFP registers because it is unknown
@ to the library how many registers are implemented by the architecture.
@ Instead, VFP registers are demand saved by logic external to __unw_getcontext.
@
.p2align 2
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
stm r0!, {r0-r7}
mov r1, r8
mov r2, r9
mov r3, r10
stm r0!, {r1-r3}
mov r1, r11
mov r2, sp
mov r3, lr
str r1, [r0, #0] @ r11
@ r12 does not need storing, it it the intra-procedure-call scratch register
str r2, [r0, #8] @ sp
str r3, [r0, #12] @ lr
str r3, [r0, #16] @ store return address as pc
@ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
@ It is safe to use here though because we are about to return, and cpsr is
@ not expected to be preserved.
movs r0, #0 @ return UNW_ESUCCESS
#else
@ 32bit thumb-2 restrictions for stm:
@ . the sp (r13) cannot be in the list
@ . the pc (r15) cannot be in the list in an STM instruction
stm r0, {r0-r12}
str sp, [r0, #52]
str lr, [r0, #56]
str lr, [r0, #60] @ store return address as pc
mov r0, #0 @ return UNW_ESUCCESS
#endif
JMP(lr)
@
@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
@
@ On entry:
@ values pointer is in r0
@
.p2align 2
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)
vstmia r0, {d0-d15}
JMP(lr)
@
@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
@
@ On entry:
@ values pointer is in r0
@
.p2align 2
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)
vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
JMP(lr)
@
@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
@
@ On entry:
@ values pointer is in r0
@
.p2align 2
#if defined(__ELF__)
.fpu vfpv3
#endif
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)
@ VFP and iwMMX instructions are only available when compiling with the flags
@ that enable them. We do not want to do that in the library (because we do not
@ want the compiler to generate instructions that access those) but this is
@ only accessed if the personality routine needs these registers. Use of
@ these registers implies they are, actually, available on the target, so
@ it's ok to execute.
@ So, generate the instructions using the corresponding coprocessor mnemonic.
vstmia r0, {d16-d31}
JMP(lr)
#if defined(_LIBUNWIND_ARM_WMMX)
@
@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
@
@ On entry:
@ values pointer is in r0
@
.p2align 2
#if defined(__ELF__)
.arch armv5te
#endif
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)
stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8
stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8
stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8
stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8
stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8
stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8
stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8
stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8
stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8
stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8
stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8
stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8
stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8
stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8
stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8
stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8
JMP(lr)
@
@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
@
@ On entry:
@ values pointer is in r0
@
.p2align 2
#if defined(__ELF__)
.arch armv5te
#endif
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4
stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4
stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4
stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4
JMP(lr)
#endif
#elif defined(__or1k__)
#
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in r3
#
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
l.sw 0(r3), r0
l.sw 4(r3), r1
l.sw 8(r3), r2
l.sw 12(r3), r3
l.sw 16(r3), r4
l.sw 20(r3), r5
l.sw 24(r3), r6
l.sw 28(r3), r7
l.sw 32(r3), r8
l.sw 36(r3), r9
l.sw 40(r3), r10
l.sw 44(r3), r11
l.sw 48(r3), r12
l.sw 52(r3), r13
l.sw 56(r3), r14
l.sw 60(r3), r15
l.sw 64(r3), r16
l.sw 68(r3), r17
l.sw 72(r3), r18
l.sw 76(r3), r19
l.sw 80(r3), r20
l.sw 84(r3), r21
l.sw 88(r3), r22
l.sw 92(r3), r23
l.sw 96(r3), r24
l.sw 100(r3), r25
l.sw 104(r3), r26
l.sw 108(r3), r27
l.sw 112(r3), r28
l.sw 116(r3), r29
l.sw 120(r3), r30
l.sw 124(r3), r31
# store ra to pc
l.sw 128(r3), r9
# zero epcr
l.sw 132(r3), r0
#elif defined(__sparc__)
#
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in o0
#
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
ta 3
add %o7, 8, %o7
std %g0, [%o0 + 0]
std %g2, [%o0 + 8]
std %g4, [%o0 + 16]
std %g6, [%o0 + 24]
std %o0, [%o0 + 32]
std %o2, [%o0 + 40]
std %o4, [%o0 + 48]
std %o6, [%o0 + 56]
std %l0, [%o0 + 64]
std %l2, [%o0 + 72]
std %l4, [%o0 + 80]
std %l6, [%o0 + 88]
std %i0, [%o0 + 96]
std %i2, [%o0 + 104]
std %i4, [%o0 + 112]
std %i6, [%o0 + 120]
jmp %o7
clr %o0 // return UNW_ESUCCESS
#endif
WEAK_ALIAS(__unw_getcontext, unw_getcontext)
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
NO_EXEC_STACK_DIRECTIVE

View File

@ -0,0 +1,183 @@
//===--------------------- Unwind_AppleExtras.cpp -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
//===----------------------------------------------------------------------===//
#include "config.h"
#include "AddressSpace.hpp"
#include "DwarfParser.hpp"
// private keymgr stuff
#define KEYMGR_GCC3_DW2_OBJ_LIST 302
extern "C" {
extern void _keymgr_set_and_unlock_processwide_ptr(int key, void *ptr);
extern void *_keymgr_get_and_lock_processwide_ptr(int key);
}
// undocumented libgcc "struct object"
struct libgcc_object {
void *start;
void *unused1;
void *unused2;
void *fde;
unsigned long encoding;
void *fde_end;
libgcc_object *next;
};
// undocumented libgcc "struct km_object_info" referenced by
// KEYMGR_GCC3_DW2_OBJ_LIST
struct libgcc_object_info {
libgcc_object *seen_objects;
libgcc_object *unseen_objects;
unsigned spare[2];
};
// static linker symbols to prevent wrong two level namespace for _Unwind symbols
#if defined(__arm__)
#define NOT_HERE_BEFORE_5_0(sym) \
extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp30 = 0; \
extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp31 = 0; \
extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\
__attribute__((visibility("default"))) const char sym##_tmp32 = 0; \
extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp40 = 0; \
extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp41 = 0; \
extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp42 = 0; \
extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp43 = 0;
#elif defined(__arm64__)
#define NOT_HERE_BEFORE_10_6(sym)
#define NEVER_HERE(sym)
#else
#define NOT_HERE_BEFORE_10_6(sym) \
extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp5 = 0;
#define NEVER_HERE(sym) \
extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp6 = 0;
#endif
#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
//
// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in
// earlier versions
//
NOT_HERE_BEFORE_10_6(_Unwind_DeleteException)
NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE)
NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind)
NOT_HERE_BEFORE_10_6(_Unwind_GetGR)
NOT_HERE_BEFORE_10_6(_Unwind_GetIP)
NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData)
NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart)
NOT_HERE_BEFORE_10_6(_Unwind_RaiseException)
NOT_HERE_BEFORE_10_6(_Unwind_Resume)
NOT_HERE_BEFORE_10_6(_Unwind_SetGR)
NOT_HERE_BEFORE_10_6(_Unwind_SetIP)
NOT_HERE_BEFORE_10_6(_Unwind_Backtrace)
NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction)
NOT_HERE_BEFORE_10_6(_Unwind_GetCFA)
NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase)
NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase)
NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow)
NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo)
NOT_HERE_BEFORE_10_6(__register_frame)
NOT_HERE_BEFORE_10_6(__deregister_frame)
//
// symbols in libSystem.dylib for compatibility, but we don't want any new code
// using them
//
NEVER_HERE(__register_frame_info_bases)
NEVER_HERE(__register_frame_info)
NEVER_HERE(__register_frame_info_table_bases)
NEVER_HERE(__register_frame_info_table)
NEVER_HERE(__register_frame_table)
NEVER_HERE(__deregister_frame_info)
NEVER_HERE(__deregister_frame_info_bases)
#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
//
// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in
// earlier versions
//
NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData)
NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart)
NOT_HERE_BEFORE_5_0(_Unwind_GetIP)
NOT_HERE_BEFORE_5_0(_Unwind_SetGR)
NOT_HERE_BEFORE_5_0(_Unwind_SetIP)
NOT_HERE_BEFORE_5_0(_Unwind_DeleteException)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register)
NOT_HERE_BEFORE_5_0(_Unwind_GetGR)
NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo)
NOT_HERE_BEFORE_5_0(_Unwind_GetCFA)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
namespace libunwind {
_LIBUNWIND_HIDDEN
bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) {
#if __MAC_OS_X_VERSION_MIN_REQUIRED
// lastly check for old style keymgr registration of dynamically generated
// FDEs acquire exclusive access to libgcc_object_info
libgcc_object_info *head = (libgcc_object_info *)
_keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
if (head != NULL) {
// look at each FDE in keymgr
for (libgcc_object *ob = head->unseen_objects; ob != NULL; ob = ob->next) {
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
const char *msg = CFI_Parser<LocalAddressSpace>::decodeFDE(
LocalAddressSpace::sThisAddressSpace,
(uintptr_t)ob->fde, &fdeInfo, &cieInfo);
if (msg == NULL) {
// Check if this FDE is for a function that includes the pc
if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
fde = (void*)fdeInfo.pcStart;
_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
head);
return true;
}
}
}
}
// release libgcc_object_info
_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
#else
(void)pc;
(void)fde;
#endif
return false;
}
}

View File

@ -0,0 +1,158 @@
/* ===-- assembly.h - libUnwind assembler support macros -------------------===
*
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
* ===----------------------------------------------------------------------===
*
* This file defines macros for use in libUnwind assembler source.
* This file is not part of the interface of this library.
*
* ===----------------------------------------------------------------------===
*/
#ifndef UNWIND_ASSEMBLY_H
#define UNWIND_ASSEMBLY_H
#if defined(__powerpc64__)
#define SEPARATOR ;
#define PPC64_OFFS_SRR0 0
#define PPC64_OFFS_CR 272
#define PPC64_OFFS_XER 280
#define PPC64_OFFS_LR 288
#define PPC64_OFFS_CTR 296
#define PPC64_OFFS_VRSAVE 304
#define PPC64_OFFS_FP 312
#define PPC64_OFFS_V 824
#ifdef _ARCH_PWR8
#define PPC64_HAS_VMX
#endif
#elif defined(__arm64__)
#define SEPARATOR %%
#else
#define SEPARATOR ;
#endif
#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR
#define PPC64_OPD2 SEPARATOR \
.p2align 3 SEPARATOR \
.quad .Lfunc_begin0 SEPARATOR \
.quad .TOC.@tocbase SEPARATOR \
.quad 0 SEPARATOR \
.text SEPARATOR \
.Lfunc_begin0:
#else
#define PPC64_OPD1
#define PPC64_OPD2
#endif
#define GLUE2(a, b) a ## b
#define GLUE(a, b) GLUE2(a, b)
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
#if defined(__APPLE__)
#define SYMBOL_IS_FUNC(name)
#define EXPORT_SYMBOL(name)
#define HIDDEN_SYMBOL(name) .private_extern name
#define WEAK_SYMBOL(name) .weak_reference name
#define WEAK_ALIAS(name, aliasname) \
.globl SYMBOL_NAME(aliasname) SEPARATOR \
WEAK_SYMBOL(aliasname) SEPARATOR \
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
#define NO_EXEC_STACK_DIRECTIVE
#elif defined(__ELF__)
#if defined(__arm__)
#define SYMBOL_IS_FUNC(name) .type name,%function
#else
#define SYMBOL_IS_FUNC(name) .type name,@function
#endif
#define EXPORT_SYMBOL(name)
#define HIDDEN_SYMBOL(name) .hidden name
#define WEAK_SYMBOL(name) .weak name
#define WEAK_ALIAS(name, aliasname) \
WEAK_SYMBOL(aliasname) SEPARATOR \
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
defined(__linux__)
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
#else
#define NO_EXEC_STACK_DIRECTIVE
#endif
#elif defined(_WIN32)
#define SYMBOL_IS_FUNC(name) \
.def name SEPARATOR \
.scl 2 SEPARATOR \
.type 32 SEPARATOR \
.endef
#define EXPORT_SYMBOL2(name) \
.section .drectve,"yn" SEPARATOR \
.ascii "-export:", #name, "\0" SEPARATOR \
.text
#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
#define EXPORT_SYMBOL(name)
#else
#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name)
#endif
#define HIDDEN_SYMBOL(name)
#if defined(__MINGW32__)
#define WEAK_ALIAS(name, aliasname) \
.globl SYMBOL_NAME(aliasname) SEPARATOR \
EXPORT_SYMBOL(aliasname) SEPARATOR \
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
#else
#define WEAK_ALIAS3(name, aliasname) \
.section .drectve,"yn" SEPARATOR \
.ascii "-alternatename:", #aliasname, "=", #name, "\0" SEPARATOR \
.text
#define WEAK_ALIAS2(name, aliasname) \
WEAK_ALIAS3(name, aliasname)
#define WEAK_ALIAS(name, aliasname) \
EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
WEAK_ALIAS2(SYMBOL_NAME(name), SYMBOL_NAME(aliasname))
#endif
#define NO_EXEC_STACK_DIRECTIVE
#elif defined(__sparc__)
#else
#error Unsupported target
#endif
#define DEFINE_LIBUNWIND_FUNCTION(name) \
.globl SYMBOL_NAME(name) SEPARATOR \
HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
PPC64_OPD1 \
SYMBOL_NAME(name): \
PPC64_OPD2
#if defined(__arm__)
#if !defined(__ARM_ARCH)
#define __ARM_ARCH 4
#endif
#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
#define ARM_HAS_BX
#endif
#ifdef ARM_HAS_BX
#define JMP(r) bx r
#else
#define JMP(r) mov pc, r
#endif
#endif /* __arm__ */
#endif /* UNWIND_ASSEMBLY_H */

View File

@ -0,0 +1,212 @@
//===----------------------------- config.h -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Defines macros used within libunwind project.
//
//===----------------------------------------------------------------------===//
#ifndef LIBUNWIND_CONFIG_H
#define LIBUNWIND_CONFIG_H
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "printf.h"
// Define static_assert() unless already defined by compiler.
#ifndef __has_feature
#define __has_feature(__x) 0
#endif
#if !(__has_feature(cxx_static_assert)) && !defined(static_assert)
#define static_assert(__b, __m) \
extern int compile_time_assert_failed[ ( __b ) ? 1 : -1 ] \
__attribute__( ( unused ) );
#endif
// Platform specific configuration defines.
#ifdef __APPLE__
#if defined(FOR_DYLD)
#define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
#else
#define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
#endif
#elif defined(_WIN32)
#ifdef __SEH__
#define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
#else
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
#endif
#else
#if defined(__ARM_DWARF_EH__) || !defined(__arm__)
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
#define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
#endif
#endif
#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
#define _LIBUNWIND_EXPORT
#define _LIBUNWIND_HIDDEN
#else
#if !defined(__ELF__) && !defined(__MACH__)
#define _LIBUNWIND_EXPORT __declspec(dllexport)
#define _LIBUNWIND_HIDDEN
#else
#define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
#define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
#endif
#endif
#define STR(a) #a
#define XSTR(a) STR(a)
#define SYMBOL_NAME(name) XSTR(__USER_LABEL_PREFIX__) #name
#if defined(__APPLE__)
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
__asm__(".globl " SYMBOL_NAME(aliasname)); \
__asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
__attribute__((weak_import));
#elif defined(__ELF__)
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
__attribute__((weak, alias(#name)));
#elif defined(_WIN32)
#if defined(__MINGW32__)
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
__attribute__((alias(#name)));
#else
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
__pragma(comment(linker, "/alternatename:" SYMBOL_NAME(aliasname) "=" \
SYMBOL_NAME(name))) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname;
#endif
#else
#error Unsupported target
#endif
#if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__)
#define _LIBUNWIND_BUILD_SJLJ_APIS
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__)
#define _LIBUNWIND_SUPPORT_FRAME_APIS
#endif
#if defined(__i386__) || defined(__x86_64__) || \
defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \
(!defined(__APPLE__) && defined(__arm__)) || \
(defined(__arm64__) || defined(__aarch64__)) || \
defined(__mips__)
#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
#define _LIBUNWIND_BUILD_ZERO_COST_APIS
#endif
#endif
#if defined(__powerpc64__) && defined(_ARCH_PWR8)
#define PPC64_HAS_VMX
#endif
#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
#define _LIBUNWIND_ABORT(msg) \
do { \
abort(); \
} while (0)
#else
#define _LIBUNWIND_ABORT(msg) \
do { \
fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \
__LINE__, msg); \
fflush(stderr); \
abort(); \
} while (0)
#endif
#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
#define _LIBUNWIND_LOG0(msg)
#define _LIBUNWIND_LOG(msg, ...)
#else
#define _LIBUNWIND_LOG0(msg) \
fprintf(stderr, "libunwind: " msg "\n")
#define _LIBUNWIND_LOG(msg, ...) \
fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__)
#endif
#if defined(NDEBUG)
#define _LIBUNWIND_LOG_IF_FALSE(x) x
#else
#define _LIBUNWIND_LOG_IF_FALSE(x) \
do { \
bool _ret = x; \
if (!_ret) \
_LIBUNWIND_LOG("" #x " failed in %s", __FUNCTION__); \
} while (0)
#endif
// Macros that define away in non-Debug builds
#ifdef NDEBUG
#define _LIBUNWIND_DEBUG_LOG(msg, ...)
#define _LIBUNWIND_TRACE_API(msg, ...)
#define _LIBUNWIND_TRACING_UNWINDING (0)
#define _LIBUNWIND_TRACING_DWARF (0)
#define _LIBUNWIND_TRACE_UNWINDING(msg, ...)
#define _LIBUNWIND_TRACE_DWARF(...)
#else
#ifdef __cplusplus
extern "C" {
#endif
extern bool logAPIs();
extern bool logUnwinding();
extern bool logDWARF();
#ifdef __cplusplus
}
#endif
#define _LIBUNWIND_DEBUG_LOG(msg, ...) _LIBUNWIND_LOG(msg, __VA_ARGS__)
#define _LIBUNWIND_TRACE_API(msg, ...) \
do { \
if (logAPIs()) \
_LIBUNWIND_LOG(msg, __VA_ARGS__); \
} while (0)
#define _LIBUNWIND_TRACING_UNWINDING logUnwinding()
#define _LIBUNWIND_TRACING_DWARF logDWARF()
#define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \
do { \
if (logUnwinding()) \
_LIBUNWIND_LOG(msg, __VA_ARGS__); \
} while (0)
#define _LIBUNWIND_TRACE_DWARF(...) \
do { \
if (logDWARF()) \
fprintf(stderr, __VA_ARGS__); \
} while (0)
#endif
#ifdef __cplusplus
// Used to fit UnwindCursor and Registers_xxx types against unw_context_t /
// unw_cursor_t sized memory blocks.
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
# define COMP_OP ==
#else
# define COMP_OP <=
#endif
template <typename _Type, typename _Mem>
struct check_fit {
template <typename T>
struct blk_count {
static const size_t count =
(sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
};
static const bool does_fit =
(blk_count<_Type>::count COMP_OP blk_count<_Mem>::count);
};
#undef COMP_OP
#endif // __cplusplus
#endif // LIBUNWIND_CONFIG_H

View File

@ -0,0 +1,239 @@
//===------------------------------- dwarf2.h -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/*
These constants were taken from version 3 of the DWARF standard,
which is Copyright (c) 2005 Free Standards Group, and
Copyright (c) 1992, 1993 UNIX International, Inc.
*/
#ifndef __DWARF2__
#define __DWARF2__
// DWARF unwind instructions
enum {
DW_CFA_nop = 0x0,
DW_CFA_set_loc = 0x1,
DW_CFA_advance_loc1 = 0x2,
DW_CFA_advance_loc2 = 0x3,
DW_CFA_advance_loc4 = 0x4,
DW_CFA_offset_extended = 0x5,
DW_CFA_restore_extended = 0x6,
DW_CFA_undefined = 0x7,
DW_CFA_same_value = 0x8,
DW_CFA_register = 0x9,
DW_CFA_remember_state = 0xA,
DW_CFA_restore_state = 0xB,
DW_CFA_def_cfa = 0xC,
DW_CFA_def_cfa_register = 0xD,
DW_CFA_def_cfa_offset = 0xE,
DW_CFA_def_cfa_expression = 0xF,
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_offset = 0x14,
DW_CFA_val_offset_sf = 0x15,
DW_CFA_val_expression = 0x16,
DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta
DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register
DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register
// GNU extensions
DW_CFA_GNU_window_save = 0x2D,
DW_CFA_GNU_args_size = 0x2E,
DW_CFA_GNU_negative_offset_extended = 0x2F,
// AARCH64 extensions
DW_CFA_AARCH64_negate_ra_state = 0x2D
};
// FSF exception handling Pointer-Encoding constants
// Used in CFI augmentation by GCC
enum {
DW_EH_PE_ptr = 0x00,
DW_EH_PE_uleb128 = 0x01,
DW_EH_PE_udata2 = 0x02,
DW_EH_PE_udata4 = 0x03,
DW_EH_PE_udata8 = 0x04,
DW_EH_PE_signed = 0x08,
DW_EH_PE_sleb128 = 0x09,
DW_EH_PE_sdata2 = 0x0A,
DW_EH_PE_sdata4 = 0x0B,
DW_EH_PE_sdata8 = 0x0C,
DW_EH_PE_absptr = 0x00,
DW_EH_PE_pcrel = 0x10,
DW_EH_PE_textrel = 0x20,
DW_EH_PE_datarel = 0x30,
DW_EH_PE_funcrel = 0x40,
DW_EH_PE_aligned = 0x50,
DW_EH_PE_indirect = 0x80,
DW_EH_PE_omit = 0xFF
};
// DWARF expressions
enum {
DW_OP_addr = 0x03, // constant address (size target specific)
DW_OP_deref = 0x06,
DW_OP_const1u = 0x08, // 1-byte constant
DW_OP_const1s = 0x09, // 1-byte constant
DW_OP_const2u = 0x0A, // 2-byte constant
DW_OP_const2s = 0x0B, // 2-byte constant
DW_OP_const4u = 0x0C, // 4-byte constant
DW_OP_const4s = 0x0D, // 4-byte constant
DW_OP_const8u = 0x0E, // 8-byte constant
DW_OP_const8s = 0x0F, // 8-byte constant
DW_OP_constu = 0x10, // ULEB128 constant
DW_OP_consts = 0x11, // SLEB128 constant
DW_OP_dup = 0x12,
DW_OP_drop = 0x13,
DW_OP_over = 0x14,
DW_OP_pick = 0x15, // 1-byte stack index
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, // ULEB128 addend
DW_OP_shl = 0x24,
DW_OP_shr = 0x25,
DW_OP_shra = 0x26,
DW_OP_xor = 0x27,
DW_OP_skip = 0x2F, // signed 2-byte constant
DW_OP_bra = 0x28, // signed 2-byte constant
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, // Literal 0
DW_OP_lit1 = 0x31, // Literal 1
DW_OP_lit2 = 0x32, // Literal 2
DW_OP_lit3 = 0x33, // Literal 3
DW_OP_lit4 = 0x34, // Literal 4
DW_OP_lit5 = 0x35, // Literal 5
DW_OP_lit6 = 0x36, // Literal 6
DW_OP_lit7 = 0x37, // Literal 7
DW_OP_lit8 = 0x38, // Literal 8
DW_OP_lit9 = 0x39, // Literal 9
DW_OP_lit10 = 0x3A, // Literal 10
DW_OP_lit11 = 0x3B, // Literal 11
DW_OP_lit12 = 0x3C, // Literal 12
DW_OP_lit13 = 0x3D, // Literal 13
DW_OP_lit14 = 0x3E, // Literal 14
DW_OP_lit15 = 0x3F, // Literal 15
DW_OP_lit16 = 0x40, // Literal 16
DW_OP_lit17 = 0x41, // Literal 17
DW_OP_lit18 = 0x42, // Literal 18
DW_OP_lit19 = 0x43, // Literal 19
DW_OP_lit20 = 0x44, // Literal 20
DW_OP_lit21 = 0x45, // Literal 21
DW_OP_lit22 = 0x46, // Literal 22
DW_OP_lit23 = 0x47, // Literal 23
DW_OP_lit24 = 0x48, // Literal 24
DW_OP_lit25 = 0x49, // Literal 25
DW_OP_lit26 = 0x4A, // Literal 26
DW_OP_lit27 = 0x4B, // Literal 27
DW_OP_lit28 = 0x4C, // Literal 28
DW_OP_lit29 = 0x4D, // Literal 29
DW_OP_lit30 = 0x4E, // Literal 30
DW_OP_lit31 = 0x4F, // Literal 31
DW_OP_reg0 = 0x50, // Contents of reg0
DW_OP_reg1 = 0x51, // Contents of reg1
DW_OP_reg2 = 0x52, // Contents of reg2
DW_OP_reg3 = 0x53, // Contents of reg3
DW_OP_reg4 = 0x54, // Contents of reg4
DW_OP_reg5 = 0x55, // Contents of reg5
DW_OP_reg6 = 0x56, // Contents of reg6
DW_OP_reg7 = 0x57, // Contents of reg7
DW_OP_reg8 = 0x58, // Contents of reg8
DW_OP_reg9 = 0x59, // Contents of reg9
DW_OP_reg10 = 0x5A, // Contents of reg10
DW_OP_reg11 = 0x5B, // Contents of reg11
DW_OP_reg12 = 0x5C, // Contents of reg12
DW_OP_reg13 = 0x5D, // Contents of reg13
DW_OP_reg14 = 0x5E, // Contents of reg14
DW_OP_reg15 = 0x5F, // Contents of reg15
DW_OP_reg16 = 0x60, // Contents of reg16
DW_OP_reg17 = 0x61, // Contents of reg17
DW_OP_reg18 = 0x62, // Contents of reg18
DW_OP_reg19 = 0x63, // Contents of reg19
DW_OP_reg20 = 0x64, // Contents of reg20
DW_OP_reg21 = 0x65, // Contents of reg21
DW_OP_reg22 = 0x66, // Contents of reg22
DW_OP_reg23 = 0x67, // Contents of reg23
DW_OP_reg24 = 0x68, // Contents of reg24
DW_OP_reg25 = 0x69, // Contents of reg25
DW_OP_reg26 = 0x6A, // Contents of reg26
DW_OP_reg27 = 0x6B, // Contents of reg27
DW_OP_reg28 = 0x6C, // Contents of reg28
DW_OP_reg29 = 0x6D, // Contents of reg29
DW_OP_reg30 = 0x6E, // Contents of reg30
DW_OP_reg31 = 0x6F, // Contents of reg31
DW_OP_breg0 = 0x70, // base register 0 + SLEB128 offset
DW_OP_breg1 = 0x71, // base register 1 + SLEB128 offset
DW_OP_breg2 = 0x72, // base register 2 + SLEB128 offset
DW_OP_breg3 = 0x73, // base register 3 + SLEB128 offset
DW_OP_breg4 = 0x74, // base register 4 + SLEB128 offset
DW_OP_breg5 = 0x75, // base register 5 + SLEB128 offset
DW_OP_breg6 = 0x76, // base register 6 + SLEB128 offset
DW_OP_breg7 = 0x77, // base register 7 + SLEB128 offset
DW_OP_breg8 = 0x78, // base register 8 + SLEB128 offset
DW_OP_breg9 = 0x79, // base register 9 + SLEB128 offset
DW_OP_breg10 = 0x7A, // base register 10 + SLEB128 offset
DW_OP_breg11 = 0x7B, // base register 11 + SLEB128 offset
DW_OP_breg12 = 0x7C, // base register 12 + SLEB128 offset
DW_OP_breg13 = 0x7D, // base register 13 + SLEB128 offset
DW_OP_breg14 = 0x7E, // base register 14 + SLEB128 offset
DW_OP_breg15 = 0x7F, // base register 15 + SLEB128 offset
DW_OP_breg16 = 0x80, // base register 16 + SLEB128 offset
DW_OP_breg17 = 0x81, // base register 17 + SLEB128 offset
DW_OP_breg18 = 0x82, // base register 18 + SLEB128 offset
DW_OP_breg19 = 0x83, // base register 19 + SLEB128 offset
DW_OP_breg20 = 0x84, // base register 20 + SLEB128 offset
DW_OP_breg21 = 0x85, // base register 21 + SLEB128 offset
DW_OP_breg22 = 0x86, // base register 22 + SLEB128 offset
DW_OP_breg23 = 0x87, // base register 23 + SLEB128 offset
DW_OP_breg24 = 0x88, // base register 24 + SLEB128 offset
DW_OP_breg25 = 0x89, // base register 25 + SLEB128 offset
DW_OP_breg26 = 0x8A, // base register 26 + SLEB128 offset
DW_OP_breg27 = 0x8B, // base register 27 + SLEB128 offset
DW_OP_breg28 = 0x8C, // base register 28 + SLEB128 offset
DW_OP_breg29 = 0x8D, // base register 29 + SLEB128 offset
DW_OP_breg30 = 0x8E, // base register 30 + SLEB128 offset
DW_OP_breg31 = 0x8F, // base register 31 + SLEB128 offset
DW_OP_regx = 0x90, // ULEB128 register
DW_OP_fbreg = 0x91, // SLEB128 offset
DW_OP_bregx = 0x92, // ULEB128 register followed by SLEB128 offset
DW_OP_piece = 0x93, // ULEB128 size of piece addressed
DW_OP_deref_size = 0x94, // 1-byte size of data retrieved
DW_OP_xderef_size = 0x95, // 1-byte size of data retrieved
DW_OP_nop = 0x96,
DW_OP_push_object_addres = 0x97,
DW_OP_call2 = 0x98, // 2-byte offset of DIE
DW_OP_call4 = 0x99, // 4-byte offset of DIE
DW_OP_call_ref = 0x9A, // 4- or 8-byte offset of DIE
DW_OP_lo_user = 0xE0,
DW_OP_APPLE_uninit = 0xF0,
DW_OP_hi_user = 0xFF
};
#endif

View File

@ -0,0 +1,322 @@
//===--------------------------- libunwind.cpp ----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements unw_* functions from <libunwind.h>
//
//===----------------------------------------------------------------------===//
#include <libunwind.h>
#include "libunwind_ext.h"
#include "config.h"
#include <stdlib.h>
#if !defined(__USING_SJLJ_EXCEPTIONS__)
#include "AddressSpace.hpp"
#include "UnwindCursor.hpp"
using namespace libunwind;
/// internal object to represent this processes address space
LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
(unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
/// Create a cursor of a thread in this process given 'context' recorded by
/// __unw_getcontext().
_LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
unw_context_t *context) {
_LIBUNWIND_TRACE_API("__unw_init_local(cursor=%p, context=%p)",
static_cast<void *>(cursor),
static_cast<void *>(context));
#if defined(__i386__)
# define REGISTER_KIND Registers_x86
#elif defined(__x86_64__)
# define REGISTER_KIND Registers_x86_64
#elif defined(__powerpc64__)
# define REGISTER_KIND Registers_ppc64
#elif defined(__ppc__)
# define REGISTER_KIND Registers_ppc
#elif defined(__aarch64__)
# define REGISTER_KIND Registers_arm64
#elif defined(__arm__)
# define REGISTER_KIND Registers_arm
#elif defined(__or1k__)
# define REGISTER_KIND Registers_or1k
#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
# define REGISTER_KIND Registers_mips_o32
#elif defined(__mips64)
# define REGISTER_KIND Registers_mips_newabi
#elif defined(__mips__)
# warning The MIPS architecture is not supported with this ABI and environment!
#elif defined(__sparc__)
# define REGISTER_KIND Registers_sparc
#else
# error Architecture not supported
#endif
// Use "placement new" to allocate UnwindCursor in the cursor buffer.
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, REGISTER_KIND> *>(cursor))
UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
context, LocalAddressSpace::sThisAddressSpace);
#undef REGISTER_KIND
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
}
_LIBUNWIND_WEAK_ALIAS(__unw_init_local, unw_init_local)
/// Get value of specified register at cursor position in stack frame.
_LIBUNWIND_HIDDEN int __unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_word_t *value) {
_LIBUNWIND_TRACE_API("__unw_get_reg(cursor=%p, regNum=%d, &value=%p)",
static_cast<void *>(cursor), regNum,
static_cast<void *>(value));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
if (co->validReg(regNum)) {
*value = co->getReg(regNum);
return UNW_ESUCCESS;
}
return UNW_EBADREG;
}
_LIBUNWIND_WEAK_ALIAS(__unw_get_reg, unw_get_reg)
/// Set value of specified register at cursor position in stack frame.
_LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_word_t value) {
_LIBUNWIND_TRACE_API("__unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR
")",
static_cast<void *>(cursor), regNum, value);
typedef LocalAddressSpace::pint_t pint_t;
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
if (co->validReg(regNum)) {
co->setReg(regNum, (pint_t)value);
// specical case altering IP to re-find info (being called by personality
// function)
if (regNum == UNW_REG_IP) {
unw_proc_info_t info;
// First, get the FDE for the old location and then update it.
co->getInfo(&info);
co->setInfoBasedOnIPRegister(false);
// If the original call expects stack adjustment, perform this now.
// Normal frame unwinding would have included the offset already in the
// CFA computation.
// Note: for PA-RISC and other platforms where the stack grows up,
// this should actually be - info.gp. LLVM doesn't currently support
// any such platforms and Clang doesn't export a macro for them.
if (info.gp)
co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp);
}
return UNW_ESUCCESS;
}
return UNW_EBADREG;
}
_LIBUNWIND_WEAK_ALIAS(__unw_set_reg, unw_set_reg)
/// Get value of specified float register at cursor position in stack frame.
_LIBUNWIND_HIDDEN int __unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_fpreg_t *value) {
_LIBUNWIND_TRACE_API("__unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)",
static_cast<void *>(cursor), regNum,
static_cast<void *>(value));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
if (co->validFloatReg(regNum)) {
*value = co->getFloatReg(regNum);
return UNW_ESUCCESS;
}
return UNW_EBADREG;
}
_LIBUNWIND_WEAK_ALIAS(__unw_get_fpreg, unw_get_fpreg)
/// Set value of specified float register at cursor position in stack frame.
_LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_fpreg_t value) {
#if defined(_LIBUNWIND_ARM_EHABI)
_LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
static_cast<void *>(cursor), regNum, value);
#else
_LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
static_cast<void *>(cursor), regNum, value);
#endif
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
if (co->validFloatReg(regNum)) {
co->setFloatReg(regNum, value);
return UNW_ESUCCESS;
}
return UNW_EBADREG;
}
_LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg, unw_set_fpreg)
/// Move cursor to next frame.
_LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("__unw_step(cursor=%p)", static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->step();
}
_LIBUNWIND_WEAK_ALIAS(__unw_step, unw_step)
/// Get unwind info at cursor position in stack frame.
_LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor,
unw_proc_info_t *info) {
_LIBUNWIND_TRACE_API("__unw_get_proc_info(cursor=%p, &info=%p)",
static_cast<void *>(cursor), static_cast<void *>(info));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->getInfo(info);
if (info->end_ip == 0)
return UNW_ENOINFO;
return UNW_ESUCCESS;
}
_LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info)
/// Resume execution at cursor position (aka longjump).
_LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->jumpto();
return UNW_EUNSPEC;
}
_LIBUNWIND_WEAK_ALIAS(__unw_resume, unw_resume)
/// Get name of function at cursor position in stack frame.
_LIBUNWIND_HIDDEN int __unw_get_proc_name(unw_cursor_t *cursor, char *buf,
size_t bufLen, unw_word_t *offset) {
_LIBUNWIND_TRACE_API("__unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)",
static_cast<void *>(cursor), static_cast<void *>(buf),
static_cast<unsigned long>(bufLen));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
if (co->getFunctionName(buf, bufLen, offset))
return UNW_ESUCCESS;
return UNW_EUNSPEC;
}
_LIBUNWIND_WEAK_ALIAS(__unw_get_proc_name, unw_get_proc_name)
/// Checks if a register is a floating-point register.
_LIBUNWIND_HIDDEN int __unw_is_fpreg(unw_cursor_t *cursor,
unw_regnum_t regNum) {
_LIBUNWIND_TRACE_API("__unw_is_fpreg(cursor=%p, regNum=%d)",
static_cast<void *>(cursor), regNum);
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->validFloatReg(regNum);
}
_LIBUNWIND_WEAK_ALIAS(__unw_is_fpreg, unw_is_fpreg)
/// Checks if a register is a floating-point register.
_LIBUNWIND_HIDDEN const char *__unw_regname(unw_cursor_t *cursor,
unw_regnum_t regNum) {
_LIBUNWIND_TRACE_API("__unw_regname(cursor=%p, regNum=%d)",
static_cast<void *>(cursor), regNum);
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->getRegisterName(regNum);
}
_LIBUNWIND_WEAK_ALIAS(__unw_regname, unw_regname)
/// Checks if current frame is signal trampoline.
_LIBUNWIND_HIDDEN int __unw_is_signal_frame(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("__unw_is_signal_frame(cursor=%p)",
static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->isSignalFrame();
}
_LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame, unw_is_signal_frame)
#ifdef __arm__
// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
_LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("__unw_get_fpreg_save_vfp_as_X(cursor=%p)",
static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->saveVFPAsX();
}
_LIBUNWIND_WEAK_ALIAS(__unw_save_vfp_as_X, unw_save_vfp_as_X)
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
/// SPI: walks cached DWARF entries
_LIBUNWIND_HIDDEN void __unw_iterate_dwarf_unwind_cache(void (*func)(
unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
_LIBUNWIND_TRACE_API("__unw_iterate_dwarf_unwind_cache(func=%p)",
reinterpret_cast<void *>(func));
DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
}
_LIBUNWIND_WEAK_ALIAS(__unw_iterate_dwarf_unwind_cache,
unw_iterate_dwarf_unwind_cache)
/// IPI: for __register_frame()
void __unw_add_dynamic_fde(unw_word_t fde) {
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
LocalAddressSpace::sThisAddressSpace,
(LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
if (message == NULL) {
// dynamically registered FDEs don't have a mach_header group they are in.
// Use fde as mh_group
unw_word_t mh_group = fdeInfo.fdeStart;
DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
fdeInfo.pcStart, fdeInfo.pcEnd,
fdeInfo.fdeStart);
} else {
_LIBUNWIND_DEBUG_LOG("__unw_add_dynamic_fde: bad fde: %s", message);
}
}
/// IPI: for __deregister_frame()
void __unw_remove_dynamic_fde(unw_word_t fde) {
// fde is own mh_group
DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
}
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
// Add logging hooks in Debug builds only
#ifndef NDEBUG
#include <stdlib.h>
_LIBUNWIND_HIDDEN
bool logAPIs() {
// do manual lock to avoid use of _cxa_guard_acquire or initializers
static bool checked = false;
static bool log = false;
if (!checked) {
log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
checked = true;
}
return log;
}
_LIBUNWIND_HIDDEN
bool logUnwinding() {
// do manual lock to avoid use of _cxa_guard_acquire or initializers
static bool checked = false;
static bool log = false;
if (!checked) {
log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL);
checked = true;
}
return log;
}
_LIBUNWIND_HIDDEN
bool logDWARF() {
// do manual lock to avoid use of _cxa_guard_acquire or initializers
static bool checked = false;
static bool log = false;
if (!checked) {
log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL);
checked = true;
}
return log;
}
#endif // NDEBUG

View File

@ -0,0 +1,65 @@
//===------------------------ libunwind_ext.h -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Extensions to libunwind API.
//
//===----------------------------------------------------------------------===//
#ifndef __LIBUNWIND_EXT__
#define __LIBUNWIND_EXT__
#include "config.h"
#include <libunwind.h>
#include <unwind.h>
#define UNW_STEP_SUCCESS 1
#define UNW_STEP_END 0
#ifdef __cplusplus
extern "C" {
#endif
extern int __unw_getcontext(unw_context_t *);
extern int __unw_init_local(unw_cursor_t *, unw_context_t *);
extern int __unw_step(unw_cursor_t *);
extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *);
extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t);
extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t);
extern int __unw_resume(unw_cursor_t *);
#ifdef __arm__
/* Save VFP registers in FSTMX format (instead of FSTMD). */
extern void __unw_save_vfp_as_X(unw_cursor_t *);
#endif
extern const char *__unw_regname(unw_cursor_t *, unw_regnum_t);
extern int __unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *);
extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t);
extern int __unw_is_signal_frame(unw_cursor_t *);
extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);
// SPI
extern void __unw_iterate_dwarf_unwind_cache(void (*func)(
unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
// IPI
extern void __unw_add_dynamic_fde(unw_word_t fde);
extern void __unw_remove_dynamic_fde(unw_word_t fde);
#if defined(_LIBUNWIND_ARM_EHABI)
extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
const uint32_t *data,
size_t offset, size_t len);
#endif
#ifdef __cplusplus
}
#endif
#endif // __LIBUNWIND_EXT__

View File

@ -0,0 +1,915 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// 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.
//
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
// embedded systems with a very limited resources. These routines are thread
// safe and reentrant!
// Use this instead of the bloated standard/newlib printf cause these use
// malloc for printf (and may not be thread safe).
//
///////////////////////////////////////////////////////////////////////////////
#include <stdbool.h>
#include <stdint.h>
#include "printf.h"
// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
// printf_config.h header file
// default: undefined
#ifdef PRINTF_INCLUDE_CONFIG_H
#include "printf_config.h"
#endif
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
// numeric number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_NTOA_BUFFER_SIZE
#define PRINTF_NTOA_BUFFER_SIZE 32U
#endif
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
// float number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_FTOA_BUFFER_SIZE
#define PRINTF_FTOA_BUFFER_SIZE 32U
#endif
// support for the floating point type (%f)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
#define PRINTF_SUPPORT_FLOAT
#endif
// support for exponential floating point notation (%e/%g)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
#define PRINTF_SUPPORT_EXPONENTIAL
#endif
// define the default floating point precision
// default: 6 digits
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
#endif
// define the largest float suitable to print with %f
// default: 1e9
#ifndef PRINTF_MAX_FLOAT
#define PRINTF_MAX_FLOAT 1e9
#endif
// support for the long long types (%llu or %p)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
#define PRINTF_SUPPORT_LONG_LONG
#endif
// support for the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
#define PRINTF_SUPPORT_PTRDIFF_T
#endif
///////////////////////////////////////////////////////////////////////////////
// internal flag definitions
#define FLAGS_ZEROPAD (1U << 0U)
#define FLAGS_LEFT (1U << 1U)
#define FLAGS_PLUS (1U << 2U)
#define FLAGS_SPACE (1U << 3U)
#define FLAGS_HASH (1U << 4U)
#define FLAGS_UPPERCASE (1U << 5U)
#define FLAGS_CHAR (1U << 6U)
#define FLAGS_SHORT (1U << 7U)
#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)
// import float.h for DBL_MAX
#if defined(PRINTF_SUPPORT_FLOAT)
#include <float.h>
#endif
// output function type
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
// wrapper (used as buffer) for output function type
typedef struct {
void (*fct)(char character, void* arg);
void* arg;
} out_fct_wrap_type;
// internal buffer output
static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
{
if (idx < maxlen) {
((char*)buffer)[idx] = character;
}
}
// internal null output
static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)character; (void)buffer; (void)idx; (void)maxlen;
}
// internal _putchar wrapper
static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)buffer; (void)idx; (void)maxlen;
if (character) {
_putchar(character);
}
}
// internal output function wrapper
static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)idx; (void)maxlen;
if (character) {
// buffer is the output fct pointer
((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);
}
}
// internal secure strlen
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
static inline unsigned int _strnlen_s(const char* str, size_t maxsize)
{
const char* s;
for (s = str; *s && maxsize--; ++s);
return (unsigned int)(s - str);
}
// internal test if char is a digit (0-9)
// \return true if char is a digit
static inline bool _is_digit(char ch)
{
return (ch >= '0') && (ch <= '9');
}
// internal ASCII string to unsigned int conversion
static unsigned int _atoi(const char** str)
{
unsigned int i = 0U;
while (_is_digit(**str)) {
i = i * 10U + (unsigned int)(*((*str)++) - '0');
}
return i;
}
// output the specified string in reverse, taking care of any zero-padding
static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)
{
const size_t start_idx = idx;
// pad spaces up to given width
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
for (size_t i = len; i < width; i++) {
out(' ', buffer, idx++, maxlen);
}
}
// reverse string
while (len) {
out(buf[--len], buffer, idx++, maxlen);
}
// append pad spaces up to given width
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) {
out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
// internal itoa format
static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
{
// pad leading zeros
if (!(flags & FLAGS_LEFT)) {
if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
// handle hash
if (flags & FLAGS_HASH) {
if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
len--;
if (len && (base == 16U)) {
len--;
}
}
if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'x';
}
else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'X';
}
else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'b';
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
buf[len++] = '0';
}
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
// internal itoa for 'long' type
static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
// internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG)
static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
#endif // PRINTF_SUPPORT_LONG_LONG
#if defined(PRINTF_SUPPORT_FLOAT)
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
#endif
// internal ftoa for fixed decimal floating point
static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0U;
double diff = 0.0;
// powers of 10
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
// test for special values
if (value != value)
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
if (value < -DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
if (value > DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
// test for very large values
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
return 0U;
#endif
}
// test for negative
bool negative = false;
if (value < 0) {
negative = true;
value = 0 - value;
}
// set default precision, if not set explicitly
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
buf[len++] = '0';
prec--;
}
int whole = (int)value;
double tmp = (value - whole) * pow10[prec];
unsigned long frac = (unsigned long)tmp;
diff = tmp - frac;
if (diff > 0.5) {
++frac;
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
if (frac >= pow10[prec]) {
frac = 0;
++whole;
}
}
else if (diff < 0.5) {
}
else if ((frac == 0U) || (frac & 1U)) {
// if halfway, round up if odd OR if last digit is 0
++frac;
}
if (prec == 0U) {
diff = value - (double)whole;
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
++whole;
}
}
else {
unsigned int count = prec;
// now do fractional part, as an unsigned number
while (len < PRINTF_FTOA_BUFFER_SIZE) {
--count;
buf[len++] = (char)(48U + (frac % 10U));
if (!(frac /= 10U)) {
break;
}
}
// add extra 0s
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
buf[len++] = '0';
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
// add decimal
buf[len++] = '.';
}
}
// do whole part, number is reversed
while (len < PRINTF_FTOA_BUFFER_SIZE) {
buf[len++] = (char)(48 + (whole % 10));
if (!(whole /= 10)) {
break;
}
}
// pad leading zeros
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
// check for NaN and special values
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
}
// determine the sign
const bool negative = value < 0;
if (negative) {
value = -value;
}
// default precision
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// determine the decimal exponent
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
union {
uint64_t U;
double F;
} conv;
conv.F = value;
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
// now we want to compute 10^expval but we want to be sure it won't overflow
exp2 = (int)(expval * 3.321928094887362 + 0.5);
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z;
conv.U = (uint64_t)(exp2 + 1023) << 52U;
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
// correct for rounding errors
if (value < conv.F) {
expval--;
conv.F /= 10;
}
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
// in "%g" mode, "prec" is the number of *significant figures* not decimals
if (flags & FLAGS_ADAPT_EXP) {
// do we want to fall-back to "%f" mode?
if ((value >= 1e-4) && (value < 1e6)) {
if ((int)prec > expval) {
prec = (unsigned)((int)prec - expval - 1);
}
else {
prec = 0;
}
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
// no characters in exponent
minwidth = 0U;
expval = 0;
}
else {
// we use one sigfig for the whole part
if ((prec > 0) && (flags & FLAGS_PRECISION)) {
--prec;
}
}
}
// will everything fit?
unsigned int fwidth = width;
if (width > minwidth) {
// we didn't fall-back so subtract the characters required for the exponent
fwidth -= minwidth;
} else {
// not enough characters, so go back to default sizing
fwidth = 0U;
}
if ((flags & FLAGS_LEFT) && minwidth) {
// if we're padding on the right, DON'T pad the floating part
fwidth = 0U;
}
// rescale the float value
if (expval) {
value /= conv.F;
}
// output the floating part
const size_t start_idx = idx;
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
// output the exponent part
if (minwidth) {
// output the exponential symbol
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
// output the exponent value
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
// might need to right-pad spaces
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
// internal vsnprintf
static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
{
unsigned int flags, width, precision, n;
size_t idx = 0U;
if (!buffer) {
// use null output function
out = _out_null;
}
while (*format)
{
// format specifier? %[flags][width][.precision][length]
if (*format != '%') {
// no
out(*format, buffer, idx++, maxlen);
format++;
continue;
}
else {
// yes, evaluate it
format++;
}
// evaluate flags
flags = 0U;
do {
switch (*format) {
case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;
case '-': flags |= FLAGS_LEFT; format++; n = 1U; break;
case '+': flags |= FLAGS_PLUS; format++; n = 1U; break;
case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break;
case '#': flags |= FLAGS_HASH; format++; n = 1U; break;
default : n = 0U; break;
}
} while (n);
// evaluate width field
width = 0U;
if (_is_digit(*format)) {
width = _atoi(&format);
}
else if (*format == '*') {
const int w = va_arg(va, int);
if (w < 0) {
flags |= FLAGS_LEFT; // reverse padding
width = (unsigned int)-w;
}
else {
width = (unsigned int)w;
}
format++;
}
// evaluate precision field
precision = 0U;
if (*format == '.') {
flags |= FLAGS_PRECISION;
format++;
if (_is_digit(*format)) {
precision = _atoi(&format);
}
else if (*format == '*') {
const int prec = (int)va_arg(va, int);
precision = prec > 0 ? (unsigned int)prec : 0U;
format++;
}
}
// evaluate length field
switch (*format) {
case 'l' :
flags |= FLAGS_LONG;
format++;
if (*format == 'l') {
flags |= FLAGS_LONG_LONG;
format++;
}
break;
case 'h' :
flags |= FLAGS_SHORT;
format++;
if (*format == 'h') {
flags |= FLAGS_CHAR;
format++;
}
break;
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
case 't' :
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
#endif
case 'j' :
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
case 'z' :
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
default :
break;
}
// evaluate specifier
switch (*format) {
case 'd' :
case 'i' :
case 'u' :
case 'x' :
case 'X' :
case 'o' :
case 'b' : {
// set the base
unsigned int base;
if (*format == 'x' || *format == 'X') {
base = 16U;
}
else if (*format == 'o') {
base = 8U;
}
else if (*format == 'b') {
base = 2U;
}
else {
base = 10U;
flags &= ~FLAGS_HASH; // no hash for dec format
}
// uppercase
if (*format == 'X') {
flags |= FLAGS_UPPERCASE;
}
// no plus or space flag for u, x, X, o, b
if ((*format != 'i') && (*format != 'd')) {
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
}
// ignore '0' flag when precision is given
if (flags & FLAGS_PRECISION) {
flags &= ~FLAGS_ZEROPAD;
}
// convert the integer
if ((*format == 'i') || (*format == 'd')) {
// signed
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
const long long value = va_arg(va, long long);
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
const long value = va_arg(va, long);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
else {
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
}
else {
// unsigned
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
}
else {
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
}
}
format++;
break;
}
#if defined(PRINTF_SUPPORT_FLOAT)
case 'f' :
case 'F' :
if (*format == 'F') flags |= FLAGS_UPPERCASE;
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
case 'e':
case 'E':
case 'g':
case 'G':
if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
case 'c' : {
unsigned int l = 1U;
// pre padding
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// char output
out((char)va_arg(va, int), buffer, idx++, maxlen);
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 's' : {
const char* p = va_arg(va, char*);
unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);
// pre padding
if (flags & FLAGS_PRECISION) {
l = (l < precision ? l : precision);
}
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// string output
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
out(*(p++), buffer, idx++, maxlen);
}
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 'p' : {
width = sizeof(void*) * 2U;
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
#if defined(PRINTF_SUPPORT_LONG_LONG)
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
if (is_ll) {
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);
}
else {
#endif
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);
#if defined(PRINTF_SUPPORT_LONG_LONG)
}
#endif
format++;
break;
}
case '%' :
out('%', buffer, idx++, maxlen);
format++;
break;
default :
out(*format, buffer, idx++, maxlen);
format++;
break;
}
}
// termination
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
// return written chars without terminating \0
return (int)idx;
}
///////////////////////////////////////////////////////////////////////////////
int printf_(const char* format, ...)
{
va_list va;
va_start(va, format);
char buffer[1];
const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
va_end(va);
_putchar('\n');
return ret;
}
int sprintf_(char* buffer, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va);
va_end(va);
return ret;
}
int snprintf_(char* buffer, size_t count, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
va_end(va);
return ret;
}
int vprintf_(const char* format, va_list va)
{
char buffer[1];
return _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
}
int vsnprintf_(char* buffer, size_t count, const char* format, va_list va)
{
return _vsnprintf(_out_buffer, buffer, count, format, va);
}
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...)
{
va_list va;
va_start(va, format);
const out_fct_wrap_type out_fct_wrap = { out, arg };
const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va);
va_end(va);
return ret;
}

View File

@ -0,0 +1,117 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// 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.
//
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
// embedded systems with a very limited resources.
// Use this instead of bloated standard/newlib printf.
// These routines are thread safe and reentrant.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _PRINTF_H_
#define _PRINTF_H_
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Output a character to a custom device like UART, used by the printf() function
* This function is declared here only. You have to write your custom implementation somewhere
* \param character Character to output
*/
void _putchar(char character);
/**
* Tiny printf implementation
* You have to implement _putchar if you use printf()
* To avoid conflicts with the regular printf() API it is overridden by macro defines
* and internal underscore-appended functions like printf_() are used
* \param format A string that specifies the format of the output
* \return The number of characters that are written into the array, not counting the terminating null character
*/
#define printf printf_
int printf_(const char* format, ...);
/**
* Tiny sprintf implementation
* Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!
* \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!
* \param format A string that specifies the format of the output
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
#define sprintf sprintf_
int sprintf_(char* buffer, const char* format, ...);
/**
* Tiny snprintf/vsnprintf implementation
* \param buffer A pointer to the buffer where to store the formatted string
* \param count The maximum number of characters to store in the buffer, including a terminating null character
* \param format A string that specifies the format of the output
* \param va A value identifying a variable arguments list
* \return The number of characters that COULD have been written into the buffer, not counting the terminating
* null character. A value equal or larger than count indicates truncation. Only when the returned value
* is non-negative and less than count, the string has been completely written.
*/
#define snprintf snprintf_
#define vsnprintf vsnprintf_
int snprintf_(char* buffer, size_t count, const char* format, ...);
int vsnprintf_(char* buffer, size_t count, const char* format, va_list va);
/**
* Tiny vprintf implementation
* \param format A string that specifies the format of the output
* \param va A value identifying a variable arguments list
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
#define vprintf vprintf_
int vprintf_(const char* format, va_list va);
/**
* printf with output function
* You may use this as dynamic alternative to printf() with its fixed _putchar() output
* \param out An output function which takes one character and an argument pointer
* \param arg An argument pointer for user data passed to output function
* \param format A string that specifies the format of the output
* \return The number of characters that are sent to the output function, not counting the terminating null character
*/
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...);
#ifdef __cplusplus
}
#endif
#endif // _PRINTF_H_

View File

@ -0,0 +1,35 @@
include(AddLLVM) # for add_lit_testsuite
macro(pythonize_bool var)
if (${var})
set(${var} True)
else()
set(${var} False)
endif()
endmacro()
if (NOT DEFINED LIBCXX_ENABLE_SHARED)
set(LIBCXX_ENABLE_SHARED ON)
endif()
pythonize_bool(LIBUNWIND_BUILD_32_BITS)
pythonize_bool(LIBCXX_ENABLE_SHARED)
pythonize_bool(LIBUNWIND_ENABLE_SHARED)
pythonize_bool(LIBUNWIND_ENABLE_THREADS)
pythonize_bool(LIBUNWIND_ENABLE_EXCEPTIONS)
pythonize_bool(LIBUNWIND_USE_COMPILER_RT)
pythonize_bool(LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY)
set(LIBUNWIND_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
"TargetInfo to use when setting up test environment.")
set(LIBUNWIND_EXECUTOR "None" CACHE STRING
"Executor to use when running tests.")
set(AUTO_GEN_COMMENT "## Autogenerated by libunwind configuration.\n# Do not edit!")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
@ONLY)
add_lit_testsuite(check-unwind "Running libunwind tests"
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${LIBUNWIND_TEST_DEPS}
)

View File

@ -0,0 +1,28 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// The Itanium ABI requires that _Unwind_Exception objects are "double-word
// aligned".
#include <unwind.h>
// EHABI : 8-byte aligned
// itanium: largest supported alignment for the system
#if defined(_LIBUNWIND_ARM_EHABI)
static_assert(alignof(_Unwind_Control_Block) == 8,
"_Unwind_Control_Block must be double-word aligned");
#else
struct MaxAligned {} __attribute__((__aligned__));
static_assert(alignof(_Unwind_Exception) == alignof(MaxAligned),
"_Unwind_Exception must be maximally aligned");
#endif
int main()
{
}

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