diff options
-rw-r--r-- | lld/include/lld/ReaderWriter/MachOLinkingContext.h | 8 | ||||
-rw-r--r-- | lld/lib/Driver/DarwinLdDriver.cpp | 49 | ||||
-rw-r--r-- | lld/lib/Driver/DarwinLdOptions.td | 6 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFile.h | 1 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp | 15 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp | 4 | ||||
-rw-r--r-- | lld/test/mach-o/data-in-code-load-command.yaml | 35 |
7 files changed, 111 insertions, 7 deletions
diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h index 07380a54ea5..da739b1fe6b 100644 --- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h +++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h @@ -163,6 +163,13 @@ public: _generateFunctionStartsLoadCommand = v; } + bool generateDataInCodeLoadCommand() const { + return _generateDataInCodeLoadCommand; + } + void setGenerateDataInCodeLoadCommand(bool v) { + _generateDataInCodeLoadCommand = v; + } + uint64_t stackSize() const { return _stackSize; } void setStackSize(uint64_t stackSize) { _stackSize = stackSize; } @@ -459,6 +466,7 @@ private: bool _mergeObjCCategories = true; bool _generateVersionLoadCommand = false; bool _generateFunctionStartsLoadCommand = false; + bool _generateDataInCodeLoadCommand = false; StringRef _bundleLoader; mutable std::unique_ptr<mach_o::ArchHandler> _archHandler; mutable std::unique_ptr<Writer> _writer; diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp index ae8a04e1bad..37348765721 100644 --- a/lld/lib/Driver/DarwinLdDriver.cpp +++ b/lld/lib/Driver/DarwinLdDriver.cpp @@ -840,6 +840,55 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args, } } + // Handle -data_in_code_info or -no_data_in_code_info + { + bool flagOn = false; + bool flagOff = false; + if (auto *arg = parsedArgs.getLastArg(OPT_data_in_code_info, + OPT_no_data_in_code_info)) { + flagOn = arg->getOption().getID() == OPT_data_in_code_info; + flagOff = arg->getOption().getID() == OPT_no_data_in_code_info; + } + + // default to adding data in code for dynamic code, static code must + // opt-in + switch (ctx.outputMachOType()) { + case llvm::MachO::MH_OBJECT: + if (!flagOff) + ctx.setGenerateDataInCodeLoadCommand(true); + break; + case llvm::MachO::MH_EXECUTE: + // dynamic executables default to generating a version load command, + // while static exectuables only generate it if required. + if (isStaticExecutable) { + if (flagOn) + ctx.setGenerateDataInCodeLoadCommand(true); + } else { + if (!flagOff) + ctx.setGenerateDataInCodeLoadCommand(true); + } + break; + case llvm::MachO::MH_PRELOAD: + case llvm::MachO::MH_KEXT_BUNDLE: + if (flagOn) + ctx.setGenerateDataInCodeLoadCommand(true); + break; + case llvm::MachO::MH_DYLINKER: + case llvm::MachO::MH_DYLIB: + case llvm::MachO::MH_BUNDLE: + if (!flagOff) + ctx.setGenerateDataInCodeLoadCommand(true); + break; + case llvm::MachO::MH_FVMLIB: + case llvm::MachO::MH_DYLDLINK: + case llvm::MachO::MH_DYLIB_STUB: + case llvm::MachO::MH_DSYM: + // We don't generate load commands for these file types, even if + // forced on. + break; + } + } + // Handle sdk_version if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_sdk_version)) { uint32_t sdkVersion = 0; diff --git a/lld/lib/Driver/DarwinLdOptions.td b/lld/lib/Driver/DarwinLdOptions.td index 9550b127817..fa07f33646e 100644 --- a/lld/lib/Driver/DarwinLdOptions.td +++ b/lld/lib/Driver/DarwinLdOptions.td @@ -49,6 +49,12 @@ def function_starts : Flag<["-"], "function_starts">, def no_function_starts : Flag<["-"], "no_function_starts">, HelpText<"Disable generation of a function starts load command">, Group<grp_opts>; +def data_in_code_info : Flag<["-"], "data_in_code_info">, + HelpText<"Force generation of a data in code load command">, + Group<grp_opts>; +def no_data_in_code_info : Flag<["-"], "no_data_in_code_info">, + HelpText<"Disable generation of a data in code load command">, + Group<grp_opts>; def mllvm : Separate<["-"], "mllvm">, MetaVarName<"<option>">, HelpText<"Options to pass to LLVM during LTO">, Group<grp_opts>; diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h index 532831212b3..400a30b8930 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h @@ -247,6 +247,7 @@ struct NormalizedFile { PackedVersion currentVersion = 0; // dylibs only bool hasUUID = false; bool hasMinVersionLoadCommand = false; + bool generateDataInCodeLoadCommand = false; std::vector<StringRef> rpaths; Hex64 entryAddress = 0; Hex64 stackSize = 0; diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp index d85920f7e19..34c48a500b9 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp @@ -288,7 +288,7 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file) _endOfLoadCommands += sizeof(linkedit_data_command); _countOfLoadCommands++; } - if (!_file.dataInCode.empty()) { + if (_file.generateDataInCodeLoadCommand) { _endOfLoadCommands += sizeof(linkedit_data_command); _countOfLoadCommands++; } @@ -463,8 +463,9 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) { ++count; } - // Add LC_DATA_IN_CODE if needed - if (!_file.dataInCode.empty()) { + // Add LC_DATA_IN_CODE if requested. Note, we do encode zero length entries. + // FIXME: Zero length entries is only to match ld64. Should we change this? + if (_file.generateDataInCodeLoadCommand) { size += sizeof(linkedit_data_command); ++count; } @@ -810,8 +811,8 @@ std::error_code MachOFileLayout::writeLoadCommands() { lc += sizeof(linkedit_data_command); } - // Add LC_DATA_IN_CODE if needed. - if (_dataInCodeSize != 0) { + // Add LC_DATA_IN_CODE if requested. + if (_file.generateDataInCodeLoadCommand) { linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc); dl->cmd = LC_DATA_IN_CODE; dl->cmdsize = sizeof(linkedit_data_command); @@ -993,8 +994,8 @@ std::error_code MachOFileLayout::writeLoadCommands() { lc += sizeof(linkedit_data_command); } - // Add LC_DATA_IN_CODE if needed. - if (_dataInCodeSize != 0) { + // Add LC_DATA_IN_CODE if requested. + if (_file.generateDataInCodeLoadCommand) { linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc); dl->cmd = LC_DATA_IN_CODE; dl->cmdsize = sizeof(linkedit_data_command); diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index d3929bdf281..b34f70343cd 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -1186,6 +1186,8 @@ void Util::addFunctionStarts(const lld::File &, NormalizedFile &file) { } void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) { + if (!_ctx.generateDataInCodeLoadCommand()) + return; for (SectionInfo *si : _sectionInfos) { for (const AtomInfo &info : si->atomsAndOffsets) { // Atoms that contain data-in-code have "transition" references @@ -1377,6 +1379,8 @@ normalizedFromAtoms(const lld::File &atomFile, // source object files. normFile.hasMinVersionLoadCommand = true; } + normFile.generateDataInCodeLoadCommand = + context.generateDataInCodeLoadCommand(); normFile.pageSize = context.pageSize(); normFile.rpaths = context.rpaths(); util.addDependentDylibs(atomFile, normFile); diff --git a/lld/test/mach-o/data-in-code-load-command.yaml b/lld/test/mach-o/data-in-code-load-command.yaml new file mode 100644 index 00000000000..604592afcd3 --- /dev/null +++ b/lld/test/mach-o/data-in-code-load-command.yaml @@ -0,0 +1,35 @@ +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml && llvm-objdump -private-headers %t | FileCheck %s +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -no_data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -data_in_code_info -no_data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -r && llvm-objdump -private-headers %t | FileCheck %s +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -r -data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -r -no_data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO + +--- !mach-o +arch: x86_64 +file-type: MH_OBJECT +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ] +sections: + - segment: __TEXT + section: __text + type: S_REGULAR + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] + address: 0x0000000000000000 + content: [ 0x00, 0x00, 0x00, 0x00 ] +global-symbols: + - name: _main + type: N_SECT + scope: [ N_EXT ] + sect: 1 + value: 0x0000000000000000 +... + +# CHECK: Load command {{[0-9]*}} +# CHECK: cmd LC_DATA_IN_CODE +# CHECK: cmdsize 16 +# CHECK: dataoff +# CHECK: datasize + +# NO_DATA_IN_CODE_INFO-NOT: LC_DATA_IN_CODE |