summaryrefslogtreecommitdiffstats
path: root/lib/Object/MachOObject.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-11-27 07:19:41 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-11-27 07:19:41 +0000
commita956d8b71755b908d8a150736e8857d2214060c6 (patch)
tree6ac44d294bb7e144b41f7316b518250c8b07a61d /lib/Object/MachOObject.cpp
parentbce55776af16b70408e2ae2e6d91f8ac1e43f6a7 (diff)
downloadexternal_llvm-a956d8b71755b908d8a150736e8857d2214060c6.zip
external_llvm-a956d8b71755b908d8a150736e8857d2214060c6.tar.gz
external_llvm-a956d8b71755b908d8a150736e8857d2214060c6.tar.bz2
Object/Mach-O: Add header and load command information.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120198 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Object/MachOObject.cpp')
-rw-r--r--lib/Object/MachOObject.cpp83
1 files changed, 80 insertions, 3 deletions
diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp
index de87605..5c17dfc 100644
--- a/lib/Object/MachOObject.cpp
+++ b/lib/Object/MachOObject.cpp
@@ -10,13 +10,49 @@
#include "llvm/Object/MachOObject.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/SwapByteOrder.h"
using namespace llvm;
-using namespace object;
+using namespace llvm::object;
+
+template<typename T>
+static void SwapValue(T &Value) {
+ Value = sys::SwapByteOrder(Value);
+}
MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_,
bool Is64Bit_)
- : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_) {
+ : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_),
+ IsSwappedEndian(IsLittleEndian != sys::isLittleEndianHost()),
+ LoadCommands(0), NumLoadedCommands(0) {
+ // Load the common header.
+ memcpy(&Header, Buffer->getBuffer().data(), sizeof(Header));
+ if (IsSwappedEndian) {
+ SwapValue(Header.Magic);
+ SwapValue(Header.CPUType);
+ SwapValue(Header.CPUSubtype);
+ SwapValue(Header.FileType);
+ SwapValue(Header.NumLoadCommands);
+ SwapValue(Header.SizeOfLoadCommands);
+ SwapValue(Header.Flags);
+ }
+
+ if (is64Bit()) {
+ memcpy(&Header64Ext, Buffer->getBuffer().data() + sizeof(Header),
+ sizeof(Header64Ext));
+ if (IsSwappedEndian) {
+ SwapValue(Header64Ext.Reserved);
+ }
+ }
+
+ // Create the load command array if sane.
+ if (getHeader().NumLoadCommands < (1 << 20))
+ LoadCommands = new LoadCommandInfo[getHeader().NumLoadCommands];
+}
+
+MachOObject::~MachOObject() {
+ delete LoadCommands;
}
MachOObject *MachOObject::LoadFromBuffer(MemoryBuffer *Buffer,
@@ -33,13 +69,54 @@ MachOObject *MachOObject::LoadFromBuffer(MemoryBuffer *Buffer,
IsLittleEndian = true;
Is64Bit = true;
} else {
- *ErrorStr = "not a Mach object file";
+ if (ErrorStr) *ErrorStr = "not a Mach object file (invalid magic)";
+ return 0;
+ }
+
+ // Ensure that the at least the full header is present.
+ unsigned HeaderSize = Is64Bit ? macho::Header64Size : macho::Header32Size;
+ if (Buffer->getBufferSize() < HeaderSize) {
+ if (ErrorStr) *ErrorStr = "not a Mach object file (invalid header)";
return 0;
}
OwningPtr<MachOObject> Object(new MachOObject(Buffer, IsLittleEndian,
Is64Bit));
+ // Check for bogus number of load commands.
+ if (Object->getHeader().NumLoadCommands >= (1 << 20)) {
+ if (ErrorStr) *ErrorStr = "not a Mach object file (unreasonable header)";
+ return 0;
+ }
+
if (ErrorStr) *ErrorStr = "";
return Object.take();
}
+
+const MachOObject::LoadCommandInfo &
+MachOObject::getLoadCommandInfo(unsigned Index) const {
+ assert(Index < getHeader().NumLoadCommands && "Invalid index!");
+
+ // Load the command, if necessary.
+ if (Index >= NumLoadedCommands) {
+ uint64_t Offset;
+ if (Index == 0) {
+ Offset = getHeaderSize();
+ } else {
+ const LoadCommandInfo &Prev = getLoadCommandInfo(Index - 1);
+ Offset = Prev.Offset + Prev.Command.Size;
+ }
+
+ LoadCommandInfo &Info = LoadCommands[Index];
+ memcpy(&Info.Command, Buffer->getBuffer().data() + Offset,
+ sizeof(macho::LoadCommand));
+ if (IsSwappedEndian) {
+ SwapValue(Info.Command.Type);
+ SwapValue(Info.Command.Size);
+ }
+ Info.Offset = Offset;
+ NumLoadedCommands = Index + 1;
+ }
+
+ return LoadCommands[Index];
+}