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