class MachOUniversalBinary : public Binary {
virtual void anchor();
+ uint32_t Magic;
uint32_t NumberOfObjects;
public:
class ObjectForArch {
uint32_t Index;
/// \brief Descriptor of the object.
MachO::fat_arch Header;
+ MachO::fat_arch_64 Header64;
public:
ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index);
}
ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
- uint32_t getCPUType() const { return Header.cputype; }
- uint32_t getCPUSubType() const { return Header.cpusubtype; }
- uint32_t getOffset() const { return Header.offset; }
- uint32_t getSize() const { return Header.size; }
- uint32_t getAlign() const { return Header.align; }
+ uint32_t getCPUType() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.cputype;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.cputype;
+ }
+ uint32_t getCPUSubType() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.cpusubtype;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.cpusubtype;
+ }
+ uint32_t getOffset() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.offset;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.offset;
+ }
+ uint32_t getSize() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.size;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.size;
+ }
+ uint32_t getAlign() const {
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ return Header.align;
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ return Header64.align;
+ }
std::string getArchTypeName() const {
- Triple T =
- MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype);
- return T.getArchName();
+ if (Parent->getMagic() == MachO::FAT_MAGIC) {
+ Triple T =
+ MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype);
+ return T.getArchName();
+ } else { // Parent->getMagic() == MachO::FAT_MAGIC_64
+ Triple T =
+ MachOObjectFile::getArchTriple(Header64.cputype,
+ Header64.cpusubtype);
+ return T.getArchName();
+ }
}
Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const;
return make_range(begin_objects(), end_objects());
}
+ uint32_t getMagic() const { return Magic; }
uint32_t getNumberOfObjects() const { return NumberOfObjects; }
// Cast methods.
MH_MAGIC_64 = 0xFEEDFACFu,
MH_CIGAM_64 = 0xCFFAEDFEu,
FAT_MAGIC = 0xCAFEBABEu,
- FAT_CIGAM = 0xBEBAFECAu
+ FAT_CIGAM = 0xBEBAFECAu,
+ FAT_MAGIC_64 = 0xCAFEBABFu,
+ FAT_CIGAM_64 = 0xBFBAFECAu
};
enum HeaderFileType {
uint32_t align;
};
+ struct fat_arch_64 {
+ uint32_t cputype;
+ uint32_t cpusubtype;
+ uint64_t offset;
+ uint64_t size;
+ uint32_t align;
+ uint32_t reserved;
+ };
+
// Structs from <mach-o/reloc.h>
struct relocation_info {
int32_t r_address;
sys::swapByteOrder(H.align);
}
+template<>
+void SwapStruct(MachO::fat_arch_64 &H) {
+ sys::swapByteOrder(H.cputype);
+ sys::swapByteOrder(H.cpusubtype);
+ sys::swapByteOrder(H.offset);
+ sys::swapByteOrder(H.size);
+ sys::swapByteOrder(H.align);
+ sys::swapByteOrder(H.reserved);
+}
+
template<typename T>
static T getUniversalBinaryStruct(const char *Ptr) {
T Res;
} else {
// Parse object header.
StringRef ParentData = Parent->getData();
- const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) +
- Index * sizeof(MachO::fat_arch);
- Header = getUniversalBinaryStruct<MachO::fat_arch>(HeaderPos);
- if (ParentData.size() < Header.offset + Header.size) {
- clear();
+ if (Parent->getMagic() == MachO::FAT_MAGIC) {
+ const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) +
+ Index * sizeof(MachO::fat_arch);
+ Header = getUniversalBinaryStruct<MachO::fat_arch>(HeaderPos);
+ if (ParentData.size() < Header.offset + Header.size) {
+ clear();
+ }
+ } else { // Parent->getMagic() == MachO::FAT_MAGIC_64
+ const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) +
+ Index * sizeof(MachO::fat_arch_64);
+ Header64 = getUniversalBinaryStruct<MachO::fat_arch_64>(HeaderPos);
+ if (ParentData.size() < Header64.offset + Header64.size) {
+ clear();
+ }
}
}
}
return errorCodeToError(object_error::parse_failed);
StringRef ParentData = Parent->getData();
- StringRef ObjectData = ParentData.substr(Header.offset, Header.size);
+ StringRef ObjectData;
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ ObjectData = ParentData.substr(Header.offset, Header.size);
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ ObjectData = ParentData.substr(Header64.offset, Header64.size);
StringRef ObjectName = Parent->getFileName();
MemoryBufferRef ObjBuffer(ObjectData, ObjectName);
return ObjectFile::createMachOObjectFile(ObjBuffer);
return object_error::parse_failed;
StringRef ParentData = Parent->getData();
- StringRef ObjectData = ParentData.substr(Header.offset, Header.size);
+ StringRef ObjectData;
+ if (Parent->getMagic() == MachO::FAT_MAGIC)
+ ObjectData = ParentData.substr(Header.offset, Header.size);
+ else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ ObjectData = ParentData.substr(Header64.offset, Header64.size);
StringRef ObjectName = Parent->getFileName();
MemoryBufferRef ObjBuffer(ObjectData, ObjectName);
return Archive::create(ObjBuffer);
MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source,
std::error_code &ec)
- : Binary(Binary::ID_MachOUniversalBinary, Source), NumberOfObjects(0) {
+ : Binary(Binary::ID_MachOUniversalBinary, Source), Magic(0),
+ NumberOfObjects(0) {
if (Data.getBufferSize() < sizeof(MachO::fat_header)) {
ec = object_error::invalid_file_type;
return;
// Check for magic value and sufficient header size.
StringRef Buf = getData();
MachO::fat_header H= getUniversalBinaryStruct<MachO::fat_header>(Buf.begin());
+ Magic = H.magic;
NumberOfObjects = H.nfat_arch;
- uint32_t MinSize = sizeof(MachO::fat_header) +
- sizeof(MachO::fat_arch) * NumberOfObjects;
- if (H.magic != MachO::FAT_MAGIC || Buf.size() < MinSize) {
+ uint32_t MinSize = sizeof(MachO::fat_header);
+ if (Magic == MachO::FAT_MAGIC)
+ MinSize += sizeof(MachO::fat_arch) * NumberOfObjects;
+ else if (Magic == MachO::FAT_MAGIC_64)
+ MinSize += sizeof(MachO::fat_arch_64) * NumberOfObjects;
+ else {
+ ec = object_error::parse_failed;
+ return;
+ }
+ if (Buf.size() < MinSize) {
ec = object_error::parse_failed;
return;
}
case 0xCA:
if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) &&
- Magic[3] == char(0xBE)) {
+ (Magic[3] == char(0xBE) || Magic[3] == char(0xBF))) {
// This is complicated by an overlap with Java class files.
// See the Mach-O section in /usr/share/file/magic for details.
if (Magic.size() >= 8 && Magic[7] < 43)
RUN: llvm-nm -arch all %p/Inputs/macho-universal.x86_64.i386 \
RUN: | FileCheck %s -check-prefix CHECK-OBJ
+RUN: llvm-nm -arch all %p/Inputs/macho-universal64.x86_64.i386 \
+RUN: | FileCheck %s -check-prefix CHECK-64-OBJ
RUN: llvm-nm -arch x86_64 %p/Inputs/macho-universal.x86_64.i386 \
RUN: | FileCheck %s -check-prefix CHECK-OBJ-x86_64
RUN: not llvm-nm -arch armv7m %p/Inputs/macho-universal.x86_64.i386 2>&1 \
RUN: | FileCheck %s -check-prefix CHECK-OBJ-foobar
RUN: llvm-nm -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
RUN: | FileCheck %s -check-prefix CHECK-AR
+RUN: llvm-nm -arch all %p/Inputs/macho-universal64-archive.x86_64.i386 \
+RUN: | FileCheck %s -check-prefix CHECK-64-AR
RUN: llvm-nm -arch i386 %p/Inputs/macho-universal-archive.x86_64.i386 \
RUN: | FileCheck %s -check-prefix CHECK-AR-i386
RUN: llvm-nm -o -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
CHECK-OBJ: macho-universal.x86_64.i386 (for architecture i386):
CHECK-OBJ: 00001fa0 T _main
+CHECK-64-OBJ: macho-universal64.x86_64.i386 (for architecture x86_64):
+CHECK-64-OBJ: 0000000100000f60 T _main
+CHECK-64-OBJ: macho-universal64.x86_64.i386 (for architecture i386):
+CHECK-64-OBJ: 00001fa0 T _main
+
CHECK-OBJ-x86_64: 0000000100000000 T __mh_execute_header
CHECK-OBJ-x86_64: 0000000100000f60 T _main
CHECK-OBJ-x86_64: U dyld_stub_binder
CHECK-AR: 00000008 D _bar
CHECK-AR: 00000000 T _foo
+CHECK-64-AR: macho-universal64-archive.x86_64.i386(foo.o) (for architecture i386):
+CHECK-64-AR: 00000008 D _bar
+CHECK-64-AR: 00000000 T _foo
+CHECK-64-AR: macho-universal64-archive.x86_64.i386(hello.o) (for architecture x86_64):
+CHECK-64-AR: 0000000000000068 s EH_frame0
+CHECK-64-AR: 000000000000003b s L_.str
+CHECK-64-AR: 0000000000000000 T _main
+CHECK-64-AR: 0000000000000080 S _main.eh
+CHECK-64-AR: U _printf
+
CHECK-AR-i386: macho-universal-archive.x86_64.i386(foo.o):
CHECK-AR-i386: 00000008 D _bar
CHECK-AR-i386: 00000000 T _foo