Page MenuHome GnuPG

Building libgcrypt-1.11.0 produces a dylib with unresolved symbols at runtime
Testing, NormalPublic

Description

Building libgcrypt-1.11.0 produces a dylib with unresolved symbols at runtime

On Darwin build targets, entry point symbols for asm code require an _ at the front of the symbol in order to be callable from C code. The configure script seems to have logic to handle this, but it is not enabled on a Darwin target. I used the following diff to resolve this on my system:

diff --git a/acinclude.m4 b/acinclude.m4
index 782b7f6a..e020cea6 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -73,6 +73,9 @@ case "${host}" in
     i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp)
         ac_cv_sys_symbol_underscore=yes
         ;;
+    x86_64-apple-darwin*)
+       ac_cv_sys_symbol_underscore=yes
+       ;;
     *)
       if test "$cross_compiling" != yes; then
          tmp_do_check="yes"

I suspect that this is also required on other Apple platforms, so I suspect that you want something like *-apple-darwin* to handle all Apple platforms, but I have no way to test this myself.

After applying this patch, regenerating configure, and building the project, the resulting dylib works correctly.

Details

Version
libgcrypt-1.11.0

Event Timeline

werner added a subscriber: werner.

Didn't you had this problem with 1.10.x ? I can't remember that we changed anything at theat code for years. The only recent change was rC656ca459e which should not have changed anything. Maybe the problem is elsewhere.

Which toolchain are you using? Cross-compiling?

werner added a project: MacOS.

The toolchain is clang / llvm and the apple ld, native build, not cross compiling.

I just rebuilt 1.10.3 on the system without any changes required. There are some changes in the function GNUPG_SYS_SYMBOL_UNDERSCORE from 1.10.3 to 1.11.0. The logic in 1.11.0 is failing to determine that it needs _ appended to the asm function definitions.

For 1.10.3, configure is outputting:

checking for _ prefix in compiled symbols... yes

For 1.11.0, configure is outputting:

checking for _ prefix in compiled symbols... no

I have verified that for 1.11.0, mpi/sysdep.h contains:

/* created by config.links - do not edit */
#define C_SYMBOL_NAME(name) name

For 1.10.3, mpi/sysdep.h contains:

% cat mpi/sysdep.h 
/* created by config.links - do not edit */
#if __STDC__
#define C_SYMBOL_NAME(name) _##name
#else
#define C_SYMBOL_NAME(name) _/**/name
#endif

The following logic from 1.11.0 acinclude.m4 cannot possibly work to detect _ at the beginning of symbol names:

if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
  # See whether the symbols have a leading underscore.
  if $GREP ' _nm_test_func$' "$nlist" >/dev/null; then
    ac_cv_sys_symbol_underscore=yes

$lt_cv_sys_global_symbol_pipe expands to:

sed -n -e 's/^.*[	 ]\([BCDEGRST][BCDEGRST]*\)[	 ][	 ]*_\([_A-Za-z][_A-Za-z0-9]*\)$/\1 _\2 \2/p' | sed '/ __gnu_lto/d'

which generates the following output when the output from nm is run through it:

T _main main
T _nm_test_func nm_test_func

This cannot possibly work correctly when grep ' _nm_test_func$' is invoked on that output because grep is looking for _nm_test_func at the end of a line.

I don't understand why the cut -d \' \' -f 2 was removed from the pipeline in 1.11.0, because that would generate the following output:

_main
_nm_test_func

That is a lot closer to what you need to test for with grep.

This diff for 1.11.0 fixes the problem for me:

diff --git a/acinclude.m4 b/acinclude.m4
index 782b7f6a..442ebcdb 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -91,12 +91,12 @@ EOF
   if AC_TRY_EVAL(ac_compile); then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \| cut -d \' \' -f 2 \> $nlist) && test -s "$nlist"; then
       # See whether the symbols have a leading underscore.
-      if $GREP ' _nm_test_func$' "$nlist" >/dev/null; then
+      if $GREP '_nm_test_func$' "$nlist" >/dev/null; then
         ac_cv_sys_symbol_underscore=yes
       else
-        if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+        if $GREP 'nm_test_func$' "$nlist" >/dev/null; then
           :
         else
           echo "configure: cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD

Here is a fix for the issue which preserves the removal of cut:

diff --git a/acinclude.m4 b/acinclude.m4
index 782b7f6a..68fa770d 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -93,10 +93,10 @@ EOF
     nlist=conftest.nm
     if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
       # See whether the symbols have a leading underscore.
-      if $GREP ' _nm_test_func$' "$nlist" >/dev/null; then
+      if $GREP "${lt_cv_sys_prefix_pattern}_nm_test_func" "$nlist" >/dev/null; then
         ac_cv_sys_symbol_underscore=yes
       else
-        if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+        if $GREP "${lt_cv_sys_prefix_pattern}nm_test_func" "$nlist" >/dev/null; then
           :
         else
           echo "configure: cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index c6f534e9..aac5c5cf 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -3752,6 +3752,8 @@ for ac_symprfx in "" "_"; do
   fi
   lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
 
+  lt_cv_sys_prefix_pattern="^\($symcode$symcode*\)[[	       ]]"
+
   # Check to see that the pipe works correctly.
   pipe_works=no

Thanks for the detailed analysis; we will check to tomorrow why this was changed.

Thank you for the report.

The change in question rC656ca459e3d8: m4: Update acinclude.m4 to use $GREP. was done by me, because of the GNU grep 3.8 (2022-09-02):

The egrep and fgrep commands, which have been deprecated since
release 2.5.3 (2007), now warn that they are obsolescent and should
be replaced by grep -E and grep -F.

I referred the implementation of libtool when I changed (which doesn't use cut), but my change was wrong (it's not the fault of original libtool).

I checked the history, and found that rCdb6a84d79e42: Fixed symbol prefix detection. Typo fixes. introduced our own way using cut command.

What I should refer (the upstream) is LT_SYS_SYMBOL_USCORE in libtool/m4/ltdl.m4.

I'm going to fix this.