From d2f65babb9c6c643ff29446ba7bd7282d3a3bac2 Mon Sep 17 00:00:00 2001 From: xzl Date: Mon, 17 Mar 2025 11:24:06 +0800 Subject: [PATCH] feat: update libffi to 3.4.7 Foreign Function Interface library (development files) Issue: https://github.com/deepin-community/sig-deepin-sysdev-team/issues/558 Log: update repo --- .circleci/config.yml | 156 --------- Makefile.am | 4 +- README.md | 13 +- acinclude.m4 | 6 + config.guess | 102 ++++-- config.sub | 241 +++++++++----- configure.ac | 16 +- configure.host | 5 - debian/changelog | 15 + debian/control | 2 +- debian/copyright | 6 +- doc/libffi.texi | 2 +- doc/version.texi | 8 +- include/ffi_cfi.h | 2 + include/ffi_common.h | 17 + src/aarch64/ffi.c | 11 +- src/aarch64/ffitarget.h | 4 +- src/aarch64/internal.h | 78 ++++- src/aarch64/sysv.S | 30 +- src/arc/arcompact.S | 4 +- src/arc/ffi.c | 8 +- src/closures.c | 6 +- src/dlmalloc.c | 1 + src/mips/n32.S | 4 + src/mips/o32.S | 4 + src/nios2/ffi.c | 304 ------------------ src/nios2/ffitarget.h | 52 --- src/nios2/sysv.S | 136 -------- src/or1k/ffi.c | 4 +- src/prep_cif.c | 5 +- src/s390/ffi.c | 29 +- src/s390/internal.h | 11 + src/s390/sysv.S | 38 +++ src/sparc/ffi.c | 16 + src/wasm32/ffi.c | 272 +--------------- src/x86/ffi.c | 5 +- src/x86/ffi64.c | 5 +- testsuite/Makefile.am | 3 +- testsuite/emscripten/build-tests.sh | 28 +- testsuite/emscripten/build.sh | 33 +- testsuite/emscripten/node-tests.sh | 31 +- testsuite/libffi.call/callback.c | 4 +- testsuite/libffi.call/callback2.c | 4 +- testsuite/libffi.call/callback3.c | 4 +- testsuite/libffi.call/callback4.c | 4 +- testsuite/libffi.call/struct_int_float.c | 88 +++++ testsuite/libffi.call/va_struct2.c | 1 + testsuite/libffi.call/va_struct3.c | 1 + .../libffi.closures/cls_multi_sshortchar.c | 2 +- .../libffi.closures/cls_multi_ushortchar.c | 2 +- testsuite/libffi.complex/complex_int.c | 2 +- 51 files changed, 651 insertions(+), 1178 deletions(-) delete mode 100644 .circleci/config.yml delete mode 100644 src/nios2/ffi.c delete mode 100644 src/nios2/ffitarget.h delete mode 100644 src/nios2/sysv.S create mode 100644 testsuite/libffi.call/struct_int_float.c 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);