1 //===- MachOUniversalWriter.h - MachO universal binary writer----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Declares the Slice class and writeUniversalBinary function for writing a 10 // MachO universal binary file. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_OBJECT_MACHOUNIVERSALWRITER_H 15 #define LLVM_OBJECT_MACHOUNIVERSALWRITER_H 16 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/Twine.h" 20 #include "llvm/BinaryFormat/MachO.h" 21 #include "llvm/Support/Compiler.h" 22 #include "llvm/Support/Error.h" 23 #include <cstdint> 24 #include <string> 25 26 namespace llvm { 27 class LLVMContext; 28 29 namespace object { 30 class Archive; 31 class Binary; 32 class IRObjectFile; 33 class MachOObjectFile; 34 35 class Slice { 36 const Binary *B; 37 uint32_t CPUType; 38 uint32_t CPUSubType; 39 std::string ArchName; 40 41 // P2Alignment field stores slice alignment values from universal 42 // binaries. This is also needed to order the slices so the total 43 // file size can be calculated before creating the output buffer. 44 uint32_t P2Alignment; 45 46 Slice(const IRObjectFile &IRO, uint32_t CPUType, uint32_t CPUSubType, 47 std::string ArchName, uint32_t Align); 48 49 public: 50 LLVM_ABI explicit Slice(const MachOObjectFile &O); 51 52 LLVM_ABI Slice(const MachOObjectFile &O, uint32_t Align); 53 54 /// This constructor takes pre-specified \param CPUType , \param CPUSubType , 55 /// \param ArchName , \param Align instead of inferring them from the archive 56 /// members. 57 LLVM_ABI Slice(const Archive &A, uint32_t CPUType, uint32_t CPUSubType, 58 std::string ArchName, uint32_t Align); 59 60 LLVM_ABI static Expected<Slice> create(const Archive &A, 61 LLVMContext *LLVMCtx = nullptr); 62 63 LLVM_ABI static Expected<Slice> create(const IRObjectFile &IRO, 64 uint32_t Align); 65 setP2Alignment(uint32_t Align)66 void setP2Alignment(uint32_t Align) { P2Alignment = Align; } 67 getBinary()68 const Binary *getBinary() const { return B; } 69 getCPUType()70 uint32_t getCPUType() const { return CPUType; } 71 getCPUSubType()72 uint32_t getCPUSubType() const { return CPUSubType; } 73 getP2Alignment()74 uint32_t getP2Alignment() const { return P2Alignment; } 75 getCPUID()76 uint64_t getCPUID() const { 77 return static_cast<uint64_t>(CPUType) << 32 | CPUSubType; 78 } 79 getArchString()80 std::string getArchString() const { 81 if (!ArchName.empty()) 82 return ArchName; 83 return ("unknown(" + Twine(CPUType) + "," + 84 Twine(CPUSubType & ~MachO::CPU_SUBTYPE_MASK) + ")") 85 .str(); 86 } 87 88 friend bool operator<(const Slice &Lhs, const Slice &Rhs) { 89 if (Lhs.CPUType == Rhs.CPUType) 90 return Lhs.CPUSubType < Rhs.CPUSubType; 91 // force arm64-family to follow after all other slices for 92 // compatibility with cctools lipo 93 if (Lhs.CPUType == MachO::CPU_TYPE_ARM64) 94 return false; 95 if (Rhs.CPUType == MachO::CPU_TYPE_ARM64) 96 return true; 97 // Sort by alignment to minimize file size 98 return Lhs.P2Alignment < Rhs.P2Alignment; 99 } 100 }; 101 102 enum class FatHeaderType { FatHeader, Fat64Header }; 103 104 LLVM_ABI Error 105 writeUniversalBinary(ArrayRef<Slice> Slices, StringRef OutputFileName, 106 FatHeaderType FatHeader = FatHeaderType::FatHeader); 107 108 LLVM_ABI Error writeUniversalBinaryToStream( 109 ArrayRef<Slice> Slices, raw_ostream &Out, 110 FatHeaderType FatHeader = FatHeaderType::FatHeader); 111 112 } // end namespace object 113 114 } // end namespace llvm 115 116 #endif // LLVM_OBJECT_MACHOUNIVERSALWRITER_H 117