mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 21:50:40 +00:00
e9ddf3a4a7
when the object is from a slice of a Mach-O Universal Binary use something like "foo.o (for architecture i386)" as part of the error message when expected. Also fixed places in these tools that were ignoring object file errors from MachOUniversalBinary::getAsObjectFile() when the code moved on to see if the slice was an archive. To do this MachOUniversalBinary::getAsObjectFile() and MachOUniversalBinary::getObjectForArch() were changed from returning ErrorOr<...> to Expected<...> then that was threaded up to its users. Converting these interfaces to Expected<> from ErrorOr<> does involve touching a number of places. To contain the changes for now the use of errorToErrorCode() is still used in two places yet to be fully converted. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271332 91177308-0d34-0410-b5e6-96231b3b80d8
137 lines
4.3 KiB
C++
137 lines
4.3 KiB
C++
//===- MachOUniversal.cpp - Mach-O universal binary -------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the MachOUniversalBinary class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Object/MachOUniversal.h"
|
|
#include "llvm/Object/Archive.h"
|
|
#include "llvm/Object/MachO.h"
|
|
#include "llvm/Object/ObjectFile.h"
|
|
#include "llvm/Support/Casting.h"
|
|
#include "llvm/Support/Host.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
using namespace llvm;
|
|
using namespace object;
|
|
|
|
template<typename T>
|
|
static void SwapStruct(T &Value);
|
|
|
|
template<>
|
|
void SwapStruct(MachO::fat_header &H) {
|
|
sys::swapByteOrder(H.magic);
|
|
sys::swapByteOrder(H.nfat_arch);
|
|
}
|
|
|
|
template<>
|
|
void SwapStruct(MachO::fat_arch &H) {
|
|
sys::swapByteOrder(H.cputype);
|
|
sys::swapByteOrder(H.cpusubtype);
|
|
sys::swapByteOrder(H.offset);
|
|
sys::swapByteOrder(H.size);
|
|
sys::swapByteOrder(H.align);
|
|
}
|
|
|
|
template<typename T>
|
|
static T getUniversalBinaryStruct(const char *Ptr) {
|
|
T Res;
|
|
memcpy(&Res, Ptr, sizeof(T));
|
|
// Universal binary headers have big-endian byte order.
|
|
if (sys::IsLittleEndianHost)
|
|
SwapStruct(Res);
|
|
return Res;
|
|
}
|
|
|
|
MachOUniversalBinary::ObjectForArch::ObjectForArch(
|
|
const MachOUniversalBinary *Parent, uint32_t Index)
|
|
: Parent(Parent), Index(Index) {
|
|
if (!Parent || Index >= Parent->getNumberOfObjects()) {
|
|
clear();
|
|
} 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();
|
|
}
|
|
}
|
|
}
|
|
|
|
Expected<std::unique_ptr<MachOObjectFile>>
|
|
MachOUniversalBinary::ObjectForArch::getAsObjectFile() const {
|
|
if (!Parent)
|
|
return errorCodeToError(object_error::parse_failed);
|
|
|
|
StringRef ParentData = Parent->getData();
|
|
StringRef ObjectData = ParentData.substr(Header.offset, Header.size);
|
|
StringRef ObjectName = Parent->getFileName();
|
|
MemoryBufferRef ObjBuffer(ObjectData, ObjectName);
|
|
return ObjectFile::createMachOObjectFile(ObjBuffer);
|
|
}
|
|
|
|
ErrorOr<std::unique_ptr<Archive>>
|
|
MachOUniversalBinary::ObjectForArch::getAsArchive() const {
|
|
if (!Parent)
|
|
return object_error::parse_failed;
|
|
|
|
StringRef ParentData = Parent->getData();
|
|
StringRef ObjectData = ParentData.substr(Header.offset, Header.size);
|
|
StringRef ObjectName = Parent->getFileName();
|
|
MemoryBufferRef ObjBuffer(ObjectData, ObjectName);
|
|
return Archive::create(ObjBuffer);
|
|
}
|
|
|
|
void MachOUniversalBinary::anchor() { }
|
|
|
|
ErrorOr<std::unique_ptr<MachOUniversalBinary>>
|
|
MachOUniversalBinary::create(MemoryBufferRef Source) {
|
|
std::error_code EC;
|
|
std::unique_ptr<MachOUniversalBinary> Ret(
|
|
new MachOUniversalBinary(Source, EC));
|
|
if (EC)
|
|
return EC;
|
|
return std::move(Ret);
|
|
}
|
|
|
|
MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source,
|
|
std::error_code &ec)
|
|
: Binary(Binary::ID_MachOUniversalBinary, Source), 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());
|
|
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) {
|
|
ec = object_error::parse_failed;
|
|
return;
|
|
}
|
|
ec = std::error_code();
|
|
}
|
|
|
|
Expected<std::unique_ptr<MachOObjectFile>>
|
|
MachOUniversalBinary::getObjectForArch(StringRef ArchName) const {
|
|
if (Triple(ArchName).getArch() == Triple::ArchType::UnknownArch)
|
|
return errorCodeToError(object_error::arch_not_found);
|
|
|
|
for (object_iterator I = begin_objects(), E = end_objects(); I != E; ++I) {
|
|
if (I->getArchTypeName() == ArchName)
|
|
return I->getAsObjectFile();
|
|
}
|
|
return errorCodeToError(object_error::arch_not_found);
|
|
}
|