1*81ad6265SDimitry Andric //===- MachOLayoutBuilder.h -------------------------------------*- C++ -*-===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric 9*81ad6265SDimitry Andric #ifndef LLVM_LIB_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H 10*81ad6265SDimitry Andric #define LLVM_LIB_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H 11*81ad6265SDimitry Andric 12*81ad6265SDimitry Andric #include "MachOObject.h" 13*81ad6265SDimitry Andric #include "llvm/ObjCopy/MachO/MachOObjcopy.h" 14*81ad6265SDimitry Andric 15*81ad6265SDimitry Andric namespace llvm { 16*81ad6265SDimitry Andric namespace objcopy { 17*81ad6265SDimitry Andric namespace macho { 18*81ad6265SDimitry Andric 19*81ad6265SDimitry Andric /// When MachO binaries include a LC_CODE_SIGNATURE load command, 20*81ad6265SDimitry Andric /// the __LINKEDIT data segment will include a section corresponding 21*81ad6265SDimitry Andric /// to the LC_CODE_SIGNATURE load command. This section serves as a signature 22*81ad6265SDimitry Andric /// for the binary. Included in the CodeSignature section is a header followed 23*81ad6265SDimitry Andric /// by a hash of the binary. If present, the CodeSignature section is the 24*81ad6265SDimitry Andric /// last component of the binary. 25*81ad6265SDimitry Andric struct CodeSignatureInfo { 26*81ad6265SDimitry Andric // NOTE: These values are to be kept in sync with those in 27*81ad6265SDimitry Andric // LLD's CodeSignatureSection class. 28*81ad6265SDimitry Andric 29*81ad6265SDimitry Andric static constexpr uint32_t Align = 16; 30*81ad6265SDimitry Andric static constexpr uint8_t BlockSizeShift = 12; 31*81ad6265SDimitry Andric // The binary is read in blocks of the following size. 32*81ad6265SDimitry Andric static constexpr size_t BlockSize = (1 << BlockSizeShift); // 4 KiB 33*81ad6265SDimitry Andric // For each block, a SHA256 hash (256 bits, 32 bytes) is written to 34*81ad6265SDimitry Andric // the CodeSignature section. 35*81ad6265SDimitry Andric static constexpr size_t HashSize = 256 / 8; 36*81ad6265SDimitry Andric static constexpr size_t BlobHeadersSize = llvm::alignTo<8>( 37*81ad6265SDimitry Andric sizeof(llvm::MachO::CS_SuperBlob) + sizeof(llvm::MachO::CS_BlobIndex)); 38*81ad6265SDimitry Andric // The size of the entire header depends upon the filename the binary is being 39*81ad6265SDimitry Andric // written to, but the rest of the header is fixed in size. 40*81ad6265SDimitry Andric static constexpr uint32_t FixedHeadersSize = 41*81ad6265SDimitry Andric BlobHeadersSize + sizeof(llvm::MachO::CS_CodeDirectory); 42*81ad6265SDimitry Andric 43*81ad6265SDimitry Andric // The offset relative to the start of the binary where 44*81ad6265SDimitry Andric // the CodeSignature section should begin. 45*81ad6265SDimitry Andric uint32_t StartOffset; 46*81ad6265SDimitry Andric // The size of the entire header, output file name size included. 47*81ad6265SDimitry Andric uint32_t AllHeadersSize; 48*81ad6265SDimitry Andric // The number of blocks required to hash the binary. 49*81ad6265SDimitry Andric uint32_t BlockCount; 50*81ad6265SDimitry Andric StringRef OutputFileName; 51*81ad6265SDimitry Andric // The size of the entire CodeSignature section, including both the header and 52*81ad6265SDimitry Andric // hashes. 53*81ad6265SDimitry Andric uint32_t Size; 54*81ad6265SDimitry Andric }; 55*81ad6265SDimitry Andric 56*81ad6265SDimitry Andric class MachOLayoutBuilder { 57*81ad6265SDimitry Andric Object &O; 58*81ad6265SDimitry Andric bool Is64Bit; 59*81ad6265SDimitry Andric StringRef OutputFileName; 60*81ad6265SDimitry Andric uint64_t PageSize; 61*81ad6265SDimitry Andric CodeSignatureInfo CodeSignature; 62*81ad6265SDimitry Andric 63*81ad6265SDimitry Andric // Points to the __LINKEDIT segment if it exists. 64*81ad6265SDimitry Andric MachO::macho_load_command *LinkEditLoadCommand = nullptr; 65*81ad6265SDimitry Andric StringTableBuilder StrTableBuilder; 66*81ad6265SDimitry Andric 67*81ad6265SDimitry Andric uint32_t computeSizeOfCmds() const; 68*81ad6265SDimitry Andric void constructStringTable(); 69*81ad6265SDimitry Andric void updateSymbolIndexes(); 70*81ad6265SDimitry Andric void updateDySymTab(MachO::macho_load_command &MLC); 71*81ad6265SDimitry Andric uint64_t layoutSegments(); 72*81ad6265SDimitry Andric uint64_t layoutRelocations(uint64_t Offset); 73*81ad6265SDimitry Andric Error layoutTail(uint64_t Offset); 74*81ad6265SDimitry Andric 75*81ad6265SDimitry Andric static StringTableBuilder::Kind getStringTableBuilderKind(const Object &O, 76*81ad6265SDimitry Andric bool Is64Bit); 77*81ad6265SDimitry Andric 78*81ad6265SDimitry Andric public: MachOLayoutBuilder(Object & O,bool Is64Bit,StringRef OutputFileName,uint64_t PageSize)79*81ad6265SDimitry Andric MachOLayoutBuilder(Object &O, bool Is64Bit, StringRef OutputFileName, 80*81ad6265SDimitry Andric uint64_t PageSize) 81*81ad6265SDimitry Andric : O(O), Is64Bit(Is64Bit), OutputFileName(OutputFileName), 82*81ad6265SDimitry Andric PageSize(PageSize), 83*81ad6265SDimitry Andric StrTableBuilder(getStringTableBuilderKind(O, Is64Bit)) {} 84*81ad6265SDimitry Andric 85*81ad6265SDimitry Andric // Recomputes and updates fields in the given object such as file offsets. 86*81ad6265SDimitry Andric Error layout(); 87*81ad6265SDimitry Andric getStringTableBuilder()88*81ad6265SDimitry Andric StringTableBuilder &getStringTableBuilder() { return StrTableBuilder; } 89*81ad6265SDimitry Andric getCodeSignature()90*81ad6265SDimitry Andric const CodeSignatureInfo &getCodeSignature() const { return CodeSignature; } 91*81ad6265SDimitry Andric }; 92*81ad6265SDimitry Andric 93*81ad6265SDimitry Andric } // end namespace macho 94*81ad6265SDimitry Andric } // end namespace objcopy 95*81ad6265SDimitry Andric } // end namespace llvm 96*81ad6265SDimitry Andric 97*81ad6265SDimitry Andric #endif // LLVM_LIB_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H 98