1 //===- MachOUniversal.h - Mach-O universal binaries -------------*- 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 // This file declares Mach-O fat/universal binaries. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_OBJECT_MACHOUNIVERSAL_H 14 #define LLVM_OBJECT_MACHOUNIVERSAL_H 15 16 #include "llvm/ADT/Triple.h" 17 #include "llvm/ADT/iterator_range.h" 18 #include "llvm/BinaryFormat/MachO.h" 19 #include "llvm/Object/Archive.h" 20 #include "llvm/Object/Binary.h" 21 #include "llvm/Object/MachO.h" 22 23 namespace llvm { 24 class StringRef; 25 class Module; 26 class LLVMContext; 27 28 namespace object { 29 class IRObjectFile; 30 31 class MachOUniversalBinary : public Binary { 32 virtual void anchor(); 33 34 uint32_t Magic; 35 uint32_t NumberOfObjects; 36 public: 37 static constexpr uint32_t MaxSectionAlignment = 15; /* 2**15 or 0x8000 */ 38 39 class ObjectForArch { 40 const MachOUniversalBinary *Parent; 41 /// Index of object in the universal binary. 42 uint32_t Index; 43 /// Descriptor of the object. 44 MachO::fat_arch Header; 45 MachO::fat_arch_64 Header64; 46 47 public: 48 ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); 49 50 void clear() { 51 Parent = nullptr; 52 Index = 0; 53 } 54 55 bool operator==(const ObjectForArch &Other) const { 56 return (Parent == Other.Parent) && (Index == Other.Index); 57 } 58 59 ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } 60 uint32_t getCPUType() const { 61 if (Parent->getMagic() == MachO::FAT_MAGIC) 62 return Header.cputype; 63 else // Parent->getMagic() == MachO::FAT_MAGIC_64 64 return Header64.cputype; 65 } 66 uint32_t getCPUSubType() const { 67 if (Parent->getMagic() == MachO::FAT_MAGIC) 68 return Header.cpusubtype; 69 else // Parent->getMagic() == MachO::FAT_MAGIC_64 70 return Header64.cpusubtype; 71 } 72 uint64_t getOffset() const { 73 if (Parent->getMagic() == MachO::FAT_MAGIC) 74 return Header.offset; 75 else // Parent->getMagic() == MachO::FAT_MAGIC_64 76 return Header64.offset; 77 } 78 uint64_t getSize() const { 79 if (Parent->getMagic() == MachO::FAT_MAGIC) 80 return Header.size; 81 else // Parent->getMagic() == MachO::FAT_MAGIC_64 82 return Header64.size; 83 } 84 uint32_t getAlign() const { 85 if (Parent->getMagic() == MachO::FAT_MAGIC) 86 return Header.align; 87 else // Parent->getMagic() == MachO::FAT_MAGIC_64 88 return Header64.align; 89 } 90 uint32_t getReserved() const { 91 if (Parent->getMagic() == MachO::FAT_MAGIC) 92 return 0; 93 else // Parent->getMagic() == MachO::FAT_MAGIC_64 94 return Header64.reserved; 95 } 96 Triple getTriple() const { 97 return MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType()); 98 } 99 std::string getArchFlagName() const { 100 const char *McpuDefault, *ArchFlag; 101 MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType(), 102 &McpuDefault, &ArchFlag); 103 return ArchFlag ? ArchFlag : std::string(); 104 } 105 106 Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const; 107 Expected<std::unique_ptr<IRObjectFile>> 108 getAsIRObject(LLVMContext &Ctx) const; 109 110 Expected<std::unique_ptr<Archive>> getAsArchive() const; 111 }; 112 113 class object_iterator { 114 ObjectForArch Obj; 115 public: 116 object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} 117 const ObjectForArch *operator->() const { return &Obj; } 118 const ObjectForArch &operator*() const { return Obj; } 119 120 bool operator==(const object_iterator &Other) const { 121 return Obj == Other.Obj; 122 } 123 bool operator!=(const object_iterator &Other) const { 124 return !(*this == Other); 125 } 126 127 object_iterator& operator++() { // Preincrement 128 Obj = Obj.getNext(); 129 return *this; 130 } 131 }; 132 133 MachOUniversalBinary(MemoryBufferRef Souce, Error &Err); 134 static Expected<std::unique_ptr<MachOUniversalBinary>> 135 create(MemoryBufferRef Source); 136 137 object_iterator begin_objects() const { 138 return ObjectForArch(this, 0); 139 } 140 object_iterator end_objects() const { 141 return ObjectForArch(nullptr, 0); 142 } 143 144 iterator_range<object_iterator> objects() const { 145 return make_range(begin_objects(), end_objects()); 146 } 147 148 uint32_t getMagic() const { return Magic; } 149 uint32_t getNumberOfObjects() const { return NumberOfObjects; } 150 151 // Cast methods. 152 static bool classof(Binary const *V) { 153 return V->isMachOUniversalBinary(); 154 } 155 156 Expected<ObjectForArch> 157 getObjectForArch(StringRef ArchName) const; 158 159 Expected<std::unique_ptr<MachOObjectFile>> 160 getMachOObjectForArch(StringRef ArchName) const; 161 162 Expected<std::unique_ptr<IRObjectFile>> 163 getIRObjectForArch(StringRef ArchName, LLVMContext &Ctx) const; 164 165 Expected<std::unique_ptr<Archive>> 166 getArchiveForArch(StringRef ArchName) const; 167 }; 168 169 } 170 } 171 172 #endif 173