diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index bf44635..0000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,156 +0,0 @@
-version: 2.1
-
-defaults: &defaults
- working_directory: ~/repo
- docker:
- # Built from:
- # https://github.com/pyodide/pyodide/blob/2ab4b0ab6aefe99fd994bb4f9ab086e5c0aebb7b/Dockerfile
- - image: pyodide/pyodide-env:20230126-chrome109-firefox109-py311
-
-jobs:
- install-emsdk:
- <<: *defaults
- steps:
- - checkout
- - run:
- name: install emsdk
- command: |
- git clone https://github.com/emscripten-core/emsdk.git --depth=1
- cd emsdk
- ./emsdk install 3.1.30
- ./emsdk activate 3.1.30
-
- - persist_to_workspace:
- root: .
- paths:
- - emsdk
-
- build:
- parameters:
- wasm-bigint:
- description: Should we build with wasm-bigint?
- type: string
- default: ""
- environment:
- WASM_BIGINT: << parameters.wasm-bigint >>
- <<: *defaults
- steps:
- - checkout
- - attach_workspace:
- at: .
-
- - run:
- name: build
- command: |
- source ./emsdk/emsdk_env.sh
- ./testsuite/emscripten/build.sh
-
- - run:
- name: build tests
- command: |
- source ./emsdk/emsdk_env.sh
- cp -r testsuite/libffi.call testsuite/libffi.call.test
- cp -r testsuite/libffi.closures testsuite/libffi.closures.test
- ./testsuite/emscripten/build-tests.sh testsuite/libffi.call.test
- ./testsuite/emscripten/build-tests.sh testsuite/libffi.closures.test
-
- - persist_to_workspace:
- root: .
- paths:
- - target
- - testsuite
-
- test:
- parameters:
- test-params:
- description: The tests to run.
- type: string
- <<: *defaults
- steps:
- - checkout
-
- - attach_workspace:
- at: .
-
- - run:
- name: run tests
- command: |
- git reset --hard
- cd testsuite/emscripten/
- mkdir test-results
- pytest \
- --junitxml=test-results/junit.xml \
- test_libffi.py \
- << parameters.test-params >>
- - store_test_results:
- path: testsuite/emscripten/test-results
-
- test-dejagnu:
- parameters:
- params:
- description: Parameters to node-tests
- type: string
- default: ""
-
- <<: *defaults
- steps:
- - checkout
-
- - attach_workspace:
- at: .
-
- - run:
- name: run tests
- command: |
- source ./emsdk/emsdk_env.sh
- testsuite/emscripten/node-tests.sh << parameters.params >>
-
-workflows:
- version: 2
- build-and-test:
- jobs:
- - install-emsdk
-
- - build:
- name: build
- requires:
- - install-emsdk
-
- - build:
- name: build-bigint
- wasm-bigint: "true"
- requires:
- - install-emsdk
-
- - test:
- name: test-firefox
- test-params: -k firefox
- requires:
- - build
- - test:
- name: test-chrome
- test-params: -k chrome
- requires:
- - build
-
- - test:
- name: test-firefox-bigint
- test-params: -k firefox
- requires:
- - build-bigint
-
- - test:
- name: test-chrome-bigint
- test-params: -k chrome
- requires:
- - build-bigint
-
- - test-dejagnu:
- name: test-dejagnu
- requires:
- - install-emsdk
- - test-dejagnu:
- name: test-dejagnu-bigint
- params: --wasm-bigint
- requires:
- - install-emsdk
diff --git a/Makefile.am b/Makefile.am
index 3de0bea..1f8aa9c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -55,7 +55,7 @@ noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \
src/m32r/ffitarget.h src/m68k/ffitarget.h \
src/m88k/ffitarget.h src/metag/ffitarget.h \
src/microblaze/ffitarget.h src/mips/ffitarget.h \
- src/moxie/ffitarget.h src/nios2/ffitarget.h \
+ src/moxie/ffitarget.h \
src/or1k/ffitarget.h src/pa/ffitarget.h \
src/powerpc/ffitarget.h src/powerpc/asm.h \
src/powerpc/ffi_powerpc.h src/riscv/ffitarget.h \
@@ -80,7 +80,7 @@ EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \
src/metag/ffi.c src/metag/sysv.S src/microblaze/ffi.c \
src/microblaze/sysv.S src/mips/ffi.c src/mips/o32.S \
src/mips/n32.S src/moxie/ffi.c src/moxie/eabi.S \
- src/nios2/ffi.c src/nios2/sysv.S src/or1k/ffi.c \
+ src/or1k/ffi.c \
src/or1k/sysv.S src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \
src/pa/hpux64.S src/powerpc/ffi.c src/powerpc/ffi_sysv.c \
src/powerpc/ffi_linux64.c src/powerpc/sysv.S \
diff --git a/README.md b/README.md
index 5552473..0d4c242 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
Status
======
-libffi-3.4.6 was released on February 18, 2024. Check the libffi web
+libffi-3.4.7 was released on February 8, 2025. Check the libffi web
page for updates: .
@@ -76,7 +76,6 @@ tested:
| MIPS | RTEMS | GCC |
| MIPS64 | Linux | GCC |
| Moxie | Bare metal | GCC |
-| Nios II | Linux | GCC |
| OpenRISC | Linux | GCC |
| PowerPC 32-bit | AIX | GCC |
| PowerPC 32-bit | AIX | IBM XL C |
@@ -201,6 +200,16 @@ History
See the git log for details at http://github.com/libffi/libffi.
+ 3.4.7 Feb-8-2024
+ Add static trampoline support for Linux on s390x.
+ Fix BTI support for ARM64.
+ Support pointer authentication for ARM64.
+ Fix ASAN compatibility.
+ Fix x86-64 calls with 6 GP registers and some SSE registers.
+ Miscellaneous fixes for ARC and Darwin ARM64.
+ Fix OpenRISC or1k and Solaris 10 builds.
+ Remove nios2 port.
+
3.4.6 Feb-18-2024
Fix long double regression on mips64 and alpha.
diff --git a/acinclude.m4 b/acinclude.m4
index 9ef93a8..9624bbe 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -180,6 +180,10 @@ AC_DEFUN([LIBFFI_CHECK_LINKER_FEATURES], [
if $LD --version 2>/dev/null | grep 'LLD '> /dev/null 2>&1; then
libat_ld_is_lld=yes
fi
+ libat_ld_is_mold=no
+ if $LD --version 2>/dev/null | grep 'mold '> /dev/null 2>&1; then
+ libat_ld_is_mold=yes
+ fi
changequote(,)
ldver=`$LD --version 2>/dev/null |
sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'`
@@ -336,6 +340,8 @@ if test $enable_symvers != no && test $libat_shared_libgcc = yes; then
enable_symvers=gnu
elif test $libat_ld_is_lld = yes ; then
enable_symvers=gnu
+ elif test $libat_ld_is_mold = yes ; then
+ enable_symvers=gnu
else
# The right tools, the right setup, but too old. Fallbacks?
AC_MSG_WARN(=== Linker version $libat_gnu_ld_version is too old for)
diff --git a/config.guess b/config.guess
index 7f76b62..f6d217a 100644
--- a/config.guess
+++ b/config.guess
@@ -1,10 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2022 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2022-01-09'
+timestamp='2024-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -47,7 +47,7 @@ me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
-Output the configuration name of the system \`$me' is run on.
+Output the configuration name of the system '$me' is run on.
Options:
-h, --help print this help, then exit
@@ -60,13 +60,13 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2022 Free Software Foundation, Inc.
+Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
@@ -102,8 +102,8 @@ GUESS=
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
+# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
+# use 'HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
@@ -155,6 +155,9 @@ Linux|GNU|GNU/*)
set_cc_for_build
cat <<-EOF > "$dummy.c"
+ #if defined(__ANDROID__)
+ LIBC=android
+ #else
#include
#if defined(__UCLIBC__)
LIBC=uclibc
@@ -162,6 +165,8 @@ Linux|GNU|GNU/*)
LIBC=dietlibc
#elif defined(__GLIBC__)
LIBC=gnu
+ #elif defined(__LLVM_LIBC__)
+ LIBC=llvm
#else
#include
/* First heuristic to detect musl libc. */
@@ -169,6 +174,7 @@ Linux|GNU|GNU/*)
LIBC=musl
#endif
#endif
+ #endif
EOF
cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
eval "$cc_set_libc"
@@ -459,7 +465,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
UNAME_RELEASE=`uname -v`
;;
esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
+ # Japanese Language versions have a version number like '4.1.3-JL'.
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
GUESS=sparc-sun-sunos$SUN_REL
;;
@@ -904,7 +910,7 @@ EOF
fi
;;
*:FreeBSD:*:*)
- UNAME_PROCESSOR=`/usr/bin/uname -p`
+ UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
amd64)
UNAME_PROCESSOR=x86_64 ;;
@@ -966,11 +972,37 @@ EOF
GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
;;
+ x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
+ ;;
+ *:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
+ ;;
*:Minix:*:*)
GUESS=$UNAME_MACHINE-unknown-minix
;;
aarch64:Linux:*:*)
- GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ set_cc_for_build
+ CPU=$UNAME_MACHINE
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __ARM_EABI__
+ #ifdef __ARM_PCS_VFP
+ ABI=eabihf
+ #else
+ ABI=eabi
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
+ esac
+ fi
+ GUESS=$CPU-unknown-linux-$LIBCABI
;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
@@ -1036,7 +1068,16 @@ EOF
k1om:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
- loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+ kvx:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ kvx:cos:*:*)
+ GUESS=$UNAME_MACHINE-unknown-cos
+ ;;
+ kvx:mbr:*:*)
+ GUESS=$UNAME_MACHINE-unknown-mbr
+ ;;
+ loongarch32:Linux:*:* | loongarch64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
m32r*:Linux:*:*)
@@ -1151,16 +1192,27 @@ EOF
;;
x86_64:Linux:*:*)
set_cc_for_build
+ CPU=$UNAME_MACHINE
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_X32 >/dev/null
- then
- LIBCABI=${LIBC}x32
- fi
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __i386__
+ ABI=x86
+ #else
+ #ifdef __ILP32__
+ ABI=x32
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ x86) CPU=i686 ;;
+ x32) LIBCABI=${LIBC}x32 ;;
+ esac
fi
- GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+ GUESS=$CPU-pc-linux-$LIBCABI
;;
xtensa*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
@@ -1180,7 +1232,7 @@ EOF
GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
;;
i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
+ # If we were able to find 'uname', then EMX Unix compatibility
# is probably installed.
GUESS=$UNAME_MACHINE-pc-os2-emx
;;
@@ -1321,7 +1373,7 @@ EOF
GUESS=ns32k-sni-sysv
fi
;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
# says
GUESS=i586-unisys-sysv4
;;
@@ -1367,8 +1419,11 @@ EOF
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
GUESS=i586-pc-haiku
;;
- x86_64:Haiku:*:*)
- GUESS=x86_64-unknown-haiku
+ ppc:Haiku:*:*) # Haiku running on Apple PowerPC
+ GUESS=powerpc-apple-haiku
+ ;;
+ *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
+ GUESS=$UNAME_MACHINE-unknown-haiku
;;
SX-4:SUPER-UX:*:*)
GUESS=sx4-nec-superux$UNAME_RELEASE
@@ -1540,6 +1595,9 @@ EOF
*:Unleashed:*:*)
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
+ *:Ironclad:*:*)
+ GUESS=$UNAME_MACHINE-unknown-ironclad
+ ;;
esac
# Do we have a guess based on uname results?
diff --git a/config.sub b/config.sub
index 630b5d9..2c5120f 100755
--- a/config.sub
+++ b/config.sub
@@ -1,10 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2022 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2022-01-03'
+timestamp='2024-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -76,13 +76,13 @@ Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2022 Free Software Foundation, Inc.
+Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
@@ -130,7 +130,7 @@ IFS=$saved_IFS
# Separate into logical components for further validation
case $1 in
*-*-*-*-*)
- echo Invalid configuration \`"$1"\': more than four components >&2
+ echo "Invalid configuration '$1': more than four components" >&2
exit 1
;;
*-*-*-*)
@@ -145,7 +145,8 @@ case $1 in
nto-qnx* | linux-* | uclinux-uclibc* \
| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
- | storm-chaos* | os2-emx* | rtmk-nova*)
+ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \
+ | windows-* )
basic_machine=$field1
basic_os=$maybe_os
;;
@@ -943,7 +944,7 @@ $basic_machine
EOF
IFS=$saved_IFS
;;
- # We use `pc' rather than `unknown'
+ # We use 'pc' rather than 'unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
@@ -1075,7 +1076,7 @@ case $cpu-$vendor in
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
cpu=i586
;;
- pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
cpu=i686
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
@@ -1180,7 +1181,7 @@ case $cpu-$vendor in
case $cpu in
1750a | 580 \
| a29k \
- | aarch64 | aarch64_be \
+ | aarch64 | aarch64_be | aarch64c | arm64ec \
| abacus \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
@@ -1199,50 +1200,29 @@ case $cpu-$vendor in
| d10v | d30v | dlx | dsp16xx \
| e2k | elxsi | epiphany \
| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | javascript \
| h8300 | h8500 \
| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i*86 | i860 | i960 | ia16 | ia64 \
| ip2k | iq2000 \
| k1om \
+ | kvx \
| le32 | le64 \
| lm32 \
- | loongarch32 | loongarch64 | loongarchx32 \
+ | loongarch32 | loongarch64 \
| m32c | m32r | m32rle \
| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
| m88110 | m88k | maxq | mb | mcore | mep | metag \
| microblaze | microblazeel \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64eb | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r3 | mipsisa32r3el \
- | mipsisa32r5 | mipsisa32r5el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r3 | mipsisa64r3el \
- | mipsisa64r5 | mipsisa64r5el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
+ | mips* \
| mmix \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
+ | nanomips* \
| nds32 | nds32le | nds32be \
| nfp \
| nios | nios2 | nios2eb | nios2el \
@@ -1274,6 +1254,7 @@ case $cpu-$vendor in
| ubicom32 \
| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
| vax \
+ | vc4 \
| visium \
| w65 \
| wasm32 | wasm64 \
@@ -1285,7 +1266,7 @@ case $cpu-$vendor in
;;
*)
- echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2
exit 1
;;
esac
@@ -1306,11 +1287,12 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if test x$basic_os != x
+if test x"$basic_os" != x
then
# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
# set os.
+obj=
case $basic_os in
gnu/linux*)
kernel=linux
@@ -1341,6 +1323,10 @@ EOF
kernel=linux
os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
;;
+ managarm*)
+ kernel=managarm
+ os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
+ ;;
*)
kernel=
os=$basic_os
@@ -1506,10 +1492,16 @@ case $os in
os=eabi
;;
*)
- os=elf
+ os=
+ obj=elf
;;
esac
;;
+ aout* | coff* | elf* | pe*)
+ # These are machine code file formats, not OSes
+ obj=$os
+ os=
+ ;;
*)
# No normalization, but not necessarily accepted, that comes below.
;;
@@ -1528,12 +1520,15 @@ else
# system, and we'll never get to this point.
kernel=
+obj=
case $cpu-$vendor in
score-*)
- os=elf
+ os=
+ obj=elf
;;
spu-*)
- os=elf
+ os=
+ obj=elf
;;
*-acorn)
os=riscix1.2
@@ -1543,28 +1538,35 @@ case $cpu-$vendor in
os=gnu
;;
arm*-semi)
- os=aout
+ os=
+ obj=aout
;;
c4x-* | tic4x-*)
- os=coff
+ os=
+ obj=coff
;;
c8051-*)
- os=elf
+ os=
+ obj=elf
;;
clipper-intergraph)
os=clix
;;
hexagon-*)
- os=elf
+ os=
+ obj=elf
;;
tic54x-*)
- os=coff
+ os=
+ obj=coff
;;
tic55x-*)
- os=coff
+ os=
+ obj=coff
;;
tic6x-*)
- os=coff
+ os=
+ obj=coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1586,19 +1588,24 @@ case $cpu-$vendor in
os=sunos3
;;
m68*-cisco)
- os=aout
+ os=
+ obj=aout
;;
mep-*)
- os=elf
+ os=
+ obj=elf
;;
mips*-cisco)
- os=elf
+ os=
+ obj=elf
;;
- mips*-*)
- os=elf
+ mips*-*|nanomips*-*)
+ os=
+ obj=elf
;;
or32-*)
- os=coff
+ os=
+ obj=coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=sysv3
@@ -1607,7 +1614,8 @@ case $cpu-$vendor in
os=sunos4.1.1
;;
pru-*)
- os=elf
+ os=
+ obj=elf
;;
*-be)
os=beos
@@ -1688,10 +1696,12 @@ case $cpu-$vendor in
os=uxpv
;;
*-rom68k)
- os=coff
+ os=
+ obj=coff
;;
*-*bug)
- os=coff
+ os=
+ obj=coff
;;
*-apple)
os=macos
@@ -1709,10 +1719,11 @@ esac
fi
-# Now, validate our (potentially fixed-up) OS.
+# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ).
+
case $os in
# Sometimes we do "kernel-libc", so those need to count as OSes.
- musl* | newlib* | relibc* | uclibc*)
+ llvm* | musl* | newlib* | relibc* | uclibc*)
;;
# Likewise for "kernel-abi"
eabi* | gnueabi*)
@@ -1720,6 +1731,9 @@ case $os in
# VxWorks passes extra cpu info in the 4th filed.
simlinux | simwindows | spe)
;;
+ # See `case $cpu-$os` validation below
+ ghcjs)
+ ;;
# Now accept the basic system types.
# The portable systems comes first.
# Each alternative MUST end in a * to match a version number.
@@ -1728,7 +1742,7 @@ case $os in
| hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
| sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
| hiux* | abug | nacl* | netware* | windows* \
- | os9* | macos* | osx* | ios* | watchos* | tvos* \
+ | os9* | macos* | osx* | ios* | tvos* | watchos* \
| mpw* | magic* | mmixware* | mon960* | lnews* \
| amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
| aos* | aros* | cloudabi* | sortix* | twizzler* \
@@ -1737,11 +1751,11 @@ case $os in
| mirbsd* | netbsd* | dicos* | openedition* | ose* \
| bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
| ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
- | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
- | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | bosx* | nextstep* | cxux* | oabi* \
+ | ptx* | ecoff* | winnt* | domain* | vsta* \
| udi* | lites* | ieee* | go32* | aux* | hcos* \
| chorusrdb* | cegcc* | glidix* | serenity* \
- | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | cygwin* | msys* | moss* | proelf* | rtems* \
| midipix* | mingw32* | mingw64* | mint* \
| uxpv* | beos* | mpeix* | udk* | moxiebox* \
| interix* | uwin* | mks* | rhapsody* | darwin* \
@@ -1754,51 +1768,118 @@ case $os in
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* )
+ | fiwix* | mlibc* | cos* | mbr* | ironclad* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
;;
+ # This refers to builds using the UEFI calling convention
+ # (which depends on the architecture) and PE file format.
+ # Note that this is both a different calling convention and
+ # different file format than that of GNU-EFI
+ # (x86_64-w64-mingw32).
+ uefi)
+ ;;
none)
;;
+ kernel* | msvc* )
+ # Restricted further below
+ ;;
+ '')
+ if test x"$obj" = x
+ then
+ echo "Invalid configuration '$1': Blank OS only allowed with explicit machine code file format" 1>&2
+ fi
+ ;;
+ *)
+ echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+case $obj in
+ aout* | coff* | elf* | pe*)
+ ;;
+ '')
+ # empty is fine
+ ;;
*)
- echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we handle the constraint that a (synthetic) cpu and os are
+# valid only in combination with each other and nowhere else.
+case $cpu-$os in
+ # The "javascript-unknown-ghcjs" triple is used by GHC; we
+ # accept it here in order to tolerate that, but reject any
+ # variations.
+ javascript-ghcjs)
+ ;;
+ javascript-* | *-ghcjs)
+ echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2
exit 1
;;
esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
-case $kernel-$os in
- linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
- | linux-musl* | linux-relibc* | linux-uclibc* )
+case $kernel-$os-$obj in
+ linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \
+ | linux-mlibc*- | linux-musl*- | linux-newlib*- \
+ | linux-relibc*- | linux-uclibc*- )
+ ;;
+ uclinux-uclibc*- )
+ ;;
+ managarm-mlibc*- | managarm-kernel*- )
;;
- uclinux-uclibc* )
+ windows*-msvc*-)
;;
- -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
+ -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \
+ | -uclibc*- )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
- echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
exit 1
;;
- kfreebsd*-gnu* | kopensolaris*-gnu*)
+ -kernel*- )
+ echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
+ exit 1
;;
- vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ *-kernel*- )
+ echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
+ exit 1
;;
- nto-qnx*)
+ *-msvc*- )
+ echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
+ exit 1
;;
- os2-emx)
+ kfreebsd*-gnu*- | kopensolaris*-gnu*-)
+ ;;
+ vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-)
+ ;;
+ nto-qnx*-)
+ ;;
+ os2-emx-)
;;
- ios*-simulator | tvos*-simulator | watchos*-simulator)
+ ios*-simulator* | tvos*-simulator* | watchos*-simulator*)
+ ;;
+ *-eabi*- | *-gnueabi*-)
;;
- *-eabi* | *-gnueabi*)
+ none--*)
+ # None (no kernel, i.e. freestanding / bare metal),
+ # can be paired with an machine code file format
;;
- -*)
+ -*-)
# Blank kernel with real OS is always fine.
;;
- *-*)
- echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ --*)
+ # Blank kernel and OS with real machine code file format is always fine.
+ ;;
+ *-*-*)
+ echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
exit 1
;;
esac
@@ -1881,7 +1962,7 @@ case $vendor in
;;
esac
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
diff --git a/configure.ac b/configure.ac
index 816bfd6..a1d02b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ([2.71])
-AC_INIT([libffi],[3.4.6],[http://github.com/libffi/libffi/issues])
+AC_INIT([libffi],[3.4.7],[http://github.com/libffi/libffi/issues])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_TARGET
@@ -42,7 +42,7 @@ AC_PROG_EGREP
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
-AC_CHECK_TOOL(READELF, readelf)
+AC_CHECK_TOOLS([READELF], [readelf greadelf])
# Test for 64-bit build.
AC_CHECK_SIZEOF([size_t])
@@ -171,7 +171,7 @@ case "$TARGET" in
libffi_cv_as_s390_zarch=no
echo 'void foo(void) { bar(); bar(); }' > conftest.c
if $CC $CFLAGS -S conftest.c > /dev/null 2>&1; then
- if grep -q brasl conftest.s; then
+ if $GREP -q brasl conftest.s; then
libffi_cv_as_s390_zarch=yes
fi
fi
@@ -189,17 +189,17 @@ AC_CACHE_CHECK([whether compiler supports pointer authentication],
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
#ifdef __clang__
# if __has_feature(ptrauth_calls)
-# define HAVE_PTRAUTH 1
+# define HAVE_ARM64E_PTRAUTH 1
# endif
#endif
-#ifndef HAVE_PTRAUTH
+#ifndef HAVE_ARM64E_PTRAUTH
# error Pointer authentication not supported
#endif
]])],[libffi_cv_as_ptrauth=yes],[libffi_cv_as_ptrauth=no])
])
if test "x$libffi_cv_as_ptrauth" = xyes; then
- AC_DEFINE(HAVE_PTRAUTH, 1,
+ AC_DEFINE(HAVE_ARM64E_PTRAUTH, 1,
[Define if your compiler supports pointer authentication.])
fi
@@ -277,7 +277,7 @@ if test "x$GCC" = "xyes"; then
libffi_cv_ro_eh_frame=yes
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
if $CC $CFLAGS -c -fpic -fexceptions $libffi_cv_no_lto -o conftest.o conftest.c > /dev/null 2>&1; then
- if $READELF -WS conftest.o 2>/dev/null | grep -q -n 'eh_frame .* WA'; then
+ if $READELF -WS conftest.o 2>/dev/null | $GREP -q -n 'eh_frame .* WA'; then
libffi_cv_ro_eh_frame=no
fi
fi
@@ -382,7 +382,7 @@ case "$target" in
[Define this if you want statically defined trampolines])
fi
;;
- *arm*-*-linux-* | aarch64*-*-linux-* | i*86-*-linux-* | x86_64-*-linux-* | loongarch*-*-linux-*)
+ *arm*-*-linux-* | aarch64*-*-linux-* | i*86-*-linux-* | x86_64-*-linux-* | loongarch*-*-linux-* | s390x*-linux-*)
AC_DEFINE(FFI_EXEC_STATIC_TRAMP, 1,
[Define this if you want statically defined trampolines])
;;
diff --git a/configure.host b/configure.host
index 4cc69be..c69a49c 100644
--- a/configure.host
+++ b/configure.host
@@ -185,11 +185,6 @@ case "${host}" in
TARGET=MIPS; TARGETDIR=mips
;;
- nios2*-linux*)
- TARGET=NIOS2; TARGETDIR=nios2
- SOURCES="ffi.c sysv.S"
- ;;
-
or1k*-*-*)
TARGET=OR1K; TARGETDIR=or1k
SOURCES="ffi.c sysv.S"
diff --git a/debian/changelog b/debian/changelog
index 90ff65e..f4bf154 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,18 @@
+libffi (3.4.7-1) unstable; urgency=medium
+
+ * New upstream version.
+ - Add static trampoline support for Linux on s390x.
+ - Fix BTI support for ARM64.
+ - Support pointer authentication for ARM64.
+ - Fix ASAN compatibility.
+ - Fix x86-64 calls with 6 GP registers and some SSE registers.
+ - Miscellaneous fixes for ARC and Darwin ARM64.
+ - Fix OpenRISC or1k and Solaris 10 builds.
+ - Remove nios2 port.
+ * Bump standards version.
+
+ -- Matthias Klose Wed, 12 Feb 2025 14:05:41 +0100
+
libffi (3.4.6-1) unstable; urgency=medium
* New upstream version.
diff --git a/debian/control b/debian/control
index 7f6aa7f..f1b6954 100644
--- a/debian/control
+++ b/debian/control
@@ -6,7 +6,7 @@ Build-Depends: debhelper (>= 11),
libltdl-dev,
dejagnu,
texinfo
-Standards-Version: 4.6.2
+Standards-Version: 4.7.0
Section: libs
Homepage: https://sourceware.org/libffi/
diff --git a/debian/copyright b/debian/copyright
index 16e989f..d7ec037 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -9,8 +9,8 @@ Upstream-Contact:
Files: *
Copyright:
- Copyright (c) 1996-2024 Red Hat, Inc.
- Copyright (C) 1996-2024 Anthony Green
+ Copyright (c) 1996-2025 Red Hat, Inc.
+ Copyright (C) 1996-2025 Anthony Green
Copyright (C) 1996-2010 Free Software Foundation, Inc
Copyright (c) 2003, 2004, 2006, 2007, 2008 Kaz Kojima
Copyright (c) 2010, 2011, Plausible Labs Cooperative , Inc.
@@ -168,7 +168,7 @@ Copyright: (C) 2003-2004, 2006, 2009-2017 Free Software Foundation, Inc.
License: GPL-2+
Files: debian/*
-Copyright: (C) 2008, 2011 Matthias Klose
+Copyright: (C) 2008-2025 Matthias Klose
License: GPL
The Debian packaging is licensed under the GPL,
see `/usr/share/common-licenses/GPL'.
diff --git a/doc/libffi.texi b/doc/libffi.texi
index d072a21..e82f944 100644
--- a/doc/libffi.texi
+++ b/doc/libffi.texi
@@ -627,7 +627,7 @@ Here is the corresponding code to describe this struct to
tm_type.size = tm_type.alignment = 0;
tm_type.type = FFI_TYPE_STRUCT;
- tm_type.elements = &tm_type_elements;
+ tm_type.elements = tm_type_elements;
for (i = 0; i < 9; i++)
tm_type_elements[i] = &ffi_type_sint;
diff --git a/doc/version.texi b/doc/version.texi
index 88b26f9..73e9e6f 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -1,4 +1,4 @@
-@set UPDATED 15 February 2024
-@set UPDATED-MONTH February 2024
-@set EDITION 3.4.6
-@set VERSION 3.4.6
+@set UPDATED 1 June 2024
+@set UPDATED-MONTH June 2024
+@set EDITION 3.4.7
+@set VERSION 3.4.7
diff --git a/include/ffi_cfi.h b/include/ffi_cfi.h
index f4c292d..8565663 100644
--- a/include/ffi_cfi.h
+++ b/include/ffi_cfi.h
@@ -49,6 +49,7 @@
# 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__
+# define cfi_window_save .cfi_window_save
#else
@@ -71,6 +72,7 @@
# define cfi_personality(enc, exp)
# define cfi_lsda(enc, exp)
# define cfi_escape(...)
+# define cfi_window_save
#endif /* HAVE_AS_CFI_PSEUDO_OP */
#endif /* FFI_CFI_H */
diff --git a/include/ffi_common.h b/include/ffi_common.h
index a9839b3..e4ed228 100644
--- a/include/ffi_common.h
+++ b/include/ffi_common.h
@@ -83,6 +83,23 @@ char *alloca ();
#include
#endif
+#ifndef __SANITIZE_ADDRESS__
+# ifdef __clang__
+# if __has_feature(address_sanitizer)
+# define FFI_ASAN
+# endif
+# endif
+#endif
+#ifdef __SANITIZE_ADDRESS__
+#define FFI_ASAN
+#endif
+
+#ifdef FFI_ASAN
+#define FFI_ASAN_NO_SANITIZE __attribute__((no_sanitize_address))
+#else
+#define FFI_ASAN_NO_SANITIZE
+#endif
+
#ifdef FFI_DEBUG
NORETURN void ffi_assert(const char *expr, const char *file, int line);
void ffi_stop_here(void);
diff --git a/src/aarch64/ffi.c b/src/aarch64/ffi.c
index 8661a35..94c643b 100644
--- a/src/aarch64/ffi.c
+++ b/src/aarch64/ffi.c
@@ -63,7 +63,7 @@ struct call_context
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
-#ifdef HAVE_PTRAUTH
+#ifdef HAVE_ARM64E_PTRAUTH
#include
#endif
#include
@@ -645,7 +645,10 @@ extern void ffi_call_SYSV (struct call_context *context, void *frame,
void *closure) FFI_HIDDEN;
/* Call a function with the provided arguments and capture the return
- value. */
+ value.
+ n.b. ffi_call_SYSV will steal the alloca'd `stack` variable here for use
+ _as its own stack_ - so we need to compile this function without ASAN */
+FFI_ASAN_NO_SANITIZE
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
void **avalue, void *closure)
@@ -682,7 +685,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
else if (flags & AARCH64_RET_NEED_COPY)
rsize = 16;
- /* Allocate consectutive stack for everything we'll need.
+ /* Allocate consecutive stack for everything we'll need.
The frame uses 40 bytes for: lr, fp, rvalue, flags, sp */
context = alloca (sizeof(struct call_context) + stack_bytes + 40 + rsize);
stack = context + 1;
@@ -877,7 +880,7 @@ ffi_prep_closure_loc (ffi_closure *closure,
#if FFI_EXEC_TRAMPOLINE_TABLE
# ifdef __MACH__
-# ifdef HAVE_PTRAUTH
+# ifdef HAVE_ARM64E_PTRAUTH
codeloc = ptrauth_auth_data(codeloc, ptrauth_key_function_pointer, 0);
# endif
void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
diff --git a/src/aarch64/ffitarget.h b/src/aarch64/ffitarget.h
index d5622e1..2ab9564 100644
--- a/src/aarch64/ffitarget.h
+++ b/src/aarch64/ffitarget.h
@@ -83,8 +83,8 @@ typedef enum ffi_abi
#if defined (__APPLE__)
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
-#elif !defined(_WIN32)
-/* iOS and Windows reserve x18 for the system. Disable Go closures until
+#elif !defined(_WIN32) && !defined(__ANDROID__)
+/* iOS, Windows and Android reserve x18 for the system. Disable Go closures until
a new static chain is chosen. */
#define FFI_GO_CLOSURES 1
#endif
diff --git a/src/aarch64/internal.h b/src/aarch64/internal.h
index b5d102b..50fa5c1 100644
--- a/src/aarch64/internal.h
+++ b/src/aarch64/internal.h
@@ -81,20 +81,64 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/* Helpers for writing assembly compatible with arm ptr auth */
#ifdef LIBFFI_ASM
-#ifdef HAVE_PTRAUTH
-#define SIGN_LR pacibsp
-#define SIGN_LR_WITH_REG(x) pacib lr, x
-#define AUTH_LR_AND_RET retab
-#define AUTH_LR_WITH_REG(x) autib lr, x
-#define BRANCH_AND_LINK_TO_REG blraaz
-#define BRANCH_TO_REG braaz
-#else
-#define SIGN_LR
-#define SIGN_LR_WITH_REG(x)
-#define AUTH_LR_AND_RET ret
-#define AUTH_LR_WITH_REG(x)
-#define BRANCH_AND_LINK_TO_REG blr
-#define BRANCH_TO_REG br
-#endif
-
-#endif
+ #if defined(HAVE_ARM64E_PTRAUTH)
+ /* ARM64E ABI For Darwin */
+ #define SIGN_LR pacibsp
+ #define SIGN_LR_WITH_REG(x) pacib lr, x
+ #define AUTH_LR_AND_RET retab
+ #define AUTH_LR_WITH_REG(x) autib lr, x
+ #define BRANCH_AND_LINK_TO_REG blraaz
+ #define SIGN_LR_LINUX_ONLY
+ #define BRANCH_TO_REG braaz
+ #define PAC_CFI_WINDOW_SAVE
+ /* Linux PAC Support */
+ #elif defined(__ARM_FEATURE_PAC_DEFAULT)
+ #define GNU_PROPERTY_AARCH64_POINTER_AUTH (1 << 1)
+ #define PAC_CFI_WINDOW_SAVE cfi_window_save
+ #define TMP_REG x9
+ #define BRANCH_TO_REG br
+ #define BRANCH_AND_LINK_TO_REG blr
+ #define SIGN_LR_LINUX_ONLY SIGN_LR
+ /* Which key to sign with? */
+ #if (__ARM_FEATURE_PAC_DEFAULT & 1) == 1
+ /* Signed with A-key */
+ #define SIGN_LR hint #25 /* paciasp */
+ #define AUTH_LR hint #29 /* autiasp */
+ #else
+ /* Signed with B-key */
+ #define SIGN_LR hint #27 /* pacibsp */
+ #define AUTH_LR hint #31 /* autibsp */
+ #endif /* __ARM_FEATURE_PAC_DEFAULT */
+ #define AUTH_LR_WITH_REG(x) _auth_lr_with_reg x
+.macro _auth_lr_with_reg modifier
+ mov TMP_REG, sp
+ mov sp, \modifier
+ AUTH_LR
+ mov sp, TMP_REG
+.endm
+ #define SIGN_LR_WITH_REG(x) _sign_lr_with_reg x
+.macro _sign_lr_with_reg modifier
+ mov TMP_REG, sp
+ mov sp, \modifier
+ SIGN_LR
+ mov sp, TMP_REG
+.endm
+ #define AUTH_LR_AND_RET _auth_lr_and_ret modifier
+.macro _auth_lr_and_ret modifier
+ AUTH_LR
+ ret
+.endm
+ #undef TMP_REG
+
+ /* No Pointer Auth */
+ #else
+ #define SIGN_LR
+ #define SIGN_LR_WITH_REG(x)
+ #define AUTH_LR_AND_RET ret
+ #define AUTH_LR_WITH_REG(x)
+ #define BRANCH_AND_LINK_TO_REG blr
+ #define SIGN_LR_LINUX_ONLY
+ #define BRANCH_TO_REG br
+ #define PAC_CFI_WINDOW_SAVE
+ #endif /* HAVE_ARM64E_PTRAUTH */
+#endif /* LIBFFI_ASM */
diff --git a/src/aarch64/sysv.S b/src/aarch64/sysv.S
index fdd0e8b..e83bc65 100644
--- a/src/aarch64/sysv.S
+++ b/src/aarch64/sysv.S
@@ -68,7 +68,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define BTI_J hint #36
/*
* The ELF Notes section needs to indicate if BTI is supported, as the first ELF loaded that doesn't
- * declare this support disables it for the whole process.
+ * declare this support disables it for memory region containing the loaded library.
*/
# define GNU_PROPERTY_AARCH64_BTI (1 << 0) /* Has Branch Target Identification */
.text
@@ -89,30 +89,30 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
x5 closure
*/
- cfi_startproc
CNAME(ffi_call_SYSV):
+ cfi_startproc
BTI_C
- /* Sign the lr with x1 since that is where it will be stored */
+ PAC_CFI_WINDOW_SAVE
+ /* Sign the lr with x1 since that is the CFA which is the modifer used in auth instructions */
SIGN_LR_WITH_REG(x1)
- /* Use a stack frame allocated by our caller. */
-#if defined(HAVE_PTRAUTH) && defined(__APPLE__)
+#if defined(HAVE_ARM64E_PTRAUTH) && defined(__APPLE__)
/* darwin's libunwind assumes that the cfa is the sp and that's the data
* used to sign the lr. In order to allow unwinding through this
* function it is necessary to point the cfa at the signing register.
*/
cfi_def_cfa(x1, 0);
-#else
- cfi_def_cfa(x1, 40);
#endif
+ /* Use a stack frame allocated by our caller. */
stp x29, x30, [x1]
+ cfi_def_cfa_register(x1)
+ cfi_rel_offset (x29, 0)
+ cfi_rel_offset (x30, 8)
mov x9, sp
str x9, [x1, #32]
mov x29, x1
- mov sp, x0
cfi_def_cfa_register(x29)
- cfi_rel_offset (x29, 0)
- cfi_rel_offset (x30, 8)
+ mov sp, x0
mov x9, x2 /* save fn */
mov x8, x3 /* install structure return */
@@ -326,6 +326,7 @@ CNAME(ffi_closure_SYSV_V):
cfi_startproc
BTI_C
SIGN_LR
+ PAC_CFI_WINDOW_SAVE
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
@@ -347,10 +348,11 @@ CNAME(ffi_closure_SYSV_V):
#endif
.align 4
- cfi_startproc
CNAME(ffi_closure_SYSV):
+ cfi_startproc
BTI_C
SIGN_LR
+ PAC_CFI_WINDOW_SAVE
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
@@ -527,6 +529,7 @@ L(do_closure):
#if defined(FFI_EXEC_STATIC_TRAMP)
.align 4
CNAME(ffi_closure_SYSV_V_alt):
+ BTI_C
/* See the comments above trampoline_code_table. */
ldr x17, [sp, #8] /* Load closure in x17 */
add sp, sp, #16 /* Restore the stack */
@@ -541,6 +544,7 @@ CNAME(ffi_closure_SYSV_V_alt):
.align 4
CNAME(ffi_closure_SYSV_alt):
+ BTI_C
/* See the comments above trampoline_code_table. */
ldr x17, [sp, #8] /* Load closure in x17 */
add sp, sp, #16 /* Restore the stack */
@@ -643,9 +647,11 @@ CNAME(ffi_go_closure_SYSV_V):
#endif
.align 4
- cfi_startproc
CNAME(ffi_go_closure_SYSV):
+ cfi_startproc
BTI_C
+ SIGN_LR_LINUX_ONLY
+ PAC_CFI_WINDOW_SAVE
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
cfi_rel_offset (x29, 0)
diff --git a/src/arc/arcompact.S b/src/arc/arcompact.S
index 1d7f1a1..e749341 100644
--- a/src/arc/arcompact.S
+++ b/src/arc/arcompact.S
@@ -39,14 +39,14 @@
#define LARG ldl
#define SARG stl
#define ADDPTR addl
-#define MOVPTR movl_s
+#define MOVPTR movl
#else
#define PTRS 4
#define FLTS 4
#define LARG ld
#define SARG st
#define ADDPTR add
-#define MOVPTR mov_s
+#define MOVPTR mov
#endif
#define FRAME_LEN (8 * PTRS + 16)
diff --git a/src/arc/ffi.c b/src/arc/ffi.c
index d729274..0632319 100644
--- a/src/arc/ffi.c
+++ b/src/arc/ffi.c
@@ -192,9 +192,10 @@ static void unmarshal_atom(call_builder *cb, int type, void *data) {
/* for arguments passed by reference returns the pointer, otherwise the arg is copied (up to MAXCOPYARG bytes) */
static void *unmarshal(call_builder *cb, ffi_type *type, int var, void *data) {
size_t realign[2];
- void *pointer;
#if defined(__ARC64_ARCH64__)
+ void *pointer;
+
if (type->size > 2 * __SIZEOF_POINTER__) {
/* pass by reference */
unmarshal_atom(cb, FFI_TYPE_POINTER, (char*)&pointer);
@@ -348,7 +349,10 @@ ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
void *user_data, void *codeloc)
{
uint32_t *tramp = (uint32_t *) & (closure->tramp[0]);
+
+#if defined(__ARC64_ARCH64__)
size_t address_ffi_closure = (size_t) ffi_closure_asm;
+#endif
switch (cif->abi)
{
@@ -367,7 +371,7 @@ ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
FFI_ASSERT (tramp == codeloc);
tramp[0] = CODE_ENDIAN (0x200a1fc0); /* mov r8, pcl */
tramp[1] = CODE_ENDIAN (0x20200f80); /* j [long imm] */
- tramp[2] = CODE_ENDIAN (ffi_closure_asm);
+ tramp[2] = CODE_ENDIAN ((uint32_t) ffi_closure_asm);
break;
#endif
diff --git a/src/closures.c b/src/closures.c
index 67a94a8..02cf78f 100644
--- a/src/closures.c
+++ b/src/closures.c
@@ -164,7 +164,7 @@ ffi_tramp_is_present (__attribute__((unused)) void *ptr)
#include
#include
-#ifdef HAVE_PTRAUTH
+#ifdef HAVE_ARM64E_PTRAUTH
#include
#endif
#include
@@ -223,7 +223,7 @@ ffi_trampoline_table_alloc (void)
/* Remap the trampoline table on top of the placeholder page */
trampoline_page = config_page + PAGE_MAX_SIZE;
-#ifdef HAVE_PTRAUTH
+#ifdef HAVE_ARM64E_PTRAUTH
trampoline_page_template = (vm_address_t)(uintptr_t)ptrauth_auth_data((void *)&ffi_closure_trampoline_table_page, ptrauth_key_function_pointer, 0);
#else
trampoline_page_template = (vm_address_t)&ffi_closure_trampoline_table_page;
@@ -268,7 +268,7 @@ ffi_trampoline_table_alloc (void)
ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
entry->trampoline =
(void *) (trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
-#ifdef HAVE_PTRAUTH
+#ifdef HAVE_ARM64E_PTRAUTH
entry->trampoline = ptrauth_sign_unauthenticated(entry->trampoline, ptrauth_key_function_pointer, 0);
#endif
diff --git a/src/dlmalloc.c b/src/dlmalloc.c
index c61ef92..17193a0 100644
--- a/src/dlmalloc.c
+++ b/src/dlmalloc.c
@@ -3388,6 +3388,7 @@ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
mchunkptr tnext = chunk_plus_offset(sp, ssize);
mchunkptr p = tnext;
int nfences = 0;
+ (void)nfences; // Suppress unused variable warning
/* reset top to new space */
init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
diff --git a/src/mips/n32.S b/src/mips/n32.S
index df58e80..08cbb95 100644
--- a/src/mips/n32.S
+++ b/src/mips/n32.S
@@ -821,3 +821,7 @@ cls_epilogue:
#endif /* __GNUC__ */
#endif
+
+#if defined __ELF__ && defined __linux__
+ .section .note.GNU-stack,"",%progbits
+#endif
diff --git a/src/mips/o32.S b/src/mips/o32.S
index 78517be..03ceed5 100644
--- a/src/mips/o32.S
+++ b/src/mips/o32.S
@@ -559,3 +559,7 @@ $LASFDE2:
$LEFDE2:
#endif
+
+#if defined __ELF__ && defined __linux__
+ .section .note.GNU-stack,"",%progbits
+#endif
diff --git a/src/nios2/ffi.c b/src/nios2/ffi.c
deleted file mode 100644
index 721080d..0000000
--- a/src/nios2/ffi.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* libffi support for Altera Nios II.
-
- Copyright (c) 2013 Mentor Graphics.
-
- 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
-#include
-
-#include
-
-/* The Nios II Processor Reference Handbook defines the procedure call
- ABI as follows.
-
- Arguments are passed as if a structure containing the types of
- the arguments were constructed. The first 16 bytes are passed in r4
- through r7, the remainder on the stack. The first 16 bytes of a function
- taking variable arguments are passed in r4-r7 in the same way.
-
- Return values of types up to 8 bytes are returned in r2 and r3. For
- return values greater than 8 bytes, the caller must allocate memory for
- the result and pass the address as if it were argument 0.
-
- While this isn't specified explicitly in the ABI documentation, GCC
- promotes integral arguments smaller than int size to 32 bits.
-
- Also of note, the ABI specifies that all structure objects are
- aligned to 32 bits even if all their fields have a smaller natural
- alignment. See FFI_AGGREGATE_ALIGNMENT. */
-
-
-/* Declare the assembly language hooks. */
-
-extern UINT64 ffi_call_sysv (void (*) (char *, extended_cif *),
- extended_cif *,
- unsigned,
- void (*fn) (void));
-extern void ffi_closure_sysv (void);
-
-/* Perform machine-dependent cif processing. */
-
-ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
-{
- /* We always want at least 16 bytes in the parameter block since it
- simplifies the low-level call function. Also round the parameter
- block size up to a multiple of 4 bytes to preserve
- 32-bit alignment of the stack pointer. */
- if (cif->bytes < 16)
- cif->bytes = 16;
- else
- cif->bytes = (cif->bytes + 3) & ~3;
-
- return FFI_OK;
-}
-
-
-/* ffi_prep_args is called by the assembly routine to transfer arguments
- to the stack using the pointers in the ecif array.
- Note that the stack buffer is big enough to fit all the arguments,
- but the first 16 bytes will be copied to registers for the actual
- call. */
-
-void ffi_prep_args (char *stack, extended_cif *ecif)
-{
- char *argp = stack;
- unsigned int i;
-
- /* The implicit return value pointer is passed as if it were a hidden
- first argument. */
- if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
- && ecif->cif->rtype->size > 8)
- {
- (*(void **) argp) = ecif->rvalue;
- argp += 4;
- }
-
- for (i = 0; i < ecif->cif->nargs; i++)
- {
- void *avalue = ecif->avalue[i];
- ffi_type *atype = ecif->cif->arg_types[i];
- size_t size = atype->size;
- size_t alignment = atype->alignment;
-
- /* Align argp as appropriate for the argument type. */
- if ((alignment - 1) & (unsigned) argp)
- argp = (char *) FFI_ALIGN (argp, alignment);
-
- /* Copy the argument, promoting integral types smaller than a
- word to word size. */
- if (size < sizeof (int))
- {
- size = sizeof (int);
- switch (atype->type)
- {
- case FFI_TYPE_SINT8:
- *(signed int *) argp = (signed int) *(SINT8 *) avalue;
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned int *) argp = (unsigned int) *(UINT8 *) avalue;
- break;
-
- case FFI_TYPE_SINT16:
- *(signed int *) argp = (signed int) *(SINT16 *) avalue;
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned int *) argp = (unsigned int) *(UINT16 *) avalue;
- break;
-
- case FFI_TYPE_STRUCT:
- memcpy (argp, avalue, atype->size);
- break;
-
- default:
- FFI_ASSERT(0);
- }
- }
- else if (size == sizeof (int))
- *(unsigned int *) argp = (unsigned int) *(UINT32 *) avalue;
- else
- memcpy (argp, avalue, size);
- argp += size;
- }
-}
-
-
-/* Call FN using the prepared CIF. RVALUE points to space allocated by
- the caller for the return value, and AVALUE is an array of argument
- pointers. */
-
-void ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
-{
-
- extended_cif ecif;
- UINT64 result;
-
- /* If bigret is true, this is the case where a return value of larger
- than 8 bytes is handled by being passed by reference as an implicit
- argument. */
- int bigret = (cif->rtype->type == FFI_TYPE_STRUCT
- && cif->rtype->size > 8);
-
- ecif.cif = cif;
- ecif.avalue = avalue;
-
- /* Allocate space for return value if this is the pass-by-reference case
- and the caller did not provide a buffer. */
- if (rvalue == NULL && bigret)
- ecif.rvalue = alloca (cif->rtype->size);
- else
- ecif.rvalue = rvalue;
-
- result = ffi_call_sysv (ffi_prep_args, &ecif, cif->bytes, fn);
-
- /* Now result contains the 64 bit contents returned from fn in
- r2 and r3. Copy the value of the appropriate size to the user-provided
- rvalue buffer. */
- if (rvalue && !bigret)
- switch (cif->rtype->size)
- {
- case 1:
- *(UINT8 *)rvalue = (UINT8) result;
- break;
- case 2:
- *(UINT16 *)rvalue = (UINT16) result;
- break;
- case 4:
- *(UINT32 *)rvalue = (UINT32) result;
- break;
- case 8:
- *(UINT64 *)rvalue = (UINT64) result;
- break;
- default:
- memcpy (rvalue, (void *)&result, cif->rtype->size);
- break;
- }
-}
-
-/* This function is invoked from the closure trampoline to invoke
- CLOSURE with argument block ARGS. Parse ARGS according to
- CLOSURE->cfi and invoke CLOSURE->fun. */
-
-static UINT64
-ffi_closure_helper (unsigned char *args,
- ffi_closure *closure)
-{
- ffi_cif *cif = closure->cif;
- unsigned char *argp = args;
- void **parsed_args = alloca (cif->nargs * sizeof (void *));
- UINT64 result;
- void *retptr;
- unsigned int i;
-
- /* First figure out what to do about the return type. If this is the
- big-structure-return case, the first arg is the hidden return buffer
- allocated by the caller. */
- if (cif->rtype->type == FFI_TYPE_STRUCT
- && cif->rtype->size > 8)
- {
- retptr = *((void **) argp);
- argp += 4;
- }
- else
- retptr = (void *) &result;
-
- /* Fill in the array of argument pointers. */
- for (i = 0; i < cif->nargs; i++)
- {
- size_t size = cif->arg_types[i]->size;
- size_t alignment = cif->arg_types[i]->alignment;
-
- /* Align argp as appropriate for the argument type. */
- if ((alignment - 1) & (unsigned) argp)
- argp = (char *) FFI_ALIGN (argp, alignment);
-
- /* Arguments smaller than an int are promoted to int. */
- if (size < sizeof (int))
- size = sizeof (int);
-
- /* Store the pointer. */
- parsed_args[i] = argp;
- argp += size;
- }
-
- /* Call the user-supplied function. */
- (closure->fun) (cif, retptr, parsed_args, closure->user_data);
- return result;
-}
-
-
-/* Initialize CLOSURE with a trampoline to call FUN with
- CIF and USER_DATA. */
-ffi_status
-ffi_prep_closure_loc (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun) (ffi_cif*, void*, void**, void*),
- void *user_data,
- void *codeloc)
-{
- unsigned int *tramp = (unsigned int *) &closure->tramp[0];
- int i;
-
- if (cif->abi != FFI_SYSV)
- return FFI_BAD_ABI;
-
- /* The trampoline looks like:
- movhi r8, %hi(ffi_closure_sysv)
- ori r8, r8, %lo(ffi_closure_sysv)
- movhi r9, %hi(ffi_closure_helper)
- ori r0, r9, %lo(ffi_closure_helper)
- movhi r10, %hi(closure)
- ori r10, r10, %lo(closure)
- jmp r8
- and then ffi_closure_sysv retrieves the closure pointer out of r10
- in addition to the arguments passed in the normal way for the call,
- and invokes ffi_closure_helper. We encode the pointer to
- ffi_closure_helper in the trampoline because making a PIC call
- to it in ffi_closure_sysv would be messy (it would have to indirect
- through the GOT). */
-
-#define HI(x) ((((unsigned int) (x)) >> 16) & 0xffff)
-#define LO(x) (((unsigned int) (x)) & 0xffff)
- tramp[0] = (0 << 27) | (8 << 22) | (HI (ffi_closure_sysv) << 6) | 0x34;
- tramp[1] = (8 << 27) | (8 << 22) | (LO (ffi_closure_sysv) << 6) | 0x14;
- tramp[2] = (0 << 27) | (9 << 22) | (HI (ffi_closure_helper) << 6) | 0x34;
- tramp[3] = (9 << 27) | (9 << 22) | (LO (ffi_closure_helper) << 6) | 0x14;
- tramp[4] = (0 << 27) | (10 << 22) | (HI (closure) << 6) | 0x34;
- tramp[5] = (10 << 27) | (10 << 22) | (LO (closure) << 6) | 0x14;
- tramp[6] = (8 << 27) | (0x0d << 11) | 0x3a;
-#undef HI
-#undef LO
-
- /* Flush the caches.
- See Example 9-4 in the Nios II Software Developer's Handbook. */
- for (i = 0; i < 7; i++)
- asm volatile ("flushd 0(%0); flushi %0" :: "r"(tramp + i) : "memory");
- asm volatile ("flushp" ::: "memory");
-
- closure->cif = cif;
- closure->fun = fun;
- closure->user_data = user_data;
-
- return FFI_OK;
-}
-
diff --git a/src/nios2/ffitarget.h b/src/nios2/ffitarget.h
deleted file mode 100644
index 134d118..0000000
--- a/src/nios2/ffitarget.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* libffi target includes for Altera Nios II.
-
- Copyright (c) 2013 Mentor Graphics.
-
- 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_LAST_ABI,
- FFI_DEFAULT_ABI = FFI_SYSV
-} ffi_abi;
-#endif
-
-/* Structures have a 4-byte alignment even if all the fields have lesser
- alignment requirements. */
-#define FFI_AGGREGATE_ALIGNMENT 4
-
-#define FFI_CLOSURES 1
-#define FFI_TRAMPOLINE_SIZE 28 /* 7 instructions */
-#define FFI_NATIVE_RAW_API 0
-
-#endif
diff --git a/src/nios2/sysv.S b/src/nios2/sysv.S
deleted file mode 100644
index 75f442b..0000000
--- a/src/nios2/sysv.S
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Low-level libffi support for Altera Nios II.
-
- Copyright (c) 2013 Mentor Graphics.
-
- 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 function is declared on the C side as
-
- extern UINT64 ffi_call_sysv (void (*arghook) (char *, extended_cif *),
- extended_cif *ecif,
- unsigned nbytes,
- void (*fn) (void));
-
- On input, the arguments appear as
- r4 = arghook
- r5 = ecif
- r6 = nbytes
- r7 = fn
-*/
-
- .section .text
- .align 2
- .global ffi_call_sysv
- .type ffi_call_sysv, @function
-
-ffi_call_sysv:
- .cfi_startproc
-
- /* Create the stack frame, saving r16 so we can use it locally. */
- addi sp, sp, -12
- .cfi_def_cfa_offset 12
- stw ra, 8(sp)
- stw fp, 4(sp)
- stw r16, 0(sp)
- .cfi_offset 31, -4
- .cfi_offset 28, -8
- .cfi_offset 16, -12
- mov fp, sp
- .cfi_def_cfa_register 28
- mov r16, r7
-
- /* Adjust the stack pointer to create the argument buffer
- nbytes long. */
- sub sp, sp, r6
-
- /* Call the arghook function. */
- mov r2, r4 /* fn */
- mov r4, sp /* argbuffer */
- callr r2 /* r5 already contains ecif */
-
- /* Pop off the first 16 bytes of the argument buffer on the stack,
- transferring the contents to the argument registers. */
- ldw r4, 0(sp)
- ldw r5, 4(sp)
- ldw r6, 8(sp)
- ldw r7, 12(sp)
- addi sp, sp, 16
-
- /* Call the user function, which leaves its result in r2 and r3. */
- callr r16
-
- /* Pop off the stack frame. */
- mov sp, fp
- ldw ra, 8(sp)
- ldw fp, 4(sp)
- ldw r16, 0(sp)
- addi sp, sp, 12
- ret
- .cfi_endproc
- .size ffi_call_sysv, .-ffi_call_sysv
-
-
-/* Closure trampolines jump here after putting the C helper address
- in r9 and the closure pointer in r10. The user-supplied arguments
- to the closure are in the normal places, in r4-r7 and on the
- stack. Push the register arguments on the stack too and then call the
- C helper function to deal with them. */
-
- .section .text
- .align 2
- .global ffi_closure_sysv
- .type ffi_closure_sysv, @function
-
-ffi_closure_sysv:
- .cfi_startproc
-
- /* Create the stack frame, pushing the register args on the stack
- just below the stack args. This is the same trick illustrated
- in Figure 7-3 in the Nios II Processor Reference Handbook, used
- for variable arguments and structures passed by value. */
- addi sp, sp, -20
- .cfi_def_cfa_offset 20
- stw ra, 0(sp)
- .cfi_offset 31, -20
- stw r4, 4(sp)
- .cfi_offset 4, -16
- stw r5, 8(sp)
- .cfi_offset 5, -12
- stw r6, 12(sp)
- .cfi_offset 6, -8
- stw r7, 16(sp)
- .cfi_offset 7, -4
-
- /* Call the helper.
- r4 = pointer to arguments on stack
- r5 = closure pointer (loaded in r10 by the trampoline)
- r9 = address of helper function (loaded by trampoline) */
- addi r4, sp, 4
- mov r5, r10
- callr r9
-
- /* Pop the stack and return. */
- ldw ra, 0(sp)
- addi sp, sp, 20
- .cfi_def_cfa_offset -20
- ret
- .cfi_endproc
- .size ffi_closure_sysv, .-ffi_closure_sysv
-
diff --git a/src/or1k/ffi.c b/src/or1k/ffi.c
index 9451d4e..7a6d28c 100644
--- a/src/or1k/ffi.c
+++ b/src/or1k/ffi.c
@@ -110,7 +110,7 @@ void* ffi_prep_args(char *stack, extended_cif *ecif)
extern void ffi_call_SYSV(unsigned,
extended_cif *,
- void *(*)(int *, extended_cif *),
+ void *(*)(char *, extended_cif *),
unsigned *,
void (*fn)(void),
unsigned);
@@ -180,7 +180,7 @@ void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5,
register int *r13 __asm__ ("r13");
ffi_closure* closure = (ffi_closure*) r13;
- char *stack_args = sp;
+ char *stack_args = (char*) sp;
/* Lay the register arguments down in a continuous chunk of memory. */
unsigned register_args[6] =
diff --git a/src/prep_cif.c b/src/prep_cif.c
index 0e2d58e..47c9259 100644
--- a/src/prep_cif.c
+++ b/src/prep_cif.c
@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
- prep_cif.c - Copyright (c) 2011, 2012, 2021 Anthony Green
+ prep_cif.c - Copyright (c) 2011, 2012, 2021, 2025 Anthony Green
Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Copyright (c) 2022 Oracle and/or its affiliates.
@@ -158,9 +158,6 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
#endif
#ifdef XTENSA
&& (cif->rtype->size > 16)
-#endif
-#ifdef NIOS2
- && (cif->rtype->size > 8)
#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
diff --git a/src/s390/ffi.c b/src/s390/ffi.c
index 4035b6e..b197cd5 100644
--- a/src/s390/ffi.c
+++ b/src/s390/ffi.c
@@ -32,6 +32,7 @@
#include
#include
#include "internal.h"
+#include
/*====================== End of Includes =============================*/
@@ -720,16 +721,30 @@ ffi_prep_closure_loc (ffi_closure *closure,
#endif
0x07f1 /* br %r1 */
};
-
+ void (*dest)(void);
unsigned long *tramp = (unsigned long *)&closure->tramp;
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
+
+#if defined(FFI_EXEC_STATIC_TRAMP)
+ if (ffi_tramp_is_present(closure))
+ {
+ /* Initialize the static trampoline's parameters. */
+ dest = ffi_closure_SYSV;
+ ffi_tramp_set_parms (closure->ftramp, dest, closure);
+ goto out;
+ }
+#endif
+
memcpy (tramp, template, sizeof(template));
tramp[2] = (unsigned long)codeloc;
tramp[3] = (unsigned long)&ffi_closure_SYSV;
+#if defined(FFI_EXEC_STATIC_TRAMP)
+out:
+#endif
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
@@ -754,3 +769,15 @@ ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
return FFI_OK;
}
+
+#if defined(FFI_EXEC_STATIC_TRAMP)
+void *
+ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
+{
+ extern void *trampoline_code_table;
+
+ *tramp_size = FFI390_TRAMP_SIZE;
+ *map_size = FFI390_TRAMP_MAP_SIZE;
+ return &trampoline_code_table;
+}
+#endif
\ No newline at end of file
diff --git a/src/s390/internal.h b/src/s390/internal.h
index b875578..eba8e86 100644
--- a/src/s390/internal.h
+++ b/src/s390/internal.h
@@ -9,3 +9,14 @@
#define FFI390_RET_IN_MEM 8
#define FFI390_RET_STRUCT (FFI390_RET_VOID | FFI390_RET_IN_MEM)
+
+
+#if defined(FFI_EXEC_STATIC_TRAMP)
+/*
+ * For the trampoline code table mapping, a mapping size of 4K is chosen.
+ */
+#define FFI390_TRAMP_MAP_SHIFT 12
+#define FFI390_TRAMP_MAP_SIZE (1 << FFI390_TRAMP_MAP_SHIFT)
+#define FFI390_TRAMP_SIZE 16
+
+#endif
diff --git a/src/s390/sysv.S b/src/s390/sysv.S
index c4b5006..d603218 100644
--- a/src/s390/sysv.S
+++ b/src/s390/sysv.S
@@ -28,6 +28,7 @@
#define LIBFFI_ASM
#include
#include
+#include "internal.h"
.text
@@ -318,6 +319,43 @@ ffi_closure_SYSV:
br %r14
.cfi_endproc
.size ffi_closure_SYSV,.-ffi_closure_SYSV
+
+
+#if defined(FFI_EXEC_STATIC_TRAMP)
+/*
+ * Below is the definition of the trampoline code table. Each element in
+ * the code table is a trampoline.
+ */
+/*
+ * The trampoline uses the volatile register r0 and r1. As the registers are
+ * marked volatile in the ABI, the original values are not saved.
+ *
+ * The trampoline has two parameters - target code to jump to and data for
+ * the target code. The trampoline extracts the parameters from its parameter
+ * block (see tramp_table_map()). The trampoline saves the data address in r0.
+ * Finally, it jumps to the target code.
+ */
+
+ .align FFI390_TRAMP_MAP_SIZE
+trampoline_code_table:
+ .rept FFI390_TRAMP_MAP_SIZE / FFI390_TRAMP_SIZE
+ basr %r1,0 # load next instruction address to r1
+ lmg %r0,%r1,4094(%r1) # load parameter block
+ # r0 -> data
+ # r1 -> code
+ br %r1 # jump to r1/code
+ .balign 8
+ .endr
+
+ .globl trampoline_code_table
+ FFI_HIDDEN(trampoline_code_table)
+#ifdef __ELF__
+ .type trampoline_code_table, @function
+ .size trampoline_code_table,.- trampoline_code_table
+#endif
+ .align FFI390_TRAMP_MAP_SIZE
+#endif /* FFI_EXEC_STATIC_TRAMP */
+
#endif /* !s390x */
#if defined __ELF__ && defined __linux__
diff --git a/src/sparc/ffi.c b/src/sparc/ffi.c
index 9e406d0..cf819ee 100644
--- a/src/sparc/ffi.c
+++ b/src/sparc/ffi.c
@@ -286,6 +286,8 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
size_t bytes = cif->bytes;
+ size_t i, nargs = cif->nargs;
+ ffi_type **arg_types = cif->arg_types;
FFI_ASSERT (cif->abi == FFI_V8);
@@ -295,6 +297,20 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
&& (cif->flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT)
bytes += FFI_ALIGN (cif->rtype->size, 8);
+ /* If we have any structure arguments, make a copy so we are passing
+ by value. */
+ for (i = 0; i < nargs; i++)
+ {
+ ffi_type *at = arg_types[i];
+ int size = at->size;
+ if (at->type == FFI_TYPE_STRUCT)
+ {
+ char *argcopy = alloca (size);
+ memcpy (argcopy, avalue[i], size);
+ avalue[i] = argcopy;
+ }
+ }
+
ffi_call_v8(cif, fn, rvalue, avalue, -bytes, closure);
}
diff --git a/src/wasm32/ffi.c b/src/wasm32/ffi.c
index 1a8c9ae..6328487 100644
--- a/src/wasm32/ffi.c
+++ b/src/wasm32/ffi.c
@@ -41,28 +41,7 @@
#define EM_JS_MACROS(ret, name, args, body...) EM_JS(ret, name, args, body)
-#if WASM_BIGINT
EM_JS_DEPS(libffi, "$getWasmTableEntry,$setWasmTableEntry,$getEmptyTableSlot,$convertJsFunctionToWasm");
-#define CALL_FUNCTION_POINTER(ptr, args...) \
- (LOG_DEBUG("CALL_FUNC_PTR", ptr, args), \
- getWasmTableEntry(ptr).apply(null, args))
-
-#define JS_FUNCTION_TO_WASM convertJsFunctionToWasm
-#else
-EM_JS_DEPS(libffi, "$getWasmTableEntry,$setWasmTableEntry,$getEmptyTableSlot,$convertJsFunctionToWasm,$dynCall,$generateFuncType,$uleb128Encode");
-#define CALL_FUNCTION_POINTER(ptr, args...) \
- (LOG_DEBUG("CALL_FUNC_PTR", sig, ptr, args), \
- dynCall(sig, ptr, args))
-
-#define JS_FUNCTION_TO_WASM createLegalizerWrapper
-#endif
-
-// Signature calculations are not needed if WASM_BIGINT is present.
-#if WASM_BIGINT
-#define SIG(sig)
-#else
-#define SIG(sig) sig
-#endif
#define DEREF_U8(addr, offset) HEAPU8[addr + offset]
#define DEREF_S8(addr, offset) HEAP8[addr + offset]
@@ -73,12 +52,7 @@ EM_JS_DEPS(libffi, "$getWasmTableEntry,$setWasmTableEntry,$getEmptyTableSlot,$co
#define DEREF_F32(addr, offset) HEAPF32[(addr >> 2) + offset]
#define DEREF_F64(addr, offset) HEAPF64[(addr >> 3) + offset]
-
-#if WASM_BIGINT
-// We have HEAPU64 in this case.
#define DEREF_U64(addr, offset) HEAPU64[(addr >> 3) + offset]
-#endif
-
#define CHECK_FIELD_OFFSET(struct, field, offset) \
_Static_assert( \
@@ -235,40 +209,6 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
ret_by_arg = true;
}
- SIG(var sig = "");
-
-#if !WASM_BIGINT
- switch(rtype_id) {
- case FFI_TYPE_VOID:
- SIG(sig = 'v');
- break;
- case FFI_TYPE_STRUCT:
- case FFI_TYPE_LONGDOUBLE:
- SIG(sig = 'vi');
- 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:
- SIG(sig = 'i');
- break;
- case FFI_TYPE_FLOAT:
- SIG(sig = 'f');
- break;
- case FFI_TYPE_DOUBLE:
- SIG(sig = 'd');
- break;
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- SIG(sig = 'j');
- break;
- }
-#endif
-
// Accumulate a Javascript list of arguments for the Javascript wrapper for
// the wasm function. The Javascript wrapper does a type conversion from
// Javascript to C automatically, here we manually do the inverse conversion
@@ -288,54 +228,33 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
args.push(DEREF_U32(arg_ptr, 0));
- SIG(sig += 'i');
break;
case FFI_TYPE_FLOAT:
args.push(DEREF_F32(arg_ptr, 0));
- SIG(sig += 'f');
break;
case FFI_TYPE_DOUBLE:
args.push(DEREF_F64(arg_ptr, 0));
- SIG(sig += 'd');
break;
case FFI_TYPE_UINT8:
args.push(DEREF_U8(arg_ptr, 0));
- SIG(sig += 'i');
break;
case FFI_TYPE_SINT8:
args.push(DEREF_S8(arg_ptr, 0));
- SIG(sig += 'i');
break;
case FFI_TYPE_UINT16:
args.push(DEREF_U16(arg_ptr, 0));
- SIG(sig += 'i');
break;
case FFI_TYPE_SINT16:
args.push(DEREF_S16(arg_ptr, 0));
- SIG(sig += 'i');
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
- #if WASM_BIGINT
args.push(DEREF_U64(arg_ptr, 0));
- #else
- args.push(DEREF_U32(arg_ptr, 0));
- args.push(DEREF_U32(arg_ptr, 1));
- #endif
- SIG(sig += 'j');
break;
case FFI_TYPE_LONGDOUBLE:
// long double is passed as a pair of BigInts.
- #if WASM_BIGINT
args.push(DEREF_U64(arg_ptr, 0));
args.push(DEREF_U64(arg_ptr, 1));
- #else
- args.push(DEREF_U32(arg_ptr, 0));
- args.push(DEREF_U32(arg_ptr, 1));
- args.push(DEREF_U32(arg_ptr, 2));
- args.push(DEREF_U32(arg_ptr, 3));
- #endif
- SIG(sig += "jj");
break;
case FFI_TYPE_STRUCT:
// Nontrivial structs are passed by pointer.
@@ -346,7 +265,6 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
STACK_ALLOC(cur_stack_ptr, size, align);
HEAP8.subarray(cur_stack_ptr, cur_stack_ptr+size).set(HEAP8.subarray(arg_ptr, arg_ptr + size));
args.push(cur_stack_ptr);
- SIG(sig += 'i');
break;
case FFI_TYPE_COMPLEX:
throw new Error('complex marshalling nyi');
@@ -365,7 +283,6 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
// just always copy extra nonsense past the end. The ownwards call will know
// not to look at it.
if (nfixedargs != nargs) {
- SIG(sig += 'i');
var struct_arg_info = [];
for (var i = nargs - 1; i >= nfixedargs; i--) {
var arg_ptr = DEREF_U32(avalue, i);
@@ -434,7 +351,8 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
}
stackRestore(cur_stack_ptr);
stackAlloc(0); // stackAlloc enforces alignment invariants on the stack pointer
- var result = CALL_FUNCTION_POINTER(fn, args);
+ LOG_DEBUG("CALL_FUNC_PTR", "fn:", fn, "args:", args);
+ var result = getWasmTableEntry(fn).apply(null, args);
// Put the stack pointer back (we moved it if there were any struct args or we
// made a varargs call)
stackRestore(orig_stack_ptr);
@@ -472,12 +390,7 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
- #if WASM_BIGINT
DEREF_U64(rvalue, 0) = result;
- #else
- DEREF_U32(rvalue, 0) = result;
- DEREF_U32(rvalue, 1) = getTempRet0();
- #endif
break;
case FFI_TYPE_COMPLEX:
throw new Error('complex ret marshalling nyi');
@@ -524,146 +437,6 @@ ffi_closure_free(void *closure) {
return ffi_closure_free_js(closure);
}
-#if !WASM_BIGINT
-
-// When !WASM_BIGINT, we assume there is no JS bigint integration, so JavaScript
-// functions cannot take 64 bit integer arguments.
-//
-// We need to make our own wasm legalizer adaptor that splits 64 bit integer
-// arguments and then calls the JavaScript trampoline, then the JavaScript
-// trampoline reassembles them, calls the closure, then splits the result (if
-// it's a 64 bit integer) and the adaptor puts it back together.
-//
-// This is basically the reverse of the Emscripten function
-// createDyncallWrapper.
-EM_JS(void, createLegalizerWrapper, (int trampoline, int sig), {
- if(!sig.includes("j")) {
- return convertJsFunctionToWasm(trampoline, sig);
- }
- var sections = [];
- var prelude = [
- 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm")
- 0x01, 0x00, 0x00, 0x00, // version: 1
- ];
- sections.push(prelude);
- var wrappersig = [
- // if return type is j, we will put the upper 32 bits into tempRet0.
- sig[0].replace("j", "i"),
- // in the rest of the argument list, one 64 bit integer is legalized into
- // two 32 bit integers.
- sig.slice(1).replace(/j/g, "ii"),
- ].join("");
-
- var typeSectionBody = [
- 0x03, // number of types = 3
- ];
- generateFuncType(wrappersig, typeSectionBody); // The signature of the wrapper we are generating
- generateFuncType(sig, typeSectionBody); // the signature of the function pointer we will call
- generateFuncType("i", typeSectionBody); // the signature of getTempRet0
-
- var typeSection = [0x01 /* Type section code */];
- uleb128Encode(typeSectionBody.length, typeSection); // length of section in bytes
- typeSection.push.apply(typeSection, typeSectionBody);
- sections.push(typeSection);
-
- var importSection = [
- 0x02, // import section code
- 0x0d, // length of section in bytes
- 0x02, // number of imports = 2
- // Import the getTempRet0 function, which we will call "r"
- 0x01, 0x65, // name "e"
- 0x01, 0x72, // name "r"
- 0x00, // importing a function
- 0x02, // type 2 = () -> i32
- // Import the wrapped function, which we will call "f"
- 0x01, 0x65, // name "e"
- 0x01, 0x66, // name "f"
- 0x00, // importing a function
- 0x00, // type 0 = wrappersig
- ];
- sections.push(importSection);
-
- var functionSection = [
- 0x03, // function section code
- 0x02, // length of section in bytes
- 0x01, // number of functions = 1
- 0x01, // type 1 = sig
- ];
- sections.push(functionSection);
-
- var exportSection = [
- 0x07, // export section code
- 0x05, // length of section in bytes
- 0x01, // One export
- 0x01, 0x66, // name "f"
- 0x00, // type: function
- 0x02, // function index 2 = the wrapper function
- ];
- sections.push(exportSection);
-
- var convert_code = [];
- convert_code.push(0x00); // no local variables (except the arguments)
-
- function localGet(j) {
- convert_code.push(0x20); // local.get
- uleb128Encode(j, convert_code);
- }
-
- for (var i = 1; i < sig.length; i++) {
- if (sig[i] == "j") {
- localGet(i - 1);
- convert_code.push(
- 0xa7 // i32.wrap_i64
- );
- localGet(i - 1);
- convert_code.push(
- 0x42, 0x20, // i64.const 32
- 0x88, // i64.shr_u
- 0xa7 // i32.wrap_i64
- );
- } else {
- localGet(i - 1);
- }
- }
- convert_code.push(
- 0x10, 0x01 // call f
- );
- if (sig[0] === "j") {
- // Need to reassemble a 64 bit integer. Lower 32 bits is on stack. Upper 32
- // bits we get from getTempRet0
- convert_code.push(
- 0xad, // i64.extend_i32_unsigned
- 0x10, 0x00, // Call function 0 (r = getTempRet0)
- // join lower 32 bits and upper 32 bits
- 0xac, // i64.extend_i32_signed
- 0x42, 0x20, // i64.const 32
- 0x86, // i64.shl,
- 0x84 // i64.or
- );
- }
- convert_code.push(0x0b); // end
-
- var codeBody = [0x01]; // one code
- uleb128Encode(convert_code.length, codeBody);
- codeBody.push.apply(codeBody, convert_code);
- var codeSection = [0x0a /* Code section code */];
- uleb128Encode(codeBody.length, codeSection);
- codeSection.push.apply(codeSection, codeBody);
- sections.push(codeSection);
-
- var bytes = new Uint8Array([].concat.apply([], sections));
- // We can compile this wasm module synchronously because it is small.
- var module = new WebAssembly.Module(bytes);
- var instance = new WebAssembly.Instance(module, {
- e: {
- r: getTempRet0,
- f: trampoline,
- },
- });
- return instance.exports.f;
-});
-#endif
-
EM_JS_MACROS(
ffi_status,
ffi_prep_closure_loc_js,
@@ -759,9 +532,9 @@ ffi_prep_closure_loc_js,
}
if (nfixedargs < nargs) {
// extra pointer to varargs stack
- sig += "i";
+ sig += 'i';
}
- LOG_DEBUG("CREATE_CLOSURE", "sig:", sig);
+ LOG_DEBUG("CREATE_CLOSURE", "sig:", sig);
function trampoline() {
var args = Array.prototype.slice.call(arguments);
var size = 0;
@@ -838,32 +611,14 @@ ffi_prep_closure_loc_js,
case FFI_TYPE_SINT64:
STACK_ALLOC(cur_ptr, 8, 8);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
- #if WASM_BIGINT
DEREF_U64(cur_ptr, 0) = cur_arg;
- #else
- // Bigint arg was split by legalizer adaptor
- DEREF_U32(cur_ptr, 0) = cur_arg;
- cur_arg = args[jsarg_idx++];
- DEREF_U32(cur_ptr, 1) = cur_arg;
- #endif
break;
case FFI_TYPE_LONGDOUBLE:
STACK_ALLOC(cur_ptr, 16, 8);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
- #if WASM_BIGINT
DEREF_U64(cur_ptr, 0) = cur_arg;
cur_arg = args[jsarg_idx++];
DEREF_U64(cur_ptr, 1) = cur_arg;
- #else
- // Was split by legalizer adaptor
- DEREF_U32(cur_ptr, 0) = cur_arg;
- cur_arg = args[jsarg_idx++];
- DEREF_U32(cur_ptr, 1) = cur_arg;
- cur_arg = args[jsarg_idx++];
- DEREF_U32(cur_ptr, 2) = cur_arg;
- cur_arg = args[jsarg_idx++];
- DEREF_U32(cur_ptr, 3) = cur_arg;
- #endif
break;
}
}
@@ -895,7 +650,7 @@ ffi_prep_closure_loc_js,
}
stackRestore(cur_ptr);
stackAlloc(0); // stackAlloc enforces alignment invariants on the stack pointer
- LOG_DEBUG("CALL_CLOSURE", "closure:", closure, "fptr", CLOSURE__fun(closure), "cif", CLOSURE__cif(closure));
+ LOG_DEBUG("CALL_CLOSURE", "closure:", closure, "fptr", CLOSURE__fun(closure), "cif", CLOSURE__cif(closure));
getWasmTableEntry(CLOSURE__fun(closure))(
CLOSURE__cif(closure), ret_ptr, args_ptr,
CLOSURE__user_data(closure)
@@ -905,26 +660,19 @@ ffi_prep_closure_loc_js,
// If we aren't supposed to return by argument, figure out what to return.
if (!ret_by_arg) {
switch (sig[0]) {
- case "i":
+ case 'i':
return DEREF_U32(ret_ptr, 0);
- case "j":
- #if WASM_BIGINT
+ case 'j':
return DEREF_U64(ret_ptr, 0);
- #else
- // Split the return i64, set the upper 32 bits into tempRet0 and return
- // the lower 32 bits.
- setTempRet0(DEREF_U32(ret_ptr, 1));
- return DEREF_U32(ret_ptr, 0);
- #endif
- case "d":
+ case 'd':
return DEREF_F64(ret_ptr, 0);
- case "f":
+ case 'f':
return DEREF_F32(ret_ptr, 0);
}
}
}
try {
- var wasm_trampoline = JS_FUNCTION_TO_WASM(trampoline, sig);
+ var wasm_trampoline = convertJsFunctionToWasm(trampoline, sig);
} catch(e) {
return FFI_BAD_TYPEDEF_MACRO;
}
diff --git a/src/x86/ffi.c b/src/x86/ffi.c
index b8bb178..6862533 100644
--- a/src/x86/ffi.c
+++ b/src/x86/ffi.c
@@ -118,7 +118,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
break;
case FFI_TYPE_STRUCT:
{
-#ifdef X86_WIN32
+#if defined(X86_WIN32) || defined(X86_DARWIN)
size_t size = cif->rtype->size;
if (size == 1)
flags = X86_RET_STRUCT_1B;
@@ -270,6 +270,9 @@ extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_
#if defined(_MSC_VER)
#pragma runtime_checks("s", off)
#endif
+/* n.b. ffi_call_unix64 will steal the alloca'd `stack` variable here for use
+ _as its own stack_ - so we need to compile this function without ASAN */
+FFI_ASAN_NO_SANITIZE
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c
index 6a8e37f..982b144 100644
--- a/src/x86/ffi64.c
+++ b/src/x86/ffi64.c
@@ -557,6 +557,9 @@ ffi_prep_cif_machdep (ffi_cif *cif)
return FFI_OK;
}
+/* n.b. ffi_call_unix64 will steal the alloca'd `stack` variable here for use
+ _as its own stack_ - so we need to compile this function without ASAN */
+FFI_ASAN_NO_SANITIZE
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
@@ -651,7 +654,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
break;
default:
reg_args->gpr[gprcount] = 0;
- memcpy (®_args->gpr[gprcount], a, size);
+ memcpy (®_args->gpr[gprcount], a, sizeof(UINT64));
}
gprcount++;
break;
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index d286cf7..92ae1aa 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -8,7 +8,7 @@ CLEANFILES = *.exe core* *.log *.sum
EXTRA_DIST = config/default.exp emscripten/build.sh emscripten/conftest.py \
emscripten/node-tests.sh emscripten/test.html emscripten/test_libffi.py \
- emscripten/build-tests.sh lib/libffi.exp lib/target-libpath.exp \
+ emscripten/build-tests.sh lib/libffi.exp lib/target-libpath.exp \
lib/wrapper.exp libffi.bhaible/Makefile libffi.bhaible/README \
libffi.bhaible/alignof.h libffi.bhaible/bhaible.exp libffi.bhaible/test-call.c \
libffi.bhaible/test-callback.c libffi.bhaible/testcases.c libffi.call/align_mixed.c \
@@ -31,6 +31,7 @@ EXTRA_DIST = config/default.exp emscripten/build.sh emscripten/conftest.py \
libffi.call/struct9.c libffi.call/struct_by_value_2.c libffi.call/struct_by_value_3.c \
libffi.call/struct_by_value_3f.c libffi.call/struct_by_value_4.c libffi.call/struct_by_value_4f.c \
libffi.call/struct_by_value_big.c libffi.call/struct_by_value_small.c libffi.call/struct_return_2H.c \
+ libffi.call/struct_int_float.c \
libffi.call/struct_return_8H.c libffi.call/uninitialized.c libffi.call/va_1.c \
libffi.call/va_2.c libffi.call/va_3.c libffi.call/va_struct1.c \
libffi.call/va_struct2.c libffi.call/va_struct3.c libffi.call/callback.c \
diff --git a/testsuite/emscripten/build-tests.sh b/testsuite/emscripten/build-tests.sh
index 7c43060..2f1dd8d 100755
--- a/testsuite/emscripten/build-tests.sh
+++ b/testsuite/emscripten/build-tests.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
-emcc_exists="$(command -v emcc)"
-if [ ! "${emcc_exists}" ]; then
- echo "Emscripten not on path"
+
+if ! [ -x "$(command -v emcc)" ]; then
+ echo "Error: emcc could not be found." >&2
exit 1
fi
@@ -10,19 +10,6 @@ set -e
cd "$1"
shift
-# Parse arguments
-while [ $# -gt 0 ]; do
- case $1 in
- --wasm-bigint) WASM_BIGINT=true ;;
- *)
- echo "ERROR: Unknown parameter: $1" >&2
- exit 1
- ;;
- esac
- shift
-done
-
-
export CFLAGS="-fPIC -O2 -I../../target/include $EXTRA_CFLAGS"
export CXXFLAGS="$CFLAGS -sNO_DISABLE_EXCEPTION_CATCHING $EXTRA_CXXFLAGS"
export LDFLAGS=" \
@@ -31,17 +18,10 @@ export LDFLAGS=" \
-sMODULARIZE \
-sMAIN_MODULE \
-sNO_DISABLE_EXCEPTION_CATCHING \
+ -sWASM_BIGINT \
$EXTRA_LD_FLAGS \
"
-# This needs to test false if there exists an environment variable called
-# WASM_BIGINT whose contents are empty. Don't use +x.
-if [ -n "${WASM_BIGINT}" ] ; then
- export LDFLAGS+=" -sWASM_BIGINT"
-else
- export LDFLAGS+=" -sEXPORTED_RUNTIME_METHODS='getTempRet0,setTempRet0'"
-fi
-
# Rename main functions to test__filename so we can link them together
ls *c | sed 's!\(.*\)\.c!sed -i "s/main/test__\1/g" \0!g' | bash
diff --git a/testsuite/emscripten/build.sh b/testsuite/emscripten/build.sh
index c77c041..83ece7b 100755
--- a/testsuite/emscripten/build.sh
+++ b/testsuite/emscripten/build.sh
@@ -1,8 +1,9 @@
#!/usr/bin/env bash
-command -v emcc >/dev/null 2>&1 || {
- echo >&2 "emsdk could not be found. Aborting."
+
+if ! [ -x "$(command -v emcc)" ]; then
+ echo "Error: emcc could not be found." >&2
exit 1
-}
+fi
set -e
@@ -13,38 +14,20 @@ TARGET=$SOURCE_DIR/target
mkdir -p "$TARGET"
# Define default arguments
-
-# JS BigInt to Wasm i64 integration, disabled by default
-# This needs to test false if there exists an environment variable called
-# WASM_BIGINT whose contents are empty. Don't use +x.
-if [ -n "${WASM_BIGINT}" ]; then
- WASM_BIGINT=true
-else
- WASM_BIGINT=false
-fi
+DEBUG=false
# Parse arguments
while [ $# -gt 0 ]; do
case $1 in
- --wasm-bigint) WASM_BIGINT=true ;;
- --debug) DEBUG=true ;;
- *)
- echo "ERROR: Unknown parameter: $1" >&2
- exit 1
- ;;
+ --debug) DEBUG=true ;;
+ *) echo "ERROR: Unknown parameter: $1" >&2; exit 1 ;;
esac
shift
done
# Common compiler flags
export CFLAGS="-O3 -fPIC"
-if [ "$WASM_BIGINT" = "true" ]; then
- # We need to detect WASM_BIGINT support at compile time
- export CFLAGS+=" -DWASM_BIGINT"
-fi
-if [ "$DEBUG" = "true" ]; then
- export CFLAGS+=" -DDEBUG_F"
-fi
+if [ "$DEBUG" = "true" ]; then export CFLAGS+=" -DDEBUG_F"; fi
export CXXFLAGS="$CFLAGS"
# Build paths
diff --git a/testsuite/emscripten/node-tests.sh b/testsuite/emscripten/node-tests.sh
index 88dd74b..016e99c 100755
--- a/testsuite/emscripten/node-tests.sh
+++ b/testsuite/emscripten/node-tests.sh
@@ -1,39 +1,14 @@
#!/bin/bash
-# JS BigInt to Wasm i64 integration, disabled by default
-WASM_BIGINT=false
-
-emcc_exists="$(command -v emcc)"
-if [ ! "${emcc_exists}" ]; then
- echo "Emscripten not on path"
+if ! [ -x "$(command -v emcc)" ]; then
+ echo "Error: emcc could not be found." >&2
exit 1
fi
-# Parse arguments
-while [ $# -gt 0 ]; do
- case $1 in
- --wasm-bigint) WASM_BIGINT=true ;;
- *)
- echo "ERROR: Unknown parameter: $1" >&2
- exit 1
- ;;
- esac
- shift
-done
-
# Common compiler flags
export CFLAGS="-fPIC $EXTRA_CFLAGS"
-if [ "$WASM_BIGINT" = "true" ]; then
- # We need to detect WASM_BIGINT support at compile time
- export CFLAGS+=" -DWASM_BIGINT"
-fi
export CXXFLAGS="$CFLAGS -sNO_DISABLE_EXCEPTION_CATCHING $EXTRA_CXXFLAGS"
-export LDFLAGS="-sEXPORTED_FUNCTIONS=_main,_malloc,_free -sALLOW_TABLE_GROWTH -sASSERTIONS -sNO_DISABLE_EXCEPTION_CATCHING"
-if [ "$WASM_BIGINT" = "true" ]; then
- export LDFLAGS+=" -sWASM_BIGINT"
-else
- export LDFLAGS+=" -sEXPORTED_RUNTIME_METHODS='getTempRet0,setTempRet0'"
-fi
+export LDFLAGS="-sEXPORTED_FUNCTIONS=_main,_malloc,_free -sALLOW_TABLE_GROWTH -sASSERTIONS -sNO_DISABLE_EXCEPTION_CATCHING -sWASM_BIGINT"
# Specific variables for cross-compilation
export CHOST="wasm32-unknown-linux" # wasm32-unknown-emscripten
diff --git a/testsuite/libffi.call/callback.c b/testsuite/libffi.call/callback.c
index ac45c62..70248cb 100644
--- a/testsuite/libffi.call/callback.c
+++ b/testsuite/libffi.call/callback.c
@@ -7,9 +7,9 @@
/* { dg-do run } */
#include "ffitest.h"
-int i=5;
+static int i=5;
-void callback(void) { i++; }
+static void callback(void) { i++; }
typedef struct
{
diff --git a/testsuite/libffi.call/callback2.c b/testsuite/libffi.call/callback2.c
index 53a3b2f..0fcc614 100644
--- a/testsuite/libffi.call/callback2.c
+++ b/testsuite/libffi.call/callback2.c
@@ -7,9 +7,9 @@
/* { dg-do run } */
#include "ffitest.h"
-int i=5;
+static int i=5;
-void callback(void) { i++; }
+static void callback(void) { i++; }
typedef struct
{
diff --git a/testsuite/libffi.call/callback3.c b/testsuite/libffi.call/callback3.c
index 4a2fd97..05bdbf6 100644
--- a/testsuite/libffi.call/callback3.c
+++ b/testsuite/libffi.call/callback3.c
@@ -7,9 +7,9 @@
/* { dg-do run } */
#include "ffitest.h"
-int i=5;
+static int i=5;
-void callback(void) { i++; }
+static void callback(void) { i++; }
typedef struct
diff --git a/testsuite/libffi.call/callback4.c b/testsuite/libffi.call/callback4.c
index 350338c..309ad35 100644
--- a/testsuite/libffi.call/callback4.c
+++ b/testsuite/libffi.call/callback4.c
@@ -7,9 +7,9 @@
/* { dg-do run } */
#include "ffitest.h"
-int i=5;
+static int i=5;
-void callback(void) { i++; }
+static void callback(void) { i++; }
typedef struct
diff --git a/testsuite/libffi.call/struct_int_float.c b/testsuite/libffi.call/struct_int_float.c
new file mode 100644
index 0000000..66ef6c4
--- /dev/null
+++ b/testsuite/libffi.call/struct_int_float.c
@@ -0,0 +1,88 @@
+/* Area: ffi_call
+ Purpose: Demonstrate structures with integers corrupting earlier floats
+ Limitations: none.
+ PR: #848
+ Originator: kellda */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+ unsigned long i;
+ float f;
+} test_structure_int_float;
+
+static float ABI_ATTR struct_int_float(test_structure_int_float ts1,
+ test_structure_int_float ts2 __UNUSED__,
+ test_structure_int_float ts3 __UNUSED__,
+ test_structure_int_float ts4 __UNUSED__,
+ test_structure_int_float ts5 __UNUSED__,
+ test_structure_int_float ts6 __UNUSED__)
+{
+ return ts1.f;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts_type;
+ ffi_type *ts_type_elements[3];
+ float rfloat;
+
+ test_structure_int_float ts_arg[6];
+
+ ts_type.size = 0;
+ ts_type.alignment = 0;
+ ts_type.type = FFI_TYPE_STRUCT;
+ ts_type.elements = ts_type_elements;
+ ts_type_elements[0] = &ffi_type_ulong;
+ ts_type_elements[1] = &ffi_type_float;
+ ts_type_elements[2] = NULL;
+
+ args[0] = &ts_type;
+ values[0] = &ts_arg[0];
+ args[1] = &ts_type;
+ values[1] = &ts_arg[1];
+ args[2] = &ts_type;
+ values[2] = &ts_arg[2];
+ args[3] = &ts_type;
+ values[3] = &ts_arg[3];
+ args[4] = &ts_type;
+ values[4] = &ts_arg[4];
+ args[5] = &ts_type;
+ values[5] = &ts_arg[5];
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 6, &ffi_type_float, args) == FFI_OK);
+
+ ts_arg[0].i = 1;
+ ts_arg[0].f = 11.11f;
+ ts_arg[1].i = 2;
+ ts_arg[1].f = 22.22f;
+ ts_arg[2].i = 3;
+ ts_arg[2].f = 33.33f;
+ ts_arg[3].i = 4;
+ ts_arg[3].f = 44.44f;
+ ts_arg[4].i = 5;
+ ts_arg[4].f = 55.55f;
+ ts_arg[5].i = 6;
+ ts_arg[5].f = 66.66f;
+
+ printf ("%g\n", ts_arg[0].f);
+ printf ("%g\n", ts_arg[1].f);
+ printf ("%g\n", ts_arg[2].f);
+ printf ("%g\n", ts_arg[3].f);
+ printf ("%g\n", ts_arg[4].f);
+ printf ("%g\n", ts_arg[5].f);
+
+ ffi_call(&cif, FFI_FN(struct_int_float), &rfloat, values);
+
+ printf ("%g\n", rfloat);
+
+ CHECK(fabs(rfloat - 11.11) < 3 * FLT_EPSILON);
+
+ exit(0);
+}
diff --git a/testsuite/libffi.call/va_struct2.c b/testsuite/libffi.call/va_struct2.c
index a8daff3..a034087 100644
--- a/testsuite/libffi.call/va_struct2.c
+++ b/testsuite/libffi.call/va_struct2.c
@@ -33,6 +33,7 @@ test_fn (int n, ...)
struct small_tag s2;
struct large_tag l;
+ (void) n;
va_start (ap, n);
s1 = va_arg (ap, struct small_tag);
l = va_arg (ap, struct large_tag);
diff --git a/testsuite/libffi.call/va_struct3.c b/testsuite/libffi.call/va_struct3.c
index d3bd280..5a52c9f 100644
--- a/testsuite/libffi.call/va_struct3.c
+++ b/testsuite/libffi.call/va_struct3.c
@@ -33,6 +33,7 @@ test_fn (int n, ...)
struct small_tag s2;
struct large_tag l;
+ (void) n;
va_start (ap, n);
s1 = va_arg (ap, struct small_tag);
l = va_arg (ap, struct large_tag);
diff --git a/testsuite/libffi.closures/cls_multi_sshortchar.c b/testsuite/libffi.closures/cls_multi_sshortchar.c
index a2b3708..42f3dde 100644
--- a/testsuite/libffi.closures/cls_multi_sshortchar.c
+++ b/testsuite/libffi.closures/cls_multi_sshortchar.c
@@ -80,7 +80,7 @@ int main (void)
/* { dg-output "1 32765 127 -128: 32765" } */
printf("res: %d\n", (signed short)res_call);
/* { dg-output "\nres: 32765" } */
- CHECK(res_call == 32765);
+ CHECK((signed short)res_call == 32765);
CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK);
diff --git a/testsuite/libffi.closures/cls_multi_ushortchar.c b/testsuite/libffi.closures/cls_multi_ushortchar.c
index 3315c99..c5af576 100644
--- a/testsuite/libffi.closures/cls_multi_ushortchar.c
+++ b/testsuite/libffi.closures/cls_multi_ushortchar.c
@@ -80,7 +80,7 @@ int main (void)
/* { dg-output "1 2 127 128: 258" } */
printf("res: %d\n", (unsigned short)res_call);
/* { dg-output "\nres: 258" } */
- CHECK(res_call == 258);
+ CHECK((unsigned short)res_call == 258);
CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK);
diff --git a/testsuite/libffi.complex/complex_int.c b/testsuite/libffi.complex/complex_int.c
index bac3190..cae5c45 100644
--- a/testsuite/libffi.complex/complex_int.c
+++ b/testsuite/libffi.complex/complex_int.c
@@ -76,7 +76,7 @@ int main (void)
printf ("%d,%di %d,%di, x %d 1234, y %d 11110\n",
(int)tc_result, (int)(tc_result * -I), 2, 8, tc_int_arg_x, tc_y);
- /* dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" */
+ /* { dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" } */
CHECK (creal (tc_result) == -2);
CHECK (cimag (tc_result) == 8);
CHECK (tc_int_arg_x == 1234);