17330f729Sjoerg //===- MachOLayoutBuilder.cpp -----------------------------------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "MachOLayoutBuilder.h"
107330f729Sjoerg #include "llvm/Support/Alignment.h"
117330f729Sjoerg #include "llvm/Support/Errc.h"
127330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
137330f729Sjoerg
147330f729Sjoerg namespace llvm {
157330f729Sjoerg namespace objcopy {
167330f729Sjoerg namespace macho {
177330f729Sjoerg
18*82d56013Sjoerg StringTableBuilder::Kind
getStringTableBuilderKind(const Object & O,bool Is64Bit)19*82d56013Sjoerg MachOLayoutBuilder::getStringTableBuilderKind(const Object &O, bool Is64Bit) {
20*82d56013Sjoerg if (O.Header.FileType == MachO::HeaderFileType::MH_OBJECT)
21*82d56013Sjoerg return Is64Bit ? StringTableBuilder::MachO64 : StringTableBuilder::MachO;
22*82d56013Sjoerg return Is64Bit ? StringTableBuilder::MachO64Linked
23*82d56013Sjoerg : StringTableBuilder::MachOLinked;
24*82d56013Sjoerg }
25*82d56013Sjoerg
computeSizeOfCmds() const267330f729Sjoerg uint32_t MachOLayoutBuilder::computeSizeOfCmds() const {
277330f729Sjoerg uint32_t Size = 0;
28*82d56013Sjoerg for (const LoadCommand &LC : O.LoadCommands) {
297330f729Sjoerg const MachO::macho_load_command &MLC = LC.MachOLoadCommand;
307330f729Sjoerg auto cmd = MLC.load_command_data.cmd;
317330f729Sjoerg switch (cmd) {
327330f729Sjoerg case MachO::LC_SEGMENT:
337330f729Sjoerg Size += sizeof(MachO::segment_command) +
347330f729Sjoerg sizeof(MachO::section) * LC.Sections.size();
357330f729Sjoerg continue;
367330f729Sjoerg case MachO::LC_SEGMENT_64:
377330f729Sjoerg Size += sizeof(MachO::segment_command_64) +
387330f729Sjoerg sizeof(MachO::section_64) * LC.Sections.size();
397330f729Sjoerg continue;
407330f729Sjoerg }
417330f729Sjoerg
427330f729Sjoerg switch (cmd) {
437330f729Sjoerg #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
447330f729Sjoerg case MachO::LCName: \
457330f729Sjoerg Size += sizeof(MachO::LCStruct) + LC.Payload.size(); \
467330f729Sjoerg break;
477330f729Sjoerg #include "llvm/BinaryFormat/MachO.def"
487330f729Sjoerg #undef HANDLE_LOAD_COMMAND
497330f729Sjoerg }
507330f729Sjoerg }
517330f729Sjoerg
527330f729Sjoerg return Size;
537330f729Sjoerg }
547330f729Sjoerg
constructStringTable()557330f729Sjoerg void MachOLayoutBuilder::constructStringTable() {
567330f729Sjoerg for (std::unique_ptr<SymbolEntry> &Sym : O.SymTable.Symbols)
577330f729Sjoerg StrTableBuilder.add(Sym->Name);
587330f729Sjoerg StrTableBuilder.finalize();
597330f729Sjoerg }
607330f729Sjoerg
updateSymbolIndexes()617330f729Sjoerg void MachOLayoutBuilder::updateSymbolIndexes() {
627330f729Sjoerg uint32_t Index = 0;
637330f729Sjoerg for (auto &Symbol : O.SymTable.Symbols)
647330f729Sjoerg Symbol->Index = Index++;
657330f729Sjoerg }
667330f729Sjoerg
677330f729Sjoerg // Updates the index and the number of local/external/undefined symbols.
updateDySymTab(MachO::macho_load_command & MLC)687330f729Sjoerg void MachOLayoutBuilder::updateDySymTab(MachO::macho_load_command &MLC) {
697330f729Sjoerg assert(MLC.load_command_data.cmd == MachO::LC_DYSYMTAB);
707330f729Sjoerg // Make sure that nlist entries in the symbol table are sorted by the those
717330f729Sjoerg // types. The order is: local < defined external < undefined external.
72*82d56013Sjoerg assert(llvm::is_sorted(O.SymTable.Symbols,
737330f729Sjoerg [](const std::unique_ptr<SymbolEntry> &A,
747330f729Sjoerg const std::unique_ptr<SymbolEntry> &B) {
75*82d56013Sjoerg bool AL = A->isLocalSymbol(),
76*82d56013Sjoerg BL = B->isLocalSymbol();
77*82d56013Sjoerg if (AL != BL)
78*82d56013Sjoerg return AL;
79*82d56013Sjoerg return !AL && !A->isUndefinedSymbol() &&
80*82d56013Sjoerg B->isUndefinedSymbol();
817330f729Sjoerg }) &&
827330f729Sjoerg "Symbols are not sorted by their types.");
837330f729Sjoerg
847330f729Sjoerg uint32_t NumLocalSymbols = 0;
857330f729Sjoerg auto Iter = O.SymTable.Symbols.begin();
867330f729Sjoerg auto End = O.SymTable.Symbols.end();
877330f729Sjoerg for (; Iter != End; ++Iter) {
887330f729Sjoerg if ((*Iter)->isExternalSymbol())
897330f729Sjoerg break;
907330f729Sjoerg
917330f729Sjoerg ++NumLocalSymbols;
927330f729Sjoerg }
937330f729Sjoerg
947330f729Sjoerg uint32_t NumExtDefSymbols = 0;
957330f729Sjoerg for (; Iter != End; ++Iter) {
967330f729Sjoerg if ((*Iter)->isUndefinedSymbol())
977330f729Sjoerg break;
987330f729Sjoerg
997330f729Sjoerg ++NumExtDefSymbols;
1007330f729Sjoerg }
1017330f729Sjoerg
1027330f729Sjoerg MLC.dysymtab_command_data.ilocalsym = 0;
1037330f729Sjoerg MLC.dysymtab_command_data.nlocalsym = NumLocalSymbols;
1047330f729Sjoerg MLC.dysymtab_command_data.iextdefsym = NumLocalSymbols;
1057330f729Sjoerg MLC.dysymtab_command_data.nextdefsym = NumExtDefSymbols;
1067330f729Sjoerg MLC.dysymtab_command_data.iundefsym = NumLocalSymbols + NumExtDefSymbols;
1077330f729Sjoerg MLC.dysymtab_command_data.nundefsym =
1087330f729Sjoerg O.SymTable.Symbols.size() - (NumLocalSymbols + NumExtDefSymbols);
1097330f729Sjoerg }
1107330f729Sjoerg
1117330f729Sjoerg // Recomputes and updates offset and size fields in load commands and sections
1127330f729Sjoerg // since they could be modified.
layoutSegments()1137330f729Sjoerg uint64_t MachOLayoutBuilder::layoutSegments() {
1147330f729Sjoerg auto HeaderSize =
1157330f729Sjoerg Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
1167330f729Sjoerg const bool IsObjectFile =
1177330f729Sjoerg O.Header.FileType == MachO::HeaderFileType::MH_OBJECT;
1187330f729Sjoerg uint64_t Offset = IsObjectFile ? (HeaderSize + O.Header.SizeOfCmds) : 0;
119*82d56013Sjoerg for (LoadCommand &LC : O.LoadCommands) {
1207330f729Sjoerg auto &MLC = LC.MachOLoadCommand;
1217330f729Sjoerg StringRef Segname;
1227330f729Sjoerg uint64_t SegmentVmAddr;
1237330f729Sjoerg uint64_t SegmentVmSize;
1247330f729Sjoerg switch (MLC.load_command_data.cmd) {
1257330f729Sjoerg case MachO::LC_SEGMENT:
1267330f729Sjoerg SegmentVmAddr = MLC.segment_command_data.vmaddr;
1277330f729Sjoerg SegmentVmSize = MLC.segment_command_data.vmsize;
1287330f729Sjoerg Segname = StringRef(MLC.segment_command_data.segname,
1297330f729Sjoerg strnlen(MLC.segment_command_data.segname,
1307330f729Sjoerg sizeof(MLC.segment_command_data.segname)));
1317330f729Sjoerg break;
1327330f729Sjoerg case MachO::LC_SEGMENT_64:
1337330f729Sjoerg SegmentVmAddr = MLC.segment_command_64_data.vmaddr;
1347330f729Sjoerg SegmentVmSize = MLC.segment_command_64_data.vmsize;
1357330f729Sjoerg Segname = StringRef(MLC.segment_command_64_data.segname,
1367330f729Sjoerg strnlen(MLC.segment_command_64_data.segname,
1377330f729Sjoerg sizeof(MLC.segment_command_64_data.segname)));
1387330f729Sjoerg break;
1397330f729Sjoerg default:
1407330f729Sjoerg continue;
1417330f729Sjoerg }
1427330f729Sjoerg
1437330f729Sjoerg if (Segname == "__LINKEDIT") {
1447330f729Sjoerg // We update the __LINKEDIT segment later (in layoutTail).
1457330f729Sjoerg assert(LC.Sections.empty() && "__LINKEDIT segment has sections");
1467330f729Sjoerg LinkEditLoadCommand = &MLC;
1477330f729Sjoerg continue;
1487330f729Sjoerg }
1497330f729Sjoerg
1507330f729Sjoerg // Update file offsets and sizes of sections.
1517330f729Sjoerg uint64_t SegOffset = Offset;
1527330f729Sjoerg uint64_t SegFileSize = 0;
1537330f729Sjoerg uint64_t VMSize = 0;
154*82d56013Sjoerg for (std::unique_ptr<Section> &Sec : LC.Sections) {
155*82d56013Sjoerg assert(SegmentVmAddr <= Sec->Addr &&
156*82d56013Sjoerg "Section's address cannot be smaller than Segment's one");
157*82d56013Sjoerg uint32_t SectOffset = Sec->Addr - SegmentVmAddr;
1587330f729Sjoerg if (IsObjectFile) {
159*82d56013Sjoerg if (!Sec->hasValidOffset()) {
160*82d56013Sjoerg Sec->Offset = 0;
1617330f729Sjoerg } else {
1627330f729Sjoerg uint64_t PaddingSize =
163*82d56013Sjoerg offsetToAlignment(SegFileSize, Align(1ull << Sec->Align));
164*82d56013Sjoerg Sec->Offset = SegOffset + SegFileSize + PaddingSize;
165*82d56013Sjoerg Sec->Size = Sec->Content.size();
166*82d56013Sjoerg SegFileSize += PaddingSize + Sec->Size;
1677330f729Sjoerg }
1687330f729Sjoerg } else {
169*82d56013Sjoerg if (!Sec->hasValidOffset()) {
170*82d56013Sjoerg Sec->Offset = 0;
1717330f729Sjoerg } else {
172*82d56013Sjoerg Sec->Offset = SegOffset + SectOffset;
173*82d56013Sjoerg Sec->Size = Sec->Content.size();
174*82d56013Sjoerg SegFileSize = std::max(SegFileSize, SectOffset + Sec->Size);
1757330f729Sjoerg }
1767330f729Sjoerg }
177*82d56013Sjoerg VMSize = std::max(VMSize, SectOffset + Sec->Size);
1787330f729Sjoerg }
1797330f729Sjoerg
1807330f729Sjoerg if (IsObjectFile) {
1817330f729Sjoerg Offset += SegFileSize;
1827330f729Sjoerg } else {
1837330f729Sjoerg Offset = alignTo(Offset + SegFileSize, PageSize);
1847330f729Sjoerg SegFileSize = alignTo(SegFileSize, PageSize);
1857330f729Sjoerg // Use the original vmsize if the segment is __PAGEZERO.
1867330f729Sjoerg VMSize =
1877330f729Sjoerg Segname == "__PAGEZERO" ? SegmentVmSize : alignTo(VMSize, PageSize);
1887330f729Sjoerg }
1897330f729Sjoerg
1907330f729Sjoerg switch (MLC.load_command_data.cmd) {
1917330f729Sjoerg case MachO::LC_SEGMENT:
1927330f729Sjoerg MLC.segment_command_data.cmdsize =
1937330f729Sjoerg sizeof(MachO::segment_command) +
1947330f729Sjoerg sizeof(MachO::section) * LC.Sections.size();
1957330f729Sjoerg MLC.segment_command_data.nsects = LC.Sections.size();
1967330f729Sjoerg MLC.segment_command_data.fileoff = SegOffset;
1977330f729Sjoerg MLC.segment_command_data.vmsize = VMSize;
1987330f729Sjoerg MLC.segment_command_data.filesize = SegFileSize;
1997330f729Sjoerg break;
2007330f729Sjoerg case MachO::LC_SEGMENT_64:
2017330f729Sjoerg MLC.segment_command_64_data.cmdsize =
2027330f729Sjoerg sizeof(MachO::segment_command_64) +
2037330f729Sjoerg sizeof(MachO::section_64) * LC.Sections.size();
2047330f729Sjoerg MLC.segment_command_64_data.nsects = LC.Sections.size();
2057330f729Sjoerg MLC.segment_command_64_data.fileoff = SegOffset;
2067330f729Sjoerg MLC.segment_command_64_data.vmsize = VMSize;
2077330f729Sjoerg MLC.segment_command_64_data.filesize = SegFileSize;
2087330f729Sjoerg break;
2097330f729Sjoerg }
2107330f729Sjoerg }
2117330f729Sjoerg
2127330f729Sjoerg return Offset;
2137330f729Sjoerg }
2147330f729Sjoerg
layoutRelocations(uint64_t Offset)2157330f729Sjoerg uint64_t MachOLayoutBuilder::layoutRelocations(uint64_t Offset) {
216*82d56013Sjoerg for (LoadCommand &LC : O.LoadCommands)
217*82d56013Sjoerg for (std::unique_ptr<Section> &Sec : LC.Sections) {
218*82d56013Sjoerg Sec->RelOff = Sec->Relocations.empty() ? 0 : Offset;
219*82d56013Sjoerg Sec->NReloc = Sec->Relocations.size();
220*82d56013Sjoerg Offset += sizeof(MachO::any_relocation_info) * Sec->NReloc;
2217330f729Sjoerg }
2227330f729Sjoerg
2237330f729Sjoerg return Offset;
2247330f729Sjoerg }
2257330f729Sjoerg
layoutTail(uint64_t Offset)2267330f729Sjoerg Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {
227*82d56013Sjoerg // If we are building the layout of an executable or dynamic library
228*82d56013Sjoerg // which does not have any segments other than __LINKEDIT,
229*82d56013Sjoerg // the Offset can be equal to zero by this time. It happens because of the
230*82d56013Sjoerg // convention that in such cases the file offsets specified by LC_SEGMENT
231*82d56013Sjoerg // start with zero (unlike the case of a relocatable object file).
232*82d56013Sjoerg const uint64_t HeaderSize =
233*82d56013Sjoerg Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
234*82d56013Sjoerg assert((!(O.Header.FileType == MachO::HeaderFileType::MH_OBJECT) ||
235*82d56013Sjoerg Offset >= HeaderSize + O.Header.SizeOfCmds) &&
236*82d56013Sjoerg "Incorrect tail offset");
237*82d56013Sjoerg Offset = std::max(Offset, HeaderSize + O.Header.SizeOfCmds);
238*82d56013Sjoerg
2397330f729Sjoerg // The order of LINKEDIT elements is as follows:
2407330f729Sjoerg // rebase info, binding info, weak binding info, lazy binding info, export
2417330f729Sjoerg // trie, data-in-code, symbol table, indirect symbol table, symbol table
242*82d56013Sjoerg // strings, code signature.
2437330f729Sjoerg uint64_t NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2447330f729Sjoerg uint64_t StartOfLinkEdit = Offset;
2457330f729Sjoerg uint64_t StartOfRebaseInfo = StartOfLinkEdit;
2467330f729Sjoerg uint64_t StartOfBindingInfo = StartOfRebaseInfo + O.Rebases.Opcodes.size();
2477330f729Sjoerg uint64_t StartOfWeakBindingInfo = StartOfBindingInfo + O.Binds.Opcodes.size();
2487330f729Sjoerg uint64_t StartOfLazyBindingInfo =
2497330f729Sjoerg StartOfWeakBindingInfo + O.WeakBinds.Opcodes.size();
2507330f729Sjoerg uint64_t StartOfExportTrie =
2517330f729Sjoerg StartOfLazyBindingInfo + O.LazyBinds.Opcodes.size();
2527330f729Sjoerg uint64_t StartOfFunctionStarts = StartOfExportTrie + O.Exports.Trie.size();
2537330f729Sjoerg uint64_t StartOfDataInCode =
2547330f729Sjoerg StartOfFunctionStarts + O.FunctionStarts.Data.size();
2557330f729Sjoerg uint64_t StartOfSymbols = StartOfDataInCode + O.DataInCode.Data.size();
2567330f729Sjoerg uint64_t StartOfIndirectSymbols =
2577330f729Sjoerg StartOfSymbols + NListSize * O.SymTable.Symbols.size();
2587330f729Sjoerg uint64_t StartOfSymbolStrings =
2597330f729Sjoerg StartOfIndirectSymbols +
2607330f729Sjoerg sizeof(uint32_t) * O.IndirectSymTable.Symbols.size();
261*82d56013Sjoerg uint64_t StartOfCodeSignature =
262*82d56013Sjoerg StartOfSymbolStrings + StrTableBuilder.getSize();
263*82d56013Sjoerg if (O.CodeSignatureCommandIndex)
264*82d56013Sjoerg StartOfCodeSignature = alignTo(StartOfCodeSignature, 16);
2657330f729Sjoerg uint64_t LinkEditSize =
266*82d56013Sjoerg (StartOfCodeSignature + O.CodeSignature.Data.size()) - StartOfLinkEdit;
2677330f729Sjoerg
2687330f729Sjoerg // Now we have determined the layout of the contents of the __LINKEDIT
2697330f729Sjoerg // segment. Update its load command.
2707330f729Sjoerg if (LinkEditLoadCommand) {
2717330f729Sjoerg MachO::macho_load_command *MLC = LinkEditLoadCommand;
2727330f729Sjoerg switch (LinkEditLoadCommand->load_command_data.cmd) {
2737330f729Sjoerg case MachO::LC_SEGMENT:
2747330f729Sjoerg MLC->segment_command_data.cmdsize = sizeof(MachO::segment_command);
2757330f729Sjoerg MLC->segment_command_data.fileoff = StartOfLinkEdit;
2767330f729Sjoerg MLC->segment_command_data.vmsize = alignTo(LinkEditSize, PageSize);
2777330f729Sjoerg MLC->segment_command_data.filesize = LinkEditSize;
2787330f729Sjoerg break;
2797330f729Sjoerg case MachO::LC_SEGMENT_64:
2807330f729Sjoerg MLC->segment_command_64_data.cmdsize = sizeof(MachO::segment_command_64);
2817330f729Sjoerg MLC->segment_command_64_data.fileoff = StartOfLinkEdit;
2827330f729Sjoerg MLC->segment_command_64_data.vmsize = alignTo(LinkEditSize, PageSize);
2837330f729Sjoerg MLC->segment_command_64_data.filesize = LinkEditSize;
2847330f729Sjoerg break;
2857330f729Sjoerg }
2867330f729Sjoerg }
2877330f729Sjoerg
288*82d56013Sjoerg for (LoadCommand &LC : O.LoadCommands) {
2897330f729Sjoerg auto &MLC = LC.MachOLoadCommand;
2907330f729Sjoerg auto cmd = MLC.load_command_data.cmd;
2917330f729Sjoerg switch (cmd) {
292*82d56013Sjoerg case MachO::LC_CODE_SIGNATURE:
293*82d56013Sjoerg MLC.linkedit_data_command_data.dataoff = StartOfCodeSignature;
294*82d56013Sjoerg MLC.linkedit_data_command_data.datasize = O.CodeSignature.Data.size();
295*82d56013Sjoerg break;
2967330f729Sjoerg case MachO::LC_SYMTAB:
2977330f729Sjoerg MLC.symtab_command_data.symoff = StartOfSymbols;
2987330f729Sjoerg MLC.symtab_command_data.nsyms = O.SymTable.Symbols.size();
2997330f729Sjoerg MLC.symtab_command_data.stroff = StartOfSymbolStrings;
3007330f729Sjoerg MLC.symtab_command_data.strsize = StrTableBuilder.getSize();
3017330f729Sjoerg break;
3027330f729Sjoerg case MachO::LC_DYSYMTAB: {
3037330f729Sjoerg if (MLC.dysymtab_command_data.ntoc != 0 ||
3047330f729Sjoerg MLC.dysymtab_command_data.nmodtab != 0 ||
3057330f729Sjoerg MLC.dysymtab_command_data.nextrefsyms != 0 ||
3067330f729Sjoerg MLC.dysymtab_command_data.nlocrel != 0 ||
3077330f729Sjoerg MLC.dysymtab_command_data.nextrel != 0)
3087330f729Sjoerg return createStringError(llvm::errc::not_supported,
3097330f729Sjoerg "shared library is not yet supported");
3107330f729Sjoerg
3117330f729Sjoerg if (!O.IndirectSymTable.Symbols.empty()) {
3127330f729Sjoerg MLC.dysymtab_command_data.indirectsymoff = StartOfIndirectSymbols;
3137330f729Sjoerg MLC.dysymtab_command_data.nindirectsyms =
3147330f729Sjoerg O.IndirectSymTable.Symbols.size();
3157330f729Sjoerg }
3167330f729Sjoerg
3177330f729Sjoerg updateDySymTab(MLC);
3187330f729Sjoerg break;
3197330f729Sjoerg }
3207330f729Sjoerg case MachO::LC_DATA_IN_CODE:
3217330f729Sjoerg MLC.linkedit_data_command_data.dataoff = StartOfDataInCode;
3227330f729Sjoerg MLC.linkedit_data_command_data.datasize = O.DataInCode.Data.size();
3237330f729Sjoerg break;
3247330f729Sjoerg case MachO::LC_FUNCTION_STARTS:
3257330f729Sjoerg MLC.linkedit_data_command_data.dataoff = StartOfFunctionStarts;
3267330f729Sjoerg MLC.linkedit_data_command_data.datasize = O.FunctionStarts.Data.size();
3277330f729Sjoerg break;
3287330f729Sjoerg case MachO::LC_DYLD_INFO:
3297330f729Sjoerg case MachO::LC_DYLD_INFO_ONLY:
3307330f729Sjoerg MLC.dyld_info_command_data.rebase_off =
3317330f729Sjoerg O.Rebases.Opcodes.empty() ? 0 : StartOfRebaseInfo;
3327330f729Sjoerg MLC.dyld_info_command_data.rebase_size = O.Rebases.Opcodes.size();
3337330f729Sjoerg MLC.dyld_info_command_data.bind_off =
3347330f729Sjoerg O.Binds.Opcodes.empty() ? 0 : StartOfBindingInfo;
3357330f729Sjoerg MLC.dyld_info_command_data.bind_size = O.Binds.Opcodes.size();
3367330f729Sjoerg MLC.dyld_info_command_data.weak_bind_off =
3377330f729Sjoerg O.WeakBinds.Opcodes.empty() ? 0 : StartOfWeakBindingInfo;
3387330f729Sjoerg MLC.dyld_info_command_data.weak_bind_size = O.WeakBinds.Opcodes.size();
3397330f729Sjoerg MLC.dyld_info_command_data.lazy_bind_off =
3407330f729Sjoerg O.LazyBinds.Opcodes.empty() ? 0 : StartOfLazyBindingInfo;
3417330f729Sjoerg MLC.dyld_info_command_data.lazy_bind_size = O.LazyBinds.Opcodes.size();
3427330f729Sjoerg MLC.dyld_info_command_data.export_off =
3437330f729Sjoerg O.Exports.Trie.empty() ? 0 : StartOfExportTrie;
3447330f729Sjoerg MLC.dyld_info_command_data.export_size = O.Exports.Trie.size();
3457330f729Sjoerg break;
346*82d56013Sjoerg // Note that LC_ENCRYPTION_INFO.cryptoff despite its name and the comment in
347*82d56013Sjoerg // <mach-o/loader.h> is not an offset in the binary file, instead, it is a
348*82d56013Sjoerg // relative virtual address. At the moment modification of the __TEXT
349*82d56013Sjoerg // segment of executables isn't supported anyway (e.g. data in code entries
350*82d56013Sjoerg // are not recalculated). Moreover, in general
351*82d56013Sjoerg // LC_ENCRYPT_INFO/LC_ENCRYPTION_INFO_64 are nontrivial to update because
352*82d56013Sjoerg // without making additional assumptions (e.g. that the entire __TEXT
353*82d56013Sjoerg // segment should be encrypted) we do not know how to recalculate the
354*82d56013Sjoerg // boundaries of the encrypted part. For now just copy over these load
355*82d56013Sjoerg // commands until we encounter a real world usecase where
356*82d56013Sjoerg // LC_ENCRYPT_INFO/LC_ENCRYPTION_INFO_64 need to be adjusted.
357*82d56013Sjoerg case MachO::LC_ENCRYPTION_INFO:
358*82d56013Sjoerg case MachO::LC_ENCRYPTION_INFO_64:
3597330f729Sjoerg case MachO::LC_LOAD_DYLINKER:
3607330f729Sjoerg case MachO::LC_MAIN:
3617330f729Sjoerg case MachO::LC_RPATH:
3627330f729Sjoerg case MachO::LC_SEGMENT:
3637330f729Sjoerg case MachO::LC_SEGMENT_64:
3647330f729Sjoerg case MachO::LC_VERSION_MIN_MACOSX:
3657330f729Sjoerg case MachO::LC_VERSION_MIN_IPHONEOS:
3667330f729Sjoerg case MachO::LC_VERSION_MIN_TVOS:
3677330f729Sjoerg case MachO::LC_VERSION_MIN_WATCHOS:
3687330f729Sjoerg case MachO::LC_BUILD_VERSION:
3697330f729Sjoerg case MachO::LC_ID_DYLIB:
3707330f729Sjoerg case MachO::LC_LOAD_DYLIB:
371*82d56013Sjoerg case MachO::LC_LOAD_WEAK_DYLIB:
3727330f729Sjoerg case MachO::LC_UUID:
3737330f729Sjoerg case MachO::LC_SOURCE_VERSION:
374*82d56013Sjoerg case MachO::LC_THREAD:
375*82d56013Sjoerg case MachO::LC_UNIXTHREAD:
3767330f729Sjoerg // Nothing to update.
3777330f729Sjoerg break;
3787330f729Sjoerg default:
3797330f729Sjoerg // Abort if it's unsupported in order to prevent corrupting the object.
3807330f729Sjoerg return createStringError(llvm::errc::not_supported,
3817330f729Sjoerg "unsupported load command (cmd=0x%x)", cmd);
3827330f729Sjoerg }
3837330f729Sjoerg }
3847330f729Sjoerg
3857330f729Sjoerg return Error::success();
3867330f729Sjoerg }
3877330f729Sjoerg
layout()3887330f729Sjoerg Error MachOLayoutBuilder::layout() {
3897330f729Sjoerg O.Header.NCmds = O.LoadCommands.size();
3907330f729Sjoerg O.Header.SizeOfCmds = computeSizeOfCmds();
3917330f729Sjoerg constructStringTable();
3927330f729Sjoerg updateSymbolIndexes();
3937330f729Sjoerg uint64_t Offset = layoutSegments();
3947330f729Sjoerg Offset = layoutRelocations(Offset);
3957330f729Sjoerg return layoutTail(Offset);
3967330f729Sjoerg }
3977330f729Sjoerg
3987330f729Sjoerg } // end namespace macho
3997330f729Sjoerg } // end namespace objcopy
4007330f729Sjoerg } // end namespace llvm
401