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 std::string getArchFlagName() const { 94 const char *McpuDefault, *ArchFlag; 95 if (Parent->getMagic() == MachO::FAT_MAGIC) { 96 Triple T = 97 MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype, 98 &McpuDefault, &ArchFlag); 99 } else { // Parent->getMagic() == MachO::FAT_MAGIC_64 100 Triple T = 101 MachOObjectFile::getArchTriple(Header64.cputype, 102 Header64.cpusubtype, 103 &McpuDefault, &ArchFlag); 104 } 105 if (ArchFlag) { 106 std::string ArchFlagName(ArchFlag); 107 return ArchFlagName; 108 } else { 109 std::string ArchFlagName(""); 110 return ArchFlagName; 111 } 112 } 113 114 Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const; 115 116 Expected<std::unique_ptr<Archive>> getAsArchive() const; 117 }; 118 119 class object_iterator { 120 ObjectForArch Obj; 121 public: 122 object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} 123 const ObjectForArch *operator->() const { return &Obj; } 124 const ObjectForArch &operator*() const { return Obj; } 125 126 bool operator==(const object_iterator &Other) const { 127 return Obj == Other.Obj; 128 } 129 bool operator!=(const object_iterator &Other) const { 130 return !(*this == Other); 131 } 132 133 object_iterator& operator++() { // Preincrement 134 Obj = Obj.getNext(); 135 return *this; 136 } 137 }; 138 139 MachOUniversalBinary(MemoryBufferRef Souce, Error &Err); 140 static Expected<std::unique_ptr<MachOUniversalBinary>> 141 create(MemoryBufferRef Source); 142 143 object_iterator begin_objects() const { 144 return ObjectForArch(this, 0); 145 } 146 object_iterator end_objects() const { 147 return ObjectForArch(nullptr, 0); 148 } 149 150 iterator_range<object_iterator> objects() const { 151 return make_range(begin_objects(), end_objects()); 152 } 153 154 uint32_t getMagic() const { return Magic; } 155 uint32_t getNumberOfObjects() const { return NumberOfObjects; } 156 157 // Cast methods. 158 static bool classof(Binary const *V) { 159 return V->isMachOUniversalBinary(); 160 } 161 162 Expected<ObjectForArch> 163 getObjectForArch(StringRef ArchName) const; 164 165 Expected<std::unique_ptr<MachOObjectFile>> 166 getMachOObjectForArch(StringRef ArchName) const; 167 168 Expected<std::unique_ptr<Archive>> 169 getArchiveForArch(StringRef ArchName) const; 170 }; 171 172 } 173 } 174 175 #endif 176