From 814dffa4b7edb36d3b05c6b96591330e33a82204 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 29 Jun 2021 18:47:55 -0700 Subject: [PATCH] [llvm-objcopy][MachO] Support LC_LINKER_OPTIMIZATION_HINT load command The load command is currently specific to arm64 and holds information for instruction rewriting, e.g. converting a GOT load to an ADR to compute a local address. (On ELF the information is usually conveyed by relocations, e.g. R_X86_64_REX_GOTPCRELX, R_PPC64_TOC16_HA) Reviewed By: alexander-shaposhnikov Differential Revision: https://reviews.llvm.org/D104968 --- .../MachO/lc-linker-optimization-hint.s | 25 ++++++++++++++++++++++ .../llvm-objcopy/MachO/MachOLayoutBuilder.cpp | 11 ++++++++-- llvm/tools/llvm-objcopy/MachO/MachOReader.cpp | 9 ++++++++ llvm/tools/llvm-objcopy/MachO/MachOReader.h | 1 + llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp | 25 ++++++++++++++++++++++ llvm/tools/llvm-objcopy/MachO/MachOWriter.h | 1 + llvm/tools/llvm-objcopy/MachO/Object.cpp | 3 +++ llvm/tools/llvm-objcopy/MachO/Object.h | 3 +++ 8 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 llvm/test/tools/llvm-objcopy/MachO/lc-linker-optimization-hint.s 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 index 0000000..2c2ec6f --- /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 index 8dc4259..6ed2180 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp @@ -251,7 +251,10 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) { 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 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) { 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 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) { // 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.cpp b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp index da47e4b..7d1c29b 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp @@ -151,6 +151,9 @@ Error MachOReader::readLoadCommands(Object &O) const { 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 @@ void MachOReader::readDataInCodeData(Object &O) const { 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 @@ Expected> MachOReader::create() const { readExportInfo(*Obj); readCodeSignature(*Obj); readDataInCodeData(*Obj); + readLinkerOptimizationHint(*Obj); readFunctionStartsData(*Obj); readIndirectSymbolTable(*Obj); readSwiftVersion(*Obj); diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.h b/llvm/tools/llvm-objcopy/MachO/MachOReader.h index b446e02..ca3a021 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.h +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.h @@ -39,6 +39,7 @@ class MachOReader : public Reader { 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/MachOWriter.cpp b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp index 24a9d28..295098e 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp @@ -107,6 +107,16 @@ size_t MachOWriter::totalSize() const { 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 @@ void MachOWriter::writeDataInCodeData() { 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 @@ void MachOWriter::writeTail() { &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/MachOWriter.h b/llvm/tools/llvm-objcopy/MachO/MachOWriter.h index 24d3671..c8c06d6 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.h +++ b/llvm/tools/llvm-objcopy/MachO/MachOWriter.h @@ -48,6 +48,7 @@ class MachOWriter { 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/Object.cpp b/llvm/tools/llvm-objcopy/MachO/Object.cpp index c82dae6..b4f98fa 100644 --- a/llvm/tools/llvm-objcopy/MachO/Object.cpp +++ b/llvm/tools/llvm-objcopy/MachO/Object.cpp @@ -46,6 +46,9 @@ void Object::updateLoadCommandIndexes() { 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; diff --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/tools/llvm-objcopy/MachO/Object.h index 978bd80..207502e 100644 --- a/llvm/tools/llvm-objcopy/MachO/Object.h +++ b/llvm/tools/llvm-objcopy/MachO/Object.h @@ -313,6 +313,7 @@ struct Object { ExportInfo Exports; IndirectSymbolTable IndirectSymTable; LinkData DataInCode; + LinkData LinkerOptimizationHint; LinkData FunctionStarts; LinkData CodeSignature; @@ -328,6 +329,8 @@ struct Object { 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; -- 2.7.4