Opened 4 years ago

Closed 4 years ago

#59983 closed defect (worksforme)

ld64-latest@274.2_2+llvm80+universal-llvm34 :dyld: Symbol not found: _lto_module_is_thinlto

Reported by: kencu (Ken) Owned by: kencu (Ken)
Priority: Normal Milestone:
Component: ports Version:
Keywords: Cc: jeremyhu (Jeremy Huddleston Sequoia)
Port: ld64

Description

While building libtapi on 10.6.8 using clang-3.7, the following link error occurs:

cd /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_tarballs_ports_devel_libtapi/libtapi/work/build/tools/clang/utils/TableGen && /opt/local/bin/cmake -E cmake_link_script CMakeFiles/clang-tblgen.dir/link.txt --verbose=ON
/opt/local/bin/clang++-mp-3.7  -Wno-unknown-warning-option -Werror=unguarded-availability-new -stdlib=libc++ -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -std=c++11 -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wcovered-switch-default -Wno-class-memaccess -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wstring-conversion -flto -fno-common -Woverloaded-virtual -Os    -DNDEBUG -arch x86_64 -mmacosx-version-min=10.6 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -L/opt/local/lib -Wl,-headerpad_max_install_names -stdlib=libc++ -flto  -Wl,-dead_strip -Wl,-object_path_lto,/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_tarballs_ports_devel_libtapi/libtapi/work/build/tools/clang/utils/TableGen/./clang-tblgen-lto.o CMakeFiles/obj.clang-tblgen.dir/ClangASTNodesEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/ClangAttrEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/ClangCommentCommandInfoEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/ClangCommentHTMLTagsEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/ClangDataCollectorsEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/ClangDiagnosticsEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/ClangOptionDocEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/ClangSACheckersEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/NeonEmitter.cpp.o CMakeFiles/obj.clang-tblgen.dir/TableGen.cpp.o  -o ../../../../bin/clang-tblgen  -Wl,-rpath,/opt/local/lib ../../../../lib/libLLVMSupport.a ../../../../lib/libLLVMTableGen.a ../../../../lib/libLLVMSupport.a -lm ../../../../lib/libLLVMDemangle.a 
dyld: lazy symbol binding failed: Symbol not found: _lto_module_is_thinlto
  Referenced from: /opt/local/libexec/llvm-3.7/bin/ld
  Expected in: /opt/local/libexec/llvm-3.7/bin/../lib/libLTO.dylib

dyld: Symbol not found: _lto_module_is_thinlto
  Referenced from: /opt/local/libexec/llvm-3.7/bin/ld
  Expected in: /opt/local/libexec/llvm-3.7/bin/../lib/libLTO.dylib

ld64-latest has been built with thinlto support, it appears, but this support is not found in the libLTO.dylib that is being referenced.

examining ld64-latest, I note that the previous version used a fixed reference to the libLTO.dylib that it was built against:

$ sudo port activate ld64-latest
The following versions of ld64-latest are currently installed:
 1) ld64-latest @274.2_2+llvm39+universal
 2) ld64-latest @274.2_2+llvm80+universal (active)
Enter a number to select an option: 1
--->  Deactivating ld64-latest @274.2_2+llvm80+universal
--->  Cleaning ld64-latest
--->  Activating ld64-latest @274.2_2+llvm39+universal

$ otool -L /opt/local/bin/ld-latest
/opt/local/bin/ld-latest:
	/opt/local/libexec/llvm-3.9/lib/libLTO.dylib (compatibility version 1.0.0, current version 3.9.1)
	/usr/lib/libc++abi.dylib (compatibility version 1.0.0, current version 3.9.1)
	/opt/local/lib/libxar.1.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 3.9.1)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)

but the new version, built against llvm80, uses an @rpath reference to libLTO.dylib, and presumably that is getting confused in the build error above, and finding the old libLTO.dylib from llvm-3.7 instead of the one ld64-latest was built against:

$ port -v installed | grep ld64
  ld64 @3_1+universal-ld64_127-ld64_236-ld64_97 (active) platform='darwin 10' archs='i386 x86_64' date='2018-09-20T16:56:39-0700'
  ld64-236 @236.3_8+llvm39+universal-llvm34 (active) platform='darwin 10' archs='i386 x86_64' date='2018-01-11T17:34:16-0800'
  ld64-latest @274.2_2+llvm39+universal-llvm34 platform='darwin 10' archs='i386 x86_64' date='2017-11-26T13:19:27-0800'
  ld64-latest @274.2_2+llvm80+universal-llvm34 (active) platform='darwin 10' archs='i386 x86_64' date='2019-12-29T15:03:58-0800'


$ file /opt/local/bin/ld-latest
/opt/local/bin/ld-latest: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|BINDS_TO_WEAK|PIE>] [i386]

$ otool -L /opt/local/bin/ld-latest
/opt/local/bin/ld-latest:
	@rpath/libLTO.dylib (compatibility version 1.0.0, current version 8.0.1)
	/usr/lib/libc++abi.dylib (compatibility version 1.0.0, current version 5.0.1)
	/opt/local/lib/libxar.1.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 5.0.1)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)

It looks like ld64-latest will need to be built against a fully-specified libLTO.dylib to function properly, and the @rpath reference to libLTO.dylib is unreliable.

Change History (4)

comment:1 Changed 4 years ago by kencu (Ken)

what I'm describing above is specifically not supposed to happen, and is supposed to be fixed up by this block in the portfile:

    post-destroot {
        # ${prefix}/bin/ld will always use the llvm we built against
        # ${prefix}/libexec/ld64/ld uses relative linking for use with the llvm ports
        file mkdir ${destroot}${prefix}/libexec/ld64
        file copy ${destroot}${prefix}/bin/ld ${destroot}${prefix}/libexec/ld64/ld-${ld64_ver}

        file rename ${destroot}${prefix}/bin/dyldinfo ${destroot}${prefix}/bin/dyldinfo-${ld64_ver}
        file rename ${destroot}${prefix}/bin/ld ${destroot}${prefix}/bin/ld-${ld64_ver}
        file rename ${destroot}${prefix}/bin/machocheck ${destroot}${prefix}/bin/machocheck-${ld64_ver}
        file rename ${destroot}${prefix}/bin/ObjectDump ${destroot}${prefix}/bin/ObjectDump-${ld64_ver}
        file rename ${destroot}${prefix}/bin/rebase ${destroot}${prefix}/bin/rebase-${ld64_ver}
        file rename ${destroot}${prefix}/bin/unwinddump ${destroot}${prefix}/bin/unwinddump-${ld64_ver}

        delete {*}[glob ${destroot}${prefix}/share/man/man1/*]

        if {${llvm_version} != ""} {
            system "install_name_tool -change ${prefix}/libexec/llvm-${llvm_version}/lib/libLTO.dylib \
                    @executable_path/../lib/libLTO.dylib ${destroot}${prefix}/libexec/ld64/ld-${ld64_ver}"
            system "install_name_tool -change @rpath/libLTO.dylib \
                    @executable_path/../lib/libLTO.dylib ${destroot}${prefix}/libexec/ld64/ld-${ld64_ver}"
        }
    }

I will have to see why that doesn't appear to have happened. Perhaps just a rebuild of ld64-latest might fix it up for me...

comment:2 Changed 4 years ago by kencu (Ken)

even so, the RPATH is set right in the /opt/local/bin/ld binary:

$ otool -l /opt/local/bin/ld | grep RPATH -A2
          cmd LC_RPATH
      cmdsize 48
         path /opt/local/libexec/llvm-8.0/lib (offset 12)

So perhaps - this is all working as it should, as per the comments in the post-destroot phase above.

comment:3 Changed 4 years ago by kencu (Ken)

I think perhaps this is related to some unprotected usage of that symbol, such as was managed here <https://github.com/macports/macports-ports/blob/master/devel/ld64/files/PR-29723629.patch>.

comment:4 Changed 4 years ago by kencu (Ken)

Resolution: worksforme
Status: assignedclosed

I'm going to close this as expected behaviour for now -- I'll reopen it if there's actually something here to fix.

Note: See TracTickets for help on using tickets.