llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.69k stars 11.87k forks source link

LLD/mac cannot link with dylib missing LC_DYLD_INFO_ONLY and LC_DYLD_EXPORTS_TRIE #64865

Open rubenvb opened 1 year ago

rubenvb commented 1 year ago

I tried using LLD for a work project which links to the Merge DICOM library (proprietary and paid unfortunately, although a trial which is definitely enough for this issue, might be procured here), and LLD 16.0.0 gives me this error:

ld64.lld: error: No LC_DYLD_INFO_ONLY or LC_DYLD_EXPORTS_TRIE found in <path-to>/mc3adv.dylib

This is a x86_64 dylib being linked into a x86_64 application (or dylib) on an M1 Mac, but that shouldn't change much.

The error is followed by a list of undefined references to symbols contained in mc3adv.dylib:

ld64.lld: error: undefined symbol: MC_Error_Message

I am most likely not allowed to provide you with the dylib, nor do I know how it was created. I can, though provide any output of diagnostic tools (e.g. otool or nm or objdump or...) if you can tell me what exactly it would be I need to do. It seems LLD does not know how to find the symbols in this dylib, but ld64 of course makes no issue in linking it.

llvmbot commented 1 year ago

@llvm/issue-subscribers-lld-macho

rubenvb commented 1 year ago

The error originates here (unsurprisingly) in the LLD code: https://github.com/llvm/llvm-project/blob/main/lld/MachO/InputFiles.cpp#L1734

otool -l output: https://gist.github.com/rubenvb/5f58c38b71ac35db0f4a5eedd223cfc3

No other otool output options seem to provide anything useful for this part of LLD. There's an indirect symbol table otool -I, there are relocation entries otool -r, and this is the Mach header:

Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777223          3  0x00           6    11       1856 0x00100004

Inspecting the ld64 source code, this all seems to point to a very old dylib:

// this is an old binary (before macOS 10.6), scan the symbol table

in this file: https://opensource.apple.com/source/dyld/dyld-733.8/dyld3/MachOLoaded.cpp.auto.html

Of course there are newer versions of this library (which may not have this arcane structure) but I suppose it is not obsolete to handle this scenario in LLD?

rubenvb commented 8 months ago

It seems LLD is missing the equivqlent of the buildExportHashTableFromSymbolTable branch in InputFiles.cpp I linked previously, that ld64 does perform:

// build hash table
if ( dyldInfo != nullptr )
    buildExportHashTableFromExportInfo(dyldInfo->export_off(), dyldInfo->export_size(), fileContent);
else if ( exportsTrie != nullptr )
    buildExportHashTableFromExportInfo(exportsTrie->dataoff(), exportsTrie->datasize(), fileContent);
else
    buildExportHashTableFromSymbolTable(dynamicInfo, symbolTable, strings, fileContent);

See https://opensource.apple.com/source/ld64/ld64-609/src/ld/parsers/macho_dylib_file.cpp.auto.html