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
23namespace llvm {
24class StringRef;
25class Module;
26class LLVMContext;
27
28namespace object {
29class IRObjectFile;
30
31class MachOUniversalBinary : public Binary {
32 virtual void anchor();
33
34 uint32_t Magic;
35 uint32_t NumberOfObjects;
36public:
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