summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-04-26 20:07:33 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-04-26 20:07:33 +0000
commit2173e1839c2d00f7f980450dd537047b7b376e6b (patch)
tree88a1b23ce0c311290c8aae04f3b4cc7d21cec65f
parentfbb2c7adc23b20141c5f78bbee07ae22028473a7 (diff)
Use llvm/Object/MachO.h in macho-dumper. Drop the old macho parser.
For Mach-O there were 2 implementations for parsing object files. A standalone llvm/Object/MachOObject.h and llvm/Object/MachO.h which implements the generic interface in llvm/Object/ObjectFile.h. This patch adds the missing features to MachO.h, moves macho-dump to use MachO.h and removes ObjectFile.h. In addition to making sure that check-all is clean, I checked that the new version produces exactly the same output in all Mach-O files in a llvm+clang build directory (including executables and shared libraries). To test the performance, I ran macho-dump over all the files in a llvm+clang build directory again, but this time redirecting the output to /dev/null. Both the old and new versions take about 4.6 seconds (2.5 user) to finish. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180624 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/ADT/InMemoryStruct.h77
-rw-r--r--include/llvm/Object/MachO.h22
-rw-r--r--include/llvm/Object/MachOObject.h212
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h2
-rw-r--r--lib/Object/CMakeLists.txt1
-rw-r--r--lib/Object/MachOObject.cpp422
-rw-r--r--lib/Object/MachOObjectFile.cpp161
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp2
-rw-r--r--tools/macho-dump/macho-dump.cpp424
9 files changed, 347 insertions, 976 deletions
diff --git a/include/llvm/ADT/InMemoryStruct.h b/include/llvm/ADT/InMemoryStruct.h
deleted file mode 100644
index a56084501a6..00000000000
--- a/include/llvm/ADT/InMemoryStruct.h
+++ /dev/null
@@ -1,77 +0,0 @@
-//===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ADT_INMEMORYSTRUCT_H
-#define LLVM_ADT_INMEMORYSTRUCT_H
-
-#include <cassert>
-
-namespace llvm {
-
-/// \brief Helper object for abstracting access to an in-memory structure which
-/// may require some kind of temporary storage.
-///
-/// This class is designed to be used for accessing file data structures which
-/// in the common case can be accessed from a direct pointer to a memory mapped
-/// object, but which in some cases may require indirect access to a temporary
-/// structure (which, for example, may have undergone endianness translation).
-template<typename T>
-class InMemoryStruct {
- typedef T value_type;
- typedef value_type &reference;
- typedef value_type *pointer;
- typedef const value_type &const_reference;
- typedef const value_type *const_pointer;
-
- /// \brief The smart pointer target.
- value_type *Target;
-
- /// \brief A temporary object which can be used as a target of the smart
- /// pointer.
- value_type Contents;
-
-private:
-
-public:
- InMemoryStruct() : Target(0) {}
- InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {}
- InMemoryStruct(pointer Value) : Target(Value) {}
- InMemoryStruct(const InMemoryStruct<T> &Value) { *this = Value; }
-
- void operator=(const InMemoryStruct<T> &Value) {
- if (Value.Target != &Value.Contents) {
- Target = Value.Target;
- } else {
- Target = &Contents;
- Contents = Value.Contents;
- }
- }
-
- const_reference operator*() const {
- assert(Target && "Cannot dereference null pointer");
- return *Target;
- }
- reference operator*() {
- assert(Target && "Cannot dereference null pointer");
- return *Target;
- }
-
- const_pointer operator->() const {
- return Target;
- }
- pointer operator->() {
- return Target;
- }
-
- operator bool() const { return Target != 0; }
-};
-
-}
-
-#endif
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index d8598ebdcf0..98d3788e44c 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -106,6 +106,9 @@ public:
virtual StringRef getLoadName() const;
+ relocation_iterator getSectionRelBegin(unsigned Index) const;
+ relocation_iterator getSectionRelEnd(unsigned Index) const;
+
// In a MachO file, sections have a segment name. This is used in the .o
// files. They have a single segment, but this field specifies which segment
// a section should be put in in the final object.
@@ -134,14 +137,32 @@ public:
// MachO specific structures.
macho::Section getSection(DataRefImpl DRI) const;
macho::Section64 getSection64(DataRefImpl DRI) const;
+ macho::Section getSection(const LoadCommandInfo &L, unsigned Index) const;
+ macho::Section64 getSection64(const LoadCommandInfo &L, unsigned Index) const;
macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const;
macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const;
+
macho::LinkeditDataLoadCommand
getLinkeditDataLoadCommand(const LoadCommandInfo &L) const;
+ macho::SegmentLoadCommand
+ getSegmentLoadCommand(const LoadCommandInfo &L) const;
+ macho::Segment64LoadCommand
+ getSegment64LoadCommand(const LoadCommandInfo &L) const;
+ macho::LinkerOptionsLoadCommand
+ getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const;
+
macho::RelocationEntry getRelocation(DataRefImpl Rel) const;
macho::Header getHeader() const;
+ macho::Header64Ext getHeader64Ext() const;
+ macho::IndirectSymbolTableEntry
+ getIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC,
+ unsigned Index) const;
+ macho::DataInCodeTableEntry getDataInCodeTableEntry(uint32_t DataOffset,
+ unsigned Index) const;
macho::SymtabLoadCommand getSymtabLoadCommand() const;
+ macho::DysymtabLoadCommand getDysymtabLoadCommand() const;
+ StringRef getStringTableData() const;
bool is64Bit() const;
void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
@@ -153,6 +174,7 @@ private:
typedef SmallVector<const char*, 1> SectionList;
SectionList Sections;
const char *SymtabLoadCmd;
+ const char *DysymtabLoadCmd;
};
}
diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h
deleted file mode 100644
index 50ee25b4639..00000000000
--- a/include/llvm/Object/MachOObject.h
+++ /dev/null
@@ -1,212 +0,0 @@
-//===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_OBJECT_MACHOOBJECT_H
-#define LLVM_OBJECT_MACHOOBJECT_H
-
-#include "llvm/ADT/InMemoryStruct.h"
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Object/MachOFormat.h"
-#include <string>
-
-namespace llvm {
-
-class MemoryBuffer;
-class raw_ostream;
-
-namespace object {
-
-/// \brief Wrapper object for manipulating Mach-O object files.
-///
-/// This class is designed to implement a full-featured, efficient, portable,
-/// and robust Mach-O interface to Mach-O object files. It does not attempt to
-/// smooth over rough edges in the Mach-O format or generalize access to object
-/// independent features.
-///
-/// The class is designed around accessing the Mach-O object which is expected
-/// to be fully loaded into memory.
-///
-/// This class is *not* suitable for concurrent use. For efficient operation,
-/// the class uses APIs which rely on the ability to cache the results of
-/// certain calls in internal objects which are not safe for concurrent
-/// access. This allows the API to be zero-copy on the common paths.
-//
-// FIXME: It would be cool if we supported a "paged" MemoryBuffer
-// implementation. This would allow us to implement a more sensible version of
-// MemoryObject which can work like a MemoryBuffer, but be more efficient for
-// objects which are in the current address space.
-class MachOObject {
-public:
- struct LoadCommandInfo {
- /// The load command information.
- macho::LoadCommand Command;
-
- /// The offset to the start of the load command in memory.
- uint64_t Offset;
- };
-
-private:
- OwningPtr<MemoryBuffer> Buffer;
-
- /// Whether the object is little endian.
- bool IsLittleEndian;
- /// Whether the object is 64-bit.
- bool Is64Bit;
- /// Whether the object is swapped endianness from the host.
- bool IsSwappedEndian;
- /// Whether the string table has been registered.
- bool HasStringTable;
-
- /// The cached information on the load commands.
- LoadCommandInfo *LoadCommands;
- mutable unsigned NumLoadedCommands;
-
- /// The cached copy of the header.
- macho::Header Header;
- macho::Header64Ext Header64Ext;
-
- /// Cache string table information.
- StringRef StringTable;
-
-private:
- MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit);
-
-public:
- ~MachOObject();
-
- /// \brief Load a Mach-O object from a MemoryBuffer object.
- ///
- /// \param Buffer - The buffer to load the object from. This routine takes
- /// exclusive ownership of the buffer (which is passed to the returned object
- /// on success).
- /// \param ErrorStr [out] - If given, will be set to a user readable error
- /// message on failure.
- /// \returns The loaded object, or null on error.
- static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer,
- std::string *ErrorStr = 0);
-
- /// @name File Information
- /// @{
-
- bool isLittleEndian() const { return IsLittleEndian; }
- bool isSwappedEndian() const { return IsSwappedEndian; }
- bool is64Bit() const { return Is64Bit; }
-
- unsigned getHeaderSize() const {
- return Is64Bit ? macho::Header64Size : macho::Header32Size;
- }
-
- StringRef getData(size_t Offset, size_t Size) const;
-
- /// @}
- /// @name String Table Data
- /// @{
-
- StringRef getStringTableData() const {
- assert(HasStringTable && "String table has not been registered!");
- return StringTable;
- }
-
- StringRef getStringAtIndex(unsigned Index) const {
- size_t End = getStringTableData().find('\0', Index);
- return getStringTableData().slice(Index, End);
- }
-
- void RegisterStringTable(macho::SymtabLoadCommand &SLC);
-
- /// @}
- /// @name Object Header Access
- /// @{
-
- const macho::Header &getHeader() const { return Header; }
- const macho::Header64Ext &getHeader64Ext() const {
- assert(is64Bit() && "Invalid access!");
- return Header64Ext;
- }
-
- /// @}
- /// @name Object Structure Access
- /// @{
-
- // TODO: Would be useful to have an iterator based version
- // of this.
- /// \brief Retrieve the information for the given load command.
- const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const;
-
- void ReadSegmentLoadCommand(
- const LoadCommandInfo &LCI,
- InMemoryStruct<macho::SegmentLoadCommand> &Res) const;
- void ReadSegment64LoadCommand(
- const LoadCommandInfo &LCI,
- InMemoryStruct<macho::Segment64LoadCommand> &Res) const;
- void ReadSymtabLoadCommand(
- const LoadCommandInfo &LCI,
- InMemoryStruct<macho::SymtabLoadCommand> &Res) const;
- void ReadDysymtabLoadCommand(
- const LoadCommandInfo &LCI,
- InMemoryStruct<macho::DysymtabLoadCommand> &Res) const;
- void ReadLinkeditDataLoadCommand(
- const LoadCommandInfo &LCI,
- InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const;
- void ReadLinkerOptionsLoadCommand(
- const LoadCommandInfo &LCI,
- InMemoryStruct<macho::LinkerOptionsLoadCommand> &Res) const;
- void ReadIndirectSymbolTableEntry(
- const macho::DysymtabLoadCommand &DLC,
- unsigned Index,
- InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const;
- void ReadSection(
- const LoadCommandInfo &LCI,
- unsigned Index,
- InMemoryStruct<macho::Section> &Res) const;
- void ReadSection64(
- const LoadCommandInfo &LCI,
- unsigned Index,
- InMemoryStruct<macho::Section64> &Res) const;
- void ReadRelocationEntry(
- uint64_t RelocationTableOffset, unsigned Index,
- InMemoryStruct<macho::RelocationEntry> &Res) const;
- void ReadSymbolTableEntry(
- uint64_t SymbolTableOffset, unsigned Index,
- InMemoryStruct<macho::SymbolTableEntry> &Res) const;
- void ReadSymbol64TableEntry(
- uint64_t SymbolTableOffset, unsigned Index,
- InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
- void ReadDataInCodeTableEntry(
- uint64_t TableOffset, unsigned Index,
- InMemoryStruct<macho::DataInCodeTableEntry> &Res) const;
- void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
-
- /// @}
-
- /// @name Object Dump Facilities
- /// @{
- /// dump - Support for debugging, callable in GDB: V->dump()
- //
- void dump() const;
- void dumpHeader() const;
-
- /// print - Implement operator<< on Value.
- ///
- void print(raw_ostream &O) const;
- void printHeader(raw_ostream &O) const;
-
- /// @}
-};
-
-inline raw_ostream &operator<<(raw_ostream &OS, const MachOObject &V) {
- V.print(OS);
- return OS;
-}
-
-} // end namespace object
-} // end namespace llvm
-
-#endif
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
index 62d84870780..f581b3f8248 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
@@ -16,7 +16,7 @@
#include "RuntimeDyldImpl.h"
#include "llvm/ADT/IndexedMap.h"
-#include "llvm/Object/MachOObject.h"
+#include "llvm/Object/MachO.h"
#include "llvm/Support/Format.h"
using namespace llvm;
diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt
index c20fc0cc399..4ed129f467e 100644
--- a/lib/Object/CMakeLists.txt
+++ b/lib/Object/CMakeLists.txt
@@ -4,7 +4,6 @@ add_llvm_library(LLVMObject
COFFObjectFile.cpp
ELFObjectFile.cpp
Error.cpp
- MachOObject.cpp
MachOObjectFile.cpp
Object.cpp
ObjectFile.cpp
diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp
deleted file mode 100644
index d88f96f298c..00000000000
--- a/lib/Object/MachOObject.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-//===- MachOObject.cpp - Mach-O Object File Wrapper -----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Object/MachOObject.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SwapByteOrder.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace llvm::object;
-
-/* Translation Utilities */
-
-template<typename T>
-static void SwapValue(T &Value) {
- Value = sys::SwapByteOrder(Value);
-}
-
-template<typename T>
-static void SwapStruct(T &Value);
-
-template<typename T>
-static void ReadInMemoryStruct(const MachOObject &MOO,
- StringRef Buffer, uint64_t Base,
- InMemoryStruct<T> &Res) {
- typedef T struct_type;
- uint64_t Size = sizeof(struct_type);
-
- // Check that the buffer contains the expected data.
- if (Base + Size > Buffer.size()) {
- Res = 0;
- return;
- }
-
- // Check whether we can return a direct pointer.
- struct_type *Ptr = reinterpret_cast<struct_type *>(
- const_cast<char *>(Buffer.data() + Base));
- if (!MOO.isSwappedEndian()) {
- Res = Ptr;
- return;
- }
-
- // Otherwise, copy the struct and translate the values.
- Res = *Ptr;
- SwapStruct(*Res);
-}
-
-/* *** */
-
-MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_,
- bool Is64Bit_)
- : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_),
- IsSwappedEndian(IsLittleEndian != sys::IsLittleEndianHost),
- HasStringTable(false), 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,
- std::string *ErrorStr) {
- // First, check the magic value and initialize the basic object info.
- bool IsLittleEndian = false, Is64Bit = false;
- StringRef Magic = Buffer->getBuffer().slice(0, 4);
- if (Magic == "\xFE\xED\xFA\xCE") {
- } else if (Magic == "\xCE\xFA\xED\xFE") {
- IsLittleEndian = true;
- } else if (Magic == "\xFE\xED\xFA\xCF") {
- Is64Bit = true;
- } else if (Magic == "\xCF\xFA\xED\xFE") {
- IsLittleEndian = true;
- Is64Bit = true;
- } else {
- 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();
-}
-
-StringRef MachOObject::getData(size_t Offset, size_t Size) const {
- return Buffer->getBuffer().substr(Offset,Size);
-}
-
-void MachOObject::RegisterStringTable(macho::SymtabLoadCommand &SLC) {
- HasStringTable = true;
- StringTable = Buffer->getBuffer().substr(SLC.StringTableOffset,
- SLC.StringTableSize);
-}
-
-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];
-}
-
-template<>
-void SwapStruct(macho::SegmentLoadCommand &Value) {
- SwapValue(Value.Type);
- SwapValue(Value.Size);
- SwapValue(Value.VMAddress);
- SwapValue(Value.VMSize);
- SwapValue(Value.FileOffset);
- SwapValue(Value.FileSize);
- SwapValue(Value.MaxVMProtection);
- SwapValue(Value.InitialVMProtection);
- SwapValue(Value.NumSections);
- SwapValue(Value.Flags);
-}
-void MachOObject::ReadSegmentLoadCommand(const LoadCommandInfo &LCI,
- InMemoryStruct<macho::SegmentLoadCommand> &Res) const {
- ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::Segment64LoadCommand &Value) {
- SwapValue(Value.Type);
- SwapValue(Value.Size);
- SwapValue(Value.VMAddress);
- SwapValue(Value.VMSize);
- SwapValue(Value.FileOffset);
- SwapValue(Value.FileSize);
- SwapValue(Value.MaxVMProtection);
- SwapValue(Value.InitialVMProtection);
- SwapValue(Value.NumSections);
- SwapValue(Value.Flags);
-}
-void MachOObject::ReadSegment64LoadCommand(const LoadCommandInfo &LCI,
- InMemoryStruct<macho::Segment64LoadCommand> &Res) const {
- ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::SymtabLoadCommand &Value) {
- SwapValue(Value.Type);
- SwapValue(Value.Size);
- SwapValue(Value.SymbolTableOffset);
- SwapValue(Value.NumSymbolTableEntries);
- SwapValue(Value.StringTableOffset);
- SwapValue(Value.StringTableSize);
-}
-void MachOObject::ReadSymtabLoadCommand(const LoadCommandInfo &LCI,
- InMemoryStruct<macho::SymtabLoadCommand> &Res) const {
- ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::DysymtabLoadCommand &Value) {
- SwapValue(Value.Type);
- SwapValue(Value.Size);
- SwapValue(Value.LocalSymbolsIndex);
- SwapValue(Value.NumLocalSymbols);
- SwapValue(Value.ExternalSymbolsIndex);
- SwapValue(Value.NumExternalSymbols);
- SwapValue(Value.UndefinedSymbolsIndex);
- SwapValue(Value.NumUndefinedSymbols);
- SwapValue(Value.TOCOffset);
- SwapValue(Value.NumTOCEntries);
- SwapValue(Value.ModuleTableOffset);
- SwapValue(Value.NumModuleTableEntries);
- SwapValue(Value.ReferenceSymbolTableOffset);
- SwapValue(Value.NumReferencedSymbolTableEntries);
- SwapValue(Value.IndirectSymbolTableOffset);
- SwapValue(Value.NumIndirectSymbolTableEntries);
- SwapValue(Value.ExternalRelocationTableOffset);
- SwapValue(Value.NumExternalRelocationTableEntries);
- SwapValue(Value.LocalRelocationTableOffset);
- SwapValue(Value.NumLocalRelocationTableEntries);
-}
-void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI,
- InMemoryStruct<macho::DysymtabLoadCommand> &Res) const {
- ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::LinkeditDataLoadCommand &Value) {
- SwapValue(Value.Type);
- SwapValue(Value.Size);
- SwapValue(Value.DataOffset);
- SwapValue(Value.DataSize);
-}
-void MachOObject::ReadLinkeditDataLoadCommand(const LoadCommandInfo &LCI,
- InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const {
- ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::LinkerOptionsLoadCommand &Value) {
- SwapValue(Value.Type);
- SwapValue(Value.Size);
- SwapValue(Value.Count);
-}
-void MachOObject::ReadLinkerOptionsLoadCommand(const LoadCommandInfo &LCI,
- InMemoryStruct<macho::LinkerOptionsLoadCommand> &Res) const {
- ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::IndirectSymbolTableEntry &Value) {
- SwapValue(Value.Index);
-}
-void
-MachOObject::ReadIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC,
- unsigned Index,
- InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const {
- uint64_t Offset = (DLC.IndirectSymbolTableOffset +
- Index * sizeof(macho::IndirectSymbolTableEntry));
- ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
-}
-
-
-template<>
-void SwapStruct(macho::Section &Value) {
- SwapValue(Value.Address);
- SwapValue(Value.Size);
- SwapValue(Value.Offset);
- SwapValue(Value.Align);
- SwapValue(Value.RelocationTableOffset);
- SwapValue(Value.NumRelocationTableEntries);
- SwapValue(Value.Flags);
- SwapValue(Value.Reserved1);
- SwapValue(Value.Reserved2);
-}
-void MachOObject::ReadSection(const LoadCommandInfo &LCI,
- unsigned Index,
- InMemoryStruct<macho::Section> &Res) const {
- assert(LCI.Command.Type == macho::LCT_Segment &&
- "Unexpected load command info!");
- uint64_t Offset = (LCI.Offset + sizeof(macho::SegmentLoadCommand) +
- Index * sizeof(macho::Section));
- ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::Section64 &Value) {
- SwapValue(Value.Address);
- SwapValue(Value.Size);
- SwapValue(Value.Offset);
- SwapValue(Value.Align);
- SwapValue(Value.RelocationTableOffset);
- SwapValue(Value.NumRelocationTableEntries);
- SwapValue(Value.Flags);
- SwapValue(Value.Reserved1);
- SwapValue(Value.Reserved2);
- SwapValue(Value.Reserved3);
-}
-void MachOObject::ReadSection64(const LoadCommandInfo &LCI,
- unsigned Index,
- InMemoryStruct<macho::Section64> &Res) const {
- assert(LCI.Command.Type == macho::LCT_Segment64 &&
- "Unexpected load command info!");
- uint64_t Offset = (LCI.Offset + sizeof(macho::Segment64LoadCommand) +
- Index * sizeof(macho::Section64));
- ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::RelocationEntry &Value) {
- SwapValue(Value.Word0);
- SwapValue(Value.Word1);
-}
-void MachOObject::ReadRelocationEntry(uint64_t RelocationTableOffset,
- unsigned Index,
- InMemoryStruct<macho::RelocationEntry> &Res) const {
- uint64_t Offset = (RelocationTableOffset +
- Index * sizeof(macho::RelocationEntry));
- ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::SymbolTableEntry &Value) {
- SwapValue(Value.StringIndex);
- SwapValue(Value.Flags);
- SwapValue(Value.Value);
-}
-void MachOObject::ReadSymbolTableEntry(uint64_t SymbolTableOffset,
- unsigned Index,
- InMemoryStruct<macho::SymbolTableEntry> &Res) const {
- uint64_t Offset = (SymbolTableOffset +
- Index * sizeof(macho::SymbolTableEntry));
- ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::Symbol64TableEntry &Value) {
- SwapValue(Value.StringIndex);
- SwapValue(Value.Flags);
- SwapValue(Value.Value);
-}
-void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset,
- unsigned Index,
- InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
- uint64_t Offset = (SymbolTableOffset +
- Index * sizeof(macho::Symbol64TableEntry));
- ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
-}
-
-template<>
-void SwapStruct(macho::DataInCodeTableEntry &Value) {
- SwapValue(Value.Offset);
- SwapValue(Value.Length);
- SwapValue(Value.Kind);
-}
-void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset,
- unsigned Index,
- InMemoryStruct<macho::DataInCodeTableEntry> &Res) const {
- uint64_t Offset = (TableOffset +
- Index * sizeof(macho::DataInCodeTableEntry));
- ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
-}
-
-void MachOObject::ReadULEB128s(uint64_t Index,
- SmallVectorImpl<uint64_t> &Out) const {
- DataExtractor extractor(Buffer->getBuffer(), true, 0);
-
- uint32_t offset = Index;
- uint64_t data = 0;
- while (uint64_t delta = extractor.getULEB128(&offset)) {
- data += delta;
- Out.push_back(data);
- }
-}
-
-/* ** */
-// Object Dumping Facilities
-void MachOObject::dump() const { print(dbgs()); dbgs() << '\n'; }
-void MachOObject::dumpHeader() const { printHeader(dbgs()); dbgs() << '\n'; }
-
-void MachOObject::printHeader(raw_ostream &O) const {
- O << "('cputype', " << Header.CPUType << ")\n";
- O << "('cpusubtype', " << Header.CPUSubtype << ")\n";
- O << "('filetype', " << Header.FileType << ")\n";
- O << "('num_load_commands', " << Header.NumLoadCommands << ")\n";
- O << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n";
- O << "('flag', " << Header.Flags << ")\n";
-
- // Print extended header if 64-bit.
- if (is64Bit())
- O << "('reserved', " << Header64Ext.Reserved << ")\n";
-}
-
-void MachOObject::print(raw_ostream &O) const {
- O << "Header:\n";
- printHeader(O);
- O << "Load Commands:\n";
-
- O << "Buffer:\n";
-}
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 38198b17938..bb6ca93176d 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -120,6 +120,11 @@ void SwapStruct(macho::Header &H) {
}
template<>
+void SwapStruct(macho::Header64Ext &E) {
+ SwapValue(E.Reserved);
+}
+
+template<>
void SwapStruct(macho::SymtabLoadCommand &C) {
SwapValue(C.Type);
SwapValue(C.Size);
@@ -130,6 +135,30 @@ void SwapStruct(macho::SymtabLoadCommand &C) {
}
template<>
+void SwapStruct(macho::DysymtabLoadCommand &C) {
+ SwapValue(C.Type);
+ SwapValue(C.Size);
+ SwapValue(C.LocalSymbolsIndex);
+ SwapValue(C.NumLocalSymbols);
+ SwapValue(C.ExternalSymbolsIndex);
+ SwapValue(C.NumExternalSymbols);
+ SwapValue(C.UndefinedSymbolsIndex);
+ SwapValue(C.NumUndefinedSymbols);
+ SwapValue(C.TOCOffset);
+ SwapValue(C.NumTOCEntries);
+ SwapValue(C.ModuleTableOffset);
+ SwapValue(C.NumModuleTableEntries);
+ SwapValue(C.ReferenceSymbolTableOffset);
+ SwapValue(C.NumReferencedSymbolTableEntries);
+ SwapValue(C.IndirectSymbolTableOffset);
+ SwapValue(C.NumIndirectSymbolTableEntries);
+ SwapValue(C.ExternalRelocationTableOffset);
+ SwapValue(C.NumExternalRelocationTableEntries);
+ SwapValue(C.LocalRelocationTableOffset);
+ SwapValue(C.NumLocalRelocationTableEntries);
+}
+
+template<>
void SwapStruct(macho::LinkeditDataLoadCommand &C) {
SwapValue(C.Type);
SwapValue(C.Size);
@@ -165,6 +194,25 @@ void SwapStruct(macho::Segment64LoadCommand &C) {
SwapValue(C.Flags);
}
+template<>
+void SwapStruct(macho::IndirectSymbolTableEntry &C) {
+ SwapValue(C.Index);
+}
+
+template<>
+void SwapStruct(macho::LinkerOptionsLoadCommand &C) {
+ SwapValue(C.Type);
+ SwapValue(C.Size);
+ SwapValue(C.Count);
+}
+
+template<>
+void SwapStruct(macho::DataInCodeTableEntry &C) {
+ SwapValue(C.Offset);
+ SwapValue(C.Length);
+ SwapValue(C.Kind);
+}
+
template<typename T>
T getStruct(const MachOObjectFile *O, const char *P) {
T Cmd;
@@ -174,32 +222,20 @@ T getStruct(const MachOObjectFile *O, const char *P) {
return Cmd;
}
-static macho::SegmentLoadCommand
-getSegmentLoadCommand(const MachOObjectFile *O,
- const MachOObjectFile::LoadCommandInfo &L) {
- return getStruct<macho::SegmentLoadCommand>(O, L.Ptr);
-}
-
-static macho::Segment64LoadCommand
-getSegment64LoadCommand(const MachOObjectFile *O,
- const MachOObjectFile::LoadCommandInfo &L) {
- return getStruct<macho::Segment64LoadCommand>(O, L.Ptr);
-}
-
static uint32_t
getSegmentLoadCommandNumSections(const MachOObjectFile *O,
const MachOObjectFile::LoadCommandInfo &L) {
if (O->is64Bit()) {
- macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
+ macho::Segment64LoadCommand S = O->getSegment64LoadCommand(L);
return S.NumSections;
}
- macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
+ macho::SegmentLoadCommand S = O->getSegmentLoadCommand(L);
return S.NumSections;
}
-static const SectionBase *
-getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
- unsigned Sec) {
+static const char *
+getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
+ unsigned Sec) {
uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
bool Is64 = O->is64Bit();
@@ -209,7 +245,7 @@ getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
sizeof(macho::Section);
uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
- return reinterpret_cast<const SectionBase*>(SectionAddr);
+ return reinterpret_cast<const char*>(SectionAddr);
}
static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
@@ -377,7 +413,7 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
bool IsLittleEndian, bool Is64bits,
error_code &ec)
: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
- SymtabLoadCmd(NULL) {
+ SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL) {
uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
macho::LoadCommandType SegmentLoadType = is64Bit() ?
macho::LCT_Segment64 : macho::LCT_Segment;
@@ -387,13 +423,14 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
if (Load.C.Type == macho::LCT_Symtab) {
assert(!SymtabLoadCmd && "Multiple symbol tables");
SymtabLoadCmd = Load.Ptr;
- }
-
- if (Load.C.Type == SegmentLoadType) {
+ } else if (Load.C.Type == macho::LCT_Dysymtab) {
+ assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
+ DysymtabLoadCmd = Load.Ptr;
+ } else if (Load.C.Type == SegmentLoadType) {
uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
for (unsigned J = 0; J < NumSections; ++J) {
- const SectionBase *Sec = getSectionBase(this, Load, J);
- Sections.push_back(reinterpret_cast<const char*>(Sec));
+ const char *Sec = getSectionPtr(this, Load, J);
+ Sections.push_back(Sec);
}
}
@@ -416,10 +453,9 @@ error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
StringRef &Res) const {
- macho::SymtabLoadCommand S = getSymtabLoadCommand();
- const char *StringTable = getPtr(this, S.StringTableOffset);
+ StringRef StringTable = getStringTableData();
SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
- const char *Start = &StringTable[Entry.StringIndex];
+ const char *Start = &StringTable.data()[Entry.StringIndex];
Res = StringRef(Start);
return object_error::success;
}
@@ -1271,6 +1307,18 @@ StringRef MachOObjectFile::getLoadName() const {
report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
}
+relocation_iterator MachOObjectFile::getSectionRelBegin(unsigned Index) const {
+ DataRefImpl DRI;
+ DRI.d.a = Index;
+ return getSectionRelBegin(DRI);
+}
+
+relocation_iterator MachOObjectFile::getSectionRelEnd(unsigned Index) const {
+ DataRefImpl DRI;
+ DRI.d.a = Index;
+ return getSectionRelEnd(DRI);
+}
+
StringRef
MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
@@ -1375,6 +1423,18 @@ macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
return getStruct<macho::Section64>(this, Sections[DRI.d.a]);
}
+macho::Section MachOObjectFile::getSection(const LoadCommandInfo &L,
+ unsigned Index) const {
+ const char *Sec = getSectionPtr(this, L, Index);
+ return getStruct<macho::Section>(this, Sec);
+}
+
+macho::Section64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
+ unsigned Index) const {
+ const char *Sec = getSectionPtr(this, L, Index);
+ return getStruct<macho::Section64>(this, Sec);
+}
+
macho::SymbolTableEntry
MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
const char *P = reinterpret_cast<const char *>(DRI.p);
@@ -1392,6 +1452,21 @@ MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandIn
return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr);
}
+macho::SegmentLoadCommand
+MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<macho::SegmentLoadCommand>(this, L.Ptr);
+}
+
+macho::Segment64LoadCommand
+MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<macho::Segment64LoadCommand>(this, L.Ptr);
+}
+
+macho::LinkerOptionsLoadCommand
+MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<macho::LinkerOptionsLoadCommand>(this, L.Ptr);
+}
+
macho::RelocationEntry
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
const char *P = reinterpret_cast<const char *>(Rel.p);
@@ -1402,11 +1477,39 @@ macho::Header MachOObjectFile::getHeader() const {
return getStruct<macho::Header>(this, getPtr(this, 0));
}
-macho::SymtabLoadCommand
-MachOObjectFile::getSymtabLoadCommand() const {
+macho::Header64Ext MachOObjectFile::getHeader64Ext() const {
+ return
+ getStruct<macho::Header64Ext>(this, getPtr(this, sizeof(macho::Header)));
+}
+
+macho::IndirectSymbolTableEntry MachOObjectFile::getIndirectSymbolTableEntry(
+ const macho::DysymtabLoadCommand &DLC,
+ unsigned Index) const {
+ uint64_t Offset = DLC.IndirectSymbolTableOffset +
+ Index * sizeof(macho::IndirectSymbolTableEntry);
+ return getStruct<macho::IndirectSymbolTableEntry>(this, getPtr(this, Offset));
+}
+
+macho::DataInCodeTableEntry
+MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
+ unsigned Index) const {
+ uint64_t Offset = DataOffset + Index * sizeof(macho::DataInCodeTableEntry);
+ return getStruct<macho::DataInCodeTableEntry>(this, getPtr(this, Offset));
+}
+
+macho::SymtabLoadCommand MachOObjectFile::getSymtabLoadCommand() const {
return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd);
}
+macho::DysymtabLoadCommand MachOObjectFile::getDysymtabLoadCommand() const {
+ return getStruct<macho::DysymtabLoadCommand>(this, DysymtabLoadCmd);
+}
+
+StringRef MachOObjectFile::getStringTableData() const {
+ macho::SymtabLoadCommand S = getSymtabLoadCommand();
+ return getData().substr(S.StringTableOffset, S.StringTableSize);
+}
+
bool MachOObjectFile::is64Bit() const {
return getType() == getMachOType(false, true) ||
getType() == getMachOType(true, true);
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index 4d8d345894d..ead541a5b80 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -17,7 +17,7 @@
#include "llvm/ExecutionEngine/ObjectBuffer.h"
#include "llvm/ExecutionEngine/ObjectImage.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
-#include "llvm/Object/MachOObject.h"
+#include "llvm/Object/MachO.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Memory.h"
diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp
index 3bd3ecc8fde..88fd4529ab4 100644
--- a/tools/macho-dump/macho-dump.cpp
+++ b/tools/macho-dump/macho-dump.cpp
@@ -11,9 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Object/MachOObject.h"
+#include "llvm/Object/MachO.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
@@ -66,7 +67,8 @@ static void DumpSegmentCommandData(StringRef Name,
outs() << " ('flags', " << Flags << ")\n";
}
-static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name,
+static int DumpSectionData(const MachOObjectFile &Obj, unsigned Index,
+ StringRef Name,
StringRef SegmentName, uint64_t Address,
uint64_t Size, uint32_t Offset,
uint32_t Align, uint32_t RelocationTableOffset,
@@ -92,26 +94,22 @@ static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name,
outs() << " ),\n";
// Dump the relocation entries.
- int Res = 0;
outs() << " ('_relocations', [\n";
- for (unsigned i = 0; i != NumRelocationTableEntries; ++i) {
- InMemoryStruct<macho::RelocationEntry> RE;
- Obj.ReadRelocationEntry(RelocationTableOffset, i, RE);
- if (!RE) {
- Res = Error("unable to read relocation table entry '" + Twine(i) + "'");
- break;
- }
-
- outs() << " # Relocation " << i << "\n";
- outs() << " (('word-0', " << format("0x%x", RE->Word0) << "),\n";
- outs() << " ('word-1', " << format("0x%x", RE->Word1) << ")),\n";
+ unsigned RelNum = 0;
+ error_code EC;
+ for (relocation_iterator I = Obj.getSectionRelBegin(Index),
+ E = Obj.getSectionRelEnd(Index); I != E; I.increment(EC), ++RelNum) {
+ macho::RelocationEntry RE = Obj.getRelocation(I->getRawDataRefImpl());
+ outs() << " # Relocation " << RelNum << "\n";
+ outs() << " (('word-0', " << format("0x%x", RE.Word0) << "),\n";
+ outs() << " ('word-1', " << format("0x%x", RE.Word1) << ")),\n";
}
outs() << " ])\n";
// Dump the section data, if requested.
if (ShowSectionData) {
outs() << " ('_section_data', '";
- StringRef Data = Obj.getData(Offset, Size);
+ StringRef Data = Obj.getData().substr(Offset, Size);
for (unsigned i = 0; i != Data.size(); ++i) {
if (i && (i % 4) == 0)
outs() << ' ';
@@ -121,208 +119,162 @@ static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name,
outs() << "')\n";
}
- return Res;
+ return 0;
}
-static int DumpSegmentCommand(MachOObject &Obj,
- const MachOObject::LoadCommandInfo &LCI) {
- InMemoryStruct<macho::SegmentLoadCommand> SLC;
- Obj.ReadSegmentLoadCommand(LCI, SLC);
- if (!SLC)
- return Error("unable to read segment load command");
+static int DumpSegmentCommand(const MachOObjectFile &Obj,
+ const MachOObjectFile::LoadCommandInfo &LCI) {
+ macho::SegmentLoadCommand SLC = Obj.getSegmentLoadCommand(LCI);
- DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress,
- SLC->VMSize, SLC->FileOffset, SLC->FileSize,
- SLC->MaxVMProtection, SLC->InitialVMProtection,
- SLC->NumSections, SLC->Flags);
+ DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress,
+ SLC.VMSize, SLC.FileOffset, SLC.FileSize,
+ SLC.MaxVMProtection, SLC.InitialVMProtection,
+ SLC.NumSections, SLC.Flags);
// Dump the sections.
- int Res = 0;
outs() << " ('sections', [\n";
- for (unsigned i = 0; i != SLC->NumSections; ++i) {
- InMemoryStruct<macho::Section> Sect;
- Obj.ReadSection(LCI, i, Sect);
- if (!SLC) {
- Res = Error("unable to read section '" + Twine(i) + "'");
- break;
- }
-
- if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16),
- StringRef(Sect->SegmentName, 16), Sect->Address,
- Sect->Size, Sect->Offset, Sect->Align,
- Sect->RelocationTableOffset,
- Sect->NumRelocationTableEntries, Sect->Flags,
- Sect->Reserved1, Sect->Reserved2)))
- break;
+ for (unsigned i = 0; i != SLC.NumSections; ++i) {
+ macho::Section Sect = Obj.getSection(LCI, i);
+ DumpSectionData(Obj, i, StringRef(Sect.Name, 16),
+ StringRef(Sect.SegmentName, 16), Sect.Address,
+ Sect.Size, Sect.Offset, Sect.Align,
+ Sect.RelocationTableOffset,
+ Sect.NumRelocationTableEntries, Sect.Flags,
+ Sect.Reserved1, Sect.Reserved2);
}
outs() << " ])\n";
- return Res;
+ return 0;
}
-static int DumpSegment64Command(MachOObject &Obj,
- const MachOObject::LoadCommandInfo &LCI) {
- InMemoryStruct<macho::Segment64LoadCommand> SLC;
- Obj.ReadSegment64LoadCommand(LCI, SLC);
- if (!SLC)
- return Error("unable to read segment load command");
-
- DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress,
- SLC->VMSize, SLC->FileOffset, SLC->FileSize,
- SLC->MaxVMProtection, SLC->InitialVMProtection,
- SLC->NumSections, SLC->Flags);
+static int DumpSegment64Command(const MachOObjectFile &Obj,
+ const MachOObjectFile::LoadCommandInfo &LCI) {
+ macho::Segment64LoadCommand SLC = Obj.getSegment64LoadCommand(LCI);
+ DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress,
+ SLC.VMSize, SLC.FileOffset, SLC.FileSize,
+ SLC.MaxVMProtection, SLC.InitialVMProtection,
+ SLC.NumSections, SLC.Flags);
// Dump the sections.
- int Res = 0;
outs() << " ('sections', [\n";
- for (unsigned i = 0; i != SLC->NumSections; ++i) {
- InMemoryStruct<macho::Section64> Sect;
- Obj.ReadSection64(LCI, i, Sect);
- if (!SLC) {
- Res = Error("unable to read section '" + Twine(i) + "'");
- break;
- }
-
- if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16),
- StringRef(Sect->SegmentName, 16), Sect->Address,
- Sect->Size, Sect->Offset, Sect->Align,
- Sect->RelocationTableOffset,
- Sect->NumRelocationTableEntries, Sect->Flags,
- Sect->Reserved1, Sect->Reserved2,
- Sect->Reserved3)))
- break;
+ for (unsigned i = 0; i != SLC.NumSections; ++i) {
+ macho::Section64 Sect = Obj.getSection64(LCI, i);
+
+ DumpSectionData(Obj, i, StringRef(Sect.Name, 16),
+ StringRef(Sect.SegmentName, 16), Sect.Address,
+ Sect.Size, Sect.Offset, Sect.Align,
+ Sect.RelocationTableOffset,
+ Sect.NumRelocationTableEntries, Sect.Flags,
+ Sect.Reserved1, Sect.Reserved2,
+ Sect.Reserved3);
}
outs() << " ])\n";
- return Res;
+ return 0;
}
-static void DumpSymbolTableEntryData(MachOObject &Obj,
+static void DumpSymbolTableEntryData(const MachOObjectFile &Obj,
unsigned Index, uint32_t StringIndex,
uint8_t Type, uint8_t SectionIndex,
- uint16_t Flags, uint64_t Value) {
+ uint16_t Flags, uint64_t Value,
+ StringRef StringTable) {
+ const char *Name = &StringTable.data()[StringIndex];
outs() << " # Symbol " << Index << "\n";
outs() << " (('n_strx', " << StringIndex << ")\n";
outs() << " ('n_type', " << format("0x%x", Type) << ")\n";
outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n";
outs() << " ('n_desc', " << Flags << ")\n";
outs() << " ('n_value', " << Value << ")\n";
- outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n";
+ outs() << " ('_string', '" << Name << "')\n";
outs() << " ),\n";
}
-static int DumpSymtabCommand(MachOObject &Obj,
- const MachOObject::LoadCommandInfo &LCI) {
- InMemoryStruct<macho::SymtabLoadCommand> SLC;
- Obj.ReadSymtabLoadCommand(LCI, SLC);
- if (!SLC)
- return Error("unable to read segment load command");
-
- outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n";
- outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n";
- outs() << " ('stroff', " << SLC->StringTableOffset << ")\n";
- outs() << " ('strsize', " << SLC->StringTableSize << ")\n";
+static int DumpSymtabCommand(const MachOObjectFile &Obj) {
+ macho::SymtabLoadCommand SLC = Obj.getSymtabLoadCommand();
- // Cache the string table data.
- Obj.RegisterStringTable(*SLC);
+ outs() << " ('symoff', " << SLC.SymbolTableOffset << ")\n";
+ outs() << " ('nsyms', " << SLC.NumSymbolTableEntries << ")\n";
+ outs() << " ('stroff', " << SLC.StringTableOffset << ")\n";
+ outs() << " ('strsize', " << SLC.StringTableSize << ")\n";
// Dump the string data.
outs() << " ('_string_data', '";
- outs().write_escaped(Obj.getStringTableData(),
+ StringRef StringTable = Obj.getStringTableData();
+ outs().write_escaped(StringTable,
/*UseHexEscapes=*/true) << "')\n";
// Dump the symbol table.
- int Res = 0;
outs() << " ('_symbols', [\n";
- for (unsigned i = 0; i != SLC->NumSymbolTableEntries; ++i) {
+ error_code EC;
+ unsigned SymNum = 0;
+ for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;
+ I.increment(EC), ++SymNum) {
+ DataRefImpl DRI = I->getRawDataRefImpl();
if (Obj.is64Bit()) {
- InMemoryStruct<macho::Symbol64TableEntry> STE;
- Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE);
- if (!STE) {
- Res = Error("unable to read symbol: '" + Twine(i) + "'");
- break;
- }
-
- DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type,
- STE->SectionIndex, STE->Flags, STE->Value);
+ macho::Symbol64TableEntry STE = Obj.getSymbol64TableEntry(DRI);
+ DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type,
+ STE.SectionIndex, STE.Flags, STE.Value,
+ StringTable);
} else {
- InMemoryStruct<macho::SymbolTableEntry> STE;
- Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE);
- if (!SLC) {
- Res = Error("unable to read symbol: '" + Twine(i) + "'");
- break;
- }
-
- DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type,
- STE->SectionIndex, STE->Flags, STE->Value);
+ macho::SymbolTableEntry STE = Obj.getSymbolTableEntry(DRI);
+ DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type,
+ STE.SectionIndex, STE.Flags, STE.Value,
+ StringTable);
}
}
outs() << " ])\n";
- return Res;
+ return 0;
}
-static int DumpDysymtabCommand(MachOObject &Obj,
- const MachOObject::LoadCommandInfo &LCI) {
- InMemoryStruct<macho::DysymtabLoadCommand> DLC;
- Obj.ReadDysymtabLoadCommand(LCI, DLC);
- if (!DLC)
- return Error("unable to read segment load command");
-
- outs() << " ('ilocalsym', " << DLC->LocalSymbolsIndex << ")\n";
- outs() << " ('nlocalsym', " << DLC->NumLocalSymbols << ")\n";
- outs() << " ('iextdefsym', " << DLC->ExternalSymbolsIndex << ")\n";
- outs() << " ('nextdefsym', " << DLC->NumExternalSymbols << ")\n";
- outs() << " ('iundefsym', " << DLC->UndefinedSymbolsIndex << ")\n";
- outs() << " ('nundefsym', " << DLC->NumUndefinedSymbols << ")\n";
- outs() << " ('tocoff', " << DLC->TOCOffset << ")\n";
- outs() << " ('ntoc', " << DLC->NumTOCEntries << ")\n";
- outs() << " ('modtaboff', " << DLC->ModuleTableOffset << ")\n";
- outs() << " ('nmodtab', " << DLC->NumModuleTableEntries << ")\n";
- outs() << " ('extrefsymoff', " << DLC->ReferenceSymbolTableOffset << ")\n";
+static int DumpDysymtabCommand(const MachOObjectFile &Obj) {
+ macho::DysymtabLoadCommand DLC = Obj.getDysymtabLoadCommand();
+
+ outs() << " ('ilocalsym', " << DLC.LocalSymbolsIndex << ")\n";
+ outs() << " ('nlocalsym', " << DLC.NumLocalSymbols << ")\n";
+ outs() << " ('iextdefsym', " << DLC.ExternalSymbolsIndex << ")\n";
+ outs() << " ('nextdefsym', " << DLC.NumExternalSymbols << ")\n";
+ outs() << " ('iundefsym', " << DLC.UndefinedSymbolsIndex << ")\n";
+ outs() << " ('nundefsym', " << DLC.NumUndefinedSymbols << ")\n";
+ outs() << " ('tocoff', " << DLC.TOCOffset << ")\n";
+ outs() << " ('ntoc', " << DLC.NumTOCEntries << ")\n";
+ outs() << " ('modtaboff', " << DLC.ModuleTableOffset << ")\n";
+ outs() << " ('nmodtab', " << DLC.NumModuleTableEntries << ")\n";
+ outs() << " ('extrefsymoff', " << DLC.ReferenceSymbolTableOffset << ")\n";
outs() << " ('nextrefsyms', "
- << DLC->NumReferencedSymbolTableEntries << ")\n";
- outs() << " ('indirectsymoff', " << DLC->IndirectSymbolTableOffset << ")\n";
+ << DLC.NumReferencedSymbolTableEntries << ")\n";
+ outs() << " ('indirectsymoff', " << DLC.IndirectSymbolTableOffset << ")\n";
outs() << " ('nindirectsyms', "
- << DLC->NumIndirectSymbolTableEntries << ")\n";
- outs() << " ('extreloff', " << DLC->ExternalRelocationTableOffset << ")\n";
- outs() << " ('nextrel', " << DLC->NumExternalRelocationTableEntries << ")\n";
- outs() << " ('locreloff', " << DLC->LocalRelocationTableOffset << ")\n";
- outs() << " ('nlocrel', " << DLC->NumLocalRelocationTableEntries << ")\n";
+ << DLC.NumIndirectSymbolTableEntries << ")\n";
+ outs() << " ('extreloff', " << DLC.ExternalRelocationTableOffset << ")\n";
+ outs() << " ('nextrel', " << DLC.NumExternalRelocationTableEntries << ")\n";
+ outs() << " ('locreloff', " << DLC.LocalRelocationTableOffset << ")\n";
+ outs() << " ('nlocrel', " << DLC.NumLocalRelocationTableEntries << ")\n";
// Dump the indirect symbol table.
- int Res = 0;
outs() << " ('_indirect_symbols', [\n";
- for (unsigned i = 0; i != DLC->NumIndirectSymbolTableEntries; ++i) {
- InMemoryStruct<macho::IndirectSymbolTableEntry> ISTE;
- Obj.ReadIndirectSymbolTableEntry(*DLC, i, ISTE);
- if (!ISTE) {
- Res = Error("unable to read segment load command");
- break;
- }
-
+ for (unsigned i = 0; i != DLC.NumIndirectSymbolTableEntries; ++i) {
+ macho::IndirectSymbolTableEntry ISTE =
+ Obj.getIndirectSymbolTableEntry(DLC, i);
outs() << " # Indirect Symbol " << i << "\n";
outs() << " (('symbol_index', "
- << format("0x%x", ISTE->Index) << "),),\n";
+ << format("0x%x", ISTE.Index) << "),),\n";
}
outs() << " ])\n";
- return Res;
+ return 0;
}
-static int DumpLinkeditDataCommand(MachOObject &Obj,
- const MachOObject::LoadCommandInfo &LCI) {
- InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
- Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
- if (!LLC)
- return Error("unable to read segment load command");
-
- outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
- << " ('datasize', " << LLC->DataSize << ")\n"
+static int
+DumpLinkeditDataCommand(const MachOObjectFile &Obj,
+ const MachOObjectFile::LoadCommandInfo &LCI) {
+ macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI);
+ outs() << " ('dataoff', " << LLC.DataOffset << ")\n"
+ << " ('datasize', " << LLC.DataSize << ")\n"
<< " ('_addresses', [\n";
SmallVector<uint64_t, 8> Addresses;
- Obj.ReadULEB128s(LLC->DataOffset, Addresses);
+ Obj.ReadULEB128s(LLC.DataOffset, Addresses);
for (unsigned i = 0, e = Addresses.size(); i != e; ++i)
outs() << " # Address " << i << '\n'
<< " ('address', " << format("0x%x", Addresses[i]) << "),\n";
@@ -332,28 +284,22 @@ static int DumpLinkeditDataCommand(MachOObject &Obj,
return 0;
}
-static int DumpDataInCodeDataCommand(MachOObject &Obj,
- const MachOObject::LoadCommandInfo &LCI) {
- InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
- Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
- if (!LLC)
- return Error("unable to read data-in-code load command");
-
- outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
- << " ('datasize', " << LLC->DataSize << ")\n"
+static int
+DumpDataInCodeDataCommand(const MachOObjectFile &Obj,
+ const MachOObjectFile::LoadCommandInfo &LCI) {
+ macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI);
+ outs() << " ('dataoff', " << LLC.DataOffset << ")\n"
+ << " ('datasize', " << LLC.DataSize << ")\n"
<< " ('_data_regions', [\n";
-
- unsigned NumRegions = LLC->DataSize / 8;
+ unsigned NumRegions = LLC.DataSize / 8;
for (unsigned i = 0; i < NumRegions; ++i) {
- InMemoryStruct<macho::DataInCodeTableEntry> DICE;
- Obj.ReadDataInCodeTableEntry(LLC->DataOffset, i, DICE);
- if (!DICE)
- return Error("unable to read DataInCodeTableEntry");
+ macho::DataInCodeTableEntry DICE =
+ Obj.getDataInCodeTableEntry(LLC.DataOffset, i);
outs() << " # DICE " << i << "\n"
- << " ('offset', " << DICE->Offset << ")\n"
- << " ('length', " << DICE->Length << ")\n"
- << " ('kind', " << DICE->Kind << ")\n";
+ << " ('offset', " << DICE.Offset << ")\n"
+ << " ('length', " << DICE.Length << ")\n"
+ << " ('kind', " << DICE.Kind << ")\n";
}
outs() <<" ])\n";
@@ -361,99 +307,111 @@ static int DumpDataInCodeDataCommand(MachOObject &Obj,
return 0;
}
-static int DumpLinkerOptionsCommand(MachOObject &Obj,
- const MachOObject::LoadCommandInfo &LCI) {
- InMemoryStruct<macho::LinkerOptionsLoadCommand> LOLC;
- Obj.ReadLinkerOptionsLoadCommand(LCI, LOLC);
- if (!LOLC)
- return Error("unable to read linker options load command");
-
- outs() << " ('count', " << LOLC->Count << ")\n"
- << " ('_strings', [\n";
-
- uint64_t DataSize = LOLC->Size - sizeof(macho::LinkerOptionsLoadCommand);
- StringRef Data = Obj.getData(
- LCI.Offset + sizeof(macho::LinkerOptionsLoadCommand), DataSize);
- for (unsigned i = 0; i != LOLC->Count; ++i) {
- std::pair<StringRef,StringRef> Split = Data.split('\0');
- outs() << "\t\"";
- outs().write_escaped(Split.first);
- outs() << "\",\n";
- Data = Split.second;
- }
- outs() <<" ])\n";
+static int
+DumpLinkerOptionsCommand(const MachOObjectFile &Obj,
+ const MachOObjectFile::LoadCommandInfo &LCI) {
+ macho::LinkerOptionsLoadCommand LOLC = Obj.getLinkerOptionsLoadCommand(LCI);
+ outs() << " ('count', " << LOLC.Count << ")\n"
+ << " ('_strings', [\n";
+
+ uint64_t DataSize = LOLC.Size - sizeof(macho::LinkerOptionsLoadCommand);
+ const char *P = LCI.Ptr + sizeof(macho::LinkerOptionsLoadCommand);
+ StringRef Data(P, DataSize);
+ for (unsigned i = 0; i != LOLC.Count; ++i) {
+ std::pair<StringRef,StringRef> Split = Data.split('\0');
+ outs() << "\t\"";
+ outs().write_escaped(Split.first);
+ outs() << "\",\n";
+ Data = Split.second;
+ }
+ outs() <<" ])\n";
return 0;
}
-
-static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
- const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index);
- int Res = 0;
-
- outs() << " # Load Command " << Index << "\n"
- << " (('command', " << LCI.Command.Type << ")\n"
- << " ('size', " << LCI.Command.Size << ")\n";
- switch (LCI.Command.Type) {
+static int DumpLoadCommand(const MachOObjectFile &Obj,
+ MachOObjectFile::LoadCommandInfo &LCI) {
+ switch (LCI.C.Type) {
case macho::LCT_Segment:
- Res = DumpSegmentCommand(Obj, LCI);
- break;
+ return DumpSegmentCommand(Obj, LCI);
case macho::LCT_Segment64:
- Res = DumpSegment64Command(Obj, LCI);
- break;
+ return DumpSegment64Command(Obj, LCI);
case macho::LCT_Symtab:
- Res = DumpSymtabCommand(Obj, LCI);
- break;
+ return DumpSymtabCommand(Obj);
case macho::LCT_Dysymtab:
- Res = DumpDysymtabCommand(Obj, LCI);
- break;
+ return DumpDysymtabCommand(Obj);
case macho::LCT_CodeSignature:
case macho::LCT_SegmentSplitInfo:
case macho::LCT_FunctionStarts:
- Res = DumpLinkeditDataCommand(Obj, LCI);
- break;
+ return DumpLinkeditDataCommand(Obj, LCI);
case macho::LCT_DataInCode:
- Res = DumpDataInCodeDataCommand(Obj, LCI);
- break;
+ return DumpDataInCodeDataCommand(Obj, LCI);
case macho::LCT_LinkerOptions:
- Res = DumpLinkerOptionsCommand(Obj, LCI);
- break;
+ return DumpLinkerOptionsCommand(Obj, LCI);
default:
- Warning("unknown load command: " + Twine(LCI.Command.Type));
- break;
+ Warning("unknown load command: " + Twine(LCI.C.Type));
+ return 0;
}
- outs() << " ),\n";
+}
+
+static int DumpLoadCommand(const MachOObjectFile &Obj, unsigned Index,
+ MachOObjectFile::LoadCommandInfo &LCI) {
+ outs() << " # Load Command " << Index << "\n"
+ << " (('command', " << LCI.C.Type << ")\n"
+ << " ('size', " << LCI.C.Size << ")\n";
+ int Res = DumpLoadCommand(Obj, LCI);
+ outs() << " ),\n";
return Res;
}
+static void printHeader(const MachOObjectFile *Obj,
+ const macho::Header &Header) {
+ outs() << "('cputype', " << Header.CPUType << ")\n";
+ outs() << "('cpusubtype', " << Header.CPUSubtype << ")\n";
+ outs() << "('filetype', " << Header.FileType << ")\n";
+ outs() << "('num_load_commands', " << Header.NumLoadCommands << ")\n";
+ outs() << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n";
+ outs() << "('flag', " << Header.Flags << ")\n";
+
+ // Print extended header if 64-bit.
+ if (Obj->is64Bit()) {
+ macho::Header64Ext Header64Ext = Obj->getHeader64Ext();
+ outs() << "('reserved', " << Header64Ext.Reserved << ")\n";
+ }
+}
+
int main(int argc, char **argv) {
ProgramName = argv[0];
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n");
- // Load the input file.
- std::string ErrorStr;
- OwningPtr<MemoryBuffer> InputBuffer;
- if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer))
- return Error("unable to read input: '" + ec.message() + "'");
+ OwningPtr<Binary> Binary;
+ if (error_code EC = createBinary(InputFile, Binary))
+ return Error("unable to read input: '" + EC.message() + "'");
- // Construct the Mach-O wrapper object.
- OwningPtr<MachOObject> InputObject(
- MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr));
+ const MachOObjectFile *InputObject = dyn_cast<MachOObjectFile>(Binary.get());
if (!InputObject)
- return Error("unable to load object: '" + ErrorStr + "'");
+ return Error("Not a MachO object");
// Print the header
- InputObject->printHeader(outs());
+ macho::Header Header = InputObject->getHeader();
+ printHeader(InputObject, Header);
// Print the load commands.
int Res = 0;
+ MachOObjectFile::LoadCommandInfo Command =
+ InputObject->getFirstLoadCommandInfo();
outs() << "('load_commands', [\n";
- for (unsigned i = 0; i != InputObject->getHeader().NumLoadCommands; ++i)
- if ((Res = DumpLoadCommand(*InputObject, i)))
+ for (unsigned i = 0; ; ++i) {
+ if (DumpLoadCommand(*InputObject, i, Command))
break;
+
+ if (i == Header.NumLoadCommands - 1)
+ break;
+ Command = InputObject->getNextLoadCommandInfo(Command);
+ }
outs() << "])\n";
return Res;