text: //===- 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
  