summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Object/MachO.h6
-rw-r--r--include/llvm/Object/ObjectFile.h4
-rw-r--r--lib/Object/MachOObjectFile.cpp35
-rw-r--r--lib/Object/MachOUniversal.cpp10
-rw-r--r--test/Object/Inputs/macho-invalid-fat_cputypebin0 -> 56 bytes
-rw-r--r--test/Object/macho-invalid.test3
6 files changed, 44 insertions, 14 deletions
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 7906db1e8a7..a26a2ef7dfe 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -194,7 +194,8 @@ public:
typedef LoadCommandList::const_iterator load_command_iterator;
static Expected<std::unique_ptr<MachOObjectFile>>
- create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits);
+ create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
+ uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0);
void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -443,7 +444,8 @@ public:
private:
MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
- Error &Err);
+ Error &Err, uint32_t UniversalCputype = 0,
+ uint32_t UniversalIndex = 0);
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 6272a5f056e..07d6b134086 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -300,7 +300,9 @@ public:
createELFObjectFile(MemoryBufferRef Object);
static Expected<std::unique_ptr<MachOObjectFile>>
- createMachOObjectFile(MemoryBufferRef Object);
+ createMachOObjectFile(MemoryBufferRef Object,
+ uint32_t UniversalCputype = 0,
+ uint32_t UniversalIndex = 0);
};
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 0edc6a71633..5bfc51ecf62 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -914,18 +914,22 @@ static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj,
Expected<std::unique_ptr<MachOObjectFile>>
MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
- bool Is64Bits) {
+ bool Is64Bits, uint32_t UniversalCputype,
+ uint32_t UniversalIndex) {
Error Err;
std::unique_ptr<MachOObjectFile> Obj(
new MachOObjectFile(std::move(Object), IsLittleEndian,
- Is64Bits, Err));
+ Is64Bits, Err, UniversalCputype,
+ UniversalIndex));
if (Err)
return std::move(Err);
return std::move(Obj);
}
MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
- bool Is64bits, Error &Err)
+ bool Is64bits, Error &Err,
+ uint32_t UniversalCputype,
+ uint32_t UniversalIndex)
: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
@@ -933,12 +937,15 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
HasPageZeroSegment(false) {
ErrorAsOutParameter ErrAsOutParam(&Err);
uint64_t SizeOfHeaders;
+ uint32_t cputype;
if (is64Bit()) {
parseHeader(this, Header64, Err);
SizeOfHeaders = sizeof(MachO::mach_header_64);
+ cputype = Header64.cputype;
} else {
parseHeader(this, Header, Err);
SizeOfHeaders = sizeof(MachO::mach_header);
+ cputype = Header.cputype;
}
if (Err)
return;
@@ -947,6 +954,12 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
Err = malformedError("load commands extend past the end of the file");
return;
}
+ if (UniversalCputype != 0 && cputype != UniversalCputype) {
+ Err = malformedError("universal header architecture: " +
+ Twine(UniversalIndex) + "'s cputype does not match "
+ "object file's mach header");
+ return;
+ }
uint32_t LoadCommandCount = getHeader().ncmds;
LoadCommandInfo Load;
@@ -3281,16 +3294,22 @@ bool MachOObjectFile::isRelocatableObject() const {
}
Expected<std::unique_ptr<MachOObjectFile>>
-ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
+ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
+ uint32_t UniversalCputype,
+ uint32_t UniversalIndex) {
StringRef Magic = Buffer.getBuffer().slice(0, 4);
if (Magic == "\xFE\xED\xFA\xCE")
- return MachOObjectFile::create(Buffer, false, false);
+ return MachOObjectFile::create(Buffer, false, false,
+ UniversalCputype, UniversalIndex);
if (Magic == "\xCE\xFA\xED\xFE")
- return MachOObjectFile::create(Buffer, true, false);
+ return MachOObjectFile::create(Buffer, true, false,
+ UniversalCputype, UniversalIndex);
if (Magic == "\xFE\xED\xFA\xCF")
- return MachOObjectFile::create(Buffer, false, true);
+ return MachOObjectFile::create(Buffer, false, true,
+ UniversalCputype, UniversalIndex);
if (Magic == "\xCF\xFA\xED\xFE")
- return MachOObjectFile::create(Buffer, true, true);
+ return MachOObjectFile::create(Buffer, true, true,
+ UniversalCputype, UniversalIndex);
return make_error<GenericBinaryError>("Unrecognized MachO magic number",
object_error::invalid_file_type);
}
diff --git a/lib/Object/MachOUniversal.cpp b/lib/Object/MachOUniversal.cpp
index f36e84d93b9..bac9d4dd3e3 100644
--- a/lib/Object/MachOUniversal.cpp
+++ b/lib/Object/MachOUniversal.cpp
@@ -73,13 +73,17 @@ MachOUniversalBinary::ObjectForArch::getAsObjectFile() const {
StringRef ParentData = Parent->getData();
StringRef ObjectData;
- if (Parent->getMagic() == MachO::FAT_MAGIC)
+ uint32_t cputype;
+ if (Parent->getMagic() == MachO::FAT_MAGIC) {
ObjectData = ParentData.substr(Header.offset, Header.size);
- else // Parent->getMagic() == MachO::FAT_MAGIC_64
+ cputype = Header.cputype;
+ } else { // Parent->getMagic() == MachO::FAT_MAGIC_64
ObjectData = ParentData.substr(Header64.offset, Header64.size);
+ cputype = Header64.cputype;
+ }
StringRef ObjectName = Parent->getFileName();
MemoryBufferRef ObjBuffer(ObjectData, ObjectName);
- return ObjectFile::createMachOObjectFile(ObjBuffer);
+ return ObjectFile::createMachOObjectFile(ObjBuffer, cputype, Index);
}
Expected<std::unique_ptr<Archive>>
diff --git a/test/Object/Inputs/macho-invalid-fat_cputype b/test/Object/Inputs/macho-invalid-fat_cputype
new file mode 100644
index 00000000000..ce30be86932
--- /dev/null
+++ b/test/Object/Inputs/macho-invalid-fat_cputype
Binary files differ
diff --git a/test/Object/macho-invalid.test b/test/Object/macho-invalid.test
index 5a00d0def52..403b968fc05 100644
--- a/test/Object/macho-invalid.test
+++ b/test/Object/macho-invalid.test
@@ -406,3 +406,6 @@ INVALID-TWOLEVELHINTS-OFFSET: macho-invalid-twolevelhints-offset': truncated or
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-twolevelhints-offset-nhints 2>&1 | FileCheck -check-prefix INVALID-TWOLEVELHINTS-OFFSET-HNINTS %s
INVALID-TWOLEVELHINTS-OFFSET-HNINTS: macho-invalid-twolevelhints-offset-nhints': truncated or malformed object (offset field plus nhints times sizeof(struct twolevel_hint) field of LC_TWOLEVEL_HINTS command 0 extends past the end of the file)
+
+RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-fat_cputype 2>&1 | FileCheck -check-prefix INVALID-FAT-CPUTYPE %s
+INVALID-FAT-CPUTYPE: macho-invalid-fat_cputype truncated or malformed object (universal header architecture: 0's cputype does not match object file's mach header)