llvm.org GIT mirror llvm / f5d5db7
Add support for Darwin’s 64-bit universal files with 64-bit offsets and sizes for the objects. Darwin added support in its Xcode 8.0 tools (released in the beta) for universal files where offsets and sizes for the objects are 64-bits to allow support for objects contained in universal files to be larger then 4gb. The change is very straight forward. There is a new magic number that differs by one bit, much like the 64-bit Mach-O files. Then there is a new structure that follow the fat_header that has the same layout but with the offset and size fields using 64-bit values instead of 32-bit values. rdar://26899493 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273207 91177308-0d34-0410-b5e6-96231b3b80d8 Kevin Enderby 3 years ago
6 changed file(s) with 122 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
2929 class MachOUniversalBinary : public Binary {
3030 virtual void anchor();
3131
32 uint32_t Magic;
3233 uint32_t NumberOfObjects;
3334 public:
3435 class ObjectForArch {
3738 uint32_t Index;
3839 /// \brief Descriptor of the object.
3940 MachO::fat_arch Header;
41 MachO::fat_arch_64 Header64;
4042
4143 public:
4244 ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index);
5153 }
5254
5355 ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
54 uint32_t getCPUType() const { return Header.cputype; }
55 uint32_t getCPUSubType() const { return Header.cpusubtype; }
56 uint32_t getOffset() const { return Header.offset; }
57 uint32_t getSize() const { return Header.size; }
58 uint32_t getAlign() const { return Header.align; }
56 uint32_t getCPUType() const {
57 if (Parent->getMagic() == MachO::FAT_MAGIC)
58 return Header.cputype;
59 else // Parent->getMagic() == MachO::FAT_MAGIC_64
60 return Header64.cputype;
61 }
62 uint32_t getCPUSubType() const {
63 if (Parent->getMagic() == MachO::FAT_MAGIC)
64 return Header.cpusubtype;
65 else // Parent->getMagic() == MachO::FAT_MAGIC_64
66 return Header64.cpusubtype;
67 }
68 uint32_t getOffset() const {
69 if (Parent->getMagic() == MachO::FAT_MAGIC)
70 return Header.offset;
71 else // Parent->getMagic() == MachO::FAT_MAGIC_64
72 return Header64.offset;
73 }
74 uint32_t getSize() const {
75 if (Parent->getMagic() == MachO::FAT_MAGIC)
76 return Header.size;
77 else // Parent->getMagic() == MachO::FAT_MAGIC_64
78 return Header64.size;
79 }
80 uint32_t getAlign() const {
81 if (Parent->getMagic() == MachO::FAT_MAGIC)
82 return Header.align;
83 else // Parent->getMagic() == MachO::FAT_MAGIC_64
84 return Header64.align;
85 }
5986 std::string getArchTypeName() const {
60 Triple T =
61 MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype);
62 return T.getArchName();
87 if (Parent->getMagic() == MachO::FAT_MAGIC) {
88 Triple T =
89 MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype);
90 return T.getArchName();
91 } else { // Parent->getMagic() == MachO::FAT_MAGIC_64
92 Triple T =
93 MachOObjectFile::getArchTriple(Header64.cputype,
94 Header64.cpusubtype);
95 return T.getArchName();
96 }
6397 }
6498
6599 Expected> getAsObjectFile() const;
102136 return make_range(begin_objects(), end_objects());
103137 }
104138
139 uint32_t getMagic() const { return Magic; }
105140 uint32_t getNumberOfObjects() const { return NumberOfObjects; }
106141
107142 // Cast methods.
2828 MH_MAGIC_64 = 0xFEEDFACFu,
2929 MH_CIGAM_64 = 0xCFFAEDFEu,
3030 FAT_MAGIC = 0xCAFEBABEu,
31 FAT_CIGAM = 0xBEBAFECAu
31 FAT_CIGAM = 0xBEBAFECAu,
32 FAT_MAGIC_64 = 0xCAFEBABFu,
33 FAT_CIGAM_64 = 0xBFBAFECAu
3234 };
3335
3436 enum HeaderFileType {
890892 uint32_t align;
891893 };
892894
895 struct fat_arch_64 {
896 uint32_t cputype;
897 uint32_t cpusubtype;
898 uint64_t offset;
899 uint64_t size;
900 uint32_t align;
901 uint32_t reserved;
902 };
903
893904 // Structs from
894905 struct relocation_info {
895906 int32_t r_address;
3939 sys::swapByteOrder(H.align);
4040 }
4141
42 template<>
43 void SwapStruct(MachO::fat_arch_64 &H) {
44 sys::swapByteOrder(H.cputype);
45 sys::swapByteOrder(H.cpusubtype);
46 sys::swapByteOrder(H.offset);
47 sys::swapByteOrder(H.size);
48 sys::swapByteOrder(H.align);
49 sys::swapByteOrder(H.reserved);
50 }
51
4252 template
4353 static T getUniversalBinaryStruct(const char *Ptr) {
4454 T Res;
5767 } else {
5868 // Parse object header.
5969 StringRef ParentData = Parent->getData();
60 const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) +
61 Index * sizeof(MachO::fat_arch);
62 Header = getUniversalBinaryStruct(HeaderPos);
63 if (ParentData.size() < Header.offset + Header.size) {
64 clear();
70 if (Parent->getMagic() == MachO::FAT_MAGIC) {
71 const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) +
72 Index * sizeof(MachO::fat_arch);
73 Header = getUniversalBinaryStruct(HeaderPos);
74 if (ParentData.size() < Header.offset + Header.size) {
75 clear();
76 }
77 } else { // Parent->getMagic() == MachO::FAT_MAGIC_64
78 const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) +
79 Index * sizeof(MachO::fat_arch_64);
80 Header64 = getUniversalBinaryStruct(HeaderPos);
81 if (ParentData.size() < Header64.offset + Header64.size) {
82 clear();
83 }
6584 }
6685 }
6786 }
7291 return errorCodeToError(object_error::parse_failed);
7392
7493 StringRef ParentData = Parent->getData();
75 StringRef ObjectData = ParentData.substr(Header.offset, Header.size);
94 StringRef ObjectData;
95 if (Parent->getMagic() == MachO::FAT_MAGIC)
96 ObjectData = ParentData.substr(Header.offset, Header.size);
97 else // Parent->getMagic() == MachO::FAT_MAGIC_64
98 ObjectData = ParentData.substr(Header64.offset, Header64.size);
7699 StringRef ObjectName = Parent->getFileName();
77100 MemoryBufferRef ObjBuffer(ObjectData, ObjectName);
78101 return ObjectFile::createMachOObjectFile(ObjBuffer);
84107 return object_error::parse_failed;
85108
86109 StringRef ParentData = Parent->getData();
87 StringRef ObjectData = ParentData.substr(Header.offset, Header.size);
110 StringRef ObjectData;
111 if (Parent->getMagic() == MachO::FAT_MAGIC)
112 ObjectData = ParentData.substr(Header.offset, Header.size);
113 else // Parent->getMagic() == MachO::FAT_MAGIC_64
114 ObjectData = ParentData.substr(Header64.offset, Header64.size);
88115 StringRef ObjectName = Parent->getFileName();
89116 MemoryBufferRef ObjBuffer(ObjectData, ObjectName);
90117 return Archive::create(ObjBuffer);
104131
105132 MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source,
106133 std::error_code &ec)
107 : Binary(Binary::ID_MachOUniversalBinary, Source), NumberOfObjects(0) {
134 : Binary(Binary::ID_MachOUniversalBinary, Source), Magic(0),
135 NumberOfObjects(0) {
108136 if (Data.getBufferSize() < sizeof(MachO::fat_header)) {
109137 ec = object_error::invalid_file_type;
110138 return;
112140 // Check for magic value and sufficient header size.
113141 StringRef Buf = getData();
114142 MachO::fat_header H= getUniversalBinaryStruct(Buf.begin());
143 Magic = H.magic;
115144 NumberOfObjects = H.nfat_arch;
116 uint32_t MinSize = sizeof(MachO::fat_header) +
117 sizeof(MachO::fat_arch) * NumberOfObjects;
118 if (H.magic != MachO::FAT_MAGIC || Buf.size() < MinSize) {
145 uint32_t MinSize = sizeof(MachO::fat_header);
146 if (Magic == MachO::FAT_MAGIC)
147 MinSize += sizeof(MachO::fat_arch) * NumberOfObjects;
148 else if (Magic == MachO::FAT_MAGIC_64)
149 MinSize += sizeof(MachO::fat_arch_64) * NumberOfObjects;
150 else {
151 ec = object_error::parse_failed;
152 return;
153 }
154 if (Buf.size() < MinSize) {
119155 ec = object_error::parse_failed;
120156 return;
121157 }
10481048
10491049 case 0xCA:
10501050 if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) &&
1051 Magic[3] == char(0xBE)) {
1051 (Magic[3] == char(0xBE) || Magic[3] == char(0xBF))) {
10521052 // This is complicated by an overlap with Java class files.
10531053 // See the Mach-O section in /usr/share/file/magic for details.
10541054 if (Magic.size() >= 8 && Magic[7] < 43)
0 RUN: llvm-nm -arch all %p/Inputs/macho-universal.x86_64.i386 \
11 RUN: | FileCheck %s -check-prefix CHECK-OBJ
2 RUN: llvm-nm -arch all %p/Inputs/macho-universal64.x86_64.i386 \
3 RUN: | FileCheck %s -check-prefix CHECK-64-OBJ
24 RUN: llvm-nm -arch x86_64 %p/Inputs/macho-universal.x86_64.i386 \
35 RUN: | FileCheck %s -check-prefix CHECK-OBJ-x86_64
46 RUN: not llvm-nm -arch armv7m %p/Inputs/macho-universal.x86_64.i386 2>&1 \
79 RUN: | FileCheck %s -check-prefix CHECK-OBJ-foobar
810 RUN: llvm-nm -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
911 RUN: | FileCheck %s -check-prefix CHECK-AR
12 RUN: llvm-nm -arch all %p/Inputs/macho-universal64-archive.x86_64.i386 \
13 RUN: | FileCheck %s -check-prefix CHECK-64-AR
1014 RUN: llvm-nm -arch i386 %p/Inputs/macho-universal-archive.x86_64.i386 \
1115 RUN: | FileCheck %s -check-prefix CHECK-AR-i386
1216 RUN: llvm-nm -o -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
1620 CHECK-OBJ: 0000000100000f60 T _main
1721 CHECK-OBJ: macho-universal.x86_64.i386 (for architecture i386):
1822 CHECK-OBJ: 00001fa0 T _main
23
24 CHECK-64-OBJ: macho-universal64.x86_64.i386 (for architecture x86_64):
25 CHECK-64-OBJ: 0000000100000f60 T _main
26 CHECK-64-OBJ: macho-universal64.x86_64.i386 (for architecture i386):
27 CHECK-64-OBJ: 00001fa0 T _main
1928
2029 CHECK-OBJ-x86_64: 0000000100000000 T __mh_execute_header
2130 CHECK-OBJ-x86_64: 0000000100000f60 T _main
3746 CHECK-AR: 00000008 D _bar
3847 CHECK-AR: 00000000 T _foo
3948
49 CHECK-64-AR: macho-universal64-archive.x86_64.i386(foo.o) (for architecture i386):
50 CHECK-64-AR: 00000008 D _bar
51 CHECK-64-AR: 00000000 T _foo
52 CHECK-64-AR: macho-universal64-archive.x86_64.i386(hello.o) (for architecture x86_64):
53 CHECK-64-AR: 0000000000000068 s EH_frame0
54 CHECK-64-AR: 000000000000003b s L_.str
55 CHECK-64-AR: 0000000000000000 T _main
56 CHECK-64-AR: 0000000000000080 S _main.eh
57 CHECK-64-AR: U _printf
58
4059 CHECK-AR-i386: macho-universal-archive.x86_64.i386(foo.o):
4160 CHECK-AR-i386: 00000008 D _bar
4261 CHECK-AR-i386: 00000000 T _foo