mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-02 00:16:25 +00:00
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 llvm-svn: 273207
This commit is contained in:
parent
c4253d06ca
commit
151c83f707
@ -30,6 +30,7 @@ namespace object {
|
||||
class MachOUniversalBinary : public Binary {
|
||||
virtual void anchor();
|
||||
|
||||
uint32_t Magic;
|
||||
uint32_t NumberOfObjects;
|
||||
public:
|
||||
class ObjectForArch {
|
||||
@ -38,6 +39,7 @@ public:
|
||||
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);
|
||||
@ -52,15 +54,47 @@ public:
|
||||
}
|
||||
|
||||
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;
|
||||
@ -103,6 +137,7 @@ public:
|
||||
return make_range(begin_objects(), end_objects());
|
||||
}
|
||||
|
||||
uint32_t getMagic() const { return Magic; }
|
||||
uint32_t getNumberOfObjects() const { return NumberOfObjects; }
|
||||
|
||||
// Cast methods.
|
||||
|
@ -29,7 +29,9 @@ namespace llvm {
|
||||
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 {
|
||||
@ -891,6 +893,15 @@ namespace llvm {
|
||||
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;
|
||||
|
@ -40,6 +40,16 @@ void SwapStruct(MachO::fat_arch &H) {
|
||||
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;
|
||||
@ -58,11 +68,20 @@ MachOUniversalBinary::ObjectForArch::ObjectForArch(
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -73,7 +92,11 @@ MachOUniversalBinary::ObjectForArch::getAsObjectFile() const {
|
||||
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);
|
||||
@ -85,7 +108,11 @@ MachOUniversalBinary::ObjectForArch::getAsArchive() const {
|
||||
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);
|
||||
@ -105,7 +132,8 @@ MachOUniversalBinary::create(MemoryBufferRef Source) {
|
||||
|
||||
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;
|
||||
@ -113,10 +141,18 @@ MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source,
|
||||
// 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;
|
||||
}
|
||||
|
@ -1049,7 +1049,7 @@ file_magic identify_magic(StringRef Magic) {
|
||||
|
||||
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)
|
||||
|
BIN
test/Object/Inputs/macho-universal64.x86_64.i386
Executable file
BIN
test/Object/Inputs/macho-universal64.x86_64.i386
Executable file
Binary file not shown.
@ -1,5 +1,7 @@
|
||||
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 \
|
||||
@ -8,6 +10,8 @@ RUN: not llvm-nm -arch foobar %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 \
|
||||
@ -18,6 +22,11 @@ CHECK-OBJ: 0000000100000f60 T _main
|
||||
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
|
||||
@ -38,6 +47,16 @@ CHECK-AR: macho-universal-archive.x86_64.i386(foo.o) (for architecture i386):
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user