diff --git a/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp index 93bc6631e64c8..d4eb6a9b9fc0b 100644 --- a/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp @@ -116,6 +116,11 @@ uint64_t MachOLayoutBuilder::layoutSegments() { const bool IsObjectFile = O.Header.FileType == MachO::HeaderFileType::MH_OBJECT; uint64_t Offset = IsObjectFile ? (HeaderSize + O.Header.SizeOfCmds) : 0; + if (O.EncryptionInfoCommandIndex) { + // If we are emitting an encryptable binary, our load commands must have a + // separate (non-encrypted) page to themselves. + Offset = alignToPowerOf2(HeaderSize + O.Header.SizeOfCmds, PageSize); + } for (LoadCommand &LC : O.LoadCommands) { auto &MLC = LC.MachOLoadCommand; StringRef Segname; diff --git a/llvm/lib/ObjCopy/MachO/MachOObject.cpp b/llvm/lib/ObjCopy/MachO/MachOObject.cpp index d593d6788e112..fe4b1cf4b12ae 100644 --- a/llvm/lib/ObjCopy/MachO/MachOObject.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOObject.cpp @@ -85,6 +85,10 @@ void Object::updateLoadCommandIndexes() { case MachO::LC_DYLD_EXPORTS_TRIE: ExportsTrieCommandIndex = Index; break; + case MachO::LC_ENCRYPTION_INFO: + case MachO::LC_ENCRYPTION_INFO_64: + EncryptionInfoCommandIndex = Index; + break; } } } diff --git a/llvm/lib/ObjCopy/MachO/MachOObject.h b/llvm/lib/ObjCopy/MachO/MachOObject.h index b3303fd291c82..b616677b83dcb 100644 --- a/llvm/lib/ObjCopy/MachO/MachOObject.h +++ b/llvm/lib/ObjCopy/MachO/MachOObject.h @@ -340,6 +340,9 @@ struct Object { /// The index of the LC_SEGMENT or LC_SEGMENT_64 load command /// corresponding to the __TEXT segment. std::optional TextSegmentCommandIndex; + /// The index of the LC_ENCRYPTION_INFO or LC_ENCRYPTION_INFO_64 load command + /// if present. + std::optional EncryptionInfoCommandIndex; BumpPtrAllocator Alloc; StringSaver NewSectionsContents; diff --git a/llvm/lib/ObjCopy/MachO/MachOReader.cpp b/llvm/lib/ObjCopy/MachO/MachOReader.cpp index 2b344f36d8e78..ef0e0262f9395 100644 --- a/llvm/lib/ObjCopy/MachO/MachOReader.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOReader.cpp @@ -184,6 +184,10 @@ Error MachOReader::readLoadCommands(Object &O) const { case MachO::LC_DYLD_CHAINED_FIXUPS: O.ChainedFixupsCommandIndex = O.LoadCommands.size(); break; + case MachO::LC_ENCRYPTION_INFO: + case MachO::LC_ENCRYPTION_INFO_64: + O.EncryptionInfoCommandIndex = O.LoadCommands.size(); + break; } #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ case MachO::LCName: \ diff --git a/llvm/test/tools/llvm-objcopy/MachO/strip-with-encryption-info.test b/llvm/test/tools/llvm-objcopy/MachO/strip-with-encryption-info.test new file mode 100644 index 0000000000000..19b06b1ec02c8 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/strip-with-encryption-info.test @@ -0,0 +1,217 @@ +# RUN: rm -rf %t && mkdir %t +# RUN: yaml2obj %s -o %t/original +# RUN: llvm-strip --strip-all %t/original -o %t/stripped +# RUN: llvm-readobj --macho-segment %t/stripped | FileCheck %s + +# CHECK-LABEL: Name: __PAGEZERO +# CHECK: fileoff: 16384 + +# CHECK-LABEL: Name: __TEXT +# CHECK: fileoff: 16384 + +# The YAML below is the following code +# int main(int argc, char **argv) { return 0; } +# Compiled on macOS against the macOS SDK and passing `-Wl,-encryptable` +# Contents are removed, since they are not important for the test. We need a +# small text segment (smaller than a page). +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x2 + ncmds: 15 + sizeofcmds: 696 + flags: 0x200085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __PAGEZERO + vmaddr: 0 + vmsize: 4294967296 + fileoff: 0 + filesize: 0 + maxprot: 0 + initprot: 0 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 32768 + fileoff: 0 + filesize: 32768 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x100004000 + size: 32 + offset: 0x4000 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - sectname: __unwind_info + segname: __TEXT + addr: 0x100004020 + size: 4152 + offset: 0x4020 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4295000064 + vmsize: 592 + fileoff: 32768 + filesize: 592 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_CHAINED_FIXUPS + cmdsize: 16 + dataoff: 32768 + datasize: 48 + - cmd: LC_DYLD_EXPORTS_TRIE + cmdsize: 16 + dataoff: 32816 + datasize: 48 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 32872 + nsyms: 2 + stroff: 32904 + strsize: 32 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 2 + iundefsym: 2 + nundefsym: 0 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ENCRYPTION_INFO_64 + cmdsize: 24 + cryptoff: 16384 + cryptsize: 16384 + cryptid: 0 + pad: 0 + - cmd: LC_LOAD_DYLINKER + cmdsize: 32 + name: 12 + Content: '/usr/lib/dyld' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4447-5555-3144-A18A-01E9EB7E7D92 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 983040 + sdk: 983552 + ntools: 1 + Tools: + - tool: 4 + version: 1310720 + - cmd: LC_MAIN + cmdsize: 24 + entryoff: 16384 + stacksize: 0 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 32864 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 32872 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 32944 + datasize: 416 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 33 + Name: main + Flags: 0x0 + Address: 0x4000 + Other: 0x0 + ImportName: '' + - TerminalSize: 2 + NodeOffset: 39 + Name: _mh_execute_header + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4294983680 + - n_strx: 8 + n_type: 0xF + n_sect: 1 + n_desc: 16 + n_value: 4294967296 + StringTable: + - ' ' + - _main + - __mh_execute_header + - '' + - '' + - '' + - '' + FunctionStarts: [ 0x4000 ] + ChainedFixups: [ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x30, 0x0, + 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] +... +