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