//===- MachOLayoutBuilder.h -------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H #define LLVM_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H #include "MachOObjcopy.h" #include "Object.h" namespace llvm { namespace objcopy { namespace macho { /// When MachO binaries include a LC_CODE_SIGNATURE load command, /// the __LINKEDIT data segment will include a section corresponding /// to the LC_CODE_SIGNATURE load command. This section serves as a signature /// for the binary. Included in the CodeSignature section is a header followed /// by a hash of the binary. If present, the CodeSignature section is the /// last component of the binary. struct CodeSignatureInfo { // NOTE: These values are to be kept in sync with those in // LLD's CodeSignatureSection class. static constexpr uint32_t Align = 16; static constexpr uint8_t BlockSizeShift = 12; // The binary is read in blocks of the following size. static constexpr size_t BlockSize = (1 << BlockSizeShift); // 4 KiB // For each block, a SHA256 hash (256 bits, 32 bytes) is written to // the CodeSignature section. static constexpr size_t HashSize = 256 / 8; static constexpr size_t BlobHeadersSize = llvm::alignTo<8>( sizeof(llvm::MachO::CS_SuperBlob) + sizeof(llvm::MachO::CS_BlobIndex)); // The size of the entire header depends upon the filename the binary is being // written to, but the rest of the header is fixed in size. static constexpr uint32_t FixedHeadersSize = BlobHeadersSize + sizeof(llvm::MachO::CS_CodeDirectory); // The offset relative to the start of the binary where // the CodeSignature section should begin. uint32_t StartOffset; // The size of the entire header, output file name size included. uint32_t AllHeadersSize; // The number of blocks required to hash the binary. uint32_t BlockCount; StringRef OutputFileName; // The size of the entire CodeSignature section, including both the header and // hashes. uint32_t Size; }; class MachOLayoutBuilder { Object &O; bool Is64Bit; StringRef OutputFileName; uint64_t PageSize; CodeSignatureInfo CodeSignature; // Points to the __LINKEDIT segment if it exists. MachO::macho_load_command *LinkEditLoadCommand = nullptr; StringTableBuilder StrTableBuilder; uint32_t computeSizeOfCmds() const; void constructStringTable(); void updateSymbolIndexes(); void updateDySymTab(MachO::macho_load_command &MLC); uint64_t layoutSegments(); uint64_t layoutRelocations(uint64_t Offset); Error layoutTail(uint64_t Offset); static StringTableBuilder::Kind getStringTableBuilderKind(const Object &O, bool Is64Bit); public: MachOLayoutBuilder(Object &O, bool Is64Bit, StringRef OutputFileName, uint64_t PageSize) : O(O), Is64Bit(Is64Bit), OutputFileName(OutputFileName), PageSize(PageSize), StrTableBuilder(getStringTableBuilderKind(O, Is64Bit)) {} // Recomputes and updates fields in the given object such as file offsets. Error layout(); StringTableBuilder &getStringTableBuilder() { return StrTableBuilder; } const CodeSignatureInfo &getCodeSignature() { return CodeSignature; } }; } // end namespace macho } // end namespace objcopy } // end namespace llvm #endif // LLVM_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H