diff --git a/llvm/test/tools/llvm-objcopy/MachO/lc-linker-optimization-hint.s b/llvm/test/tools/llvm-objcopy/MachO/lc-linker-optimization-hint.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/lc-linker-optimization-hint.s @@ -0,0 +1,25 @@ +# REQUIRES: aarch64-registered-target +## Test that we can copy LC_LINKER_OPTIMIZATION_HINT. + +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t.o +# RUN: llvm-objdump --macho --link-opt-hints - < %t.o > %tloh.txt +# RUN: FileCheck --input-file=%tloh.txt %s + +# CHECK: Linker optimiztion hints (8 total bytes) +# CHECK-NEXT: identifier 7 AdrpAdd + +# RUN: llvm-objcopy %t.o %t.copy.o +# RUN: llvm-objdump --macho --link-opt-hints - < %t.copy.o | diff %tloh.txt - + +.text +.align 2 +_test: +L1: + adrp x0, _foo@PAGE +L2: + add x0, x0, _foo@PAGEOFF +.loh AdrpAdd L1, L2 + +.data +_foo: + .long 0 diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp @@ -251,7 +251,10 @@ uint64_t StartOfFunctionStarts = StartOfExportTrie + O.Exports.Trie.size(); uint64_t StartOfDataInCode = StartOfFunctionStarts + O.FunctionStarts.Data.size(); - uint64_t StartOfSymbols = StartOfDataInCode + O.DataInCode.Data.size(); + uint64_t StartOfLinkerOptimizationHint = + StartOfDataInCode + O.DataInCode.Data.size(); + uint64_t StartOfSymbols = + StartOfLinkerOptimizationHint + O.LinkerOptimizationHint.Data.size(); uint64_t StartOfIndirectSymbols = StartOfSymbols + NListSize * O.SymTable.Symbols.size(); uint64_t StartOfSymbolStrings = @@ -320,6 +323,11 @@ MLC.linkedit_data_command_data.dataoff = StartOfDataInCode; MLC.linkedit_data_command_data.datasize = O.DataInCode.Data.size(); break; + case MachO::LC_LINKER_OPTIMIZATION_HINT: + MLC.linkedit_data_command_data.dataoff = StartOfLinkerOptimizationHint; + MLC.linkedit_data_command_data.datasize = + O.LinkerOptimizationHint.Data.size(); + break; case MachO::LC_FUNCTION_STARTS: MLC.linkedit_data_command_data.dataoff = StartOfFunctionStarts; MLC.linkedit_data_command_data.datasize = O.FunctionStarts.Data.size(); @@ -355,7 +363,6 @@ // LC_ENCRYPT_INFO/LC_ENCRYPTION_INFO_64 need to be adjusted. case MachO::LC_ENCRYPTION_INFO: case MachO::LC_ENCRYPTION_INFO_64: - case MachO::LC_LINKER_OPTIMIZATION_HINT: case MachO::LC_LOAD_DYLINKER: case MachO::LC_MAIN: case MachO::LC_RPATH: diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.h b/llvm/tools/llvm-objcopy/MachO/MachOReader.h --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.h +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.h @@ -39,6 +39,7 @@ void readLinkData(Object &O, Optional LCIndex, LinkData &LD) const; void readCodeSignature(Object &O) const; void readDataInCodeData(Object &O) const; + void readLinkerOptimizationHint(Object &O) const; void readFunctionStartsData(Object &O) const; void readIndirectSymbolTable(Object &O) const; void readSwiftVersion(Object &O) const; diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp @@ -151,6 +151,9 @@ case MachO::LC_DATA_IN_CODE: O.DataInCodeCommandIndex = O.LoadCommands.size(); break; + case MachO::LC_LINKER_OPTIMIZATION_HINT: + O.LinkerOptimizationHintCommandIndex = O.LoadCommands.size(); + break; case MachO::LC_FUNCTION_STARTS: O.FunctionStartsCommandIndex = O.LoadCommands.size(); break; @@ -276,6 +279,11 @@ return readLinkData(O, O.DataInCodeCommandIndex, O.DataInCode); } +void MachOReader::readLinkerOptimizationHint(Object &O) const { + return readLinkData(O, O.LinkerOptimizationHintCommandIndex, + O.LinkerOptimizationHint); +} + void MachOReader::readFunctionStartsData(Object &O) const { return readLinkData(O, O.FunctionStartsCommandIndex, O.FunctionStarts); } @@ -330,6 +338,7 @@ readExportInfo(*Obj); readCodeSignature(*Obj); readDataInCodeData(*Obj); + readLinkerOptimizationHint(*Obj); readFunctionStartsData(*Obj); readIndirectSymbolTable(*Obj); readSwiftVersion(*Obj); diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.h b/llvm/tools/llvm-objcopy/MachO/MachOWriter.h --- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.h +++ b/llvm/tools/llvm-objcopy/MachO/MachOWriter.h @@ -48,6 +48,7 @@ void writeLinkData(Optional LCIndex, const LinkData &LD); void writeCodeSignatureData(); void writeDataInCodeData(); + void writeLinkerOptimizationHint(); void writeFunctionStartsData(); void writeTail(); diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp @@ -107,6 +107,16 @@ LinkEditDataCommand.datasize); } + if (O.LinkerOptimizationHintCommandIndex) { + const MachO::linkedit_data_command &LinkEditDataCommand = + O.LoadCommands[*O.LinkerOptimizationHintCommandIndex] + .MachOLoadCommand.linkedit_data_command_data; + + if (LinkEditDataCommand.dataoff) + Ends.push_back(LinkEditDataCommand.dataoff + + LinkEditDataCommand.datasize); + } + if (O.FunctionStartsCommandIndex) { const MachO::linkedit_data_command &LinkEditDataCommand = O.LoadCommands[*O.FunctionStartsCommandIndex] @@ -421,6 +431,11 @@ return writeLinkData(O.DataInCodeCommandIndex, O.DataInCode); } +void MachOWriter::writeLinkerOptimizationHint() { + return writeLinkData(O.LinkerOptimizationHintCommandIndex, + O.LinkerOptimizationHint); +} + void MachOWriter::writeFunctionStartsData() { return writeLinkData(O.FunctionStartsCommandIndex, O.FunctionStarts); } @@ -490,6 +505,16 @@ &MachOWriter::writeDataInCodeData); } + if (O.LinkerOptimizationHintCommandIndex) { + const MachO::linkedit_data_command &LinkEditDataCommand = + O.LoadCommands[*O.LinkerOptimizationHintCommandIndex] + .MachOLoadCommand.linkedit_data_command_data; + + if (LinkEditDataCommand.dataoff) + Queue.emplace_back(LinkEditDataCommand.dataoff, + &MachOWriter::writeLinkerOptimizationHint); + } + if (O.FunctionStartsCommandIndex) { const MachO::linkedit_data_command &LinkEditDataCommand = O.LoadCommands[*O.FunctionStartsCommandIndex] diff --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/tools/llvm-objcopy/MachO/Object.h --- a/llvm/tools/llvm-objcopy/MachO/Object.h +++ b/llvm/tools/llvm-objcopy/MachO/Object.h @@ -313,6 +313,7 @@ ExportInfo Exports; IndirectSymbolTable IndirectSymTable; LinkData DataInCode; + LinkData LinkerOptimizationHint; LinkData FunctionStarts; LinkData CodeSignature; @@ -328,6 +329,8 @@ Optional DySymTabCommandIndex; /// The index LC_DATA_IN_CODE load comamnd if present. Optional DataInCodeCommandIndex; + /// The index of LC_LINKER_OPTIMIZATIN_HINT load comamnd if present. + Optional LinkerOptimizationHintCommandIndex; /// The index LC_FUNCTION_STARTS load comamnd if present. Optional FunctionStartsCommandIndex; diff --git a/llvm/tools/llvm-objcopy/MachO/Object.cpp b/llvm/tools/llvm-objcopy/MachO/Object.cpp --- a/llvm/tools/llvm-objcopy/MachO/Object.cpp +++ b/llvm/tools/llvm-objcopy/MachO/Object.cpp @@ -46,6 +46,9 @@ case MachO::LC_DATA_IN_CODE: DataInCodeCommandIndex = Index; break; + case MachO::LC_LINKER_OPTIMIZATION_HINT: + LinkerOptimizationHintCommandIndex = Index; + break; case MachO::LC_FUNCTION_STARTS: FunctionStartsCommandIndex = Index; break;