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