Commit 10c7897b authored by swift_gan's avatar swift_gan

temp save

parent 74883690
...@@ -5,6 +5,7 @@ import android.app.Application; ...@@ -5,6 +5,7 @@ import android.app.Application;
import android.os.Build; import android.os.Build;
import android.util.Log; import android.util.Log;
import com.swift.sandhook.nativehook.NativeHook;
import com.swift.sandhook.test.TestClass; import com.swift.sandhook.test.TestClass;
import com.swift.sandhook.testHookers.ActivityHooker; import com.swift.sandhook.testHookers.ActivityHooker;
import com.swift.sandhook.testHookers.CtrHook; import com.swift.sandhook.testHookers.CtrHook;
...@@ -36,6 +37,8 @@ public class MyApp extends Application { ...@@ -36,6 +37,8 @@ public class MyApp extends Application {
SandHookConfig.SDK_INT = 29; SandHookConfig.SDK_INT = 29;
} }
NativeHook.test();
SandHook.disableVMInline(); SandHook.disableVMInline();
SandHook.tryDisableProfile(getPackageName()); SandHook.tryDisableProfile(getPackageName());
SandHook.disableDex2oatInline(false); SandHook.disableDex2oatInline(false);
...@@ -80,20 +83,25 @@ public class MyApp extends Application { ...@@ -80,20 +83,25 @@ public class MyApp extends Application {
}); });
XposedHelpers.findAndHookMethod(MainActivity.class, "testStub", TestClass.class, int.class, String.class, boolean.class, char.class, String.class, new XC_MethodHook() { new Thread(new Runnable() {
@Override @Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable { public void run() {
super.beforeHookedMethod(param); XposedHelpers.findAndHookMethod(MainActivity.class, "testStub", TestClass.class, int.class, String.class, boolean.class, char.class, String.class, new XC_MethodHook() {
param.args[1] = 2; @Override
Log.e("XposedCompat", "beforeHookedMethod: " + param.method.getName()); protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
param.args[1] = 2;
Log.e("XposedCompat", "beforeHookedMethod: " + param.method.getName());
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Log.e("XposedCompat", "afterHookedMethod: " + param.method.getName());
}
});
} }
}).start();
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Log.e("XposedCompat", "afterHookedMethod: " + param.method.getName());
}
});
try { try {
ClassLoader classLoader = getClassLoader(); ClassLoader classLoader = getClassLoader();
......
...@@ -7,7 +7,7 @@ buildscript { ...@@ -7,7 +7,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.3' classpath 'com.android.tools.build:gradle:3.3.1'
classpath 'com.novoda:bintray-release:0.8.1' classpath 'com.novoda:bintray-release:0.8.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
......
...@@ -17,7 +17,9 @@ if(${CMAKE_ANDROID_ARCH_ABI} STREQUAL "arm64-v8a") ...@@ -17,7 +17,9 @@ if(${CMAKE_ANDROID_ARCH_ABI} STREQUAL "arm64-v8a")
src/main/cpp/archs/arm/arm64/register/register_list_arm64.cpp src/main/cpp/archs/arm/arm64/register/register_list_arm64.cpp
src/main/cpp/archs/arm/arm64/decoder/decoder_arm64.cpp src/main/cpp/archs/arm/arm64/decoder/decoder_arm64.cpp
src/main/cpp/archs/arm/arm64/relocate/code_relocate_arm64.cpp src/main/cpp/archs/arm/arm64/relocate/code_relocate_arm64.cpp
src/main/cpp/archs/arm/arm64/hook/hook_arm64.cpp) src/main/cpp/archs/arm/arm64/hook/hook_arm64.cpp
src/main/cpp/libffi/aarch64/ffi_arm64.c
src/main/cpp/libffi/aarch64/sysv_arm64.S)
elseif (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi-v7a") elseif (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi-v7a")
set(OS_DEPENDENDED_SRC set(OS_DEPENDENDED_SRC
...@@ -30,7 +32,9 @@ elseif (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi-v7a") ...@@ -30,7 +32,9 @@ elseif (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi-v7a")
src/main/cpp/archs/arm/arm32/decoder/decoder_arm32.cpp src/main/cpp/archs/arm/arm32/decoder/decoder_arm32.cpp
src/main/cpp/archs/arm/arm32/hook/hook_arm32.cpp src/main/cpp/archs/arm/arm32/hook/hook_arm32.cpp
src/main/cpp/archs/arm/arm32/hook/breakpoint_shellcode.S src/main/cpp/archs/arm/arm32/hook/breakpoint_shellcode.S
src/main/cpp/archs/arm/arm32/relocate/code_relocate_arm32.cpp) src/main/cpp/archs/arm/arm32/relocate/code_relocate_arm32.cpp
src/main/cpp/libffi/arm/ffi_armv7.c
src/main/cpp/libffi/arm/sysv_armv7.S)
endif() endif()
add_library( # Sets the name of the library. add_library( # Sets the name of the library.
...@@ -48,6 +52,17 @@ add_library( # Sets the name of the library. ...@@ -48,6 +52,17 @@ add_library( # Sets the name of the library.
src/main/cpp/buffer/code_buffer.cpp src/main/cpp/buffer/code_buffer.cpp
src/main/cpp/utils/platform.cpp src/main/cpp/utils/platform.cpp
src/main/cpp/hook/hook.cpp src/main/cpp/hook/hook.cpp
src/main/cpp/javabridge/type_bridge.cpp
src/main/cpp/javabridge/arguments.cpp
src/main/cpp/libffi/closures.c
src/main/cpp/libffi/debug.c
src/main/cpp/libffi/dlmalloc.c
src/main/cpp/libffi/java_raw_api.c
src/main/cpp/libffi/prep_cif.c
src/main/cpp/libffi/raw_api.c
src/main/cpp/libffi/types.c
src/main/cpp/libffi/ffi_cxx.cc
${OS_DEPENDENDED_SRC}) ${OS_DEPENDENDED_SRC})
...@@ -71,7 +86,10 @@ include_directories( ...@@ -71,7 +86,10 @@ include_directories(
src/main/cpp/archs/arm/arm32/decoder src/main/cpp/archs/arm/arm32/decoder
src/main/cpp/archs/arm/arm32/hook src/main/cpp/archs/arm/arm32/hook
src/main/cpp/archs/arm/arm32/relocate src/main/cpp/archs/arm/arm32/relocate
src/main/cpp/antihook src/main/cpp
src/main/javabridge
src/main/cpp/libffi
src/main/cpp/libffi/platform_include
) )
# Searches for a specified prebuilt library and stores the path as a # Searches for a specified prebuilt library and stores the path as a
...@@ -99,6 +117,6 @@ target_link_libraries( # Specifies the target library. ...@@ -99,6 +117,6 @@ target_link_libraries( # Specifies the target library.
${log-lib}) ${log-lib})
add_definitions(-std=c++11) set(CMAKE_CXX_STANDARD 14)
ENABLE_LANGUAGE(ASM) ENABLE_LANGUAGE(ASM)
\ No newline at end of file
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// //
#include <cstdlib> #include <cstdlib>
#include <unistd.h>
#include "hook_arm64.h" #include "hook_arm64.h"
#include "code_buffer.h" #include "code_buffer.h"
#include "lock.h" #include "lock.h"
...@@ -181,4 +182,8 @@ void InlineHookArm64Android::ExceptionHandler(int num, sigcontext *context) { ...@@ -181,4 +182,8 @@ void InlineHookArm64Android::ExceptionHandler(int num, sigcontext *context) {
return; return;
HookInfo &hook_info = hook_infos[hvc.imme]; HookInfo &hook_info = hook_infos[hvc.imme];
context->pc = reinterpret_cast<U64>(hook_info.replace); context->pc = reinterpret_cast<U64>(hook_info.replace);
if (callback != nullptr) {
callback();
callback = nullptr;
}
} }
...@@ -43,6 +43,7 @@ namespace SandHook { ...@@ -43,6 +43,7 @@ namespace SandHook {
std::mutex hook_lock; std::mutex hook_lock;
public: public:
static InlineHook* instance; static InlineHook* instance;
void (*callback)(void) = nullptr;
}; };
} }
......
//
// Created by 甘尧 on 2019-07-22.
//
#include "arguments.h"
//
// Created by 甘尧 on 2019-07-22.
//
#pragma once
//
// Created by 甘尧 on 2019-07-22.
//
#include "type_bridge.h"
using namespace SandHook::JavaBridge;
void Types::Load(JNIEnv *env) {
jclass clazz;
env->PushLocalFrame(16);
#define LOAD_CLASS(c, s) clazz = env->FindClass(s); (c) = reinterpret_cast<jclass>(env->NewWeakGlobalRef(clazz))
#define LOAD_LANG_CLASS(c, s) LOAD_CLASS(java_lang_##c, "java/lang/" #c); java_lang_##c##_init = env->GetMethodID(java_lang_##c, "<init>", s)
LOAD_LANG_CLASS(Integer, "(I)V");
LOAD_LANG_CLASS(Long, "(J)V");
LOAD_LANG_CLASS(Float, "(F)V");
LOAD_LANG_CLASS(Double, "(D)V");
LOAD_LANG_CLASS(Byte, "(B)V");
LOAD_LANG_CLASS(Short, "(S)V");
LOAD_LANG_CLASS(Boolean, "(Z)V");
LOAD_LANG_CLASS(Character, "(C)V");
#undef LOAD_CLASS
#undef LOAD_LANG_CLASS
#define LOAD_METHOD(k, c, r, s) java_value_##c = env->GetMethodID(k, r "Value", s)
#define LOAD_NUMBER(c, r, s) LOAD_METHOD(java_lang_Number, c, r, s)
jclass java_lang_Number = env->FindClass("java/lang/Number");
LOAD_NUMBER(Integer, "int", "()I");
LOAD_NUMBER(Long, "long", "()J");
LOAD_NUMBER(Float, "float", "()F");
LOAD_NUMBER(Double, "double", "()D");
LOAD_NUMBER(Byte, "byte", "()B");
LOAD_NUMBER(Short, "short", "()S");
LOAD_METHOD(java_lang_Boolean, Boolean, "boolean", "()Z");
LOAD_METHOD(java_lang_Character, Character, "char", "()C");
env->PopLocalFrame(nullptr);
#undef LOAD_METHOD
#undef LOAD_NUMBER
}
//
// Created by 甘尧 on 2019-07-22.
//
#pragma once
#include "jni.h"
namespace SandHook {
namespace JavaBridge {
struct Types {
#define LANG_ClASS(c) static jclass java_lang_##c; static jmethodID java_lang_##c##_init; static jmethodID java_value_##c;
LANG_ClASS(Integer);
LANG_ClASS(Long);
LANG_ClASS(Float);
LANG_ClASS(Double);
LANG_ClASS(Byte);
LANG_ClASS(Short);
LANG_ClASS(Boolean);
LANG_ClASS(Character);
#undef LANG_ClASS
static void Load(JNIEnv *env);
#define LANG_BOX_DEF(c, t) static jobject To##c(JNIEnv *env, t v);
#define LANG_UNBOX_V_DEF(k, c, t) static t From##c(JNIEnv *env, jobject j);
#define LANG_UNBOX_DEF(c, t) LANG_UNBOX_V_DEF(c, c, t)
LANG_BOX_DEF(Object, jobject);
LANG_BOX_DEF(Integer, jint);
LANG_BOX_DEF(Long, jlong);
LANG_BOX_DEF(Float, jfloat);
LANG_BOX_DEF(Double, jdouble);
LANG_BOX_DEF(Byte, jbyte);
LANG_BOX_DEF(Short, jshort);
LANG_BOX_DEF(Boolean, jboolean);
LANG_BOX_DEF(Character, jchar);
LANG_UNBOX_V_DEF(Int, Integer, jint);
LANG_UNBOX_DEF(Object, jobject);
LANG_UNBOX_DEF(Long, jlong);
LANG_UNBOX_DEF(Float, jfloat);
LANG_UNBOX_DEF(Double, jdouble);
LANG_UNBOX_DEF(Byte, jbyte);
LANG_UNBOX_DEF(Short, jshort);
LANG_UNBOX_DEF(Boolean, jboolean);
LANG_UNBOX_V_DEF(Char, Character, jchar);
#undef LANG_BOX_DEF
#undef LANG_UNBOX_V_DEF
#undef LANG_UNBOX_DEF
};
#define EXPORT_LANG_ClASS(c) jclass Types::java_lang_##c; jmethodID Types::java_lang_##c##_init; jmethodID Types::java_value_##c;
EXPORT_LANG_ClASS(Integer);
EXPORT_LANG_ClASS(Long);
EXPORT_LANG_ClASS(Float);
EXPORT_LANG_ClASS(Double);
EXPORT_LANG_ClASS(Byte);
EXPORT_LANG_ClASS(Short);
EXPORT_LANG_ClASS(Boolean);
EXPORT_LANG_ClASS(Character);
#undef EXPORT_LANG_ClASS
#define LANG_BOX(c, t) jobject Types::To##c(JNIEnv *env, t v) { \
return env->NewObject(Types::java_lang_##c, Types::java_lang_##c##_init, v); \
}
#define LANG_UNBOX_V(k, c, t) t Types::From##c(JNIEnv *env, jobject j) { \
return env->Call##k##Method(j, Types::java_value_##c); \
}
#define LANG_UNBOX(c, t) LANG_UNBOX_V(c, c, t)
LANG_BOX(Integer, jint);
LANG_BOX(Long, jlong);
LANG_BOX(Float, jfloat);
LANG_BOX(Double, jdouble);
LANG_BOX(Byte, jbyte);
LANG_BOX(Short, jshort);
LANG_BOX(Boolean, jboolean);
LANG_BOX(Character, jchar);
jobject Types::ToObject(JNIEnv *env, jobject obj) {
return obj;
}
LANG_UNBOX_V(Int, Integer, jint);
LANG_UNBOX(Long, jlong);
LANG_UNBOX(Float, jfloat);
LANG_UNBOX(Double, jdouble);
LANG_UNBOX(Byte, jbyte);
LANG_UNBOX(Short, jshort);
LANG_UNBOX(Boolean, jboolean);
LANG_UNBOX_V(Char, Character, jchar);
jobject Types::FromObject(JNIEnv *env, jobject obj) {
return obj;
}
#undef LANG_BOX
#undef LANG_UNBOX_V
#undef LANG_UNBOX
}
}
#if defined(__aarch64__) || defined(__arm64__)
/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_common.h>
#include "internal.h"
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
all further uses in this file will refer to the 128-bit type. */
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
# if FFI_TYPE_LONGDOUBLE != 4
# error FFI_TYPE_LONGDOUBLE out of date
# endif
#else
# undef FFI_TYPE_LONGDOUBLE
# define FFI_TYPE_LONGDOUBLE 4
#endif
union _d
{
UINT64 d;
UINT32 s[2];
};
struct _v
{
union _d d[2] __attribute__((aligned(16)));
};
struct call_context
{
struct _v v[N_V_ARG_REG];
UINT64 x[N_X_ARG_REG];
};
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
#include <mach/vm_param.h>
#endif
#else
#if defined (__clang__) && defined (__APPLE__)
extern void sys_icache_invalidate (void *start, size_t len);
#endif
static inline void
ffi_clear_cache (void *start, void *end)
{
#if defined (__clang__) && defined (__APPLE__)
sys_icache_invalidate (start, (char *)end - (char *)start);
#elif defined (__GNUC__)
__builtin___clear_cache (start, end);
#else
#error "Missing builtin to flush instruction cache"
#endif
}
#endif
/* A subroutine of is_vfp_type. Given a structure type, return the type code
of the first non-structure element. Recurse for structure elements.
Return -1 if the structure is in fact empty, i.e. no nested elements. */
static int
is_hfa0 (const ffi_type *ty)
{
ffi_type **elements = ty->elements;
int i, ret = -1;
if (elements != NULL)
for (i = 0; elements[i]; ++i)
{
ret = elements[i]->type;
if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
{
ret = is_hfa0 (elements[i]);
if (ret < 0)
continue;
}
break;
}
return ret;
}
/* A subroutine of is_vfp_type. Given a structure type, return true if all
of the non-structure elements are the same as CANDIDATE. */
static int
is_hfa1 (const ffi_type *ty, int candidate)
{
ffi_type **elements = ty->elements;
int i;
if (elements != NULL)
for (i = 0; elements[i]; ++i)
{
int t = elements[i]->type;
if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
{
if (!is_hfa1 (elements[i], candidate))
return 0;
}
else if (t != candidate)
return 0;
}
return 1;
}
/* Determine if TY may be allocated to the FP registers. This is both an
fp scalar type as well as an homogenous floating point aggregate (HFA).
That is, a structure consisting of 1 to 4 members of all the same type,
where that type is an fp scalar.
Returns non-zero iff TY is an HFA. The result is the AARCH64_RET_*
constant for the type. */
static int
is_vfp_type (const ffi_type *ty)
{
ffi_type **elements;
int candidate, i;
size_t size, ele_count;
/* Quickest tests first. */
candidate = ty->type;
switch (candidate)
{
default:
return 0;
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
ele_count = 1;
goto done;
case FFI_TYPE_COMPLEX:
candidate = ty->elements[0]->type;
switch (candidate)
{
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
ele_count = 2;
goto done;
}
return 0;
case FFI_TYPE_STRUCT:
break;
}
/* No HFA types are smaller than 4 bytes, or larger than 64 bytes. */
size = ty->size;
if (size < 4 || size > 64)
return 0;
/* Find the type of the first non-structure member. */
elements = ty->elements;
candidate = elements[0]->type;
if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
{
for (i = 0; ; ++i)
{
candidate = is_hfa0 (elements[i]);
if (candidate >= 0)
break;
}
}
/* If the first member is not a floating point type, it's not an HFA.
Also quickly re-check the size of the structure. */
switch (candidate)
{
case FFI_TYPE_FLOAT:
ele_count = size / sizeof(float);
if (size != ele_count * sizeof(float))
return 0;
break;
case FFI_TYPE_DOUBLE:
ele_count = size / sizeof(double);
if (size != ele_count * sizeof(double))
return 0;
break;
case FFI_TYPE_LONGDOUBLE:
ele_count = size / sizeof(long double);
if (size != ele_count * sizeof(long double))
return 0;
break;
default:
return 0;
}
if (ele_count > 4)
return 0;
/* Finally, make sure that all scalar elements are the same type. */
for (i = 0; elements[i]; ++i)
{
int t = elements[i]->type;
if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
{
if (!is_hfa1 (elements[i], candidate))
return 0;
}
else if (t != candidate)
return 0;
}
/* All tests succeeded. Encode the result. */
done:
return candidate * 4 + (4 - (int)ele_count);
}
/* Representation of the procedure call argument marshalling
state.
The terse state variable names match the names used in the AARCH64
PCS. */
struct arg_state
{
unsigned ngrn; /* Next general-purpose register number. */
unsigned nsrn; /* Next vector register number. */
size_t nsaa; /* Next stack offset. */
#if defined (__APPLE__)
unsigned allocating_variadic;
#endif
};
/* Initialize a procedure call argument marshalling state. */
static void
arg_init (struct arg_state *state)
{
state->ngrn = 0;
state->nsrn = 0;
state->nsaa = 0;
#if defined (__APPLE__)
state->allocating_variadic = 0;
#endif
}
/* Allocate an aligned slot on the stack and return a pointer to it. */
static void *
allocate_to_stack (struct arg_state *state, void *stack,
size_t alignment, size_t size)
{
size_t nsaa = state->nsaa;
/* Round up the NSAA to the larger of 8 or the natural
alignment of the argument's type. */
#if defined (__APPLE__)
if (state->allocating_variadic && alignment < 8)
alignment = 8;
#else
if (alignment < 8)
alignment = 8;
#endif
nsaa = FFI_ALIGN (nsaa, alignment);
state->nsaa = nsaa + size;
return (char *)stack + nsaa;
}
static ffi_arg
extend_integer_type (void *source, int type)
{
switch (type)
{
case FFI_TYPE_UINT8:
return *(UINT8 *) source;
case FFI_TYPE_SINT8:
return *(SINT8 *) source;
case FFI_TYPE_UINT16:
return *(UINT16 *) source;
case FFI_TYPE_SINT16:
return *(SINT16 *) source;
case FFI_TYPE_UINT32:
return *(UINT32 *) source;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
return *(SINT32 *) source;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
return *(UINT64 *) source;
break;
case FFI_TYPE_POINTER:
return *(uintptr_t *) source;
default:
abort();
}
}
static void
extend_hfa_type (void *dest, void *src, int h)
{
ssize_t f = h - AARCH64_RET_S4;
void *x0;
asm volatile (
"adr %0, 0f\n"
" add %0, %0, %1\n"
" br %0\n"
"0: ldp s16, s17, [%3]\n" /* S4 */
" ldp s18, s19, [%3, #8]\n"
" b 4f\n"
" ldp s16, s17, [%3]\n" /* S3 */
" ldr s18, [%3, #8]\n"
" b 3f\n"
" ldp s16, s17, [%3]\n" /* S2 */
" b 2f\n"
" nop\n"
" ldr s16, [%3]\n" /* S1 */
" b 1f\n"
" nop\n"
" ldp d16, d17, [%3]\n" /* D4 */
" ldp d18, d19, [%3, #16]\n"
" b 4f\n"
" ldp d16, d17, [%3]\n" /* D3 */
" ldr d18, [%3, #16]\n"
" b 3f\n"
" ldp d16, d17, [%3]\n" /* D2 */
" b 2f\n"
" nop\n"
" ldr d16, [%3]\n" /* D1 */
" b 1f\n"
" nop\n"
" ldp q16, q17, [%3]\n" /* Q4 */
" ldp q18, q19, [%3, #32]\n"
" b 4f\n"
" ldp q16, q17, [%3]\n" /* Q3 */
" ldr q18, [%3, #32]\n"
" b 3f\n"
" ldp q16, q17, [%3]\n" /* Q2 */
" b 2f\n"
" nop\n"
" ldr q16, [%3]\n" /* Q1 */
" b 1f\n"
"4: str q19, [%2, #48]\n"
"3: str q18, [%2, #32]\n"
"2: str q17, [%2, #16]\n"
"1: str q16, [%2]"
: "=&r"(x0)
: "r"(f * 12), "r"(dest), "r"(src)
: "memory", "v16", "v17", "v18", "v19");
}
static void *
compress_hfa_type (void *dest, void *reg, int h)
{
switch (h)
{
case AARCH64_RET_S1:
if (dest == reg)
{
#ifdef __AARCH64EB__
dest += 12;
#endif
}
else
*(float *)dest = *(float *)reg;
break;
case AARCH64_RET_S2:
asm ("ldp q16, q17, [%1]\n\t"
"st2 { v16.s, v17.s }[0], [%0]"
: : "r"(dest), "r"(reg) : "memory", "v16", "v17");
break;
case AARCH64_RET_S3:
asm ("ldp q16, q17, [%1]\n\t"
"ldr q18, [%1, #32]\n\t"
"st3 { v16.s, v17.s, v18.s }[0], [%0]"
: : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18");
break;
case AARCH64_RET_S4:
asm ("ldp q16, q17, [%1]\n\t"
"ldp q18, q19, [%1, #32]\n\t"
"st4 { v16.s, v17.s, v18.s, v19.s }[0], [%0]"
: : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19");
break;
case AARCH64_RET_D1:
if (dest == reg)
{
#ifdef __AARCH64EB__
dest += 8;
#endif
}
else
*(double *)dest = *(double *)reg;
break;
case AARCH64_RET_D2:
asm ("ldp q16, q17, [%1]\n\t"
"st2 { v16.d, v17.d }[0], [%0]"
: : "r"(dest), "r"(reg) : "memory", "v16", "v17");
break;
case AARCH64_RET_D3:
asm ("ldp q16, q17, [%1]\n\t"
"ldr q18, [%1, #32]\n\t"
"st3 { v16.d, v17.d, v18.d }[0], [%0]"
: : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18");
break;
case AARCH64_RET_D4:
asm ("ldp q16, q17, [%1]\n\t"
"ldp q18, q19, [%1, #32]\n\t"
"st4 { v16.d, v17.d, v18.d, v19.d }[0], [%0]"
: : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19");
break;
default:
if (dest != reg)
return memcpy (dest, reg, 16 * (4 - (h & 3)));
break;
}
return dest;
}
/* Either allocate an appropriate register for the argument type, or if
none are available, allocate a stack slot and return a pointer
to the allocated space. */
static void *
allocate_int_to_reg_or_stack (struct call_context *context,
struct arg_state *state,
void *stack, size_t size)
{
if (state->ngrn < N_X_ARG_REG)
return &context->x[state->ngrn++];
state->ngrn = N_X_ARG_REG;
return allocate_to_stack (state, stack, size, size);
}
ffi_status
ffi_prep_cif_machdep (ffi_cif *cif)
{
ffi_type *rtype = cif->rtype;
size_t bytes = cif->bytes;
int flags, i, n;
switch (rtype->type)
{
case FFI_TYPE_VOID:
flags = AARCH64_RET_VOID;
break;
case FFI_TYPE_UINT8:
flags = AARCH64_RET_UINT8;
break;
case FFI_TYPE_UINT16:
flags = AARCH64_RET_UINT16;
break;
case FFI_TYPE_UINT32:
flags = AARCH64_RET_UINT32;
break;
case FFI_TYPE_SINT8:
flags = AARCH64_RET_SINT8;
break;
case FFI_TYPE_SINT16:
flags = AARCH64_RET_SINT16;
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
flags = AARCH64_RET_SINT32;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
flags = AARCH64_RET_INT64;
break;
case FFI_TYPE_POINTER:
flags = (sizeof(void *) == 4 ? AARCH64_RET_UINT32 : AARCH64_RET_INT64);
break;
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
case FFI_TYPE_STRUCT:
case FFI_TYPE_COMPLEX:
flags = is_vfp_type (rtype);
if (flags == 0)
{
size_t s = rtype->size;
if (s > 16)
{
flags = AARCH64_RET_VOID | AARCH64_RET_IN_MEM;
bytes += 8;
}
else if (s == 16)
flags = AARCH64_RET_INT128;
else if (s == 8)
flags = AARCH64_RET_INT64;
else
flags = AARCH64_RET_INT128 | AARCH64_RET_NEED_COPY;
}
break;
default:
abort();
}
for (i = 0, n = cif->nargs; i < n; i++)
if (is_vfp_type (cif->arg_types[i]))
{
flags |= AARCH64_FLAG_ARG_V;
break;
}
/* Round the stack up to a multiple of the stack alignment requirement. */
cif->bytes = (unsigned) FFI_ALIGN(bytes, 16);
cif->flags = flags;
#if defined (__APPLE__)
cif->aarch64_nfixedargs = 0;
#endif
return FFI_OK;
}
#if defined (__APPLE__)
/* Perform Apple-specific cif processing for variadic calls */
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
unsigned int nfixedargs,
unsigned int ntotalargs)
{
ffi_status status = ffi_prep_cif_machdep (cif);
cif->aarch64_nfixedargs = nfixedargs;
return status;
}
#endif /* __APPLE__ */
extern void ffi_call_SYSV (struct call_context *context, void *frame,
void (*fn)(void), void *rvalue, int flags,
void *closure) FFI_HIDDEN;
/* Call a function with the provided arguments and capture the return
value. */
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
void **avalue, void *closure)
{
struct call_context *context;
void *stack, *frame, *rvalue;
struct arg_state state;
size_t stack_bytes, rtype_size, rsize;
int i, nargs, flags;
ffi_type *rtype;
flags = cif->flags;
rtype = cif->rtype;
rtype_size = rtype->size;
stack_bytes = cif->bytes;
/* If the target function returns a structure via hidden pointer,
then we cannot allow a null rvalue. Otherwise, mash a null
rvalue to void return type. */
rsize = 0;
if (flags & AARCH64_RET_IN_MEM)
{
if (orig_rvalue == NULL)
rsize = rtype_size;
}
else if (orig_rvalue == NULL)
flags &= AARCH64_FLAG_ARG_V;
else if (flags & AARCH64_RET_NEED_COPY)
rsize = 16;
/* Allocate consectutive stack for everything we'll need. */
context = alloca (sizeof(struct call_context) + stack_bytes + 32 + rsize);
stack = context + 1;
frame = stack + stack_bytes;
rvalue = (rsize ? frame + 32 : orig_rvalue);
arg_init (&state);
for (i = 0, nargs = cif->nargs; i < nargs; i++)
{
ffi_type *ty = cif->arg_types[i];
size_t s = ty->size;
void *a = avalue[i];
int h, t;
t = ty->type;
switch (t)
{
case FFI_TYPE_VOID:
FFI_ASSERT (0);
break;
/* If the argument is a basic type the argument is allocated to an
appropriate register, or if none are available, to the stack. */
case FFI_TYPE_INT:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER:
do_pointer:
{
ffi_arg ext = extend_integer_type (a, t);
if (state.ngrn < N_X_ARG_REG)
context->x[state.ngrn++] = ext;
else
{
void *d = allocate_to_stack (&state, stack, ty->alignment, s);
state.ngrn = N_X_ARG_REG;
/* Note that the default abi extends each argument
to a full 64-bit slot, while the iOS abi allocates
only enough space. */
#ifdef __APPLE__
memcpy(d, a, s);
#else
*(ffi_arg *)d = ext;
#endif
}
}
break;
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
case FFI_TYPE_STRUCT:
case FFI_TYPE_COMPLEX:
{
void *dest;
h = is_vfp_type (ty);
if (h)
{
int elems = 4 - (h & 3);
if (state.nsrn + elems <= N_V_ARG_REG)
{
dest = &context->v[state.nsrn];
state.nsrn += elems;
extend_hfa_type (dest, a, h);
break;
}
state.nsrn = N_V_ARG_REG;
dest = allocate_to_stack (&state, stack, ty->alignment, s);
}
else if (s > 16)
{
/* If the argument is a composite type that is larger than 16
bytes, then the argument has been copied to memory, and
the argument is replaced by a pointer to the copy. */
a = &avalue[i];
t = FFI_TYPE_POINTER;
s = sizeof (void *);
goto do_pointer;
}
else
{
size_t n = (s + 7) / 8;
if (state.ngrn + n <= N_X_ARG_REG)
{
/* If the argument is a composite type and the size in
double-words is not more than the number of available
X registers, then the argument is copied into
consecutive X registers. */
dest = &context->x[state.ngrn];
state.ngrn += n;
}
else
{
/* Otherwise, there are insufficient X registers. Further
X register allocations are prevented, the NSAA is
adjusted and the argument is copied to memory at the
adjusted NSAA. */
state.ngrn = N_X_ARG_REG;
dest = allocate_to_stack (&state, stack, ty->alignment, s);
}
}
memcpy (dest, a, s);
}
break;
default:
abort();
}
#if defined (__APPLE__)
if (i + 1 == cif->aarch64_nfixedargs)
{
state.ngrn = N_X_ARG_REG;
state.nsrn = N_V_ARG_REG;
state.allocating_variadic = 1;
}
#endif
}
ffi_call_SYSV (context, frame, fn, rvalue, flags, closure);
if (flags & AARCH64_RET_NEED_COPY)
memcpy (orig_rvalue, rvalue, rtype_size);
}
void
ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
{
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
#ifdef FFI_GO_CLOSURES
void
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
void **avalue, void *closure)
{
ffi_call_int (cif, fn, rvalue, avalue, closure);
}
#endif /* FFI_GO_CLOSURES */
/* Build a trampoline. */
extern void ffi_closure_SYSV (void) FFI_HIDDEN;
extern void ffi_closure_SYSV_V (void) FFI_HIDDEN;
ffi_status
ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
void (*start)(void);
if (cif->flags & AARCH64_FLAG_ARG_V)
start = ffi_closure_SYSV_V;
else
start = ffi_closure_SYSV;
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
config[0] = closure;
config[1] = start;
#endif
#else
static const unsigned char trampoline[16] = {
0x90, 0x00, 0x00, 0x58, /* ldr x16, tramp+16 */
0xf1, 0xff, 0xff, 0x10, /* adr x17, tramp+0 */
0x00, 0x02, 0x1f, 0xd6 /* br x16 */
};
char *tramp = closure->tramp;
memcpy (tramp, trampoline, sizeof(trampoline));
*(UINT64 *)(tramp + 16) = (uintptr_t)start;
ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE);
#endif
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
return FFI_OK;
}
#ifdef FFI_GO_CLOSURES
extern void ffi_go_closure_SYSV (void) FFI_HIDDEN;
extern void ffi_go_closure_SYSV_V (void) FFI_HIDDEN;
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*))
{
void (*start)(void);
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
if (cif->flags & AARCH64_FLAG_ARG_V)
start = ffi_go_closure_SYSV_V;
else
start = ffi_go_closure_SYSV;
closure->tramp = start;
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}
#endif /* FFI_GO_CLOSURES */
/* Primary handler to setup and invoke a function within a closure.
A closure when invoked enters via the assembler wrapper
ffi_closure_SYSV(). The wrapper allocates a call context on the
stack, saves the interesting registers (from the perspective of
the calling convention) into the context then passes control to
ffi_closure_SYSV_inner() passing the saved context and a pointer to
the stack at the point ffi_closure_SYSV() was invoked.
On the return path the assembler wrapper will reload call context
registers.
ffi_closure_SYSV_inner() marshalls the call context into ffi value
descriptors, invokes the wrapped function, then marshalls the return
value back into the call context. */
int FFI_HIDDEN
ffi_closure_SYSV_inner (ffi_cif *cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
struct call_context *context,
void *stack, void *rvalue, void *struct_rvalue)
{
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
int i, h, nargs, flags;
struct arg_state state;
arg_init (&state);
for (i = 0, nargs = cif->nargs; i < nargs; i++)
{
ffi_type *ty = cif->arg_types[i];
int t = ty->type;
size_t n, s = ty->size;
switch (t)
{
case FFI_TYPE_VOID:
FFI_ASSERT (0);
break;
case FFI_TYPE_INT:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER:
avalue[i] = allocate_int_to_reg_or_stack (context, &state, stack, s);
break;
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
case FFI_TYPE_STRUCT:
case FFI_TYPE_COMPLEX:
h = is_vfp_type (ty);
if (h)
{
n = 4 - (h & 3);
if (state.nsrn + n <= N_V_ARG_REG)
{
void *reg = &context->v[state.nsrn];
state.nsrn += n;
/* Eeek! We need a pointer to the structure, however the
homogeneous float elements are being passed in individual
registers, therefore for float and double the structure
is not represented as a contiguous sequence of bytes in
our saved register context. We don't need the original
contents of the register storage, so we reformat the
structure into the same memory. */
avalue[i] = compress_hfa_type (reg, reg, h);
}
else
{
state.nsrn = N_V_ARG_REG;
avalue[i] = allocate_to_stack (&state, stack,
ty->alignment, s);
}
}
else if (s > 16)
{
/* Replace Composite type of size greater than 16 with a
pointer. */
avalue[i] = *(void **)
allocate_int_to_reg_or_stack (context, &state, stack,
sizeof (void *));
}
else
{
n = (s + 7) / 8;
if (state.ngrn + n <= N_X_ARG_REG)
{
avalue[i] = &context->x[state.ngrn];
state.ngrn += n;
}
else
{
state.ngrn = N_X_ARG_REG;
avalue[i] = allocate_to_stack (&state, stack,
ty->alignment, s);
}
}
break;
default:
abort();
}
#if defined (__APPLE__)
if (i + 1 == cif->aarch64_nfixedargs)
{
state.ngrn = N_X_ARG_REG;
state.nsrn = N_V_ARG_REG;
state.allocating_variadic = 1;
}
#endif
}
flags = cif->flags;
if (flags & AARCH64_RET_IN_MEM)
rvalue = struct_rvalue;
fun (cif, rvalue, avalue, user_data);
return flags;
}
#endif
\ No newline at end of file
#if defined(__aarch64__) || defined(__arm64__)
/*
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define AARCH64_RET_VOID 0
#define AARCH64_RET_INT64 1
#define AARCH64_RET_INT128 2
#define AARCH64_RET_UNUSED3 3
#define AARCH64_RET_UNUSED4 4
#define AARCH64_RET_UNUSED5 5
#define AARCH64_RET_UNUSED6 6
#define AARCH64_RET_UNUSED7 7
/* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4,
so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT). */
#define AARCH64_RET_S4 8
#define AARCH64_RET_S3 9
#define AARCH64_RET_S2 10
#define AARCH64_RET_S1 11
#define AARCH64_RET_D4 12
#define AARCH64_RET_D3 13
#define AARCH64_RET_D2 14
#define AARCH64_RET_D1 15
#define AARCH64_RET_Q4 16
#define AARCH64_RET_Q3 17
#define AARCH64_RET_Q2 18
#define AARCH64_RET_Q1 19
/* Note that each of the sub-64-bit integers gets two entries. */
#define AARCH64_RET_UINT8 20
#define AARCH64_RET_UINT16 22
#define AARCH64_RET_UINT32 24
#define AARCH64_RET_SINT8 26
#define AARCH64_RET_SINT16 28
#define AARCH64_RET_SINT32 30
#define AARCH64_RET_MASK 31
#define AARCH64_RET_IN_MEM (1 << 5)
#define AARCH64_RET_NEED_COPY (1 << 6)
#define AARCH64_FLAG_ARG_V_BIT 7
#define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT)
#define N_X_ARG_REG 8
#define N_V_ARG_REG 8
#define CALL_CONTEXT_SIZE (N_V_ARG_REG * 16 + N_X_ARG_REG * 8)
#endif
\ No newline at end of file
#if defined(__aarch64__)
/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#include "internal.h"
#ifdef HAVE_MACHINE_ASM_H
#include <machine/asm.h>
#else
#ifdef __USER_LABEL_PREFIX__
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
/* Use the right prefix for global labels. */
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
#else
#define CNAME(x) x
#endif
#endif
#ifdef __AARCH64EB__
# define BE(X) X
#else
# define BE(X) 0
#endif
#ifdef __ILP32__
#define PTR_REG(n) w##n
#else
#define PTR_REG(n) x##n
#endif
#ifdef __ILP32__
#define PTR_SIZE 4
#else
#define PTR_SIZE 8
#endif
.text
.align 4
/* ffi_call_SYSV
extern void ffi_call_SYSV (void *stack, void *frame,
void (*fn)(void), void *rvalue,
int flags, void *closure);
Therefore on entry we have:
x0 stack
x1 frame
x2 fn
x3 rvalue
x4 flags
x5 closure
*/
cfi_startproc
CNAME(ffi_call_SYSV):
/* Use a stack frame allocated by our caller. */
cfi_def_cfa(x1, 32);
stp x29, x30, [x1]
mov x29, x1
mov sp, x0
cfi_def_cfa_register(x29)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
mov x9, x2 /* save fn */
mov x8, x3 /* install structure return */
#ifdef FFI_GO_CLOSURES
mov x18, x5 /* install static chain */
#endif
stp x3, x4, [x29, #16] /* save rvalue and flags */
/* Load the vector argument passing registers, if necessary. */
tbz w4, #AARCH64_FLAG_ARG_V_BIT, 1f
ldp q0, q1, [sp, #0]
ldp q2, q3, [sp, #32]
ldp q4, q5, [sp, #64]
ldp q6, q7, [sp, #96]
1:
/* Load the core argument passing registers, including
the structure return pointer. */
ldp x0, x1, [sp, #16*N_V_ARG_REG + 0]
ldp x2, x3, [sp, #16*N_V_ARG_REG + 16]
ldp x4, x5, [sp, #16*N_V_ARG_REG + 32]
ldp x6, x7, [sp, #16*N_V_ARG_REG + 48]
/* Deallocate the context, leaving the stacked arguments. */
add sp, sp, #CALL_CONTEXT_SIZE
blr x9 /* call fn */
ldp x3, x4, [x29, #16] /* reload rvalue and flags */
/* Partially deconstruct the stack frame. */
mov sp, x29
cfi_def_cfa_register (sp)
ldp x29, x30, [x29]
/* Save the return value as directed. */
adr x5, 0f
and w4, w4, #AARCH64_RET_MASK
add x5, x5, x4, lsl #3
br x5
/* Note that each table entry is 2 insns, and thus 8 bytes.
For integer data, note that we're storing into ffi_arg
and therefore we want to extend to 64 bits; these types
have two consecutive entries allocated for them. */
.align 4
0: ret /* VOID */
nop
1: str x0, [x3] /* INT64 */
ret
2: stp x0, x1, [x3] /* INT128 */
ret
3: brk #1000 /* UNUSED */
ret
4: brk #1000 /* UNUSED */
ret
5: brk #1000 /* UNUSED */
ret
6: brk #1000 /* UNUSED */
ret
7: brk #1000 /* UNUSED */
ret
8: st4 { v0.s, v1.s, v2.s, v3.s }[0], [x3] /* S4 */
ret
9: st3 { v0.s, v1.s, v2.s }[0], [x3] /* S3 */
ret
10: stp s0, s1, [x3] /* S2 */
ret
11: str s0, [x3] /* S1 */
ret
12: st4 { v0.d, v1.d, v2.d, v3.d }[0], [x3] /* D4 */
ret
13: st3 { v0.d, v1.d, v2.d }[0], [x3] /* D3 */
ret
14: stp d0, d1, [x3] /* D2 */
ret
15: str d0, [x3] /* D1 */
ret
16: str q3, [x3, #48] /* Q4 */
nop
17: str q2, [x3, #32] /* Q3 */
nop
18: stp q0, q1, [x3] /* Q2 */
ret
19: str q0, [x3] /* Q1 */
ret
20: uxtb w0, w0 /* UINT8 */
str x0, [x3]
21: ret /* reserved */
nop
22: uxth w0, w0 /* UINT16 */
str x0, [x3]
23: ret /* reserved */
nop
24: mov w0, w0 /* UINT32 */
str x0, [x3]
25: ret /* reserved */
nop
26: sxtb x0, w0 /* SINT8 */
str x0, [x3]
27: ret /* reserved */
nop
28: sxth x0, w0 /* SINT16 */
str x0, [x3]
29: ret /* reserved */
nop
30: sxtw x0, w0 /* SINT32 */
str x0, [x3]
31: ret /* reserved */
nop
cfi_endproc
.globl CNAME(ffi_call_SYSV)
#ifdef __ELF__
.type CNAME(ffi_call_SYSV), #function
.hidden CNAME(ffi_call_SYSV)
.size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV)
#endif
/* ffi_closure_SYSV
Closure invocation glue. This is the low level code invoked directly by
the closure trampoline to setup and call a closure.
On entry x17 points to a struct ffi_closure, x16 has been clobbered
all other registers are preserved.
We allocate a call context and save the argument passing registers,
then invoked the generic C ffi_closure_SYSV_inner() function to do all
the real work, on return we load the result passing registers back from
the call context.
*/
#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64)
.align 4
CNAME(ffi_closure_SYSV_V):
cfi_startproc
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
/* Save the argument passing vector registers. */
stp q0, q1, [sp, #16 + 0]
stp q2, q3, [sp, #16 + 32]
stp q4, q5, [sp, #16 + 64]
stp q6, q7, [sp, #16 + 96]
b 0f
cfi_endproc
.globl CNAME(ffi_closure_SYSV_V)
#ifdef __ELF__
.type CNAME(ffi_closure_SYSV_V), #function
.hidden CNAME(ffi_closure_SYSV_V)
.size CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V)
#endif
.align 4
cfi_startproc
CNAME(ffi_closure_SYSV):
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
0:
mov x29, sp
/* Save the argument passing core registers. */
stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
/* Load ffi_closure_inner arguments. */
ldp PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET] /* load cif, fn */
ldr PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2] /* load user_data */
.Ldo_closure:
add x3, sp, #16 /* load context */
add x4, sp, #ffi_closure_SYSV_FS /* load stack */
add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */
mov x6, x8 /* load struct_rval */
bl CNAME(ffi_closure_SYSV_inner)
/* Load the return value as directed. */
adr x1, 0f
and w0, w0, #AARCH64_RET_MASK
add x1, x1, x0, lsl #3
add x3, sp, #16+CALL_CONTEXT_SIZE
br x1
/* Note that each table entry is 2 insns, and thus 8 bytes. */
.align 4
0: b 99f /* VOID */
nop
1: ldr x0, [x3] /* INT64 */
b 99f
2: ldp x0, x1, [x3] /* INT128 */
b 99f
3: brk #1000 /* UNUSED */
nop
4: brk #1000 /* UNUSED */
nop
5: brk #1000 /* UNUSED */
nop
6: brk #1000 /* UNUSED */
nop
7: brk #1000 /* UNUSED */
nop
8: ldr s3, [x3, #12] /* S4 */
nop
9: ldr s2, [x3, #8] /* S3 */
nop
10: ldp s0, s1, [x3] /* S2 */
b 99f
11: ldr s0, [x3] /* S1 */
b 99f
12: ldr d3, [x3, #24] /* D4 */
nop
13: ldr d2, [x3, #16] /* D3 */
nop
14: ldp d0, d1, [x3] /* D2 */
b 99f
15: ldr d0, [x3] /* D1 */
b 99f
16: ldr q3, [x3, #48] /* Q4 */
nop
17: ldr q2, [x3, #32] /* Q3 */
nop
18: ldp q0, q1, [x3] /* Q2 */
b 99f
19: ldr q0, [x3] /* Q1 */
b 99f
20: ldrb w0, [x3, #BE(7)] /* UINT8 */
b 99f
21: brk #1000 /* reserved */
nop
22: ldrh w0, [x3, #BE(6)] /* UINT16 */
b 99f
23: brk #1000 /* reserved */
nop
24: ldr w0, [x3, #BE(4)] /* UINT32 */
b 99f
25: brk #1000 /* reserved */
nop
26: ldrsb x0, [x3, #BE(7)] /* SINT8 */
b 99f
27: brk #1000 /* reserved */
nop
28: ldrsh x0, [x3, #BE(6)] /* SINT16 */
b 99f
29: brk #1000 /* reserved */
nop
30: ldrsw x0, [x3, #BE(4)] /* SINT32 */
nop
31: /* reserved */
99: ldp x29, x30, [sp], #ffi_closure_SYSV_FS
cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
cfi_restore (x29)
cfi_restore (x30)
ret
cfi_endproc
.globl CNAME(ffi_closure_SYSV)
#ifdef __ELF__
.type CNAME(ffi_closure_SYSV), #function
.hidden CNAME(ffi_closure_SYSV)
.size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
#endif
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
#include <mach/machine/vm_param.h>
.align PAGE_MAX_SHIFT
CNAME(ffi_closure_trampoline_table_page):
.rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE
adr x16, -PAGE_MAX_SIZE
ldp x17, x16, [x16]
br x16
nop /* each entry in the trampoline config page is 2*sizeof(void*) so the trampoline itself cannot be smaller that 16 bytes */
.endr
.globl CNAME(ffi_closure_trampoline_table_page)
#ifdef __ELF__
.type CNAME(ffi_closure_trampoline_table_page), #function
.hidden CNAME(ffi_closure_trampoline_table_page)
.size CNAME(ffi_closure_trampoline_table_page), . - CNAME(ffi_closure_trampoline_table_page)
#endif
#endif
#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
#ifdef FFI_GO_CLOSURES
.align 4
CNAME(ffi_go_closure_SYSV_V):
cfi_startproc
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
/* Save the argument passing vector registers. */
stp q0, q1, [sp, #16 + 0]
stp q2, q3, [sp, #16 + 32]
stp q4, q5, [sp, #16 + 64]
stp q6, q7, [sp, #16 + 96]
b 0f
cfi_endproc
.globl CNAME(ffi_go_closure_SYSV_V)
#ifdef __ELF__
.type CNAME(ffi_go_closure_SYSV_V), #function
.hidden CNAME(ffi_go_closure_SYSV_V)
.size CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V)
#endif
.align 4
cfi_startproc
CNAME(ffi_go_closure_SYSV):
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
cfi_rel_offset (x30, 8)
0:
mov x29, sp
/* Save the argument passing core registers. */
stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
/* Load ffi_closure_inner arguments. */
ldp PTR_REG(0), PTR_REG(1), [x18, #PTR_SIZE]/* load cif, fn */
mov x2, x18 /* load user_data */
b .Ldo_closure
cfi_endproc
.globl CNAME(ffi_go_closure_SYSV)
#ifdef __ELF__
.type CNAME(ffi_go_closure_SYSV), #function
.hidden CNAME(ffi_go_closure_SYSV)
.size CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV)
#endif
#endif /* FFI_GO_CLOSURES */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",%progbits
#endif
#endif
#ifdef __arm__
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2011 Timothy Wall
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
Copyright (c) 2011 Anthony Green
Copyright (c) 2011 Free Software Foundation
Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
ARM Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_common.h>
#include <stdint.h>
#include <stdlib.h>
#include "internal.h"
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
#include <mach/machine/vm_param.h>
#endif
#else
extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
#endif
/* Forward declares. */
static int vfp_type_p (const ffi_type *);
static void layout_vfp_args (ffi_cif *);
static void *
ffi_align (ffi_type *ty, void *p)
{
/* Align if necessary */
size_t alignment;
#ifdef _WIN32_WCE
alignment = 4;
#else
alignment = ty->alignment;
if (alignment < 4)
alignment = 4;
#endif
return (void *) FFI_ALIGN (p, alignment);
}
static size_t
ffi_put_arg (ffi_type *ty, void *src, void *dst)
{
size_t z = ty->size;
switch (ty->type)
{
case FFI_TYPE_SINT8:
*(UINT32 *)dst = *(SINT8 *)src;
break;
case FFI_TYPE_UINT8:
*(UINT32 *)dst = *(UINT8 *)src;
break;
case FFI_TYPE_SINT16:
*(UINT32 *)dst = *(SINT16 *)src;
break;
case FFI_TYPE_UINT16:
*(UINT32 *)dst = *(UINT16 *)src;
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
case FFI_TYPE_FLOAT:
*(UINT32 *)dst = *(UINT32 *)src;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_DOUBLE:
*(UINT64 *)dst = *(UINT64 *)src;
break;
case FFI_TYPE_STRUCT:
case FFI_TYPE_COMPLEX:
memcpy (dst, src, z);
break;
default:
abort();
}
return FFI_ALIGN (z, 4);
}
/* ffi_prep_args is called once stack space has been allocated
for the function's arguments.
The vfp_space parameter is the load area for VFP regs, the return
value is cif->vfp_used (word bitset of VFP regs used for passing
arguments). These are only used for the VFP hard-float ABI.
*/
static void
ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
void **avalue, char *argp)
{
ffi_type **arg_types = cif->arg_types;
int i, n;
if (flags == ARM_TYPE_STRUCT)
{
*(void **) argp = rvalue;
argp += 4;
}
for (i = 0, n = cif->nargs; i < n; i++)
{
ffi_type *ty = arg_types[i];
argp = ffi_align (ty, argp);
argp += ffi_put_arg (ty, avalue[i], argp);
}
}
static void
ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
void **avalue, char *stack, char *vfp_space)
{
ffi_type **arg_types = cif->arg_types;
int i, n, vi = 0;
char *argp, *regp, *eo_regp;
char stack_used = 0;
char done_with_regs = 0;
/* The first 4 words on the stack are used for values
passed in core registers. */
regp = stack;
eo_regp = argp = regp + 16;
/* If the function returns an FFI_TYPE_STRUCT in memory,
that address is passed in r0 to the function. */
if (flags == ARM_TYPE_STRUCT)
{
*(void **) regp = rvalue;
regp += 4;
}
for (i = 0, n = cif->nargs; i < n; i++)
{
ffi_type *ty = arg_types[i];
void *a = avalue[i];
int is_vfp_type = vfp_type_p (ty);
/* Allocated in VFP registers. */
if (vi < cif->vfp_nargs && is_vfp_type)
{
char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4;
ffi_put_arg (ty, a, vfp_slot);
continue;
}
/* Try allocating in core registers. */
else if (!done_with_regs && !is_vfp_type)
{
char *tregp = ffi_align (ty, regp);
size_t size = ty->size;
size = (size < 4) ? 4 : size; // pad
/* Check if there is space left in the aligned register
area to place the argument. */
if (tregp + size <= eo_regp)
{
regp = tregp + ffi_put_arg (ty, a, tregp);
done_with_regs = (regp == argp);
// ensure we did not write into the stack area
FFI_ASSERT (regp <= argp);
continue;
}
/* In case there are no arguments in the stack area yet,
the argument is passed in the remaining core registers
and on the stack. */
else if (!stack_used)
{
stack_used = 1;
done_with_regs = 1;
argp = tregp + ffi_put_arg (ty, a, tregp);
FFI_ASSERT (eo_regp < argp);
continue;
}
}
/* Base case, arguments are passed on the stack */
stack_used = 1;
argp = ffi_align (ty, argp);
argp += ffi_put_arg (ty, a, argp);
}
}
/* Perform machine dependent cif processing */
ffi_status
ffi_prep_cif_machdep (ffi_cif *cif)
{
int flags = 0, cabi = cif->abi;
size_t bytes = cif->bytes;
/* Map out the register placements of VFP register args. The VFP
hard-float calling conventions are slightly more sophisticated
than the base calling conventions, so we do it here instead of
in ffi_prep_args(). */
if (cabi == FFI_VFP)
layout_vfp_args (cif);
/* Set the return type flag */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
flags = ARM_TYPE_VOID;
break;
case FFI_TYPE_INT:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
flags = ARM_TYPE_INT;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
flags = ARM_TYPE_INT64;
break;
case FFI_TYPE_FLOAT:
flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT);
break;
case FFI_TYPE_DOUBLE:
flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64);
break;
case FFI_TYPE_STRUCT:
case FFI_TYPE_COMPLEX:
if (cabi == FFI_VFP)
{
int h = vfp_type_p (cif->rtype);
flags = ARM_TYPE_VFP_N;
if (h == 0x100 + FFI_TYPE_FLOAT)
flags = ARM_TYPE_VFP_S;
if (h == 0x100 + FFI_TYPE_DOUBLE)
flags = ARM_TYPE_VFP_D;
if (h != 0)
break;
}
/* A Composite Type not larger than 4 bytes is returned in r0.
A Composite Type larger than 4 bytes, or whose size cannot
be determined statically ... is stored in memory at an
address passed [in r0]. */
if (cif->rtype->size <= 4)
flags = ARM_TYPE_INT;
else
{
flags = ARM_TYPE_STRUCT;
bytes += 4;
}
break;
default:
abort();
}
/* Round the stack up to a multiple of 8 bytes. This isn't needed
everywhere, but it is on some platforms, and it doesn't harm anything
when it isn't needed. */
bytes = FFI_ALIGN (bytes, 8);
/* Minimum stack space is the 4 register arguments that we pop. */
if (bytes < 4*4)
bytes = 4*4;
cif->bytes = bytes;
cif->flags = flags;
return FFI_OK;
}
/* Perform machine dependent cif processing for variadic calls */
ffi_status
ffi_prep_cif_machdep_var (ffi_cif * cif,
unsigned int nfixedargs, unsigned int ntotalargs)
{
/* VFP variadic calls actually use the SYSV ABI */
if (cif->abi == FFI_VFP)
cif->abi = FFI_SYSV;
return ffi_prep_cif_machdep (cif);
}
/* Prototypes for assembly functions, in sysv.S. */
struct call_frame
{
void *fp;
void *lr;
void *rvalue;
int flags;
void *closure;
};
extern void ffi_call_SYSV (void *stack, struct call_frame *,
void (*fn) (void)) FFI_HIDDEN;
extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
static void
ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
void **avalue, void *closure)
{
int flags = cif->flags;
ffi_type *rtype = cif->rtype;
size_t bytes, rsize, vfp_size;
char *stack, *vfp_space, *new_rvalue;
struct call_frame *frame;
rsize = 0;
if (rvalue == NULL)
{
/* If the return value is a struct and we don't have a return
value address then we need to make one. Otherwise the return
value is in registers and we can ignore them. */
if (flags == ARM_TYPE_STRUCT)
rsize = rtype->size;
else
flags = ARM_TYPE_VOID;
}
else if (flags == ARM_TYPE_VFP_N)
{
/* Largest case is double x 4. */
rsize = 32;
}
else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
rsize = 4;
/* Largest case. */
vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);
bytes = cif->bytes;
stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
vfp_space = NULL;
if (vfp_size)
{
vfp_space = stack;
stack += vfp_size;
}
frame = (struct call_frame *)(stack + bytes);
new_rvalue = rvalue;
if (rsize)
new_rvalue = (void *)(frame + 1);
frame->rvalue = new_rvalue;
frame->flags = flags;
frame->closure = closure;
if (vfp_space)
{
ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
}
else
{
ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
ffi_call_SYSV (stack, frame, fn);
}
if (rvalue && rvalue != new_rvalue)
memcpy (rvalue, new_rvalue, rtype->size);
}
void
ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
{
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
void
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
void **avalue, void *closure)
{
ffi_call_int (cif, fn, rvalue, avalue, closure);
}
static void *
ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
char *argp, void **avalue)
{
ffi_type **arg_types = cif->arg_types;
int i, n;
if (cif->flags == ARM_TYPE_STRUCT)
{
rvalue = *(void **) argp;
argp += 4;
}
else
{
if (cif->rtype->size && cif->rtype->size < 4)
*(uint32_t *) rvalue = 0;
}
for (i = 0, n = cif->nargs; i < n; i++)
{
ffi_type *ty = arg_types[i];
size_t z = ty->size;
argp = ffi_align (ty, argp);
avalue[i] = (void *) argp;
argp += z;
}
return rvalue;
}
static void *
ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
char *vfp_space, void **avalue)
{
ffi_type **arg_types = cif->arg_types;
int i, n, vi = 0;
char *argp, *regp, *eo_regp;
char done_with_regs = 0;
char stack_used = 0;
regp = stack;
eo_regp = argp = regp + 16;
if (cif->flags == ARM_TYPE_STRUCT)
{
rvalue = *(void **) regp;
regp += 4;
}
for (i = 0, n = cif->nargs; i < n; i++)
{
ffi_type *ty = arg_types[i];
int is_vfp_type = vfp_type_p (ty);
size_t z = ty->size;
if (vi < cif->vfp_nargs && is_vfp_type)
{
avalue[i] = vfp_space + cif->vfp_args[vi++] * 4;
continue;
}
else if (!done_with_regs && !is_vfp_type)
{
char *tregp = ffi_align (ty, regp);
z = (z < 4) ? 4 : z; // pad
/* If the arguments either fits into the registers or uses registers
and stack, while we haven't read other things from the stack */
if (tregp + z <= eo_regp || !stack_used)
{
/* Because we're little endian, this is what it turns into. */
avalue[i] = (void *) tregp;
regp = tregp + z;
/* If we read past the last core register, make sure we
have not read from the stack before and continue
reading after regp. */
if (regp > eo_regp)
{
FFI_ASSERT (!stack_used);
argp = regp;
}
if (regp >= eo_regp)
{
done_with_regs = 1;
stack_used = 1;
}
continue;
}
}
stack_used = 1;
argp = ffi_align (ty, argp);
avalue[i] = (void *) argp;
argp += z;
}
return rvalue;
}
struct closure_frame
{
char vfp_space[8*8] __attribute__((aligned(8)));
char result[8*4];
char argp[];
};
int FFI_HIDDEN
ffi_closure_inner_SYSV (ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data,
struct closure_frame *frame)
{
void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
frame->argp, avalue);
fun (cif, rvalue, avalue, user_data);
return cif->flags;
}
int FFI_HIDDEN
ffi_closure_inner_VFP (ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data,
struct closure_frame *frame)
{
void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
frame->vfp_space, avalue);
fun (cif, rvalue, avalue, user_data);
return cif->flags;
}
void ffi_closure_SYSV (void) FFI_HIDDEN;
void ffi_closure_VFP (void) FFI_HIDDEN;
void ffi_go_closure_SYSV (void) FFI_HIDDEN;
void ffi_go_closure_VFP (void) FFI_HIDDEN;
/* the cif must already be prep'ed */
ffi_status
ffi_prep_closure_loc (ffi_closure * closure,
ffi_cif * cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data, void *codeloc)
{
void (*closure_func) (void) = ffi_closure_SYSV;
if (cif->abi == FFI_VFP)
{
/* We only need take the vfp path if there are vfp arguments. */
if (cif->vfp_used)
closure_func = ffi_closure_VFP;
}
else if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
#if FFI_EXEC_TRAMPOLINE_TABLE
void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
config[0] = closure;
config[1] = closure_func;
#else
memcpy (closure->tramp, ffi_arm_trampoline, 8);
#if defined (__QNX__)
msync(closure->tramp, 8, 0x1000000); /* clear data map */
msync(codeloc, 8, 0x1000000); /* clear insn map */
#else
__clear_cache(closure->tramp, closure->tramp + 8); /* clear data map */
__clear_cache(codeloc, codeloc + 8); /* clear insn map */
#endif
*(void (**)(void))(closure->tramp + 8) = closure_func;
#endif
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
return FFI_OK;
}
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *))
{
void (*closure_func) (void) = ffi_go_closure_SYSV;
if (cif->abi == FFI_VFP)
{
/* We only need take the vfp path if there are vfp arguments. */
if (cif->vfp_used)
closure_func = ffi_go_closure_VFP;
}
else if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
closure->tramp = closure_func;
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}
/* Below are routines for VFP hard-float support. */
/* A subroutine of vfp_type_p. Given a structure type, return the type code
of the first non-structure element. Recurse for structure elements.
Return -1 if the structure is in fact empty, i.e. no nested elements. */
static int
is_hfa0 (const ffi_type *ty)
{
ffi_type **elements = ty->elements;
int i, ret = -1;
if (elements != NULL)
for (i = 0; elements[i]; ++i)
{
ret = elements[i]->type;
if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
{
ret = is_hfa0 (elements[i]);
if (ret < 0)
continue;
}
break;
}
return ret;
}
/* A subroutine of vfp_type_p. Given a structure type, return true if all
of the non-structure elements are the same as CANDIDATE. */
static int
is_hfa1 (const ffi_type *ty, int candidate)
{
ffi_type **elements = ty->elements;
int i;
if (elements != NULL)
for (i = 0; elements[i]; ++i)
{
int t = elements[i]->type;
if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
{
if (!is_hfa1 (elements[i], candidate))
return 0;
}
else if (t != candidate)
return 0;
}
return 1;
}
/* Determine if TY is an homogenous floating point aggregate (HFA).
That is, a structure consisting of 1 to 4 members of all the same type,
where that type is a floating point scalar.
Returns non-zero iff TY is an HFA. The result is an encoded value where
bits 0-7 contain the type code, and bits 8-10 contain the element count. */
static int
vfp_type_p (const ffi_type *ty)
{
ffi_type **elements;
int candidate, i;
size_t size, ele_count;
/* Quickest tests first. */
candidate = ty->type;
switch (ty->type)
{
default:
return 0;
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
ele_count = 1;
goto done;
case FFI_TYPE_COMPLEX:
candidate = ty->elements[0]->type;
if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE)
return 0;
ele_count = 2;
goto done;
case FFI_TYPE_STRUCT:
break;
}
/* No HFA types are smaller than 4 bytes, or larger than 32 bytes. */
size = ty->size;
if (size < 4 || size > 32)
return 0;
/* Find the type of the first non-structure member. */
elements = ty->elements;
candidate = elements[0]->type;
if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
{
for (i = 0; ; ++i)
{
candidate = is_hfa0 (elements[i]);
if (candidate >= 0)
break;
}
}
/* If the first member is not a floating point type, it's not an HFA.
Also quickly re-check the size of the structure. */
switch (candidate)
{
case FFI_TYPE_FLOAT:
ele_count = size / sizeof(float);
if (size != ele_count * sizeof(float))
return 0;
break;
case FFI_TYPE_DOUBLE:
ele_count = size / sizeof(double);
if (size != ele_count * sizeof(double))
return 0;
break;
default:
return 0;
}
if (ele_count > 4)
return 0;
/* Finally, make sure that all scalar elements are the same type. */
for (i = 0; elements[i]; ++i)
{
int t = elements[i]->type;
if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
{
if (!is_hfa1 (elements[i], candidate))
return 0;
}
else if (t != candidate)
return 0;
}
/* All tests succeeded. Encode the result. */
done:
return (ele_count << 8) | candidate;
}
static int
place_vfp_arg (ffi_cif *cif, int h)
{
unsigned short reg = cif->vfp_reg_free;
int align = 1, nregs = h >> 8;
if ((h & 0xff) == FFI_TYPE_DOUBLE)
align = 2, nregs *= 2;
/* Align register number. */
if ((reg & 1) && align == 2)
reg++;
while (reg + nregs <= 16)
{
int s, new_used = 0;
for (s = reg; s < reg + nregs; s++)
{
new_used |= (1 << s);
if (cif->vfp_used & (1 << s))
{
reg += align;
goto next_reg;
}
}
/* Found regs to allocate. */
cif->vfp_used |= new_used;
cif->vfp_args[cif->vfp_nargs++] = reg;
/* Update vfp_reg_free. */
if (cif->vfp_used & (1 << cif->vfp_reg_free))
{
reg += nregs;
while (cif->vfp_used & (1 << reg))
reg += 1;
cif->vfp_reg_free = reg;
}
return 0;
next_reg:;
}
// done, mark all regs as used
cif->vfp_reg_free = 16;
cif->vfp_used = 0xFFFF;
return 1;
}
static void
layout_vfp_args (ffi_cif * cif)
{
int i;
/* Init VFP fields */
cif->vfp_used = 0;
cif->vfp_nargs = 0;
cif->vfp_reg_free = 0;
memset (cif->vfp_args, -1, 16); /* Init to -1. */
for (i = 0; i < cif->nargs; i++)
{
int h = vfp_type_p (cif->arg_types[i]);
if (h && place_vfp_arg (cif, h) == 1)
break;
}
}
#endif
\ No newline at end of file
#ifdef __arm__
#define ARM_TYPE_VFP_S 0
#define ARM_TYPE_VFP_D 1
#define ARM_TYPE_VFP_N 2
#define ARM_TYPE_INT64 3
#define ARM_TYPE_INT 4
#define ARM_TYPE_VOID 5
#define ARM_TYPE_STRUCT 6
#endif
\ No newline at end of file
#ifdef __arm__
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
ARM Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#include "internal.h"
/* GCC 4.8 provides __ARM_ARCH; construct it otherwise. */
#ifndef __ARM_ARCH
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|| defined(__ARM_ARCH_7EM__)
# define __ARM_ARCH 7
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
|| defined(__ARM_ARCH_6M__)
# define __ARM_ARCH 6
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|| defined(__ARM_ARCH_5TEJ__)
# define __ARM_ARCH 5
# else
# define __ARM_ARCH 4
# endif
#endif
/* Conditionally compile unwinder directives. */
#ifdef __ARM_EABI__
# define UNWIND(...) __VA_ARGS__
#else
# define UNWIND(...)
#endif
#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
.cfi_sections .debug_frame
#endif
#define CONCAT(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
#ifdef __USER_LABEL_PREFIX__
# define CNAME(X) CONCAT (__USER_LABEL_PREFIX__, X)
#else
# define CNAME(X) X
#endif
#ifdef __ELF__
# define SIZE(X) .size CNAME(X), . - CNAME(X)
# define TYPE(X, Y) .type CNAME(X), Y
#else
# define SIZE(X)
# define TYPE(X, Y)
#endif
#define ARM_FUNC_START_LOCAL(name) \
.align 3; \
TYPE(CNAME(name), %function); \
CNAME(name):
#define ARM_FUNC_START(name) \
.globl CNAME(name); \
FFI_HIDDEN(CNAME(name)); \
ARM_FUNC_START_LOCAL(name)
#define ARM_FUNC_END(name) \
SIZE(name)
/* Aid in defining a jump table with 8 bytes between entries. */
/* ??? The clang assembler doesn't handle .if with symbolic expressions. */
#ifdef __clang__
# define E(index)
#else
# define E(index) \
.if . - 0b - 8*index; \
.error "type table out of sync"; \
.endif
#endif
.text
.syntax unified
.arm
#ifndef __clang__
/* We require interworking on LDM, which implies ARMv5T,
which implies the existance of BLX. */
.arch armv5t
#endif
/* Note that we use STC and LDC to encode VFP instructions,
so that we do not need ".fpu vfp", nor get that added to
the object file attributes. These will not be executed
unless the FFI_VFP abi is used. */
@ r0: stack
@ r1: frame
@ r2: fn
@ r3: vfp_used
ARM_FUNC_START(ffi_call_VFP)
UNWIND(.fnstart)
cfi_startproc
cmp r3, #3 @ load only d0 if possible
#ifdef __clang__
vldrle d0, [sp]
vldmgt sp, {d0-d7}
#else
ldcle p11, cr0, [r0] @ vldrle d0, [sp]
ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7}
#endif
add r0, r0, #64 @ discard the vfp register args
/* FALLTHRU */
ARM_FUNC_END(ffi_call_VFP)
ARM_FUNC_START(ffi_call_SYSV)
stm r1, {fp, lr}
mov fp, r1
@ This is a bit of a lie wrt the origin of the unwind info, but
@ now we've got the usual frame pointer and two saved registers.
UNWIND(.save {fp,lr})
UNWIND(.setfp fp, sp)
cfi_def_cfa(fp, 8)
cfi_rel_offset(fp, 0)
cfi_rel_offset(lr, 4)
mov sp, r0 @ install the stack pointer
mov lr, r2 @ move the fn pointer out of the way
ldr ip, [fp, #16] @ install the static chain
ldmia sp!, {r0-r3} @ move first 4 parameters in registers.
blx lr @ call fn
@ Load r2 with the pointer to storage for the return value
@ Load r3 with the return type code
ldr r2, [fp, #8]
ldr r3, [fp, #12]
@ Deallocate the stack with the arguments.
mov sp, fp
cfi_def_cfa_register(sp)
@ Store values stored in registers.
.align 3
add pc, pc, r3, lsl #3
nop
0:
E(ARM_TYPE_VFP_S)
#ifdef __clang__
vstr s0, [r2]
#else
stc p10, cr0, [r2] @ vstr s0, [r2]
#endif
pop {fp,pc}
E(ARM_TYPE_VFP_D)
#ifdef __clang__
vstr d0, [r2]
#else
stc p11, cr0, [r2] @ vstr d0, [r2]
#endif
pop {fp,pc}
E(ARM_TYPE_VFP_N)
#ifdef __clang__
vstm r2, {d0-d3}
#else
stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3}
#endif
pop {fp,pc}
E(ARM_TYPE_INT64)
str r1, [r2, #4]
nop
E(ARM_TYPE_INT)
str r0, [r2]
pop {fp,pc}
E(ARM_TYPE_VOID)
pop {fp,pc}
nop
E(ARM_TYPE_STRUCT)
pop {fp,pc}
cfi_endproc
UNWIND(.fnend)
ARM_FUNC_END(ffi_call_SYSV)
/*
int ffi_closure_inner_* (cif, fun, user_data, frame)
*/
ARM_FUNC_START(ffi_go_closure_SYSV)
cfi_startproc
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
ldr r0, [ip, #4] @ load cif
ldr r1, [ip, #8] @ load fun
mov r2, ip @ load user_data
b 0f
cfi_endproc
ARM_FUNC_END(ffi_go_closure_SYSV)
ARM_FUNC_START(ffi_closure_SYSV)
UNWIND(.fnstart)
cfi_startproc
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
#if FFI_EXEC_TRAMPOLINE_TABLE
ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure*
#endif
ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif
ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun
ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data
0:
add ip, sp, #16 @ compute entry sp
sub sp, sp, #64+32 @ allocate frame
cfi_adjust_cfa_offset(64+32)
stmdb sp!, {ip,lr}
/* Remember that EABI unwind info only applies at call sites.
We need do nothing except note the save of the stack pointer
and the link registers. */
UNWIND(.save {sp,lr})
cfi_adjust_cfa_offset(8)
cfi_rel_offset(lr, 4)
add r3, sp, #8 @ load frame
bl CNAME(ffi_closure_inner_SYSV)
@ Load values returned in registers.
add r2, sp, #8+64 @ load result
adr r3, CNAME(ffi_closure_ret)
add pc, r3, r0, lsl #3
cfi_endproc
UNWIND(.fnend)
ARM_FUNC_END(ffi_closure_SYSV)
ARM_FUNC_START(ffi_go_closure_VFP)
cfi_startproc
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
ldr r0, [ip, #4] @ load cif
ldr r1, [ip, #8] @ load fun
mov r2, ip @ load user_data
b 0f
cfi_endproc
ARM_FUNC_END(ffi_go_closure_VFP)
ARM_FUNC_START(ffi_closure_VFP)
UNWIND(.fnstart)
cfi_startproc
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
#if FFI_EXEC_TRAMPOLINE_TABLE
ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure*
#endif
ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif
ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun
ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data
0:
add ip, sp, #16
sub sp, sp, #64+32 @ allocate frame
cfi_adjust_cfa_offset(64+32)
#ifdef __clang__
vstm sp, {d0-d7}
#else
stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7}
#endif
stmdb sp!, {ip,lr}
/* See above. */
UNWIND(.save {sp,lr})
cfi_adjust_cfa_offset(8)
cfi_rel_offset(lr, 4)
add r3, sp, #8 @ load frame
bl CNAME(ffi_closure_inner_VFP)
@ Load values returned in registers.
add r2, sp, #8+64 @ load result
adr r3, CNAME(ffi_closure_ret)
add pc, r3, r0, lsl #3
cfi_endproc
UNWIND(.fnend)
ARM_FUNC_END(ffi_closure_VFP)
/* Load values returned in registers for both closure entry points.
Note that we use LDM with SP in the register set. This is deprecated
by ARM, but not yet unpredictable. */
ARM_FUNC_START_LOCAL(ffi_closure_ret)
cfi_startproc
cfi_rel_offset(sp, 0)
cfi_rel_offset(lr, 4)
0:
E(ARM_TYPE_VFP_S)
#ifdef __clang__
vldr s0, [r2]
#else
ldc p10, cr0, [r2] @ vldr s0, [r2]
#endif
ldm sp, {sp,pc}
E(ARM_TYPE_VFP_D)
#ifdef __clang__
vldr d0, [r2]
#else
ldc p11, cr0, [r2] @ vldr d0, [r2]
#endif
ldm sp, {sp,pc}
E(ARM_TYPE_VFP_N)
#ifdef __clang__
vldm r2, {d0-d3}
#else
ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3}
#endif
ldm sp, {sp,pc}
E(ARM_TYPE_INT64)
ldr r1, [r2, #4]
nop
E(ARM_TYPE_INT)
ldr r0, [r2]
ldm sp, {sp,pc}
E(ARM_TYPE_VOID)
ldm sp, {sp,pc}
nop
E(ARM_TYPE_STRUCT)
ldm sp, {sp,pc}
cfi_endproc
ARM_FUNC_END(ffi_closure_ret)
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
#include <mach/machine/vm_param.h>
.align PAGE_MAX_SHIFT
ARM_FUNC_START(ffi_closure_trampoline_table_page)
.rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE
adr ip, #-PAGE_MAX_SIZE @ the config page is PAGE_MAX_SIZE behind the trampoline page
sub ip, #8 @ account for pc bias
ldr pc, [ip, #4] @ jump to ffi_closure_SYSV or ffi_closure_VFP
.endr
ARM_FUNC_END(ffi_closure_trampoline_table_page)
#endif
#else
ARM_FUNC_START(ffi_arm_trampoline)
0: adr ip, 0b
ldr pc, 1f
1: .long 0
ARM_FUNC_END(ffi_arm_trampoline)
#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",%progbits
#endif
#endif
\ No newline at end of file
/* -----------------------------------------------------------------------
closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc.
Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
Code to allocate and deallocate memory for closures.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#if defined __linux__ && !defined _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_common.h>
#ifdef __NetBSD__
#include <sys/param.h>
#endif
#if __NetBSD_Version__ - 0 >= 799007200
/* NetBSD with PROT_MPROTECT */
#include <sys/mman.h>
#include <stddef.h>
#include <unistd.h>
static const size_t overhead =
(sizeof(max_align_t) > sizeof(void *) + sizeof(size_t)) ?
sizeof(max_align_t)
: sizeof(void *) + sizeof(size_t);
#define ADD_TO_POINTER(p, d) ((void *)((uintptr_t)(p) + (d)))
void *
ffi_closure_alloc (size_t size, void **code)
{
static size_t page_size;
size_t rounded_size;
void *codeseg, *dataseg;
int prot;
/* Expect that PAX mprotect is active and a separate code mapping is necessary. */
if (!code)
return NULL;
/* Obtain system page size. */
if (!page_size)
page_size = sysconf(_SC_PAGESIZE);
/* Round allocation size up to the next page, keeping in mind the size field and pointer to code map. */
rounded_size = (size + overhead + page_size - 1) & ~(page_size - 1);
/* Primary mapping is RW, but request permission to switch to PROT_EXEC later. */
prot = PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC);
dataseg = mmap(NULL, rounded_size, prot, MAP_ANON | MAP_PRIVATE, -1, 0);
if (dataseg == MAP_FAILED)
return NULL;
/* Create secondary mapping and switch it to RX. */
codeseg = mremap(dataseg, rounded_size, NULL, rounded_size, MAP_REMAPDUP);
if (codeseg == MAP_FAILED) {
munmap(dataseg, rounded_size);
return NULL;
}
if (mprotect(codeseg, rounded_size, PROT_READ | PROT_EXEC) == -1) {
munmap(codeseg, rounded_size);
munmap(dataseg, rounded_size);
return NULL;
}
/* Remember allocation size and location of the secondary mapping for ffi_closure_free. */
memcpy(dataseg, &rounded_size, sizeof(rounded_size));
memcpy(ADD_TO_POINTER(dataseg, sizeof(size_t)), &codeseg, sizeof(void *));
*code = ADD_TO_POINTER(codeseg, overhead);
return ADD_TO_POINTER(dataseg, overhead);
}
void
ffi_closure_free (void *ptr)
{
void *codeseg, *dataseg;
size_t rounded_size;
dataseg = ADD_TO_POINTER(ptr, -overhead);
memcpy(&rounded_size, dataseg, sizeof(rounded_size));
memcpy(&codeseg, ADD_TO_POINTER(dataseg, sizeof(size_t)), sizeof(void *));
munmap(dataseg, rounded_size);
munmap(codeseg, rounded_size);
}
#else /* !NetBSD with PROT_MPROTECT */
#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
# if __linux__ && !defined(__ANDROID__)
/* This macro indicates it may be forbidden to map anonymous memory
with both write and execute permission. Code compiled when this
option is defined will attempt to map such pages once, but if it
fails, it falls back to creating a temporary file in a writable and
executable filesystem and mapping pages from it into separate
locations in the virtual memory space, one location writable and
another executable. */
# define FFI_MMAP_EXEC_WRIT 1
# define HAVE_MNTENT 1
# endif
# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
/* Windows systems may have Data Execution Protection (DEP) enabled,
which requires the use of VirtualMalloc/VirtualFree to alloc/free
executable memory. */
# define FFI_MMAP_EXEC_WRIT 1
# endif
#endif
#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
# if defined(__linux__) && !defined(__ANDROID__)
/* When defined to 1 check for SELinux and if SELinux is active,
don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
might cause audit messages. */
# define FFI_MMAP_EXEC_SELINUX 1
# endif
#endif
#if FFI_CLOSURES
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
#include <mach/mach.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
extern void *ffi_closure_trampoline_table_page;
typedef struct ffi_trampoline_table ffi_trampoline_table;
typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
struct ffi_trampoline_table
{
/* contiguous writable and executable pages */
vm_address_t config_page;
vm_address_t trampoline_page;
/* free list tracking */
uint16_t free_count;
ffi_trampoline_table_entry *free_list;
ffi_trampoline_table_entry *free_list_pool;
ffi_trampoline_table *prev;
ffi_trampoline_table *next;
};
struct ffi_trampoline_table_entry
{
void *(*trampoline) ();
ffi_trampoline_table_entry *next;
};
/* Total number of trampolines that fit in one trampoline table */
#define FFI_TRAMPOLINE_COUNT (PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE)
static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
static ffi_trampoline_table *ffi_trampoline_tables = NULL;
static ffi_trampoline_table *
ffi_trampoline_table_alloc (void)
{
ffi_trampoline_table *table;
vm_address_t config_page;
vm_address_t trampoline_page;
vm_address_t trampoline_page_template;
vm_prot_t cur_prot;
vm_prot_t max_prot;
kern_return_t kt;
uint16_t i;
/* Allocate two pages -- a config page and a placeholder page */
config_page = 0x0;
kt = vm_allocate (mach_task_self (), &config_page, PAGE_MAX_SIZE * 2,
VM_FLAGS_ANYWHERE);
if (kt != KERN_SUCCESS)
return NULL;
/* Remap the trampoline table on top of the placeholder page */
trampoline_page = config_page + PAGE_MAX_SIZE;
trampoline_page_template = (vm_address_t)&ffi_closure_trampoline_table_page;
#ifdef __arm__
/* ffi_closure_trampoline_table_page can be thumb-biased on some ARM archs */
trampoline_page_template &= ~1UL;
#endif
kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_MAX_SIZE, 0x0,
VM_FLAGS_OVERWRITE, mach_task_self (), trampoline_page_template,
FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
if (kt != KERN_SUCCESS)
{
vm_deallocate (mach_task_self (), config_page, PAGE_MAX_SIZE * 2);
return NULL;
}
/* We have valid trampoline and config pages */
table = calloc (1, sizeof (ffi_trampoline_table));
table->free_count = FFI_TRAMPOLINE_COUNT;
table->config_page = config_page;
table->trampoline_page = trampoline_page;
/* Create and initialize the free list */
table->free_list_pool =
calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry));
for (i = 0; i < table->free_count; i++)
{
ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
entry->trampoline =
(void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
if (i < table->free_count - 1)
entry->next = &table->free_list_pool[i + 1];
}
table->free_list = table->free_list_pool;
return table;
}
static void
ffi_trampoline_table_free (ffi_trampoline_table *table)
{
/* Remove from the list */
if (table->prev != NULL)
table->prev->next = table->next;
if (table->next != NULL)
table->next->prev = table->prev;
/* Deallocate pages */
vm_deallocate (mach_task_self (), table->config_page, PAGE_MAX_SIZE * 2);
/* Deallocate free list */
free (table->free_list_pool);
free (table);
}
void *
ffi_closure_alloc (size_t size, void **code)
{
/* Create the closure */
ffi_closure *closure = malloc (size);
if (closure == NULL)
return NULL;
pthread_mutex_lock (&ffi_trampoline_lock);
/* Check for an active trampoline table with available entries. */
ffi_trampoline_table *table = ffi_trampoline_tables;
if (table == NULL || table->free_list == NULL)
{
table = ffi_trampoline_table_alloc ();
if (table == NULL)
{
pthread_mutex_unlock (&ffi_trampoline_lock);
free (closure);
return NULL;
}
/* Insert the new table at the top of the list */
table->next = ffi_trampoline_tables;
if (table->next != NULL)
table->next->prev = table;
ffi_trampoline_tables = table;
}
/* Claim the free entry */
ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
ffi_trampoline_tables->free_list = entry->next;
ffi_trampoline_tables->free_count--;
entry->next = NULL;
pthread_mutex_unlock (&ffi_trampoline_lock);
/* Initialize the return values */
*code = entry->trampoline;
closure->trampoline_table = table;
closure->trampoline_table_entry = entry;
return closure;
}
void
ffi_closure_free (void *ptr)
{
ffi_closure *closure = ptr;
pthread_mutex_lock (&ffi_trampoline_lock);
/* Fetch the table and entry references */
ffi_trampoline_table *table = closure->trampoline_table;
ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
/* Return the entry to the free list */
entry->next = table->free_list;
table->free_list = entry;
table->free_count++;
/* If all trampolines within this table are free, and at least one other table exists, deallocate
* the table */
if (table->free_count == FFI_TRAMPOLINE_COUNT
&& ffi_trampoline_tables != table)
{
ffi_trampoline_table_free (table);
}
else if (ffi_trampoline_tables != table)
{
/* Otherwise, bump this table to the top of the list */
table->prev = NULL;
table->next = ffi_trampoline_tables;
if (ffi_trampoline_tables != NULL)
ffi_trampoline_tables->prev = table;
ffi_trampoline_tables = table;
}
pthread_mutex_unlock (&ffi_trampoline_lock);
/* Free the closure */
free (closure);
}
#endif
// Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations.
#elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */
#define USE_LOCKS 1
#define USE_DL_PREFIX 1
#ifdef __GNUC__
#ifndef USE_BUILTIN_FFS
#define USE_BUILTIN_FFS 1
#endif
#endif
/* We need to use mmap, not sbrk. */
#define HAVE_MORECORE 0
/* We could, in theory, support mremap, but it wouldn't buy us anything. */
#define HAVE_MREMAP 0
/* We have no use for this, so save some code and data. */
#define NO_MALLINFO 1
/* We need all allocations to be in regular segments, otherwise we
lose track of the corresponding code address. */
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
/* Don't allocate more than a page unless needed. */
#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <string.h>
#include <stdio.h>
#if !defined(X86_WIN32) && !defined(X86_WIN64)
#ifdef HAVE_MNTENT
#include <mntent.h>
#endif /* HAVE_MNTENT */
#include <sys/param.h>
#include <pthread.h>
/* We don't want sys/mman.h to be included after we redefine mmap and
dlmunmap. */
#include <sys/mman.h>
#define LACKS_SYS_MMAN_H 1
#if FFI_MMAP_EXEC_SELINUX
#include <sys/statfs.h>
#include <stdlib.h>
static int selinux_enabled = -1;
static int
selinux_enabled_check (void)
{
struct statfs sfs;
FILE *f;
char *buf = NULL;
size_t len = 0;
if (statfs ("/selinux", &sfs) >= 0
&& (unsigned int) sfs.f_type == 0xf97cff8cU)
return 1;
f = fopen ("/proc/mounts", "r");
if (f == NULL)
return 0;
while (getline (&buf, &len, f) >= 0)
{
char *p = strchr (buf, ' ');
if (p == NULL)
break;
p = strchr (p + 1, ' ');
if (p == NULL)
break;
if (strncmp (p + 1, "selinuxfs ", 10) == 0)
{
free (buf);
fclose (f);
return 1;
}
}
free (buf);
fclose (f);
return 0;
}
#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
: (selinux_enabled = selinux_enabled_check ()))
#else
#define is_selinux_enabled() 0
#endif /* !FFI_MMAP_EXEC_SELINUX */
/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
#include <stdlib.h>
static int emutramp_enabled = -1;
static int
emutramp_enabled_check (void)
{
char *buf = NULL;
size_t len = 0;
FILE *f;
int ret;
f = fopen ("/proc/self/status", "r");
if (f == NULL)
return 0;
ret = 0;
while (getline (&buf, &len, f) != -1)
if (!strncmp (buf, "PaX:", 4))
{
char emutramp;
if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
ret = (emutramp == 'E');
break;
}
free (buf);
fclose (f);
return ret;
}
#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
: (emutramp_enabled = emutramp_enabled_check ()))
#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
#elif defined (__CYGWIN__) || defined(__INTERIX)
#include <sys/mman.h>
/* Cygwin is Linux-like, but not quite that Linux-like. */
#define is_selinux_enabled() 0
#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX
#define is_emutramp_enabled() 0
#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
/* Declare all functions defined in dlmalloc.c as static. */
static void *dlmalloc(size_t);
static void dlfree(void*);
static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
static void *dlvalloc(size_t) MAYBE_UNUSED;
static int dlmallopt(int, int) MAYBE_UNUSED;
static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
static void *dlpvalloc(size_t) MAYBE_UNUSED;
static int dlmalloc_trim(size_t) MAYBE_UNUSED;
static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
static void dlmalloc_stats(void) MAYBE_UNUSED;
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
/* Use these for mmap and munmap within dlmalloc.c. */
static void *dlmmap(void *, size_t, int, int, int, off_t);
static int dlmunmap(void *, size_t);
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
#define mmap dlmmap
#define munmap dlmunmap
#include "dlmalloc.c"
#undef mmap
#undef munmap
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
/* A mutex used to synchronize access to *exec* variables in this file. */
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
/* A file descriptor of a temporary file from which we'll map
executable pages. */
static int execfd = -1;
/* The amount of space already allocated from the temporary file. */
static size_t execsize = 0;
/* Open a temporary file name, and immediately unlink it. */
static int
open_temp_exec_file_name (char *name, int flags)
{
int fd;
#ifdef HAVE_MKOSTEMP
fd = mkostemp (name, flags);
#else
fd = mkstemp (name);
#endif
if (fd != -1)
unlink (name);
return fd;
}
/* Open a temporary file in the named directory. */
static int
open_temp_exec_file_dir (const char *dir)
{
static const char suffix[] = "/ffiXXXXXX";
int lendir, flags;
char *tempname;
#ifdef O_TMPFILE
int fd;
#endif
#ifdef O_CLOEXEC
flags = O_CLOEXEC;
#else
flags = 0;
#endif
#ifdef O_TMPFILE
fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700);
/* If the running system does not support the O_TMPFILE flag then retry without it. */
if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) {
return fd;
} else {
errno = 0;
}
#endif
lendir = (int) strlen (dir);
tempname = __builtin_alloca (lendir + sizeof (suffix));
if (!tempname)
return -1;
memcpy (tempname, dir, lendir);
memcpy (tempname + lendir, suffix, sizeof (suffix));
return open_temp_exec_file_name (tempname, flags);
}
/* Open a temporary file in the directory in the named environment
variable. */
static int
open_temp_exec_file_env (const char *envvar)
{
const char *value = getenv (envvar);
if (!value)
return -1;
return open_temp_exec_file_dir (value);
}
#ifdef HAVE_MNTENT
/* Open a temporary file in an executable and writable mount point
listed in the mounts file. Subsequent calls with the same mounts
keep searching for mount points in the same file. Providing NULL
as the mounts file closes the file. */
static int
open_temp_exec_file_mnt (const char *mounts)
{
static const char *last_mounts;
static FILE *last_mntent;
if (mounts != last_mounts)
{
if (last_mntent)
endmntent (last_mntent);
last_mounts = mounts;
if (mounts)
last_mntent = setmntent (mounts, "r");
else
last_mntent = NULL;
}
if (!last_mntent)
return -1;
for (;;)
{
int fd;
struct mntent mnt;
char buf[MAXPATHLEN * 3];
if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)) == NULL)
return -1;
if (hasmntopt (&mnt, "ro")
|| hasmntopt (&mnt, "noexec")
|| access (mnt.mnt_dir, W_OK))
continue;
fd = open_temp_exec_file_dir (mnt.mnt_dir);
if (fd != -1)
return fd;
}
}
#endif /* HAVE_MNTENT */
/* Instructions to look for a location to hold a temporary file that
can be mapped in for execution. */
static struct
{
int (*func)(const char *);
const char *arg;
int repeat;
} open_temp_exec_file_opts[] = {
{ open_temp_exec_file_env, "TMPDIR", 0 },
{ open_temp_exec_file_dir, "/tmp", 0 },
{ open_temp_exec_file_dir, "/var/tmp", 0 },
{ open_temp_exec_file_dir, "/dev/shm", 0 },
{ open_temp_exec_file_env, "HOME", 0 },
#ifdef HAVE_MNTENT
{ open_temp_exec_file_mnt, "/etc/mtab", 1 },
{ open_temp_exec_file_mnt, "/proc/mounts", 1 },
#endif /* HAVE_MNTENT */
};
/* Current index into open_temp_exec_file_opts. */
static int open_temp_exec_file_opts_idx = 0;
/* Reset a current multi-call func, then advances to the next entry.
If we're at the last, go back to the first and return nonzero,
otherwise return zero. */
static int
open_temp_exec_file_opts_next (void)
{
if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
open_temp_exec_file_opts_idx++;
if (open_temp_exec_file_opts_idx
== (sizeof (open_temp_exec_file_opts)
/ sizeof (*open_temp_exec_file_opts)))
{
open_temp_exec_file_opts_idx = 0;
return 1;
}
return 0;
}
/* Return a file descriptor of a temporary zero-sized file in a
writable and executable filesystem. */
static int
open_temp_exec_file (void)
{
int fd;
do
{
fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
(open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
|| fd == -1)
{
if (open_temp_exec_file_opts_next ())
break;
}
}
while (fd == -1);
return fd;
}
/* We need to allocate space in a file that will be backing a writable
mapping. Several problems exist with the usual approaches:
- fallocate() is Linux-only
- posix_fallocate() is not available on all platforms
- ftruncate() does not allocate space on filesystems with sparse files
Failure to allocate the space will cause SIGBUS to be thrown when
the mapping is subsequently written to. */
static int
allocate_space (int fd, off_t offset, off_t len)
{
static size_t page_size;
/* Obtain system page size. */
if (!page_size)
page_size = sysconf(_SC_PAGESIZE);
unsigned char buf[page_size];
memset (buf, 0, page_size);
while (len > 0)
{
off_t to_write = (len < page_size) ? len : page_size;
if (write (fd, buf, to_write) < to_write)
return -1;
len -= to_write;
}
return 0;
}
/* Map in a chunk of memory from the temporary exec file into separate
locations in the virtual memory address space, one writable and one
executable. Returns the address of the writable portion, after
storing an offset to the corresponding executable portion at the
last word of the requested chunk. */
static void *
dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
{
void *ptr;
if (execfd == -1)
{
open_temp_exec_file_opts_idx = 0;
retry_open:
execfd = open_temp_exec_file ();
if (execfd == -1)
return MFAIL;
}
offset = execsize;
if (allocate_space (execfd, offset, length))
return MFAIL;
flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
flags |= MAP_SHARED;
ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
flags, execfd, offset);
if (ptr == MFAIL)
{
if (!offset)
{
close (execfd);
goto retry_open;
}
ftruncate (execfd, offset);
return MFAIL;
}
else if (!offset
&& open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
open_temp_exec_file_opts_next ();
start = mmap (start, length, prot, flags, execfd, offset);
if (start == MFAIL)
{
munmap (ptr, length);
ftruncate (execfd, offset);
return start;
}
mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
execsize += length;
return start;
}
/* Map in a writable and executable chunk of memory if possible.
Failing that, fall back to dlmmap_locked. */
static void *
dlmmap (void *start, size_t length, int prot,
int flags, int fd, off_t offset)
{
void *ptr;
assert (start == NULL && length % malloc_getpagesize == 0
&& prot == (PROT_READ | PROT_WRITE)
&& flags == (MAP_PRIVATE | MAP_ANONYMOUS)
&& fd == -1 && offset == 0);
if (execfd == -1 && is_emutramp_enabled ())
{
ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
return ptr;
}
if (execfd == -1 && !is_selinux_enabled ())
{
ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
/* Cool, no need to mess with separate segments. */
return ptr;
/* If MREMAP_DUP is ever introduced and implemented, try mmap
with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
MREMAP_DUP and prot at this point. */
}
if (execsize == 0 || execfd == -1)
{
pthread_mutex_lock (&open_temp_exec_file_mutex);
ptr = dlmmap_locked (start, length, prot, flags, offset);
pthread_mutex_unlock (&open_temp_exec_file_mutex);
return ptr;
}
return dlmmap_locked (start, length, prot, flags, offset);
}
/* Release memory at the given address, as well as the corresponding
executable page if it's separate. */
static int
dlmunmap (void *start, size_t length)
{
/* We don't bother decreasing execsize or truncating the file, since
we can't quite tell whether we're unmapping the end of the file.
We don't expect frequent deallocation anyway. If we did, we
could locate pages in the file by writing to the pages being
deallocated and checking that the file contents change.
Yuck. */
msegmentptr seg = segment_holding (gm, start);
void *code;
if (seg && (code = add_segment_exec_offset (start, seg)) != start)
{
int ret = munmap (code, length);
if (ret)
return ret;
}
return munmap (start, length);
}
#if FFI_CLOSURE_FREE_CODE
/* Return segment holding given code address. */
static msegmentptr
segment_holding_code (mstate m, char* addr)
{
msegmentptr sp = &m->seg;
for (;;) {
if (addr >= add_segment_exec_offset (sp->base, sp)
&& addr < add_segment_exec_offset (sp->base, sp) + sp->size)
return sp;
if ((sp = sp->next) == 0)
return 0;
}
}
#endif
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
/* Allocate a chunk of memory with the given size. Returns a pointer
to the writable address, and sets *CODE to the executable
corresponding virtual address. */
void *
ffi_closure_alloc (size_t size, void **code)
{
void *ptr;
if (!code)
return NULL;
ptr = dlmalloc (size);
if (ptr)
{
msegmentptr seg = segment_holding (gm, ptr);
*code = add_segment_exec_offset (ptr, seg);
}
return ptr;
}
/* Release a chunk of memory allocated with ffi_closure_alloc. If
FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
writable or the executable address given. Otherwise, only the
writable address can be provided here. */
void
ffi_closure_free (void *ptr)
{
#if FFI_CLOSURE_FREE_CODE
msegmentptr seg = segment_holding_code (gm, ptr);
if (seg)
ptr = sub_segment_exec_offset (ptr, seg);
#endif
dlfree (ptr);
}
# else /* ! FFI_MMAP_EXEC_WRIT */
/* On many systems, memory returned by malloc is writable and
executable, so just use it. */
#include <stdlib.h>
void *
ffi_closure_alloc (size_t size, void **code)
{
if (!code)
return NULL;
return *code = malloc (size);
}
void
ffi_closure_free (void *ptr)
{
free (ptr);
}
# endif /* ! FFI_MMAP_EXEC_WRIT */
#endif /* FFI_CLOSURES */
#endif /* NetBSD with PROT_MPROTECT */
/* -----------------------------------------------------------------------
debug.c - Copyright (c) 1996 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <stdio.h>
/* General debugging routines */
void ffi_stop_here(void)
{
/* This function is only useful for debugging purposes.
Place a breakpoint on ffi_stop_here to be notified of
significant events. */
}
/* This function should only be called via the FFI_ASSERT() macro */
void ffi_assert(char *expr, char *file, int line)
{
fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line);
ffi_stop_here();
abort();
}
/* Perform a sanity check on an ffi_type structure */
void ffi_type_test(ffi_type *a, char *file, int line)
{
FFI_ASSERT_AT(a != NULL, file, line);
FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX)
|| a->elements != NULL, file, line);
FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX
|| (a->elements != NULL
&& a->elements[0] != NULL && a->elements[1] == NULL),
file, line);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifdef __aarch64__
#include <ffi_arm64.h>
#endif
#ifdef __i386__
#include <ffi_i386.h>
#endif
#ifdef __arm__
#include <ffi_armv7.h>
#endif
#ifdef __x86_64__
#include <ffi_x86_64.h>
#endif
/* -----------------------------------------------------------------------
ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc.
Conditionally assemble cfi directives. Only necessary for building libffi.
----------------------------------------------------------------------- */
#ifndef FFI_CFI_H
#define FFI_CFI_H
#ifdef HAVE_AS_CFI_PSEUDO_OP
# define cfi_startproc .cfi_startproc
# define cfi_endproc .cfi_endproc
# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off
# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
# define cfi_offset(reg, off) .cfi_offset reg, off
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
# define cfi_register(r1, r2) .cfi_register r1, r2
# define cfi_return_column(reg) .cfi_return_column reg
# define cfi_restore(reg) .cfi_restore reg
# define cfi_same_value(reg) .cfi_same_value reg
# define cfi_undefined(reg) .cfi_undefined reg
# define cfi_remember_state .cfi_remember_state
# define cfi_restore_state .cfi_restore_state
# define cfi_window_save .cfi_window_save
# define cfi_personality(enc, exp) .cfi_personality enc, exp
# define cfi_lsda(enc, exp) .cfi_lsda enc, exp
# define cfi_escape(...) .cfi_escape __VA_ARGS__
#else
# define cfi_startproc
# define cfi_endproc
# define cfi_def_cfa(reg, off)
# define cfi_def_cfa_register(reg)
# define cfi_def_cfa_offset(off)
# define cfi_adjust_cfa_offset(off)
# define cfi_offset(reg, off)
# define cfi_rel_offset(reg, off)
# define cfi_register(r1, r2)
# define cfi_return_column(reg)
# define cfi_restore(reg)
# define cfi_same_value(reg)
# define cfi_undefined(reg)
# define cfi_remember_state
# define cfi_restore_state
# define cfi_window_save
# define cfi_personality(enc, exp)
# define cfi_lsda(enc, exp)
# define cfi_escape(...)
#endif /* HAVE_AS_CFI_PSEUDO_OP */
#endif /* FFI_CFI_H */
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (C) 2011, 2012, 2013 Anthony Green
Copyright (C) 2007 Free Software Foundation, Inc
Copyright (c) 1996 Red Hat, Inc.
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
#ifndef FFI_COMMON_H
#define FFI_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <fficonfig.h>
/* Do not move this. Some versions of AIX are very picky about where
this is positioned. */
#ifdef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
/* mingw64 defines this already in malloc.h. */
# ifndef alloca
# define alloca __builtin_alloca
# endif
# endif
# define MAYBE_UNUSED __attribute__((__unused__))
#else
# define MAYBE_UNUSED
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
# ifdef _MSC_VER
# define alloca _alloca
# else
char *alloca ();
# endif
# endif
# endif
# endif
#endif
/* Check for the existence of memcpy. */
#if STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
#if defined(FFI_DEBUG)
#include <stdio.h>
#endif
#ifdef FFI_DEBUG
void ffi_assert(char *expr, char *file, int line);
void ffi_stop_here(void);
void ffi_type_test(ffi_type *a, char *file, int line);
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
#else
#define FFI_ASSERT(x)
#define FFI_ASSERT_AT(x, f, l)
#define FFI_ASSERT_VALID_TYPE(x)
#endif
/* v cast to size_t and aligned up to a multiple of a */
#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
/* v cast to size_t and aligned down to a multiple of a */
#define FFI_ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
unsigned int nfixedargs, unsigned int ntotalargs);
#if HAVE_LONG_DOUBLE_VARIANT
/* Used to adjust size/alignment of ffi types. */
void ffi_prep_types (ffi_abi abi);
#endif
/* Used internally, but overridden by some architectures */
ffi_status ffi_prep_cif_core(ffi_cif *cif,
ffi_abi abi,
unsigned int isvariadic,
unsigned int nfixedargs,
unsigned int ntotalargs,
ffi_type *rtype,
ffi_type **atypes);
/* Extended cif, used in callback from assembly routine */
typedef struct
{
ffi_cif *cif;
void *rvalue;
void **avalue;
} extended_cif;
/* Terse sized type definitions. */
#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C)
typedef unsigned char UINT8;
typedef signed char SINT8;
typedef unsigned short UINT16;
typedef signed short SINT16;
typedef unsigned int UINT32;
typedef signed int SINT32;
# ifdef _MSC_VER
typedef unsigned __int64 UINT64;
typedef signed __int64 SINT64;
# else
# include <inttypes.h>
typedef uint64_t UINT64;
typedef int64_t SINT64;
# endif
#else
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
#endif
typedef float FLOAT32;
#ifndef __GNUC__
#define __builtin_expect(x, expected_value) (x)
#endif
#define LIKELY(x) __builtin_expect(!!(x),1)
#define UNLIKELY(x) __builtin_expect((x)!=0,0)
#ifdef __cplusplus
}
#endif
#endif
#include "ffi_cxx.h"
FFICallInterface::~FFICallInterface() {
for (FFIClosure *closure : closures_) {
delete closure;
}
delete cif_;
delete types_;
}
void FFIDispatcher(ffi_cif *cif OPTION, void *ret, void **args, void *userdata) {
FFIClosure *closure = reinterpret_cast<FFIClosure *>(userdata);
FFICallback callback = closure->GetCallback();
callback(closure, ret, args, closure->GetUserData());
}
FFIClosure *FFICallInterface::CreateClosure(void *userdata, FFICallback callback) {
std::lock_guard<std::mutex> guard(lock_);
FFIClosure *closure = new FFIClosure(this, userdata, callback);
ffi_prep_closure_loc(closure->closure_, cif_, FFIDispatcher, closure, closure->code_);
closures_.push_back(closure);
return closure;
}
static ffi_type *FFIGetCType(FFIType type) {
switch (type) {
case FFIType::kFFITypeVoid:
return &ffi_type_void;
case FFIType::kFFITypeU1:
return &ffi_type_uint8;
case FFIType::kFFITypeU2:
return &ffi_type_uint16;
case FFIType::kFFITypeU4:
return &ffi_type_uint32;
case FFIType::kFFITypeU8:
return &ffi_type_uint64;
case FFIType::kFFITypeS1:
return &ffi_type_sint8;
case FFIType::kFFITypeS2:
return &ffi_type_sint16;
case FFIType::kFFITypeS4:
return &ffi_type_sint32;
case FFIType::kFFITypeS8:
return &ffi_type_sint64;
case FFIType::kFFITypePointer:
return &ffi_type_pointer;
case FFIType::kFFITypeFloat:
return &ffi_type_float;
case FFIType::kFFITypeDouble:
return &ffi_type_double;
}
}
FFICallInterface *FFICallInterface::FinalizeCif() {
cif_ = new ffi_cif;
types_ = new ffi_type *[parameters_.size()];
int idx = 0;
for (FFIType type : parameters_) {
types_[idx] = FFIGetCType(type);
idx++;
}
ffi_prep_cif(cif_, FFI_DEFAULT_ABI,
(unsigned int) parameters_.size(), FFIGetCType(return_type_), types_);
return this;
}
#ifndef WHALE_FFI_CXX_H_
#define WHALE_FFI_CXX_H_
#include <cstdarg>
#include <list>
#include <mutex>
#include "ffi.h"
#define OPTION __unused
enum class FFIType {
kFFITypeVoid,
kFFITypeU1,
kFFITypeU2,
kFFITypeU4,
kFFITypeU8,
kFFITypeS1,
kFFITypeS2,
kFFITypeS4,
kFFITypeS8,
kFFITypePointer,
kFFITypeFloat,
kFFITypeDouble,
};
class FFICallInterface;
class FFIClosure;
typedef void (*FFICallback)(FFIClosure *closure, void *ret, void **args, void *userdata);
class FFIClosure {
public:
FFIClosure(FFICallInterface *cif, void *userdata, FFICallback callback) : cif_(cif),
userdata_(userdata),
callback_(callback) {
closure_ = reinterpret_cast<ffi_closure *>(ffi_closure_alloc(sizeof(ffi_closure), &code_));
}
~FFIClosure() {
ffi_closure_free(closure_);
}
void *GetCode() {
return code_;
}
void *GetUserData() {
return userdata_;
}
FFICallInterface *GetCif() {
return cif_;
}
FFICallback GetCallback() {
return callback_;
}
private:
friend class FFICallInterface;
FFICallInterface *cif_;
ffi_closure *closure_;
FFICallback callback_;
void *code_;
void *userdata_;
};
class FFICallInterface {
public:
FFICallInterface(const FFIType return_type) : return_type_(return_type) {}
~FFICallInterface();
FFICallInterface *Parameter(const FFIType parameter) {
parameters_.push_back(parameter);
return this;
}
FFICallInterface *Parameters(unsigned int count, ...) {
va_list ap;
va_start(ap, count);
while (count-- > 0) {
Parameter(va_arg(ap, FFIType));
}
va_end(ap);
return this;
}
FFICallInterface *FinalizeCif();
size_t GetParameterCount() {
return parameters_.size();
}
std::list<FFIType> GetParameters() {
return parameters_;
}
FFIClosure *CreateClosure(void *userdata, FFICallback callback);
void RemoveClosure(FFIClosure *closure) {
std::lock_guard<std::mutex> guard(lock_);
closures_.remove(closure);
}
private:
std::mutex lock_;
ffi_cif *cif_;
ffi_type **types_;
std::list<FFIType> parameters_;
const FFIType return_type_;
std::list<FFIClosure *> closures_;
};
#endif //WHALE_FFI_CXX_H_
#if defined(__aarch64__) || defined(__arm64__)
#include <fficonfig_arm64.h>
#endif
#ifdef __i386__
#include <fficonfig_i386.h>
#endif
#ifdef __arm__
#include <fficonfig_armv7.h>
#endif
#ifdef __x86_64__
#include <fficonfig_x86_64.h>
#endif
#ifdef __aarch64__
#include <ffitarget_arm64.h>
#endif
#ifdef __i386__
#include <ffitarget_i386.h>
#endif
#ifdef __arm__
#include <ffitarget_armv7.h>
#endif
#ifdef __x86_64__
#include <ffitarget_x86_64.h>
#endif
/* -----------------------------------------------------------------------
java_raw_api.c - Copyright (c) 1999, 2007, 2008 Red Hat, Inc.
Cloned from raw_api.c
Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
$Id $
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
/* This defines a Java- and 64-bit specific variant of the raw API. */
/* It assumes that "raw" argument blocks look like Java stacks on a */
/* 64-bit machine. Arguments that can be stored in a single stack */
/* stack slots (longs, doubles) occupy 128 bits, but only the first */
/* 64 bits are actually used. */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#if !defined(NO_JAVA_RAW_API)
size_t
ffi_java_raw_size (ffi_cif *cif)
{
size_t result = 0;
int i;
ffi_type **at = cif->arg_types;
for (i = cif->nargs-1; i >= 0; i--, at++)
{
switch((*at) -> type) {
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
result += 2 * FFI_SIZEOF_JAVA_RAW;
break;
case FFI_TYPE_STRUCT:
/* No structure parameters in Java. */
abort();
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
result += FFI_SIZEOF_JAVA_RAW;
}
}
return result;
}
void
ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
{
unsigned i;
ffi_type **tp = cif->arg_types;
#if WORDS_BIGENDIAN
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
switch ((*tp)->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
*args = (void*) ((char*)(raw++) + 3);
break;
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
*args = (void*) ((char*)(raw++) + 2);
break;
#if FFI_SIZEOF_JAVA_RAW == 8
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
*args = (void *)raw;
raw += 2;
break;
#endif
case FFI_TYPE_POINTER:
*args = (void*) &(raw++)->ptr;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
*args = raw;
raw +=
FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
}
}
#else /* WORDS_BIGENDIAN */
#if !PDP
/* then assume little endian */
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
#if FFI_SIZEOF_JAVA_RAW == 8
switch((*tp)->type) {
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
*args = (void*) raw;
raw += 2;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
*args = (void*) raw++;
}
#else /* FFI_SIZEOF_JAVA_RAW != 8 */
*args = (void*) raw;
raw +=
FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
#endif /* FFI_SIZEOF_JAVA_RAW == 8 */
}
#else
#error "pdp endian not supported"
#endif /* ! PDP */
#endif /* WORDS_BIGENDIAN */
}
void
ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
{
unsigned i;
ffi_type **tp = cif->arg_types;
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
switch ((*tp)->type)
{
case FFI_TYPE_UINT8:
#if WORDS_BIGENDIAN
*(UINT32*)(raw++) = *(UINT8*) (*args);
#else
(raw++)->uint = *(UINT8*) (*args);
#endif
break;
case FFI_TYPE_SINT8:
#if WORDS_BIGENDIAN
*(SINT32*)(raw++) = *(SINT8*) (*args);
#else
(raw++)->sint = *(SINT8*) (*args);
#endif
break;
case FFI_TYPE_UINT16:
#if WORDS_BIGENDIAN
*(UINT32*)(raw++) = *(UINT16*) (*args);
#else
(raw++)->uint = *(UINT16*) (*args);
#endif
break;
case FFI_TYPE_SINT16:
#if WORDS_BIGENDIAN
*(SINT32*)(raw++) = *(SINT16*) (*args);
#else
(raw++)->sint = *(SINT16*) (*args);
#endif
break;
case FFI_TYPE_UINT32:
#if WORDS_BIGENDIAN
*(UINT32*)(raw++) = *(UINT32*) (*args);
#else
(raw++)->uint = *(UINT32*) (*args);
#endif
break;
case FFI_TYPE_SINT32:
#if WORDS_BIGENDIAN
*(SINT32*)(raw++) = *(SINT32*) (*args);
#else
(raw++)->sint = *(SINT32*) (*args);
#endif
break;
case FFI_TYPE_FLOAT:
(raw++)->flt = *(FLOAT32*) (*args);
break;
#if FFI_SIZEOF_JAVA_RAW == 8
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
raw->uint = *(UINT64*) (*args);
raw += 2;
break;
#endif
case FFI_TYPE_POINTER:
(raw++)->ptr = **(void***) args;
break;
default:
#if FFI_SIZEOF_JAVA_RAW == 8
FFI_ASSERT(0); /* Should have covered all cases */
#else
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
raw +=
FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
#endif
}
}
}
#if !FFI_NATIVE_RAW_API
static void
ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
{
#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
switch (cif->rtype->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_UINT32:
*(UINT64 *)rvalue <<= 32;
break;
case FFI_TYPE_SINT8:
case FFI_TYPE_SINT16:
case FFI_TYPE_SINT32:
case FFI_TYPE_INT:
#if FFI_SIZEOF_JAVA_RAW == 4
case FFI_TYPE_POINTER:
#endif
*(SINT64 *)rvalue <<= 32;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
break;
}
#endif
}
static void
ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
{
#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
switch (cif->rtype->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_UINT32:
*(UINT64 *)rvalue >>= 32;
break;
case FFI_TYPE_SINT8:
case FFI_TYPE_SINT16:
case FFI_TYPE_SINT32:
case FFI_TYPE_INT:
*(SINT64 *)rvalue >>= 32;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
break;
}
#endif
}
/* This is a generic definition of ffi_raw_call, to be used if the
* native system does not provide a machine-specific implementation.
* Having this, allows code to be written for the raw API, without
* the need for system-specific code to handle input in that format;
* these following couple of functions will handle the translation forth
* and back automatically. */
void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue,
ffi_java_raw *raw)
{
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
ffi_java_raw_to_ptrarray (cif, raw, avalue);
ffi_call (cif, fn, rvalue, avalue);
ffi_java_rvalue_to_raw (cif, rvalue);
}
#if FFI_CLOSURES /* base system provides closures */
static void
ffi_java_translate_args (ffi_cif *cif, void *rvalue,
void **avalue, void *user_data)
{
ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
ffi_java_ptrarray_to_raw (cif, avalue, raw);
(*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data);
ffi_java_raw_to_rvalue (cif, rvalue);
}
ffi_status
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data,
void *codeloc)
{
ffi_status status;
status = ffi_prep_closure_loc ((ffi_closure*) cl,
cif,
&ffi_java_translate_args,
codeloc,
codeloc);
if (status == FFI_OK)
{
cl->fun = fun;
cl->user_data = user_data;
}
return status;
}
/* Again, here is the generic version of ffi_prep_raw_closure, which
* will install an intermediate "hub" for translation of arguments from
* the pointer-array format, to the raw format */
ffi_status
ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data)
{
return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
}
#endif /* FFI_CLOSURES */
#endif /* !FFI_NATIVE_RAW_API */
#endif /* !NO_JAVA_RAW_API */
#if defined(__aarch64__) || defined(__arm64__)
/* -----------------------------------------------------------------*-C-*-
libffi 3.3-rc0 - Copyright (c) 2011, 2014 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
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.
----------------------------------------------------------------------- */
/* -------------------------------------------------------------------
Most of the API is documented in doc/libffi.texi.
The raw API is designed to bypass some of the argument packing and
unpacking on architectures for which it can be avoided. Routines
are provided to emulate the raw API if the underlying platform
doesn't allow faster implementation.
More details on the raw API can be found in:
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
and
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-------------------------------------------------------------------- */
#ifndef LIBFFI_H
#define LIBFFI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Specify which architecture libffi is configured for. */
#ifndef AARCH64
#define AARCH64
#endif
/* ---- System configuration information --------------------------------- */
#include <ffitarget.h>
#ifndef LIBFFI_ASM
#if defined(_MSC_VER) && !defined(__clang__)
#define __attribute__(X)
#endif
#include <stddef.h>
#include <limits.h>
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
But we can find it either under the correct ANSI name, or under GNU
C's internal name. */
#define FFI_64_BIT_MAX 9223372036854775807
#ifdef LONG_LONG_MAX
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
#else
# ifdef LLONG_MAX
# define FFI_LONG_LONG_MAX LLONG_MAX
# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif /* _AIX52 or newer */
# else
# ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif
# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
# ifndef __PPC64__
# if defined (__IBMC__) || defined (__IBMCPP__)
# define FFI_LONG_LONG_MAX LONGLONG_MAX
# endif
# endif /* __PPC64__ */
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif
# endif
#endif
/* The closure code assumes that this works on pointers, i.e. a size_t
can hold a pointer. */
typedef struct _ffi_type
{
size_t size;
unsigned short alignment;
unsigned short type;
struct _ffi_type **elements;
} ffi_type;
/* Need minimal decorations for DLLs to work on Windows. GCC has
autoimport and autoexport. Always mark externally visible symbols
as dllimport for MSVC clients, even if it means an extra indirection
when using the static version of the library.
Besides, as a workaround, they can define FFI_BUILDING if they
*know* they are going to link with the static library. */
#if defined _MSC_VER
# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */
# define FFI_API __declspec(dllexport)
# elif !defined FFI_BUILDING /* Importing libffi.DLL */
# define FFI_API __declspec(dllimport)
# else /* Building/linking static library */
# define FFI_API
# endif
#else
# define FFI_API
#endif
/* The externally visible type declarations also need the MSVC DLL
decorations, or they will not be exported from the object file. */
#if defined LIBFFI_HIDE_BASIC_TYPES
# define FFI_EXTERN FFI_API
#else
# define FFI_EXTERN extern FFI_API
#endif
#ifndef LIBFFI_HIDE_BASIC_TYPES
#if SCHAR_MAX == 127
# define ffi_type_uchar ffi_type_uint8
# define ffi_type_schar ffi_type_sint8
#else
#error "char size not supported"
#endif
#if SHRT_MAX == 32767
# define ffi_type_ushort ffi_type_uint16
# define ffi_type_sshort ffi_type_sint16
#elif SHRT_MAX == 2147483647
# define ffi_type_ushort ffi_type_uint32
# define ffi_type_sshort ffi_type_sint32
#else
#error "short size not supported"
#endif
#if INT_MAX == 32767
# define ffi_type_uint ffi_type_uint16
# define ffi_type_sint ffi_type_sint16
#elif INT_MAX == 2147483647
# define ffi_type_uint ffi_type_uint32
# define ffi_type_sint ffi_type_sint32
#elif INT_MAX == 9223372036854775807
# define ffi_type_uint ffi_type_uint64
# define ffi_type_sint ffi_type_sint64
#else
#error "int size not supported"
#endif
#if LONG_MAX == 2147483647
# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
#error "no 64-bit data type supported"
# endif
#elif LONG_MAX != FFI_64_BIT_MAX
#error "long size not supported"
#endif
#if LONG_MAX == 2147483647
# define ffi_type_ulong ffi_type_uint32
# define ffi_type_slong ffi_type_sint32
#elif LONG_MAX == FFI_64_BIT_MAX
# define ffi_type_ulong ffi_type_uint64
# define ffi_type_slong ffi_type_sint64
#else
#error "long size not supported"
#endif
/* These are defined in types.c. */
FFI_EXTERN ffi_type ffi_type_void;
FFI_EXTERN ffi_type ffi_type_uint8;
FFI_EXTERN ffi_type ffi_type_sint8;
FFI_EXTERN ffi_type ffi_type_uint16;
FFI_EXTERN ffi_type ffi_type_sint16;
FFI_EXTERN ffi_type ffi_type_uint32;
FFI_EXTERN ffi_type ffi_type_sint32;
FFI_EXTERN ffi_type ffi_type_uint64;
FFI_EXTERN ffi_type ffi_type_sint64;
FFI_EXTERN ffi_type ffi_type_float;
FFI_EXTERN ffi_type ffi_type_double;
FFI_EXTERN ffi_type ffi_type_pointer;
#if 1
FFI_EXTERN ffi_type ffi_type_longdouble;
#else
#define ffi_type_longdouble ffi_type_double
#endif
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
FFI_EXTERN ffi_type ffi_type_complex_float;
FFI_EXTERN ffi_type ffi_type_complex_double;
#if 1
FFI_EXTERN ffi_type ffi_type_complex_longdouble;
#else
#define ffi_type_complex_longdouble ffi_type_complex_double
#endif
#endif
#endif /* LIBFFI_HIDE_BASIC_TYPES */
typedef enum {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
} ffi_status;
typedef struct {
ffi_abi abi;
unsigned nargs;
ffi_type **arg_types;
ffi_type *rtype;
unsigned bytes;
unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
FFI_EXTRA_CIF_FIELDS;
#endif
} ffi_cif;
/* ---- Definitions for the raw API -------------------------------------- */
#ifndef FFI_SIZEOF_ARG
# if LONG_MAX == 2147483647
# define FFI_SIZEOF_ARG 4
# elif LONG_MAX == FFI_64_BIT_MAX
# define FFI_SIZEOF_ARG 8
# endif
#endif
#ifndef FFI_SIZEOF_JAVA_RAW
# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
#endif
typedef union {
ffi_sarg sint;
ffi_arg uint;
float flt;
char data[FFI_SIZEOF_ARG];
void* ptr;
} ffi_raw;
#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
/* This is a special case for mips64/n32 ABI (and perhaps others) where
sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
typedef union {
signed int sint;
unsigned int uint;
float flt;
char data[FFI_SIZEOF_JAVA_RAW];
void* ptr;
} ffi_java_raw;
#else
typedef ffi_raw ffi_java_raw;
#endif
FFI_API
void ffi_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_raw *avalue);
FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
FFI_API size_t ffi_raw_size (ffi_cif *cif);
/* This is analogous to the raw API, except it uses Java parameter
packing, even on 64-bit machines. I.e. on 64-bit machines longs
and doubles are followed by an empty 64-bit word. */
FFI_API
void ffi_java_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_java_raw *avalue);
FFI_API
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
FFI_API
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
FFI_API
size_t ffi_java_raw_size (ffi_cif *cif);
/* ---- Definitions for closures ----------------------------------------- */
#if FFI_CLOSURES
#ifdef _MSC_VER
__declspec(align(8))
#endif
typedef struct {
#if FFI_EXEC_TRAMPOLINE_TABLE
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
} ffi_closure
#ifdef __GNUC__
__attribute__((aligned (8)))
#endif
;
#ifndef __GNUC__
# ifdef __sgi
# pragma pack 0
# endif
#endif
FFI_API void *ffi_closure_alloc (size_t size, void **code);
FFI_API void ffi_closure_free (void *);
FFI_API ffi_status
ffi_prep_closure (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405)
__attribute__((deprecated ("use ffi_prep_closure_loc instead")))
#elif defined(__GNUC__) && __GNUC__ >= 3
__attribute__((deprecated))
#endif
;
FFI_API ffi_status
ffi_prep_closure_loc (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void*codeloc);
#ifdef __sgi
# pragma pack 8
#endif
typedef struct {
#if FFI_EXEC_TRAMPOLINE_TABLE
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
void *user_data;
} ffi_raw_closure;
typedef struct {
#if FFI_EXEC_TRAMPOLINE_TABLE
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the translation, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
void *user_data;
} ffi_java_raw_closure;
FFI_API ffi_status
ffi_prep_raw_closure (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data);
FFI_API ffi_status
ffi_prep_raw_closure_loc (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc);
FFI_API ffi_status
ffi_prep_java_raw_closure (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data);
FFI_API ffi_status
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data,
void *codeloc);
#endif /* FFI_CLOSURES */
#if FFI_GO_CLOSURES
typedef struct {
void *tramp;
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
} ffi_go_closure;
FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*));
FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure);
#endif /* FFI_GO_CLOSURES */
/* ---- Public interface definition -------------------------------------- */
FFI_API
ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
ffi_type *rtype,
ffi_type **atypes);
FFI_API
ffi_status ffi_prep_cif_var(ffi_cif *cif,
ffi_abi abi,
unsigned int nfixedargs,
unsigned int ntotalargs,
ffi_type *rtype,
ffi_type **atypes);
FFI_API
void ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue);
FFI_API
ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
size_t *offsets);
/* Useful for eliminating compiler warnings. */
#define FFI_FN(f) ((void (*)(void))f)
/* ---- Definitions shared with assembly code ---------------------------- */
#endif
/* If these change, update src/mips/ffitarget.h. */
#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if 1
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
#define FFI_TYPE_UINT64 11
#define FFI_TYPE_SINT64 12
#define FFI_TYPE_STRUCT 13
#define FFI_TYPE_POINTER 14
#define FFI_TYPE_COMPLEX 15
/* This should always refer to the last type code (for sanity checks). */
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
#ifdef __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
#ifdef __arm__
/* -----------------------------------------------------------------*-C-*-
libffi 3.3-rc0 - Copyright (c) 2011, 2014 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
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.
----------------------------------------------------------------------- */
/* -------------------------------------------------------------------
Most of the API is documented in doc/libffi.texi.
The raw API is designed to bypass some of the argument packing and
unpacking on architectures for which it can be avoided. Routines
are provided to emulate the raw API if the underlying platform
doesn't allow faster implementation.
More details on the raw API can be found in:
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
and
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-------------------------------------------------------------------- */
#ifndef LIBFFI_H
#define LIBFFI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Specify which architecture libffi is configured for. */
#ifndef ARM
#define ARM
#endif
/* ---- System configuration information --------------------------------- */
#include <ffitarget.h>
#ifndef LIBFFI_ASM
#if defined(_MSC_VER) && !defined(__clang__)
#define __attribute__(X)
#endif
#include <stddef.h>
#include <limits.h>
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
But we can find it either under the correct ANSI name, or under GNU
C's internal name. */
#define FFI_64_BIT_MAX 9223372036854775807
#ifdef LONG_LONG_MAX
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
#else
# ifdef LLONG_MAX
# define FFI_LONG_LONG_MAX LLONG_MAX
# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif /* _AIX52 or newer */
# else
# ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif
# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
# ifndef __PPC64__
# if defined (__IBMC__) || defined (__IBMCPP__)
# define FFI_LONG_LONG_MAX LONGLONG_MAX
# endif
# endif /* __PPC64__ */
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif
# endif
#endif
/* The closure code assumes that this works on pointers, i.e. a size_t
can hold a pointer. */
typedef struct _ffi_type
{
size_t size;
unsigned short alignment;
unsigned short type;
struct _ffi_type **elements;
} ffi_type;
/* Need minimal decorations for DLLs to work on Windows. GCC has
autoimport and autoexport. Always mark externally visible symbols
as dllimport for MSVC clients, even if it means an extra indirection
when using the static version of the library.
Besides, as a workaround, they can define FFI_BUILDING if they
*know* they are going to link with the static library. */
#if defined _MSC_VER
# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */
# define FFI_API __declspec(dllexport)
# elif !defined FFI_BUILDING /* Importing libffi.DLL */
# define FFI_API __declspec(dllimport)
# else /* Building/linking static library */
# define FFI_API
# endif
#else
# define FFI_API
#endif
/* The externally visible type declarations also need the MSVC DLL
decorations, or they will not be exported from the object file. */
#if defined LIBFFI_HIDE_BASIC_TYPES
# define FFI_EXTERN FFI_API
#else
# define FFI_EXTERN extern FFI_API
#endif
#ifndef LIBFFI_HIDE_BASIC_TYPES
#if SCHAR_MAX == 127
# define ffi_type_uchar ffi_type_uint8
# define ffi_type_schar ffi_type_sint8
#else
#error "char size not supported"
#endif
#if SHRT_MAX == 32767
# define ffi_type_ushort ffi_type_uint16
# define ffi_type_sshort ffi_type_sint16
#elif SHRT_MAX == 2147483647
# define ffi_type_ushort ffi_type_uint32
# define ffi_type_sshort ffi_type_sint32
#else
#error "short size not supported"
#endif
#if INT_MAX == 32767
# define ffi_type_uint ffi_type_uint16
# define ffi_type_sint ffi_type_sint16
#elif INT_MAX == 2147483647
# define ffi_type_uint ffi_type_uint32
# define ffi_type_sint ffi_type_sint32
#elif INT_MAX == 9223372036854775807
# define ffi_type_uint ffi_type_uint64
# define ffi_type_sint ffi_type_sint64
#else
#error "int size not supported"
#endif
#if LONG_MAX == 2147483647
# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
#error "no 64-bit data type supported"
# endif
#elif LONG_MAX != FFI_64_BIT_MAX
#error "long size not supported"
#endif
#if LONG_MAX == 2147483647
# define ffi_type_ulong ffi_type_uint32
# define ffi_type_slong ffi_type_sint32
#elif LONG_MAX == FFI_64_BIT_MAX
# define ffi_type_ulong ffi_type_uint64
# define ffi_type_slong ffi_type_sint64
#else
#error "long size not supported"
#endif
/* These are defined in types.c. */
FFI_EXTERN ffi_type ffi_type_void;
FFI_EXTERN ffi_type ffi_type_uint8;
FFI_EXTERN ffi_type ffi_type_sint8;
FFI_EXTERN ffi_type ffi_type_uint16;
FFI_EXTERN ffi_type ffi_type_sint16;
FFI_EXTERN ffi_type ffi_type_uint32;
FFI_EXTERN ffi_type ffi_type_sint32;
FFI_EXTERN ffi_type ffi_type_uint64;
FFI_EXTERN ffi_type ffi_type_sint64;
FFI_EXTERN ffi_type ffi_type_float;
FFI_EXTERN ffi_type ffi_type_double;
FFI_EXTERN ffi_type ffi_type_pointer;
#if 1
FFI_EXTERN ffi_type ffi_type_longdouble;
#else
#define ffi_type_longdouble ffi_type_double
#endif
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
FFI_EXTERN ffi_type ffi_type_complex_float;
FFI_EXTERN ffi_type ffi_type_complex_double;
#if 1
FFI_EXTERN ffi_type ffi_type_complex_longdouble;
#else
#define ffi_type_complex_longdouble ffi_type_complex_double
#endif
#endif
#endif /* LIBFFI_HIDE_BASIC_TYPES */
typedef enum {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
} ffi_status;
typedef struct {
ffi_abi abi;
unsigned nargs;
ffi_type **arg_types;
ffi_type *rtype;
unsigned bytes;
unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
FFI_EXTRA_CIF_FIELDS;
#endif
} ffi_cif;
/* ---- Definitions for the raw API -------------------------------------- */
#ifndef FFI_SIZEOF_ARG
# if LONG_MAX == 2147483647
# define FFI_SIZEOF_ARG 4
# elif LONG_MAX == FFI_64_BIT_MAX
# define FFI_SIZEOF_ARG 8
# endif
#endif
#ifndef FFI_SIZEOF_JAVA_RAW
# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
#endif
typedef union {
ffi_sarg sint;
ffi_arg uint;
float flt;
char data[FFI_SIZEOF_ARG];
void* ptr;
} ffi_raw;
#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
/* This is a special case for mips64/n32 ABI (and perhaps others) where
sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
typedef union {
signed int sint;
unsigned int uint;
float flt;
char data[FFI_SIZEOF_JAVA_RAW];
void* ptr;
} ffi_java_raw;
#else
typedef ffi_raw ffi_java_raw;
#endif
FFI_API
void ffi_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_raw *avalue);
FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
FFI_API size_t ffi_raw_size (ffi_cif *cif);
/* This is analogous to the raw API, except it uses Java parameter
packing, even on 64-bit machines. I.e. on 64-bit machines longs
and doubles are followed by an empty 64-bit word. */
FFI_API
void ffi_java_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_java_raw *avalue);
FFI_API
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
FFI_API
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
FFI_API
size_t ffi_java_raw_size (ffi_cif *cif);
/* ---- Definitions for closures ----------------------------------------- */
#if FFI_CLOSURES
#ifdef _MSC_VER
__declspec(align(8))
#endif
typedef struct {
#if FFI_EXEC_TRAMPOLINE_TABLE
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
} ffi_closure
#ifdef __GNUC__
__attribute__((aligned (8)))
#endif
;
#ifndef __GNUC__
# ifdef __sgi
# pragma pack 0
# endif
#endif
FFI_API void *ffi_closure_alloc (size_t size, void **code);
FFI_API void ffi_closure_free (void *);
FFI_API ffi_status
ffi_prep_closure (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405)
__attribute__((deprecated ("use ffi_prep_closure_loc instead")))
#elif defined(__GNUC__) && __GNUC__ >= 3
__attribute__((deprecated))
#endif
;
FFI_API ffi_status
ffi_prep_closure_loc (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void*codeloc);
#ifdef __sgi
# pragma pack 8
#endif
typedef struct {
#if FFI_EXEC_TRAMPOLINE_TABLE
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
void *user_data;
} ffi_raw_closure;
typedef struct {
#if FFI_EXEC_TRAMPOLINE_TABLE
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the translation, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
void *user_data;
} ffi_java_raw_closure;
FFI_API ffi_status
ffi_prep_raw_closure (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data);
FFI_API ffi_status
ffi_prep_raw_closure_loc (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc);
FFI_API ffi_status
ffi_prep_java_raw_closure (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data);
FFI_API ffi_status
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data,
void *codeloc);
#endif /* FFI_CLOSURES */
#if FFI_GO_CLOSURES
typedef struct {
void *tramp;
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
} ffi_go_closure;
FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*));
FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure);
#endif /* FFI_GO_CLOSURES */
/* ---- Public interface definition -------------------------------------- */
FFI_API
ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
ffi_type *rtype,
ffi_type **atypes);
FFI_API
ffi_status ffi_prep_cif_var(ffi_cif *cif,
ffi_abi abi,
unsigned int nfixedargs,
unsigned int ntotalargs,
ffi_type *rtype,
ffi_type **atypes);
FFI_API
void ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue);
FFI_API
ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
size_t *offsets);
/* Useful for eliminating compiler warnings. */
#define FFI_FN(f) ((void (*)(void))f)
/* ---- Definitions shared with assembly code ---------------------------- */
#endif
/* If these change, update src/mips/ffitarget.h. */
#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if 1
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
#define FFI_TYPE_UINT64 11
#define FFI_TYPE_SINT64 12
#define FFI_TYPE_STRUCT 13
#define FFI_TYPE_POINTER 14
#define FFI_TYPE_COMPLEX 15
/* This should always refer to the last type code (for sanity checks). */
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
#ifdef __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
#ifdef __i386__
/* -----------------------------------------------------------------*-C-*-
libffi 3.3-rc0 - Copyright (c) 2011, 2014 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
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.
----------------------------------------------------------------------- */
/* -------------------------------------------------------------------
Most of the API is documented in doc/libffi.texi.
The raw API is designed to bypass some of the argument packing and
unpacking on architectures for which it can be avoided. Routines
are provided to emulate the raw API if the underlying platform
doesn't allow faster implementation.
More details on the raw API can be found in:
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
and
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-------------------------------------------------------------------- */
#ifndef LIBFFI_H
#define LIBFFI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Specify which architecture libffi is configured for. */
#ifndef X86_UNIX
#define X86_UNIX
#endif
/* ---- System configuration information --------------------------------- */
#include <ffitarget.h>
#ifndef LIBFFI_ASM
#if defined(_MSC_VER) && !defined(__clang__)
#define __attribute__(X)
#endif
#include <stddef.h>
#include <limits.h>
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
But we can find it either under the correct ANSI name, or under GNU
C's internal name. */
#define FFI_64_BIT_MAX 9223372036854775807
#ifdef LONG_LONG_MAX
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
#else
# ifdef LLONG_MAX
# define FFI_LONG_LONG_MAX LLONG_MAX
# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif /* _AIX52 or newer */
# else
# ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif
# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
# ifndef __PPC64__
# if defined (__IBMC__) || defined (__IBMCPP__)
# define FFI_LONG_LONG_MAX LONGLONG_MAX
# endif
# endif /* __PPC64__ */
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif
# endif
#endif
/* The closure code assumes that this works on pointers, i.e. a size_t
can hold a pointer. */
typedef struct _ffi_type
{
size_t size;
unsigned short alignment;
unsigned short type;
struct _ffi_type **elements;
} ffi_type;
/* Need minimal decorations for DLLs to work on Windows. GCC has
autoimport and autoexport. Always mark externally visible symbols
as dllimport for MSVC clients, even if it means an extra indirection
when using the static version of the library.
Besides, as a workaround, they can define FFI_BUILDING if they
*know* they are going to link with the static library. */
#if defined _MSC_VER
# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */
# define FFI_API __declspec(dllexport)
# elif !defined FFI_BUILDING /* Importing libffi.DLL */
# define FFI_API __declspec(dllimport)
# else /* Building/linking static library */
# define FFI_API
# endif
#else
# define FFI_API
#endif
/* The externally visible type declarations also need the MSVC DLL
decorations, or they will not be exported from the object file. */
#if defined LIBFFI_HIDE_BASIC_TYPES
# define FFI_EXTERN FFI_API
#else
# define FFI_EXTERN extern FFI_API
#endif
#ifndef LIBFFI_HIDE_BASIC_TYPES
#if SCHAR_MAX == 127
# define ffi_type_uchar ffi_type_uint8
# define ffi_type_schar ffi_type_sint8
#else
#error "char size not supported"
#endif
#if SHRT_MAX == 32767
# define ffi_type_ushort ffi_type_uint16
# define ffi_type_sshort ffi_type_sint16
#elif SHRT_MAX == 2147483647
# define ffi_type_ushort ffi_type_uint32
# define ffi_type_sshort ffi_type_sint32
#else
#error "short size not supported"
#endif
#if INT_MAX == 32767
# define ffi_type_uint ffi_type_uint16
# define ffi_type_sint ffi_type_sint16
#elif INT_MAX == 2147483647
# define ffi_type_uint ffi_type_uint32
# define ffi_type_sint ffi_type_sint32
#elif INT_MAX == 9223372036854775807
# define ffi_type_uint ffi_type_uint64
# define ffi_type_sint ffi_type_sint64
#else
#error "int size not supported"
#endif
#if LONG_MAX == 2147483647
# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
#error "no 64-bit data type supported"
# endif
#elif LONG_MAX != FFI_64_BIT_MAX
#error "long size not supported"
#endif
#if LONG_MAX == 2147483647
# define ffi_type_ulong ffi_type_uint32
# define ffi_type_slong ffi_type_sint32
#elif LONG_MAX == FFI_64_BIT_MAX
# define ffi_type_ulong ffi_type_uint64
# define ffi_type_slong ffi_type_sint64
#else
#error "long size not supported"
#endif
/* These are defined in types.c. */
FFI_EXTERN ffi_type ffi_type_void;
FFI_EXTERN ffi_type ffi_type_uint8;
FFI_EXTERN ffi_type ffi_type_sint8;
FFI_EXTERN ffi_type ffi_type_uint16;
FFI_EXTERN ffi_type ffi_type_sint16;
FFI_EXTERN ffi_type ffi_type_uint32;
FFI_EXTERN ffi_type ffi_type_sint32;
FFI_EXTERN ffi_type ffi_type_uint64;
FFI_EXTERN ffi_type ffi_type_sint64;
FFI_EXTERN ffi_type ffi_type_float;
FFI_EXTERN ffi_type ffi_type_double;
FFI_EXTERN ffi_type ffi_type_pointer;
#if 1
FFI_EXTERN ffi_type ffi_type_longdouble;
#else
#define ffi_type_longdouble ffi_type_double
#endif
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
FFI_EXTERN ffi_type ffi_type_complex_float;
FFI_EXTERN ffi_type ffi_type_complex_double;
#if 1
FFI_EXTERN ffi_type ffi_type_complex_longdouble;
#else
#define ffi_type_complex_longdouble ffi_type_complex_double
#endif
#endif
#endif /* LIBFFI_HIDE_BASIC_TYPES */
typedef enum {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
} ffi_status;
typedef struct {
ffi_abi abi;
unsigned nargs;
ffi_type **arg_types;
ffi_type *rtype;
unsigned bytes;
unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
FFI_EXTRA_CIF_FIELDS;
#endif
} ffi_cif;
/* ---- Definitions for the raw API -------------------------------------- */
#ifndef FFI_SIZEOF_ARG
# if LONG_MAX == 2147483647
# define FFI_SIZEOF_ARG 4
# elif LONG_MAX == FFI_64_BIT_MAX
# define FFI_SIZEOF_ARG 8
# endif
#endif
#ifndef FFI_SIZEOF_JAVA_RAW
# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
#endif
typedef union {
ffi_sarg sint;
ffi_arg uint;
float flt;
char data[FFI_SIZEOF_ARG];
void* ptr;
} ffi_raw;
#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
/* This is a special case for mips64/n32 ABI (and perhaps others) where
sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
typedef union {
signed int sint;
unsigned int uint;
float flt;
char data[FFI_SIZEOF_JAVA_RAW];
void* ptr;
} ffi_java_raw;
#else
typedef ffi_raw ffi_java_raw;
#endif
FFI_API
void ffi_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_raw *avalue);
FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
FFI_API size_t ffi_raw_size (ffi_cif *cif);
/* This is analogous to the raw API, except it uses Java parameter
packing, even on 64-bit machines. I.e. on 64-bit machines longs
and doubles are followed by an empty 64-bit word. */
FFI_API
void ffi_java_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_java_raw *avalue);
FFI_API
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
FFI_API
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
FFI_API
size_t ffi_java_raw_size (ffi_cif *cif);
/* ---- Definitions for closures ----------------------------------------- */
#if FFI_CLOSURES
#ifdef _MSC_VER
__declspec(align(8))
#endif
typedef struct {
#if 0
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
} ffi_closure
#ifdef __GNUC__
__attribute__((aligned (8)))
#endif
;
#ifndef __GNUC__
# ifdef __sgi
# pragma pack 0
# endif
#endif
FFI_API void *ffi_closure_alloc (size_t size, void **code);
FFI_API void ffi_closure_free (void *);
FFI_API ffi_status
ffi_prep_closure (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405)
__attribute__((deprecated ("use ffi_prep_closure_loc instead")))
#elif defined(__GNUC__) && __GNUC__ >= 3
__attribute__((deprecated))
#endif
;
FFI_API ffi_status
ffi_prep_closure_loc (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void*codeloc);
#ifdef __sgi
# pragma pack 8
#endif
typedef struct {
#if 0
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
void *user_data;
} ffi_raw_closure;
typedef struct {
#if 0
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the translation, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
void *user_data;
} ffi_java_raw_closure;
FFI_API ffi_status
ffi_prep_raw_closure (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data);
FFI_API ffi_status
ffi_prep_raw_closure_loc (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc);
FFI_API ffi_status
ffi_prep_java_raw_closure (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data);
FFI_API ffi_status
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data,
void *codeloc);
#endif /* FFI_CLOSURES */
#if FFI_GO_CLOSURES
typedef struct {
void *tramp;
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
} ffi_go_closure;
FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*));
FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure);
#endif /* FFI_GO_CLOSURES */
/* ---- Public interface definition -------------------------------------- */
FFI_API
ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
ffi_type *rtype,
ffi_type **atypes);
FFI_API
ffi_status ffi_prep_cif_var(ffi_cif *cif,
ffi_abi abi,
unsigned int nfixedargs,
unsigned int ntotalargs,
ffi_type *rtype,
ffi_type **atypes);
FFI_API
void ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue);
FFI_API
ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
size_t *offsets);
/* Useful for eliminating compiler warnings. */
#define FFI_FN(f) ((void (*)(void))f)
/* ---- Definitions shared with assembly code ---------------------------- */
#endif
/* If these change, update src/mips/ffitarget.h. */
#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if 1
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
#define FFI_TYPE_UINT64 11
#define FFI_TYPE_SINT64 12
#define FFI_TYPE_STRUCT 13
#define FFI_TYPE_POINTER 14
#define FFI_TYPE_COMPLEX 15
/* This should always refer to the last type code (for sanity checks). */
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
#ifdef __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
#ifdef __x86_64__
/* -----------------------------------------------------------------*-C-*-
libffi 3.3-rc0 - Copyright (c) 2011, 2014 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
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.
----------------------------------------------------------------------- */
/* -------------------------------------------------------------------
Most of the API is documented in doc/libffi.texi.
The raw API is designed to bypass some of the argument packing and
unpacking on architectures for which it can be avoided. Routines
are provided to emulate the raw API if the underlying platform
doesn't allow faster implementation.
More details on the raw API can be found in:
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
and
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-------------------------------------------------------------------- */
#ifndef LIBFFI_H
#define LIBFFI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Specify which architecture libffi is configured for. */
#ifndef X86_64
#define X86_64
#endif
/* ---- System configuration information --------------------------------- */
#include <ffitarget.h>
#ifndef LIBFFI_ASM
#if defined(_MSC_VER) && !defined(__clang__)
#define __attribute__(X)
#endif
#include <stddef.h>
#include <limits.h>
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
But we can find it either under the correct ANSI name, or under GNU
C's internal name. */
#define FFI_64_BIT_MAX 9223372036854775807
#ifdef LONG_LONG_MAX
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
#else
# ifdef LLONG_MAX
# define FFI_LONG_LONG_MAX LLONG_MAX
# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif /* _AIX52 or newer */
# else
# ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif
# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
# ifndef __PPC64__
# if defined (__IBMC__) || defined (__IBMCPP__)
# define FFI_LONG_LONG_MAX LONGLONG_MAX
# endif
# endif /* __PPC64__ */
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif
# endif
#endif
/* The closure code assumes that this works on pointers, i.e. a size_t
can hold a pointer. */
typedef struct _ffi_type
{
size_t size;
unsigned short alignment;
unsigned short type;
struct _ffi_type **elements;
} ffi_type;
/* Need minimal decorations for DLLs to work on Windows. GCC has
autoimport and autoexport. Always mark externally visible symbols
as dllimport for MSVC clients, even if it means an extra indirection
when using the static version of the library.
Besides, as a workaround, they can define FFI_BUILDING if they
*know* they are going to link with the static library. */
#if defined _MSC_VER
# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */
# define FFI_API __declspec(dllexport)
# elif !defined FFI_BUILDING /* Importing libffi.DLL */
# define FFI_API __declspec(dllimport)
# else /* Building/linking static library */
# define FFI_API
# endif
#else
# define FFI_API
#endif
/* The externally visible type declarations also need the MSVC DLL
decorations, or they will not be exported from the object file. */
#if defined LIBFFI_HIDE_BASIC_TYPES
# define FFI_EXTERN FFI_API
#else
# define FFI_EXTERN extern FFI_API
#endif
#ifndef LIBFFI_HIDE_BASIC_TYPES
#if SCHAR_MAX == 127
# define ffi_type_uchar ffi_type_uint8
# define ffi_type_schar ffi_type_sint8
#else
#error "char size not supported"
#endif
#if SHRT_MAX == 32767
# define ffi_type_ushort ffi_type_uint16
# define ffi_type_sshort ffi_type_sint16
#elif SHRT_MAX == 2147483647
# define ffi_type_ushort ffi_type_uint32
# define ffi_type_sshort ffi_type_sint32
#else
#error "short size not supported"
#endif
#if INT_MAX == 32767
# define ffi_type_uint ffi_type_uint16
# define ffi_type_sint ffi_type_sint16
#elif INT_MAX == 2147483647
# define ffi_type_uint ffi_type_uint32
# define ffi_type_sint ffi_type_sint32
#elif INT_MAX == 9223372036854775807
# define ffi_type_uint ffi_type_uint64
# define ffi_type_sint ffi_type_sint64
#else
#error "int size not supported"
#endif
#if LONG_MAX == 2147483647
# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
#error "no 64-bit data type supported"
# endif
#elif LONG_MAX != FFI_64_BIT_MAX
#error "long size not supported"
#endif
#if LONG_MAX == 2147483647
# define ffi_type_ulong ffi_type_uint32
# define ffi_type_slong ffi_type_sint32
#elif LONG_MAX == FFI_64_BIT_MAX
# define ffi_type_ulong ffi_type_uint64
# define ffi_type_slong ffi_type_sint64
#else
#error "long size not supported"
#endif
/* These are defined in types.c. */
FFI_EXTERN ffi_type ffi_type_void;
FFI_EXTERN ffi_type ffi_type_uint8;
FFI_EXTERN ffi_type ffi_type_sint8;
FFI_EXTERN ffi_type ffi_type_uint16;
FFI_EXTERN ffi_type ffi_type_sint16;
FFI_EXTERN ffi_type ffi_type_uint32;
FFI_EXTERN ffi_type ffi_type_sint32;
FFI_EXTERN ffi_type ffi_type_uint64;
FFI_EXTERN ffi_type ffi_type_sint64;
FFI_EXTERN ffi_type ffi_type_float;
FFI_EXTERN ffi_type ffi_type_double;
FFI_EXTERN ffi_type ffi_type_pointer;
#if 1
FFI_EXTERN ffi_type ffi_type_longdouble;
#else
#define ffi_type_longdouble ffi_type_double
#endif
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
FFI_EXTERN ffi_type ffi_type_complex_float;
FFI_EXTERN ffi_type ffi_type_complex_double;
#if 1
FFI_EXTERN ffi_type ffi_type_complex_longdouble;
#else
#define ffi_type_complex_longdouble ffi_type_complex_double
#endif
#endif
#endif /* LIBFFI_HIDE_BASIC_TYPES */
typedef enum {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
} ffi_status;
typedef struct {
ffi_abi abi;
unsigned nargs;
ffi_type **arg_types;
ffi_type *rtype;
unsigned bytes;
unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
FFI_EXTRA_CIF_FIELDS;
#endif
} ffi_cif;
/* ---- Definitions for the raw API -------------------------------------- */
#ifndef FFI_SIZEOF_ARG
# if LONG_MAX == 2147483647
# define FFI_SIZEOF_ARG 4
# elif LONG_MAX == FFI_64_BIT_MAX
# define FFI_SIZEOF_ARG 8
# endif
#endif
#ifndef FFI_SIZEOF_JAVA_RAW
# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
#endif
typedef union {
ffi_sarg sint;
ffi_arg uint;
float flt;
char data[FFI_SIZEOF_ARG];
void* ptr;
} ffi_raw;
#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
/* This is a special case for mips64/n32 ABI (and perhaps others) where
sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
typedef union {
signed int sint;
unsigned int uint;
float flt;
char data[FFI_SIZEOF_JAVA_RAW];
void* ptr;
} ffi_java_raw;
#else
typedef ffi_raw ffi_java_raw;
#endif
FFI_API
void ffi_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_raw *avalue);
FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
FFI_API size_t ffi_raw_size (ffi_cif *cif);
/* This is analogous to the raw API, except it uses Java parameter
packing, even on 64-bit machines. I.e. on 64-bit machines longs
and doubles are followed by an empty 64-bit word. */
FFI_API
void ffi_java_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_java_raw *avalue);
FFI_API
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
FFI_API
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
FFI_API
size_t ffi_java_raw_size (ffi_cif *cif);
/* ---- Definitions for closures ----------------------------------------- */
#if FFI_CLOSURES
#ifdef _MSC_VER
__declspec(align(8))
#endif
typedef struct {
#if 0
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
} ffi_closure
#ifdef __GNUC__
__attribute__((aligned (8)))
#endif
;
#ifndef __GNUC__
# ifdef __sgi
# pragma pack 0
# endif
#endif
FFI_API void *ffi_closure_alloc (size_t size, void **code);
FFI_API void ffi_closure_free (void *);
FFI_API ffi_status
ffi_prep_closure (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405)
__attribute__((deprecated ("use ffi_prep_closure_loc instead")))
#elif defined(__GNUC__) && __GNUC__ >= 3
__attribute__((deprecated))
#endif
;
FFI_API ffi_status
ffi_prep_closure_loc (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void*codeloc);
#ifdef __sgi
# pragma pack 8
#endif
typedef struct {
#if 0
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
void *user_data;
} ffi_raw_closure;
typedef struct {
#if 0
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* If this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the translation, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
void *user_data;
} ffi_java_raw_closure;
FFI_API ffi_status
ffi_prep_raw_closure (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data);
FFI_API ffi_status
ffi_prep_raw_closure_loc (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc);
FFI_API ffi_status
ffi_prep_java_raw_closure (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data);
FFI_API ffi_status
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data,
void *codeloc);
#endif /* FFI_CLOSURES */
#if FFI_GO_CLOSURES
typedef struct {
void *tramp;
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
} ffi_go_closure;
FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*));
FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure);
#endif /* FFI_GO_CLOSURES */
/* ---- Public interface definition -------------------------------------- */
FFI_API
ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
ffi_type *rtype,
ffi_type **atypes);
FFI_API
ffi_status ffi_prep_cif_var(ffi_cif *cif,
ffi_abi abi,
unsigned int nfixedargs,
unsigned int ntotalargs,
ffi_type *rtype,
ffi_type **atypes);
FFI_API
void ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue);
FFI_API
ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
size_t *offsets);
/* Useful for eliminating compiler warnings. */
#define FFI_FN(f) ((void (*)(void))f)
/* ---- Definitions shared with assembly code ---------------------------- */
#endif
/* If these change, update src/mips/ffitarget.h. */
#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if 1
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
#define FFI_TYPE_UINT64 11
#define FFI_TYPE_SINT64 12
#define FFI_TYPE_STRUCT 13
#define FFI_TYPE_POINTER 14
#define FFI_TYPE_COMPLEX 15
/* This should always refer to the last type code (for sanity checks). */
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
#ifdef __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
#if defined(__aarch64__) || defined(__arm64__)
/* fficonfig.h. Generated from fficonfig.h.in by configure. */
/* fficonfig.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* Define to the flags needed for the .section .eh_frame directive. */
#define EH_FRAME_FLAGS "aw"
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
#ifdef __APPLE__
#define FFI_EXEC_TRAMPOLINE_TABLE 1
#endif
/* Define this if you want to enable pax emulated trampolines */
/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
/* Cannot use malloc on this target, so, we revert to alternative means */
#ifdef linux
#define FFI_MMAP_EXEC_WRIT 1
#endif
/* Define this if you do not want support for the raw API. */
/* #undef FFI_NO_RAW_API */
/* Define this if you do not want support for aggregate types. */
/* #undef FFI_NO_STRUCTS */
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#define HAVE_ALLOCA_H 1
/* Define if your assembler supports .cfi_* directives. */
#define HAVE_AS_CFI_PSEUDO_OP 1
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
/* Define if the compiler uses zarch features. */
/* #undef HAVE_AS_S390_ZARCH */
/* Define if your assembler and linker support unaligned PC relative relocs.
*/
/* #undef HAVE_AS_SPARC_UA_PCREL */
/* Define if your assembler supports unwind section type. */
/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
/* Define if your assembler supports PC relative relocs. */
/* #undef HAVE_AS_X86_PCREL */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define if __attribute__((visibility("hidden"))) is supported. */
#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if you have the long double type and it is bigger than a double */
/* #undef HAVE_LONG_DOUBLE */
/* Define if you support more than one size of the long double type */
/* #undef HAVE_LONG_DOUBLE_VARIANT */
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mkostemp' function. */
/* #undef HAVE_MKOSTEMP */
/* Define to 1 if you have the `mmap' function. */
#define HAVE_MMAP 1
/* Define if mmap with MAP_ANON(YMOUS) works. */
#define HAVE_MMAP_ANON 1
/* Define if mmap of /dev/zero works. */
/* #undef HAVE_MMAP_DEV_ZERO */
/* Define if read-only mmap of a plain file works. */
#define HAVE_MMAP_FILE 1
/* Define if .eh_frame sections should be read-only. */
/* #undef HAVE_RO_EH_FRAME */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if GNU symbol versioning is used for libatomic. */
/* #undef LIBFFI_GNU_SYMBOL_VERSIONING */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libffi"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "http://github.com/libffi/libffi/issues"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libffi"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libffi 3.3-rc0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libffi"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.3-rc0"
/* The size of `double', as computed by sizeof. */
#define SIZEOF_DOUBLE 8
/* The size of `long double', as computed by sizeof. */
#define SIZEOF_LONG_DOUBLE 8
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 8
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if symbols are underscored. */
#define SYMBOL_UNDERSCORE 1
/* Define this if you are using Purify and want to suppress spurious messages.
*/
/* #undef USING_PURIFY */
/* Version number of package */
#define VERSION "3.3-rc0"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
#ifdef LIBFFI_ASM
#ifdef __APPLE__
#define FFI_HIDDEN(name) .private_extern name
#else
#define FFI_HIDDEN(name) .hidden name
#endif
#else
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
#endif
#else
#ifdef LIBFFI_ASM
#define FFI_HIDDEN(name)
#else
#define FFI_HIDDEN
#endif
#endif
#endif
\ No newline at end of file
#ifdef __arm__
/* fficonfig.h. Generated from fficonfig.h.in by configure. */
/* fficonfig.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* Define to the flags needed for the .section .eh_frame directive. */
#define EH_FRAME_FLAGS "aw"
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
#ifdef __APPLE__
#define FFI_EXEC_TRAMPOLINE_TABLE 1
#endif
/* Define this if you want to enable pax emulated trampolines */
/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
/* Cannot use malloc on this target, so, we revert to alternative means */
#ifdef linux
#define FFI_MMAP_EXEC_WRIT 1
#endif
/* Define this if you do not want support for the raw API. */
/* #undef FFI_NO_RAW_API */
/* Define this if you do not want support for aggregate types. */
/* #undef FFI_NO_STRUCTS */
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#define HAVE_ALLOCA_H 1
/* Define if your assembler supports .cfi_* directives. */
#define HAVE_AS_CFI_PSEUDO_OP 1
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
/* Define if the compiler uses zarch features. */
/* #undef HAVE_AS_S390_ZARCH */
/* Define if your assembler and linker support unaligned PC relative relocs.
*/
/* #undef HAVE_AS_SPARC_UA_PCREL */
/* Define if your assembler supports unwind section type. */
/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
/* Define if your assembler supports PC relative relocs. */
/* #undef HAVE_AS_X86_PCREL */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define if __attribute__((visibility("hidden"))) is supported. */
#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if you have the long double type and it is bigger than a double */
/* #undef HAVE_LONG_DOUBLE */
/* Define if you support more than one size of the long double type */
/* #undef HAVE_LONG_DOUBLE_VARIANT */
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mkostemp' function. */
/* #undef HAVE_MKOSTEMP */
/* Define to 1 if you have the `mmap' function. */
#define HAVE_MMAP 1
/* Define if mmap with MAP_ANON(YMOUS) works. */
#define HAVE_MMAP_ANON 1
/* Define if mmap of /dev/zero works. */
/* #undef HAVE_MMAP_DEV_ZERO */
/* Define if read-only mmap of a plain file works. */
#define HAVE_MMAP_FILE 1
/* Define if .eh_frame sections should be read-only. */
/* #undef HAVE_RO_EH_FRAME */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if GNU symbol versioning is used for libatomic. */
/* #undef LIBFFI_GNU_SYMBOL_VERSIONING */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libffi"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "http://github.com/libffi/libffi/issues"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libffi"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libffi 3.3-rc0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libffi"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.3-rc0"
/* The size of `double', as computed by sizeof. */
#define SIZEOF_DOUBLE 8
/* The size of `long double', as computed by sizeof. */
#define SIZEOF_LONG_DOUBLE 8
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 4
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if symbols are underscored. */
#define SYMBOL_UNDERSCORE 1
/* Define this if you are using Purify and want to suppress spurious messages.
*/
/* #undef USING_PURIFY */
/* Version number of package */
#define VERSION "3.3-rc0"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
#ifdef LIBFFI_ASM
#ifdef __APPLE__
#define FFI_HIDDEN(name) .private_extern name
#else
#define FFI_HIDDEN(name) .hidden name
#endif
#else
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
#endif
#else
#ifdef LIBFFI_ASM
#define FFI_HIDDEN(name)
#else
#define FFI_HIDDEN
#endif
#endif
#endif
\ No newline at end of file
#ifdef __i386__
/* fficonfig.h. Generated from fficonfig.h.in by configure. */
/* fficonfig.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* Define to the flags needed for the .section .eh_frame directive. */
#define EH_FRAME_FLAGS "aw"
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
/* #undef FFI_EXEC_TRAMPOLINE_TABLE */
/* Define this if you want to enable pax emulated trampolines */
/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
/* Cannot use malloc on this target, so, we revert to alternative means */
#define FFI_MMAP_EXEC_WRIT 1
/* Define this if you do not want support for the raw API. */
/* #undef FFI_NO_RAW_API */
/* Define this if you do not want support for aggregate types. */
/* #undef FFI_NO_STRUCTS */
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#define HAVE_ALLOCA_H 1
/* Define if your assembler supports .cfi_* directives. */
#define HAVE_AS_CFI_PSEUDO_OP 1
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
/* Define if the compiler uses zarch features. */
/* #undef HAVE_AS_S390_ZARCH */
/* Define if your assembler and linker support unaligned PC relative relocs.
*/
/* #undef HAVE_AS_SPARC_UA_PCREL */
/* Define if your assembler supports unwind section type. */
/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
/* Define if your assembler supports PC relative relocs. */
#define HAVE_AS_X86_PCREL 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define if __attribute__((visibility("hidden"))) is supported. */
#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if you have the long double type and it is bigger than a double */
#define HAVE_LONG_DOUBLE 1
/* Define if you support more than one size of the long double type */
/* #undef HAVE_LONG_DOUBLE_VARIANT */
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mkostemp' function. */
/* #undef HAVE_MKOSTEMP */
/* Define to 1 if you have the `mmap' function. */
#define HAVE_MMAP 1
/* Define if mmap with MAP_ANON(YMOUS) works. */
#define HAVE_MMAP_ANON 1
/* Define if mmap of /dev/zero works. */
/* #undef HAVE_MMAP_DEV_ZERO */
/* Define if read-only mmap of a plain file works. */
#define HAVE_MMAP_FILE 1
/* Define if .eh_frame sections should be read-only. */
/* #undef HAVE_RO_EH_FRAME */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if GNU symbol versioning is used for libatomic. */
/* #undef LIBFFI_GNU_SYMBOL_VERSIONING */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libffi"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "http://github.com/libffi/libffi/issues"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libffi"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libffi 3.3-rc0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libffi"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.3-rc0"
/* The size of `double', as computed by sizeof. */
#define SIZEOF_DOUBLE 8
/* The size of `long double', as computed by sizeof. */
#define SIZEOF_LONG_DOUBLE 16
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 4
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if symbols are underscored. */
#define SYMBOL_UNDERSCORE 1
/* Define this if you are using Purify and want to suppress spurious messages.
*/
/* #undef USING_PURIFY */
/* Version number of package */
#define VERSION "3.3-rc0"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
#ifdef LIBFFI_ASM
#ifdef __APPLE__
#define FFI_HIDDEN(name) .private_extern name
#else
#define FFI_HIDDEN(name) .hidden name
#endif
#else
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
#endif
#else
#ifdef LIBFFI_ASM
#define FFI_HIDDEN(name)
#else
#define FFI_HIDDEN
#endif
#endif
#endif
\ No newline at end of file
#ifdef __x86_64__
/* fficonfig.h. Generated from fficonfig.h.in by configure. */
/* fficonfig.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* Define to the flags needed for the .section .eh_frame directive. */
#define EH_FRAME_FLAGS "aw"
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
/* #undef FFI_EXEC_TRAMPOLINE_TABLE */
/* Define this if you want to enable pax emulated trampolines */
/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
/* Cannot use malloc on this target, so, we revert to alternative means */
#define FFI_MMAP_EXEC_WRIT 1
/* Define this if you do not want support for the raw API. */
/* #undef FFI_NO_RAW_API */
/* Define this if you do not want support for aggregate types. */
/* #undef FFI_NO_STRUCTS */
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#define HAVE_ALLOCA_H 1
/* Define if your assembler supports .cfi_* directives. */
#define HAVE_AS_CFI_PSEUDO_OP 1
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
/* Define if the compiler uses zarch features. */
/* #undef HAVE_AS_S390_ZARCH */
/* Define if your assembler and linker support unaligned PC relative relocs.
*/
/* #undef HAVE_AS_SPARC_UA_PCREL */
/* Define if your assembler supports unwind section type. */
/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
/* Define if your assembler supports PC relative relocs. */
#define HAVE_AS_X86_PCREL 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define if __attribute__((visibility("hidden"))) is supported. */
#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if you have the long double type and it is bigger than a double */
#define HAVE_LONG_DOUBLE 1
/* Define if you support more than one size of the long double type */
/* #undef HAVE_LONG_DOUBLE_VARIANT */
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mkostemp' function. */
/* #undef HAVE_MKOSTEMP */
/* Define to 1 if you have the `mmap' function. */
#define HAVE_MMAP 1
/* Define if mmap with MAP_ANON(YMOUS) works. */
#define HAVE_MMAP_ANON 1
/* Define if mmap of /dev/zero works. */
/* #undef HAVE_MMAP_DEV_ZERO */
/* Define if read-only mmap of a plain file works. */
#define HAVE_MMAP_FILE 1
/* Define if .eh_frame sections should be read-only. */
/* #undef HAVE_RO_EH_FRAME */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if GNU symbol versioning is used for libatomic. */
/* #undef LIBFFI_GNU_SYMBOL_VERSIONING */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libffi"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "http://github.com/libffi/libffi/issues"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libffi"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libffi 3.3-rc0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libffi"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.3-rc0"
/* The size of `double', as computed by sizeof. */
#define SIZEOF_DOUBLE 8
/* The size of `long double', as computed by sizeof. */
#define SIZEOF_LONG_DOUBLE 16
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 8
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if symbols are underscored. */
#define SYMBOL_UNDERSCORE 1
/* Define this if you are using Purify and want to suppress spurious messages.
*/
/* #undef USING_PURIFY */
/* Version number of package */
#define VERSION "3.3-rc0"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
#ifdef LIBFFI_ASM
#ifdef __APPLE__
#define FFI_HIDDEN(name) .private_extern name
#else
#define FFI_HIDDEN(name) .hidden name
#endif
#else
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
#endif
#else
#ifdef LIBFFI_ASM
#define FFI_HIDDEN(name)
#else
#define FFI_HIDDEN
#endif
#endif
#endif
\ No newline at end of file
#ifdef __aarch64__
/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
#ifndef LIBFFI_ASM
#ifdef __ILP32__
#define FFI_SIZEOF_ARG 8
#define FFI_SIZEOF_JAVA_RAW 4
typedef unsigned long long ffi_arg;
typedef signed long long ffi_sarg;
#else
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
#endif
typedef enum ffi_abi
{
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
#define FFI_TRAMPOLINE_SIZE 16
#define FFI_TRAMPOLINE_CLOSURE_OFFSET 16
#else
#error "No trampoline table implementation"
#endif
#else
#define FFI_TRAMPOLINE_SIZE 24
#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE
#endif
/* ---- Internal ---- */
#if defined (__APPLE__)
#define FFI_TARGET_SPECIFIC_VARIADIC
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
#else
/* iOS reserves x18 for the system. Disable Go closures until
a new static chain is chosen. */
#define FFI_GO_CLOSURES 1
#endif
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif
#endif
\ No newline at end of file
#ifdef __arm__
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 2010 CodeSourcery
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for ARM.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_VFP,
FFI_LAST_ABI,
#ifdef __ARM_PCS_VFP
FFI_DEFAULT_ABI = FFI_VFP,
#else
FFI_DEFAULT_ABI = FFI_SYSV,
#endif
} ffi_abi;
#endif
#define FFI_EXTRA_CIF_FIELDS \
int vfp_used; \
unsigned short vfp_reg_free, vfp_nargs; \
signed char vfp_args[16] \
#define FFI_TARGET_SPECIFIC_VARIADIC
#define FFI_TARGET_HAS_COMPLEX_TYPE
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
#define FFI_TRAMPOLINE_SIZE 12
#define FFI_TRAMPOLINE_CLOSURE_OFFSET 8
#else
#error "No trampoline table implementation"
#endif
#else
#define FFI_TRAMPOLINE_SIZE 12
#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE
#endif
#endif
#endif
\ No newline at end of file
#ifdef __i386__
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2012, 2014, 2018 Anthony Green
Copyright (c) 1996-2003, 2010 Red Hat, Inc.
Copyright (C) 2008 Free Software Foundation, Inc.
Target configuration macros for x86 and x86-64.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
/* ---- System specific configurations ----------------------------------- */
/* For code common to all platforms on x86 and x86_64. */
#define X86_ANY
#if defined (X86_64) && defined (__i386__)
#undef X86_64
#define X86
#endif
#ifdef X86_WIN64
#define FFI_SIZEOF_ARG 8
#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
#endif
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
#ifndef _MSC_VER
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif
/* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM
#ifdef X86_WIN64
#ifdef _MSC_VER
typedef unsigned __int64 ffi_arg;
typedef __int64 ffi_sarg;
#else
typedef unsigned long long ffi_arg;
typedef long long ffi_sarg;
#endif
#else
#if defined __x86_64__ && defined __ILP32__
#define FFI_SIZEOF_ARG 8
#define FFI_SIZEOF_JAVA_RAW 4
typedef unsigned long long ffi_arg;
typedef long long ffi_sarg;
#else
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
#endif
#endif
typedef enum ffi_abi {
#if defined(X86_WIN64)
FFI_FIRST_ABI = 0,
FFI_WIN64, /* sizeof(long double) == 8 - microsoft compilers */
FFI_GNUW64, /* sizeof(long double) == 16 - GNU compilers */
FFI_LAST_ABI,
#ifdef __GNUC__
FFI_DEFAULT_ABI = FFI_GNUW64
#else
FFI_DEFAULT_ABI = FFI_WIN64
#endif
#elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
FFI_FIRST_ABI = 1,
FFI_UNIX64,
FFI_WIN64,
FFI_EFI64 = FFI_WIN64,
FFI_GNUW64,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_UNIX64
#elif defined(X86_WIN32)
FFI_FIRST_ABI = 0,
FFI_SYSV = 1,
FFI_STDCALL = 2,
FFI_THISCALL = 3,
FFI_FASTCALL = 4,
FFI_MS_CDECL = 5,
FFI_PASCAL = 6,
FFI_REGISTER = 7,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_MS_CDECL
#else
FFI_FIRST_ABI = 0,
FFI_SYSV = 1,
FFI_THISCALL = 3,
FFI_FASTCALL = 4,
FFI_STDCALL = 5,
FFI_PASCAL = 6,
FFI_REGISTER = 7,
FFI_MS_CDECL = 8,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
#endif
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)
#define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4)
#if defined (X86_64) || defined(X86_WIN64) \
|| (defined (__x86_64__) && defined (X86_DARWIN))
# define FFI_TRAMPOLINE_SIZE 24
# define FFI_NATIVE_RAW_API 0
#else
# define FFI_TRAMPOLINE_SIZE 12
# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
#endif
#endif
#endif
\ No newline at end of file
#ifdef __x86_64__
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2012, 2014, 2018 Anthony Green
Copyright (c) 1996-2003, 2010 Red Hat, Inc.
Copyright (C) 2008 Free Software Foundation, Inc.
Target configuration macros for x86 and x86-64.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
/* ---- System specific configurations ----------------------------------- */
/* For code common to all platforms on x86 and x86_64. */
#define X86_ANY
#if defined (X86_64) && defined (__i386__)
#undef X86_64
#define X86
#endif
#ifdef X86_WIN64
#define FFI_SIZEOF_ARG 8
#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
#endif
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
#ifndef _MSC_VER
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif
/* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM
#ifdef X86_WIN64
#ifdef _MSC_VER
typedef unsigned __int64 ffi_arg;
typedef __int64 ffi_sarg;
#else
typedef unsigned long long ffi_arg;
typedef long long ffi_sarg;
#endif
#else
#if defined __x86_64__ && defined __ILP32__
#define FFI_SIZEOF_ARG 8
#define FFI_SIZEOF_JAVA_RAW 4
typedef unsigned long long ffi_arg;
typedef long long ffi_sarg;
#else
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
#endif
#endif
typedef enum ffi_abi {
#if defined(X86_WIN64)
FFI_FIRST_ABI = 0,
FFI_WIN64, /* sizeof(long double) == 8 - microsoft compilers */
FFI_GNUW64, /* sizeof(long double) == 16 - GNU compilers */
FFI_LAST_ABI,
#ifdef __GNUC__
FFI_DEFAULT_ABI = FFI_GNUW64
#else
FFI_DEFAULT_ABI = FFI_WIN64
#endif
#elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
FFI_FIRST_ABI = 1,
FFI_UNIX64,
FFI_WIN64,
FFI_EFI64 = FFI_WIN64,
FFI_GNUW64,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_UNIX64
#elif defined(X86_WIN32)
FFI_FIRST_ABI = 0,
FFI_SYSV = 1,
FFI_STDCALL = 2,
FFI_THISCALL = 3,
FFI_FASTCALL = 4,
FFI_MS_CDECL = 5,
FFI_PASCAL = 6,
FFI_REGISTER = 7,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_MS_CDECL
#else
FFI_FIRST_ABI = 0,
FFI_SYSV = 1,
FFI_THISCALL = 3,
FFI_FASTCALL = 4,
FFI_STDCALL = 5,
FFI_PASCAL = 6,
FFI_REGISTER = 7,
FFI_MS_CDECL = 8,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
#endif
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)
#define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4)
#if defined (X86_64) || defined(X86_WIN64) \
|| (defined (__x86_64__) && defined (X86_DARWIN))
# define FFI_TRAMPOLINE_SIZE 24
# define FFI_NATIVE_RAW_API 0
#else
# define FFI_TRAMPOLINE_SIZE 12
# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
#endif
#endif
#endif
\ No newline at end of file
/* -----------------------------------------------------------------------
prep_cif.c - Copyright (c) 2011, 2012 Anthony Green
Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
/* Round up to FFI_SIZEOF_ARG. */
#define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG)
/* Perform machine independent initialization of aggregate type
specifications. */
static ffi_status initialize_aggregate(ffi_type *arg, size_t *offsets)
{
ffi_type **ptr;
if (UNLIKELY(arg == NULL || arg->elements == NULL))
return FFI_BAD_TYPEDEF;
arg->size = 0;
arg->alignment = 0;
ptr = &(arg->elements[0]);
if (UNLIKELY(ptr == 0))
return FFI_BAD_TYPEDEF;
while ((*ptr) != NULL)
{
if (UNLIKELY(((*ptr)->size == 0)
&& (initialize_aggregate((*ptr), NULL) != FFI_OK)))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */
FFI_ASSERT_VALID_TYPE(*ptr);
arg->size = FFI_ALIGN(arg->size, (*ptr)->alignment);
if (offsets)
*offsets++ = arg->size;
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment : (*ptr)->alignment;
ptr++;
}
/* Structure size includes tail padding. This is important for
structures that fit in one register on ABIs like the PowerPC64
Linux ABI that right justify small structs in a register.
It's also needed for nested structure layout, for example
struct A { long a; char b; }; struct B { struct A x; char y; };
should find y at an offset of 2*sizeof(long) and result in a
total size of 3*sizeof(long). */
arg->size = FFI_ALIGN (arg->size, arg->alignment);
/* On some targets, the ABI defines that structures have an additional
alignment beyond the "natural" one based on their elements. */
#ifdef FFI_AGGREGATE_ALIGNMENT
if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
arg->alignment = FFI_AGGREGATE_ALIGNMENT;
#endif
if (arg->size == 0)
return FFI_BAD_TYPEDEF;
else
return FFI_OK;
}
#ifndef __CRIS__
/* The CRIS ABI specifies structure elements to have byte
alignment only, so it completely overrides this functions,
which assumes "natural" alignment and padding. */
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
/* For non variadic functions isvariadic should be 0 and
nfixedargs==ntotalargs.
For variadic calls, isvariadic should be 1 and nfixedargs
and ntotalargs set as appropriate. nfixedargs must always be >=1 */
ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
unsigned int isvariadic,
unsigned int nfixedargs,
unsigned int ntotalargs,
ffi_type *rtype, ffi_type **atypes)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT(cif != NULL);
FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
FFI_ASSERT(nfixedargs <= ntotalargs);
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
return FFI_BAD_ABI;
cif->abi = abi;
cif->arg_types = atypes;
cif->nargs = ntotalargs;
cif->rtype = rtype;
cif->flags = 0;
#if HAVE_LONG_DOUBLE_VARIANT
ffi_prep_types (abi);
#endif
/* Initialize the return type if necessary */
if ((cif->rtype->size == 0)
&& (initialize_aggregate(cif->rtype, NULL) != FFI_OK))
return FFI_BAD_TYPEDEF;
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
if (rtype->type == FFI_TYPE_COMPLEX)
abort();
#endif
/* Perform a sanity check on the return type */
FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef TILE
&& (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
#endif
#ifdef XTENSA
&& (cif->rtype->size > 16)
#endif
#ifdef NIOS2
&& (cif->rtype->size > 8)
#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
/* Initialize any uninitialized aggregate type definitions */
if (((*ptr)->size == 0)
&& (initialize_aggregate((*ptr), NULL) != FFI_OK))
return FFI_BAD_TYPEDEF;
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
if ((*ptr)->type == FFI_TYPE_COMPLEX)
abort();
#endif
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
{
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = (unsigned)FFI_ALIGN(bytes, (*ptr)->alignment);
#ifdef TILE
if (bytes < 10 * FFI_SIZEOF_ARG &&
bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
{
/* An argument is never split between the 10 parameter
registers and the stack. */
bytes = 10 * FFI_SIZEOF_ARG;
}
#endif
#ifdef XTENSA
if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
bytes = 6*4;
#endif
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#endif
}
cif->bytes = bytes;
/* Perform machine dependent cif processing */
#ifdef FFI_TARGET_SPECIFIC_VARIADIC
if (isvariadic)
return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
#endif
return ffi_prep_cif_machdep(cif);
}
#endif /* not __CRIS__ */
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
ffi_type *rtype, ffi_type **atypes)
{
return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
}
ffi_status ffi_prep_cif_var(ffi_cif *cif,
ffi_abi abi,
unsigned int nfixedargs,
unsigned int ntotalargs,
ffi_type *rtype,
ffi_type **atypes)
{
return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
}
#if FFI_CLOSURES
ffi_status
ffi_prep_closure (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
{
return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
}
#endif
ffi_status
ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets)
{
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
return FFI_BAD_ABI;
if (struct_type->type != FFI_TYPE_STRUCT)
return FFI_BAD_TYPEDEF;
#if HAVE_LONG_DOUBLE_VARIANT
ffi_prep_types (abi);
#endif
return initialize_aggregate(struct_type, offsets);
}
/* -----------------------------------------------------------------------
raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc.
Author: Kresten Krab Thorup <krab@gnu.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 in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
/* This file defines generic functions for use with the raw api. */
#include <ffi.h>
#include <ffi_common.h>
#if !FFI_NO_RAW_API
size_t
ffi_raw_size (ffi_cif *cif)
{
size_t result = 0;
int i;
ffi_type **at = cif->arg_types;
for (i = cif->nargs-1; i >= 0; i--, at++)
{
#if !FFI_NO_STRUCTS
if ((*at)->type == FFI_TYPE_STRUCT)
result += FFI_ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
else
#endif
result += FFI_ALIGN ((*at)->size, FFI_SIZEOF_ARG);
}
return result;
}
void
ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
{
unsigned i;
ffi_type **tp = cif->arg_types;
#if WORDS_BIGENDIAN
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
switch ((*tp)->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
break;
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
break;
#if FFI_SIZEOF_ARG >= 4
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
break;
#endif
#if !FFI_NO_STRUCTS
case FFI_TYPE_STRUCT:
*args = (raw++)->ptr;
break;
#endif
case FFI_TYPE_COMPLEX:
*args = (raw++)->ptr;
break;
case FFI_TYPE_POINTER:
*args = (void*) &(raw++)->ptr;
break;
default:
*args = raw;
raw += FFI_ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
}
}
#else /* WORDS_BIGENDIAN */
#if !PDP
/* then assume little endian */
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
#if !FFI_NO_STRUCTS
if ((*tp)->type == FFI_TYPE_STRUCT)
{
*args = (raw++)->ptr;
}
else
#endif
if ((*tp)->type == FFI_TYPE_COMPLEX)
{
*args = (raw++)->ptr;
}
else
{
*args = (void*) raw;
raw += FFI_ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
}
}
#else
#error "pdp endian not supported"
#endif /* ! PDP */
#endif /* WORDS_BIGENDIAN */
}
void
ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
{
unsigned i;
ffi_type **tp = cif->arg_types;
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
switch ((*tp)->type)
{
case FFI_TYPE_UINT8:
(raw++)->uint = *(UINT8*) (*args);
break;
case FFI_TYPE_SINT8:
(raw++)->sint = *(SINT8*) (*args);
break;
case FFI_TYPE_UINT16:
(raw++)->uint = *(UINT16*) (*args);
break;
case FFI_TYPE_SINT16:
(raw++)->sint = *(SINT16*) (*args);
break;
#if FFI_SIZEOF_ARG >= 4
case FFI_TYPE_UINT32:
(raw++)->uint = *(UINT32*) (*args);
break;
case FFI_TYPE_SINT32:
(raw++)->sint = *(SINT32*) (*args);
break;
#endif
#if !FFI_NO_STRUCTS
case FFI_TYPE_STRUCT:
(raw++)->ptr = *args;
break;
#endif
case FFI_TYPE_COMPLEX:
(raw++)->ptr = *args;
break;
case FFI_TYPE_POINTER:
(raw++)->ptr = **(void***) args;
break;
default:
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
raw += FFI_ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
}
}
}
#if !FFI_NATIVE_RAW_API
/* This is a generic definition of ffi_raw_call, to be used if the
* native system does not provide a machine-specific implementation.
* Having this, allows code to be written for the raw API, without
* the need for system-specific code to handle input in that format;
* these following couple of functions will handle the translation forth
* and back automatically. */
void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
{
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
ffi_raw_to_ptrarray (cif, raw, avalue);
ffi_call (cif, fn, rvalue, avalue);
}
#if FFI_CLOSURES /* base system provides closures */
static void
ffi_translate_args (ffi_cif *cif, void *rvalue,
void **avalue, void *user_data)
{
ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
ffi_ptrarray_to_raw (cif, avalue, raw);
(*cl->fun) (cif, rvalue, raw, cl->user_data);
}
ffi_status
ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc)
{
ffi_status status;
status = ffi_prep_closure_loc ((ffi_closure*) cl,
cif,
&ffi_translate_args,
codeloc,
codeloc);
if (status == FFI_OK)
{
cl->fun = fun;
cl->user_data = user_data;
}
return status;
}
#endif /* FFI_CLOSURES */
#endif /* !FFI_NATIVE_RAW_API */
#if FFI_CLOSURES
/* Again, here is the generic version of ffi_prep_raw_closure, which
* will install an intermediate "hub" for translation of arguments from
* the pointer-array format, to the raw format */
ffi_status
ffi_prep_raw_closure (ffi_raw_closure* cl,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data)
{
return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
}
#endif /* FFI_CLOSURES */
#endif /* !FFI_NO_RAW_API */
/* -----------------------------------------------------------------------
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
Predefined ffi_types needed by libffi.
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.
----------------------------------------------------------------------- */
/* Hide the basic type definitions from the header file, so that we
can redefine them here as "const". */
#define LIBFFI_HIDE_BASIC_TYPES
#include <ffi.h>
#include <ffi_common.h>
/* Type definitions */
#define FFI_TYPEDEF(name, type, id, maybe_const)\
struct struct_align_##name { \
char c; \
type x; \
}; \
FFI_EXTERN \
maybe_const ffi_type ffi_type_##name = { \
sizeof(type), \
offsetof(struct struct_align_##name, x), \
id, NULL \
}
#define FFI_COMPLEX_TYPEDEF(name, type, maybe_const) \
static ffi_type *ffi_elements_complex_##name [2] = { \
(ffi_type *)(&ffi_type_##name), NULL \
}; \
struct struct_align_complex_##name { \
char c; \
_Complex type x; \
}; \
FFI_EXTERN \
maybe_const ffi_type ffi_type_complex_##name = { \
sizeof(_Complex type), \
offsetof(struct struct_align_complex_##name, x), \
FFI_TYPE_COMPLEX, \
(ffi_type **)ffi_elements_complex_##name \
}
/* Size and alignment are fake here. They must not be 0. */
FFI_EXTERN const ffi_type ffi_type_void = {
1, 1, FFI_TYPE_VOID, NULL
};
FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8, const);
FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8, const);
FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16, const);
FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16, const);
FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32, const);
FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32, const);
FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64, const);
FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64, const);
FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER, const);
FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT, const);
FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE, const);
#if !defined HAVE_LONG_DOUBLE_VARIANT || defined __alpha__
#define FFI_LDBL_CONST const
#else
#define FFI_LDBL_CONST
#endif
#ifdef __alpha__
/* Even if we're not configured to default to 128-bit long double,
maintain binary compatibility, as -mlong-double-128 can be used
at any time. */
/* Validate the hard-coded number below. */
# if defined(__LONG_DOUBLE_128__) && FFI_TYPE_LONGDOUBLE != 4
# error FFI_TYPE_LONGDOUBLE out of date
# endif
const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL };
#elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE, FFI_LDBL_CONST);
#endif
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
FFI_COMPLEX_TYPEDEF(float, float, const);
FFI_COMPLEX_TYPEDEF(double, double, const);
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
FFI_COMPLEX_TYPEDEF(longdouble, long double, FFI_LDBL_CONST);
#endif
#endif
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
// //
#include <jni.h> #include <jni.h>
#include <log.h>
#include <unistd.h>
#include "sandhook_native.h" #include "sandhook_native.h"
#include "hook.h" #include "hook.h"
#include "elf.h" #include "elf.h"
...@@ -10,6 +12,191 @@ ...@@ -10,6 +12,191 @@
using namespace SandHook::Hook; using namespace SandHook::Hook;
using namespace SandHook::Elf; using namespace SandHook::Elf;
int m1 = 5;
int m3 = 1036;
int m2 = 1035;
int m4 = 5;
void (*dosth3Backup)(int, int) = nullptr;
void (*dosth4Backup)() = nullptr;
void (*dosth4Backup2)() = nullptr;
void (*innerSuspendVM)() = nullptr;
static void (*heapPreForkBackup)(void *) = nullptr;
static void myHeapPreFork(void *heap) {
heapPreForkBackup(heap);
}
void SuspendVMReplace() {
LOGE("VM Suspend!");
innerSuspendVM();
}
void do2() {
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = 1 + 1;
}
void do3(int x, int y) {
do2();
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = a + b + c;
LOGE("do3 = %d", y);
}
void do5() {
LOGE("x = %d", 5);
}
void do4() {
int a = 1 + 1;
int b = a + 1;
int d = a + 1;
int e = a + 1;
}
static std::atomic_int count;
void do4replace() {
LOGE("do4replace :%d", count++);
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = 1 + 1;
dosth4Backup();
}
void do4replace2() {
int a = 1 + 1;
int c = 1 + 1;
int d = 1 + 1;
dosth4Backup2();
}
void do3replace(int x, int y) {
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = 1 + 1;
dosth3Backup(x, y);
}
void do1() {
do2();
}
void breakCallback(REG regs[]) {
LOGE("breakCallback = %d SP = %d", regs[0], regs);
}
class Visitor : public InstVisitor {
bool Visit(Unit<Base> *unit, void *pc) override {
BaseInst* instruction = reinterpret_cast<BaseInst *>(unit);
instruction->Assemble();
return true;
}
};
static void *ThreadEntry2(void *arg) {
while(true) {
*(int*)(0) = 1;
LOGE("ThreadEntry2");
}
LOGE("ThreadEntry2");
return nullptr;
}
static void *ThreadEntry(void *arg) {
pthread_t pthread_ptr_;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024 * 128);
pthread_create(&pthread_ptr_, &attr, ThreadEntry2, nullptr);
while(true) {
*(int*)(0) = 1;
LOGE("ThreadEntry1");
}
return nullptr;
}
std::atomic_bool inited;
static void callback() {
if (inited)
return;
inited = true;
pthread_t pthread_ptr_;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024 * 128);
pthread_create(&pthread_ptr_, &attr, ThreadEntry, nullptr);
}
typedef enum {
SP_DEFAULT = -1,
SP_BACKGROUND = 0,
SP_FOREGROUND = 1,
SP_SYSTEM = 2, // can't be used with set_sched_policy()
SP_AUDIO_APP = 3,
SP_AUDIO_SYS = 4,
SP_TOP_APP = 5,
SP_RT_APP = 6,
SP_RESTRICTED = 7,
SP_CNT,
SP_MAX = SP_CNT - 1,
SP_SYSTEM_DEFAULT = SP_FOREGROUND,
} SchedPolicy;
extern "C"
JNIEXPORT void JNICALL
Java_com_swift_sandhook_nativehook_NativeHook_test(JNIEnv *env, jclass jclass1) {
// dosth4Backup = reinterpret_cast<void (*)()>(InlineHook::instance->SingleInstHook(
// reinterpret_cast<void *>(do4),
// reinterpret_cast<void *>(do4replace)));
//
// InlineHook::instance->callback = callback;
//
//
// do4();
//
// if (sizeof(void*) == 8) {
// heapPreForkBackup = reinterpret_cast<void (*)(void *)>(SandSingleInstHookSym("/system/lib64/libart.so", "_ZN3art2gc4Heap13PreZygoteForkEv",
// reinterpret_cast<void *>(myHeapPreFork)));
// innerSuspendVM = reinterpret_cast<void (*)()>(SandSingleInstHookSym("/system/lib64/libart.so", "_ZN3art3Dbg9SuspendVMEv",
// reinterpret_cast<void *>(SuspendVMReplace)));
// } else {
// heapPreForkBackup = reinterpret_cast<void (*)(void *)>(SandSingleInstHookSym("/system/lib/libart.so", "_ZN3art2gc4Heap13PreZygoteForkEv",
// reinterpret_cast<void *>(myHeapPreFork)));
// innerSuspendVM = reinterpret_cast<void (*)()>(SandSingleInstHookSym("/system/lib/libart.so", "_ZN3art3Dbg9SuspendVMEv",
// reinterpret_cast<void *>(SuspendVMReplace)));
// }
//
// void* do3P = reinterpret_cast<void *>(do3);
//
// InlineHook::instance->BreakPoint(reinterpret_cast<void *>((Addr)do3), breakCallback);
//
// LOGE("ok");
//
// do3(100, 2);
}
extern "C" extern "C"
EXPORT void* SandGetSym(const char* so, const char* symb) { EXPORT void* SandGetSym(const char* so, const char* symb) {
ElfImg elfImg(so); ElfImg elfImg(so);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment