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 does not leave the same amount of install_name header padding as ld64 #53550

Open rsesek opened 2 years ago

rsesek commented 2 years ago

I've noticed that Mach-O lld does not leave the same amount of padding in the output image as ld64, which means sometimes install_name_tool can fail. Small example:

dylib.c

int __attribute__((visibility("default"))) GetRandomNumber() {
  return 42;
}

exe.c

#include <stdio.h>

extern int GetRandomNumber();

int main() {
  printf("random number = %d\n", GetRandomNumber());
}

Then run the following commands (you may need to tweak -isysroot) using ld64:

% clang -shared -olibsmallrandom.dylib -Wl,-install_name,libsmallrandom.dylib dylib.c -isysroot ~/sdk/mac
% clang -o exe -L. -lsmallrandom -framework AppKit -framework AVFoundation exe.c -isysroot ~/sdk/mac
% install_name_tool -change libsmallrandom.dylib @executable_path/../../Frameworks/Random.framework/Frameworks/libsmallrandom.dylib ./exe

Then repeat with lld:

% clang -shared -olibsmallrandom.dylib -Wl,-install_name,libsmallrandom.dylib dylib.c -isysroot ~/sdk/mac -fuse-ld=lld
% clang -o exe -L. -lsmallrandom -framework AppKit -framework AVFoundation exe.c -isysroot ~/sdk/mac -fuse-ld=lld
% install_name_tool -change libsmallrandom.dylib @executable_path/../../Frameworks/Random.framework/Frameworks/libsmallrandom.dylib ./exe
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: changing install names or rpaths can't be redone for: ./exe (for architecture x86_64) because larger updated load commands do not fit (the program must be relinked, and you may need to use -headerpad or -headerpad_max_install_names)

If you repeat the link of exe.c with -Wl,-headerpad_max_install_names then it succeeds.

The repro also requires adding some other dependent dylibs so that the padding that lld does leave gets consumed.

I'm not sure this is a bug per se, or just an acceptable change in behavior. I actually think it'd be preferable to address issue #53549 rather than changing this.

llvmbot commented 2 years ago

@llvm/issue-subscribers-lld-macho

int3 commented 2 years ago

Yeah, this is a known deviation in behavior. See the commit message in https://reviews.llvm.org/D84714. Only thing really stopping us is implementation complexity. I've punted on it since the workaround (-headerpad and -headerpad_max_install_names like you mentioned) seem easy enough.

I guess the advantage of implementing #53549 is that we don't have to waste any space at all in the header...