diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -37,6 +37,7 @@ bool forceLoadObjC = false; bool staticLink = false; bool searchDylibsFirst = false; + bool headerPadMaxInstallNames = false; uint32_t headerPad; llvm::StringRef installName; llvm::StringRef outputFile; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -524,6 +524,8 @@ config->installName = args.getLastArgValue(OPT_install_name, config->outputFile); config->headerPad = args::getHex(args, OPT_headerpad, /*Default=*/32); + config->headerPadMaxInstallNames = + args.hasArg(OPT_headerpad_max_install_names); config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE; config->runtimePaths = args::getStrings(args, OPT_rpath); config->allLoad = args.hasArg(OPT_all_load); @@ -606,6 +608,7 @@ case OPT_L: case OPT_ObjC: case OPT_headerpad: + case OPT_headerpad_max_install_names: case OPT_install_name: case OPT_rpath: case OPT_sub_library: diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -687,11 +687,10 @@ Group; def headerpad : Separate<["-"], "headerpad">, MetaVarName<"">, - HelpText<"Allocate hex extra space for future expansion of the load commands via install_name_tool">, + HelpText<"Allocate hex extra space for future expansion of the load commands via install_name_tool (default is 0x20)">, Group; def headerpad_max_install_names : Flag<["-"], "headerpad_max_install_names">, HelpText<"Allocate extra space so all load-command paths can expand to MAXPATHLEN via install_name_tool">, - Flags<[HelpHidden]>, Group; def bind_at_load : Flag<["-"], "bind_at_load">, HelpText<"Tell dyld to bind all symbols at load time, rather than lazily">, diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -47,7 +47,7 @@ } uint64_t MachHeaderSection::getSize() const { - return sizeof(MachO::mach_header_64) + sizeOfCmds + config->headerPad; + return (sizeof(MachO::mach_header_64) + sizeOfCmds + config->headerPad); } void MachHeaderSection::writeTo(uint8_t *buf) const { diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -27,6 +27,8 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" +#include + using namespace llvm; using namespace llvm::MachO; using namespace lld; @@ -208,7 +210,9 @@ // * LC_REEXPORT_DYLIB class LCDylib : public LoadCommand { public: - LCDylib(LoadCommandType type, StringRef path) : type(type), path(path) {} + LCDylib(LoadCommandType type, StringRef path) : type(type), path(path) { + instanceCount++; + } uint32_t getSize() const override { return alignTo(sizeof(dylib_command) + path.size() + 1, 8); @@ -226,11 +230,16 @@ buf[path.size()] = '\0'; } + static uint32_t getInstanceCount() { return instanceCount; } + private: LoadCommandType type; StringRef path; + static uint32_t instanceCount; }; +uint32_t LCDylib::instanceCount = 0; + class LCLoadDylinker : public LoadCommand { public: uint32_t getSize() const override { @@ -366,6 +375,12 @@ make(LC_REEXPORT_DYLIB, dylibFile->dylibName)); } } + + const uint32_t MACOS_MAXPATHLEN = 1024; + config->headerPad = std::max( + config->headerPad, (config->headerPadMaxInstallNames + ? LCDylib::getInstanceCount() * MACOS_MAXPATHLEN + : 0)); } static size_t getSymbolPriority(const SymbolPriorityEntry &entry, diff --git a/lld/test/MachO/headerpad.s b/lld/test/MachO/headerpad.s --- a/lld/test/MachO/headerpad.s +++ b/lld/test/MachO/headerpad.s @@ -9,30 +9,78 @@ ## alignment behavior. # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o +# RUN: lld -flavor darwinnew -o %t %t.o +# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=PADx +# +# PADx: magic {{.+}} ncmds sizeofcmds flags +# PADx-NEXT: MH_MAGIC_64 {{.+}} 9 [[#%u, CMDSIZE:]] {{.*}} +# PADx: sectname __text +# PADx-NEXT: segname __TEXT +# PADx-NEXT: addr +# PADx-NEXT: size +# PADx-NEXT: offset [[#%u, CMDSIZE + 0x20 + 0x20]] + # RUN: lld -flavor darwinnew -o %t %t.o -headerpad 0 # RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=PAD0 -# PAD0: magic cputype cpusubtype caps filetype ncmds sizeofcmds flags -# PAD0-NEXT: MH_MAGIC_64 X86_64 ALL LIB64 EXECUTE 9 [[#%u, CMDSIZE:]] {{.*}} +# RUN: lld -flavor darwinnew -o %t %t.o -headerpad 0 -headerpad_max_install_names +# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=PAD0 +# +# PAD0: magic {{.+}} ncmds sizeofcmds flags +# PAD0-NEXT: MH_MAGIC_64 {{.+}} 9 [[#%u, CMDSIZE:]] {{.*}} # PAD0: sectname __text # PAD0-NEXT: segname __TEXT # PAD0-NEXT: addr # PAD0-NEXT: size -# PAD0-NEXT: offset [[#%u, CMDSIZE + 32]] +# PAD0-NEXT: offset [[#%u, CMDSIZE + 0x20 + 0]] # RUN: lld -flavor darwinnew -o %t %t.o -headerpad 11 # RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=PAD11 # RUN: lld -flavor darwinnew -o %t %t.o -headerpad 0x11 # RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=PAD11 -# RUN: lld -flavor darwinnew -o %t %t.o -headerpad 0X11 +# RUN: lld -flavor darwinnew -o %t %t.o -headerpad 0X11 -headerpad_max_install_names # RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=PAD11 - +# # PAD11: magic {{.+}} ncmds sizeofcmds flags # PAD11-NEXT: MH_MAGIC_64 {{.+}} 9 [[#%u, CMDSIZE:]] {{.*}} # PAD11: sectname __text # PAD11-NEXT: segname __TEXT # PAD11-NEXT: addr # PAD11-NEXT: size -# PAD11-NEXT: offset [[#%u, CMDSIZE + 32 + 0x11]] +# PAD11-NEXT: offset [[#%u, CMDSIZE + 0x20 + 0x11]] + +# RUN: echo "" | llvm-mc -filetype=obj -triple=x86_64-apple-darwin -o %T/null.o +# RUN: lld -flavor darwinnew -o %T/libnull.dylib %T/null.o -dylib \ +# RUN: -headerpad_max_install_names +# RUN: llvm-objdump --macho --all-headers %T/libnull.dylib | FileCheck %s --check-prefix=PADMAX +# RUN: lld -flavor darwinnew -o %T/libnull.dylib %T/null.o -dylib \ +# RUN: -headerpad_max_install_names \ +# RUN: -syslibroot %S/Inputs/MacOSX.sdk -lSystem +# RUN: llvm-objdump --macho --all-headers %T/libnull.dylib | FileCheck %s --check-prefix=PADMAX +# RUN: lld -flavor darwinnew -o %T/libnull.dylib %T/null.o -dylib \ +# RUN: -headerpad_max_install_names \ +# RUN: -syslibroot %S/Inputs/MacOSX.sdk -lSystem -sub_library libSystem +# RUN: llvm-objdump --macho --all-headers %T/libnull.dylib | FileCheck %s --check-prefix=PADMAX +# +# PADMAX: magic {{.+}} ncmds sizeofcmds flags +# PADMAX-NEXT: MH_MAGIC_64 {{.+}} [[#%u, N:]] [[#%u, CMDSIZE:]] {{.*}} +# PADMAX: sectname __text +# PADMAX-NEXT: segname __TEXT +# PADMAX-NEXT: addr +# PADMAX-NEXT: size +# PADMAX-NEXT: offset [[#%u, CMDSIZE + 0x20 + mul(0x400, N - 6)]] + +# RUN: lld -flavor darwinnew -o %T/libnull.dylib %T/null.o -dylib \ +# RUN: -headerpad_max_install_names -headerpad 0x1001 \ +# RUN: -syslibroot %S/Inputs/MacOSX.sdk -lSystem -sub_library libSystem +# RUN: llvm-objdump --macho --all-headers %T/libnull.dylib | FileCheck %s --check-prefix=PADOVR +# +# PADOVR: magic {{.+}} ncmds sizeofcmds flags +# PADOVR-NEXT: MH_MAGIC_64 {{.+}} [[#%u, N:]] [[#%u, CMDSIZE:]] {{.*}} +# PADOVR: sectname __text +# PADOVR-NEXT: segname __TEXT +# PADOVR-NEXT: addr +# PADOVR-NEXT: size +# PADOVR-NEXT: offset [[#%u, CMDSIZE + 0x20 + 0x1001]] .globl _main _main: