Page MenuHome GnuPG

libgcrypt: ARM64 Builds on macOS fail
Open, NormalPublic

Description

I tried to build libgcrypt on macOS for ARM64 ("Apple Silicon"), using clang (the default compiler shipped with XCode). I cross-compile on x86_64 for arm using --host=aarch64-apple-darwin

The build fails with the following error:

/bin/sh ../libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I..  -I../src -I../src -I/Users/patrick/gnupg22/distarm64/include -Ofast -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk  -arch arm64  -Ofast -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -MT mpih-add1-asm.lo -MD -MP -MF .deps/mpih-add1-asm.Tpo -c -o mpih-add1-asm.lo mpih-add1-asm.S
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I.. -I../src -I../src -I/Users/patrick/gnupg22/distarm64/include -Ofast -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -arch arm64 -Ofast -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -MT mpih-add1-asm.lo -MD -MP -MF .deps/mpih-add1-asm.Tpo -c mpih-add1-asm.S  -fno-common -DPIC -o .libs/mpih-add1-asm.o
mpih-add1-asm.S:37:1: error: unknown directive
.type _gcry_mpih_add_n,%function
^
mpih-add1-asm.S:71:1: error: unknown directive
.size _gcry_mpih_add_n,.-_gcry_mpih_add_n;
^
make[2]: *** [mpih-add1-asm.lo] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

The build succeeds using --disable-adm but I'm not sure about the negative performance impact.

Details

Version
libgcrypt 1.8.7

Event Timeline

werner added a subscriber: werner.

You say that you build using clang but the log shows that you invoke gcc.

Sorry, I forgot to mention that Apple ships a gcc-wrapper for clang. It just accepts gcc command lines parameters and translates them to clang parameters.
Here is the output of gcc --version:

gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

And the arm64 cross-compiler:

gcc -arch arm64 --version
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: aarch64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Why the hell do they that? The standard compiler on a system is called cc which may translated to whatever the system installs for it. gcc is a specific implementation with certain properties. Di you try CC=clang to override this?

Yes, I did. Identical result.

ARM64 has been only tested on platforms which support ELF.

While it doesn't looks good (using AMD64 even if it's ARM64), I think this patch should be applied:

diff --git a/cipher/asm-common-aarch64.h b/cipher/asm-common-aarch64.h
index 4ffc1b71..f5029b55 100644
--- a/cipher/asm-common-aarch64.h
+++ b/cipher/asm-common-aarch64.h
@@ -23,7 +23,7 @@
 
 #include <config.h>
 
-#ifdef __ELF__
+#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
 # define ELF(...) __VA_ARGS__
 #else
 # define ELF(...) /*_*/

HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS is never defined on ARM64 as it depends on "$mpi_cpu_arch" == "x86". Instead I think new check for GCC assembly ELF directives would be needed in configure.ac, similar to HAVE_GCC_ASM_CFI_DIRECTIVES check. Following check should work, but I have not yet tested it:

#
# Check whether GCC assembler supports for ELF directives.
#
AC_CACHE_CHECK([whether GCC assembler supports for ELF directives],
       [gcry_cv_gcc_asm_elf_directives],
       [gcry_cv_gcc_asm_elf_directives=no
        AC_LINK_IFELSE([AC_LANG_PROGRAM( 
          [[__asm__(
                /* Test if ELF directives '.type' and '.size' are supported.  */
                "asmfunc:\n\t"
                ".size asmfunc,.-asmfunc;\n\t"
                ".type asmfunc,STT_FUNC;\n\t"
            );]])],
          [gcry_cv_gcc_asm_elf_directives=yes])])
if test "$gcry_cv_gcc_asm_elf_directives" = "yes" ; then
   AC_DEFINE(HAVE_GCC_ASM_ELF_DIRECTIVES,1,
             [Defined if underlying assembler supports for ELF directives])
fi

Another issue that comes in to mind is that current ARM/ARM64 HW feature detection most likely wont work on MacOS. Thus HW accelerated AES&SHA&GHASH implementation wont be used.

ARM64 has been only tested on platforms which support ELF.

While it doesn't looks good (using AMD64 even if it's ARM64), I think this patch should be applied:

diff --git a/cipher/asm-common-aarch64.h b/cipher/asm-common-aarch64.h
...

I tried to apply the patch on libgcrypt-1.8.7, but there is no file cipher/asm-common-aarch64.h.

The patch for configure.ac at least doesn't fail.

AArch64 clang support was added to 'master' on 2018-03-28. One would need to backport commits 8ee38806245ca8452051b1a245f44082323f37f6...9b58e4a03ba3aeff7bae3f40da706977870c9649 to 1.8 branch.

OK, then we'll have to live with --disable-asm until the next major version is released, or switch to gcc.

werner triaged this task as Normal priority.Jan 5 2021, 9:18 AM

I have now tried to build libgcrypt 1.9.0 for arm64 using clang. I get the following error:

libtool: compile:  clang -DHAVE_CONFIG_H -I. -I.. -I../src -I../src -I../mpi -I../mpi -I/Users/patrick/gnupg22/dist_arm64/include -Ofast -isysroot /Users/patrick/SDKs/MacOSX11.0.sdk -arch arm64 -Ofast -isysroot /Users/patrick/SDKs/MacOSX11.0.sdk -MT cipher-gcm-armv8-aarch64-ce.lo -MD -MP -MF .deps/cipher-gcm-armv8-aarch64-ce.Tpo -c cipher-gcm-armv8-aarch64-ce.S  -fno-common -DPIC -o .libs/cipher-gcm-armv8-aarch64-ce.o
cipher-gcm-armv8-aarch64-ce.S:208:3: error: ADR/ADRP relocations must be GOT relative
  adrp x5, :got:.Lrconst ; ldr x5, [x5, #:got_lo12:.Lrconst] ;
  ^
cipher-gcm-armv8-aarch64-ce.S:208:3: error: unknown AArch64 fixup kind!
  adrp x5, :got:.Lrconst ; ldr x5, [x5, #:got_lo12:.Lrconst] ;
  ^
cipher-gcm-armv8-aarch64-ce.S:386:3: error: ADR/ADRP relocations must be GOT relative
  adrp x2, :got:.Lrconst ; ldr x2, [x2, #:got_lo12:.Lrconst] ;
  ^
cipher-gcm-armv8-aarch64-ce.S:386:3: error: unknown AArch64 fixup kind!
  adrp x2, :got:.Lrconst ; ldr x2, [x2, #:got_lo12:.Lrconst] ;

Problem is in GET_DATA_POINTER macro. MacOS assembler expects data references in some different format than Linux. Could you try following edit and see if libgcrypt then compiles? In cipher/asm-common-aarch64.h, there is definition of GET_DATA_POINTER macro:

#ifdef _WIN32
#define GET_DATA_POINTER(reg, name) \
	adrp    reg, name ; \
	add     reg, reg, #:lo12:name ;
#else
#define GET_DATA_POINTER(reg, name) \
	adrp    reg, :got:name ; \
	ldr     reg, [reg, #:got_lo12:name] ;
#endif

Try changing #ifdef check to #if 1:

#if 1
#define GET_DATA_POINTER(reg, name) \
	adrp    reg, name ; \
	add     reg, reg, #:lo12:name ;
#else
#define GET_DATA_POINTER(reg, name) \
	adrp    reg, :got:name ; \
	ldr     reg, [reg, #:got_lo12:name] ;
#endif

I tried it - that doesn't help. Same error message.

Does attached patch help?

Compiling now works, but I get the following linker errors:

libtool: link: clang -dynamiclib  -o .libs/libgcrypt.20.dylib  .libs/libgcrypt_la-visibility.o .libs/libgcrypt_la-misc.o .libs/libgcrypt_la-global.o .libs/libgcrypt_la-sexp.o .libs/libgcrypt_la-hwfeatures.o .libs/libgcrypt_la-stdmem.o .libs/libgcrypt_la-secmem.o .libs/libgcrypt_la-missing-string.o .libs/libgcrypt_la-fips.o .libs/libgcrypt_la-hmac256.o .libs/libgcrypt_la-context.o .libs/libgcrypt_la-hwf-arm.o   -Wl,-force_load,../cipher/.libs/libcipher.a -Wl,-force_load,../random/.libs/librandom.a -Wl,-force_load,../mpi/.libs/libmpi.a -Wl,-force_load,../compat/.libs/libcompat.a  -L/Users/patrick/gnupg22/dist_arm64/lib /Users/patrick/gnupg22/dist_arm64/lib/libgpg-error.dylib  -arch arm64 -Ofast -isysroot /Users/patrick/SDKs/MacOSX11.0.sdk -arch arm64 -Ofast -isysroot /Users/patrick/SDKs/MacOSX11.0.sdk   -install_name  /Users/patrick/gnupg22/dist_arm64/lib/libgcrypt.20.dylib -compatibility_version 24 -current_version 24.1 -Wl,-single_module
ld: warning: arm64 function not 4-byte aligned: _gcry_mpih_add_n from ../mpi/.libs/libmpi.a(mpih-add1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Loop from ../mpi/.libs/libmpi.a(mpih-add1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Large_loop from ../mpi/.libs/libmpi.a(mpih-add1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Lend from ../mpi/.libs/libmpi.a(mpih-add1-asm.o)
ld: warning: arm64 function not 4-byte aligned: _gcry_mpih_sub_n from ../mpi/.libs/libmpi.a(mpih-sub1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Loop from ../mpi/.libs/libmpi.a(mpih-sub1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Large_loop from ../mpi/.libs/libmpi.a(mpih-sub1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Lend from ../mpi/.libs/libmpi.a(mpih-sub1-asm.o)
ld: warning: arm64 function not 4-byte aligned: _gcry_mpih_mul_1 from ../mpi/.libs/libmpi.a(mpih-mul1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Loop from ../mpi/.libs/libmpi.a(mpih-mul1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Large_loop from ../mpi/.libs/libmpi.a(mpih-mul1-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Lend from ../mpi/.libs/libmpi.a(mpih-mul1-asm.o)
ld: warning: arm64 function not 4-byte aligned: _gcry_mpih_addmul_1 from ../mpi/.libs/libmpi.a(mpih-mul2-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Loop from ../mpi/.libs/libmpi.a(mpih-mul2-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Large_loop from ../mpi/.libs/libmpi.a(mpih-mul2-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Lend from ../mpi/.libs/libmpi.a(mpih-mul2-asm.o)
ld: warning: arm64 function not 4-byte aligned: _gcry_mpih_submul_1 from ../mpi/.libs/libmpi.a(mpih-mul3-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Loop from ../mpi/.libs/libmpi.a(mpih-mul3-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Large_loop from ../mpi/.libs/libmpi.a(mpih-mul3-asm.o)
ld: warning: arm64 function not 4-byte aligned: .Loop_end from ../mpi/.libs/libmpi.a(mpih-mul3-asm.o)
Undefined symbols for architecture arm64:
  "__gcry_mpih_add_n", referenced from:
      __gcry_mpi_add in libmpi.a(mpi-add.o)
      __gcry_mpih_add in libmpi.a(mpi-inline.o)
      __gcry_mpi_invm in libmpi.a(mpi-inv.o)
      __gcry_mpih_divrem in libmpi.a(mpih-div.o)
      __gcry_mpih_sqr_n_basecase in libmpi.a(mpih-mul.o)
      __gcry_mpih_sqr_n in libmpi.a(mpih-mul.o)
      __gcry_mpih_mul_n in libmpi.a(mpih-mul.o)
      ...
     (maybe you meant: __gcry_mpih_add_n_cond)
  "__gcry_mpih_addmul_1", referenced from:
      __gcry_mpih_sqr_n_basecase in libmpi.a(mpih-mul.o)
      __gcry_mpih_sqr_n in libmpi.a(mpih-mul.o)
      __gcry_mpih_mul_n in libmpi.a(mpih-mul.o)
      _mul_n in libmpi.a(mpih-mul.o)
      __gcry_mpih_mul_karatsuba_case in libmpi.a(mpih-mul.o)
      __gcry_mpih_mul in libmpi.a(mpih-mul.o)
  "__gcry_mpih_mul_1", referenced from:
      __gcry_mpi_mul_ui in libmpi.a(mpi-mul.o)
      __gcry_mpih_sqr_n_basecase in libmpi.a(mpih-mul.o)
      __gcry_mpih_sqr_n in libmpi.a(mpih-mul.o)
      __gcry_mpih_mul_n in libmpi.a(mpih-mul.o)
      _mul_n in libmpi.a(mpih-mul.o)
      __gcry_mpih_mul_karatsuba_case in libmpi.a(mpih-mul.o)
      __gcry_mpih_mul in libmpi.a(mpih-mul.o)
      ...
  "__gcry_mpih_sub_n", referenced from:
      __gcry_ecc_fill_in_curve in libcipher.a(ecc-curves.o)
      __gcry_ecc_get_curve in libcipher.a(ecc-curves.o)
      __gcry_mpi_add in libmpi.a(mpi-add.o)
      __gcry_mpih_sub in libmpi.a(mpi-inline.o)
      __gcry_mpi_invm in libmpi.a(mpi-inv.o)
      _mpih_invm_pow2 in libmpi.a(mpi-inv.o)
      __gcry_mpi_powm in libmpi.a(mpi-pow.o)
      ...
     (maybe you meant: __gcry_mpih_sub_n_cond)
  "__gcry_mpih_submul_1", referenced from:
      __gcry_mpih_divrem in libmpi.a(mpih-div.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [libgcrypt.la] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

Does it build if configure with parameter 'ac_cv_sys_symbol_underscore=yes'? <path-to-libgcrypt-source>/configure ac_cv_sys_symbol_underscore=yes --host=aarch64-apple-darwin ...

no, that doesn't change anything.

Sorry to dig up an old thread...

I encountered the same (or similar) problem at Issue T5370, Apple M1 and Symbol not found: __gcry_mpih_mul_1. Here's the patch I used to clear the issues: libgcrypt-darwin.patch. libgcrypt and GnuPG tested OK after the patch.

If you are having problems with System Integrity Protection (SIP), then you want this patch, too: libgcrypt.patch.