mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
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
This commit is contained in:
parent
fbb2c7adc2
commit
2173e1839c
@ -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
|
|
@ -106,6 +106,9 @@ public:
|
|||||||
|
|
||||||
virtual StringRef getLoadName() const;
|
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
|
// 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
|
// files. They have a single segment, but this field specifies which segment
|
||||||
// a section should be put in in the final object.
|
// a section should be put in in the final object.
|
||||||
@ -134,14 +137,32 @@ public:
|
|||||||
// MachO specific structures.
|
// MachO specific structures.
|
||||||
macho::Section getSection(DataRefImpl DRI) const;
|
macho::Section getSection(DataRefImpl DRI) const;
|
||||||
macho::Section64 getSection64(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::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const;
|
||||||
macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const;
|
macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const;
|
||||||
|
|
||||||
macho::LinkeditDataLoadCommand
|
macho::LinkeditDataLoadCommand
|
||||||
getLinkeditDataLoadCommand(const LoadCommandInfo &L) const;
|
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::RelocationEntry getRelocation(DataRefImpl Rel) const;
|
||||||
macho::Header getHeader() 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::SymtabLoadCommand getSymtabLoadCommand() const;
|
||||||
|
macho::DysymtabLoadCommand getDysymtabLoadCommand() const;
|
||||||
|
|
||||||
|
StringRef getStringTableData() const;
|
||||||
bool is64Bit() const;
|
bool is64Bit() const;
|
||||||
void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
|
void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
|
||||||
|
|
||||||
@ -153,6 +174,7 @@ private:
|
|||||||
typedef SmallVector<const char*, 1> SectionList;
|
typedef SmallVector<const char*, 1> SectionList;
|
||||||
SectionList Sections;
|
SectionList Sections;
|
||||||
const char *SymtabLoadCmd;
|
const char *SymtabLoadCmd;
|
||||||
|
const char *DysymtabLoadCmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "RuntimeDyldImpl.h"
|
#include "RuntimeDyldImpl.h"
|
||||||
#include "llvm/ADT/IndexedMap.h"
|
#include "llvm/ADT/IndexedMap.h"
|
||||||
#include "llvm/Object/MachOObject.h"
|
#include "llvm/Object/MachO.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
@ -4,7 +4,6 @@ add_llvm_library(LLVMObject
|
|||||||
COFFObjectFile.cpp
|
COFFObjectFile.cpp
|
||||||
ELFObjectFile.cpp
|
ELFObjectFile.cpp
|
||||||
Error.cpp
|
Error.cpp
|
||||||
MachOObject.cpp
|
|
||||||
MachOObjectFile.cpp
|
MachOObjectFile.cpp
|
||||||
Object.cpp
|
Object.cpp
|
||||||
ObjectFile.cpp
|
ObjectFile.cpp
|
||||||
|
@ -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";
|
|
||||||
}
|
|
@ -119,6 +119,11 @@ void SwapStruct(macho::Header &H) {
|
|||||||
SwapValue(H.Flags);
|
SwapValue(H.Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void SwapStruct(macho::Header64Ext &E) {
|
||||||
|
SwapValue(E.Reserved);
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void SwapStruct(macho::SymtabLoadCommand &C) {
|
void SwapStruct(macho::SymtabLoadCommand &C) {
|
||||||
SwapValue(C.Type);
|
SwapValue(C.Type);
|
||||||
@ -129,6 +134,30 @@ void SwapStruct(macho::SymtabLoadCommand &C) {
|
|||||||
SwapValue(C.StringTableSize);
|
SwapValue(C.StringTableSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<>
|
template<>
|
||||||
void SwapStruct(macho::LinkeditDataLoadCommand &C) {
|
void SwapStruct(macho::LinkeditDataLoadCommand &C) {
|
||||||
SwapValue(C.Type);
|
SwapValue(C.Type);
|
||||||
@ -165,6 +194,25 @@ void SwapStruct(macho::Segment64LoadCommand &C) {
|
|||||||
SwapValue(C.Flags);
|
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>
|
template<typename T>
|
||||||
T getStruct(const MachOObjectFile *O, const char *P) {
|
T getStruct(const MachOObjectFile *O, const char *P) {
|
||||||
T Cmd;
|
T Cmd;
|
||||||
@ -174,32 +222,20 @@ T getStruct(const MachOObjectFile *O, const char *P) {
|
|||||||
return Cmd;
|
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
|
static uint32_t
|
||||||
getSegmentLoadCommandNumSections(const MachOObjectFile *O,
|
getSegmentLoadCommandNumSections(const MachOObjectFile *O,
|
||||||
const MachOObjectFile::LoadCommandInfo &L) {
|
const MachOObjectFile::LoadCommandInfo &L) {
|
||||||
if (O->is64Bit()) {
|
if (O->is64Bit()) {
|
||||||
macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
|
macho::Segment64LoadCommand S = O->getSegment64LoadCommand(L);
|
||||||
return S.NumSections;
|
return S.NumSections;
|
||||||
}
|
}
|
||||||
macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
|
macho::SegmentLoadCommand S = O->getSegmentLoadCommand(L);
|
||||||
return S.NumSections;
|
return S.NumSections;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const SectionBase *
|
static const char *
|
||||||
getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
|
getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
|
||||||
unsigned Sec) {
|
unsigned Sec) {
|
||||||
uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
|
uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
|
||||||
|
|
||||||
bool Is64 = O->is64Bit();
|
bool Is64 = O->is64Bit();
|
||||||
@ -209,7 +245,7 @@ getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
|
|||||||
sizeof(macho::Section);
|
sizeof(macho::Section);
|
||||||
|
|
||||||
uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
|
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) {
|
static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
|
||||||
@ -377,7 +413,7 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
|
|||||||
bool IsLittleEndian, bool Is64bits,
|
bool IsLittleEndian, bool Is64bits,
|
||||||
error_code &ec)
|
error_code &ec)
|
||||||
: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
|
: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
|
||||||
SymtabLoadCmd(NULL) {
|
SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL) {
|
||||||
uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
|
uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
|
||||||
macho::LoadCommandType SegmentLoadType = is64Bit() ?
|
macho::LoadCommandType SegmentLoadType = is64Bit() ?
|
||||||
macho::LCT_Segment64 : macho::LCT_Segment;
|
macho::LCT_Segment64 : macho::LCT_Segment;
|
||||||
@ -387,13 +423,14 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
|
|||||||
if (Load.C.Type == macho::LCT_Symtab) {
|
if (Load.C.Type == macho::LCT_Symtab) {
|
||||||
assert(!SymtabLoadCmd && "Multiple symbol tables");
|
assert(!SymtabLoadCmd && "Multiple symbol tables");
|
||||||
SymtabLoadCmd = Load.Ptr;
|
SymtabLoadCmd = Load.Ptr;
|
||||||
}
|
} else if (Load.C.Type == macho::LCT_Dysymtab) {
|
||||||
|
assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
|
||||||
if (Load.C.Type == SegmentLoadType) {
|
DysymtabLoadCmd = Load.Ptr;
|
||||||
|
} else if (Load.C.Type == SegmentLoadType) {
|
||||||
uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
|
uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
|
||||||
for (unsigned J = 0; J < NumSections; ++J) {
|
for (unsigned J = 0; J < NumSections; ++J) {
|
||||||
const SectionBase *Sec = getSectionBase(this, Load, J);
|
const char *Sec = getSectionPtr(this, Load, J);
|
||||||
Sections.push_back(reinterpret_cast<const char*>(Sec));
|
Sections.push_back(Sec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,10 +453,9 @@ error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
|
|||||||
|
|
||||||
error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
|
error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
|
||||||
StringRef &Res) const {
|
StringRef &Res) const {
|
||||||
macho::SymtabLoadCommand S = getSymtabLoadCommand();
|
StringRef StringTable = getStringTableData();
|
||||||
const char *StringTable = getPtr(this, S.StringTableOffset);
|
|
||||||
SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
|
SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
|
||||||
const char *Start = &StringTable[Entry.StringIndex];
|
const char *Start = &StringTable.data()[Entry.StringIndex];
|
||||||
Res = StringRef(Start);
|
Res = StringRef(Start);
|
||||||
return object_error::success;
|
return object_error::success;
|
||||||
}
|
}
|
||||||
@ -1271,6 +1307,18 @@ StringRef MachOObjectFile::getLoadName() const {
|
|||||||
report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
|
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
|
StringRef
|
||||||
MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
|
MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
|
||||||
ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
|
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]);
|
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
|
macho::SymbolTableEntry
|
||||||
MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
|
MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
|
||||||
const char *P = reinterpret_cast<const char *>(DRI.p);
|
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);
|
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
|
macho::RelocationEntry
|
||||||
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
|
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
|
||||||
const char *P = reinterpret_cast<const char *>(Rel.p);
|
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));
|
return getStruct<macho::Header>(this, getPtr(this, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
macho::SymtabLoadCommand
|
macho::Header64Ext MachOObjectFile::getHeader64Ext() const {
|
||||||
MachOObjectFile::getSymtabLoadCommand() 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);
|
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 {
|
bool MachOObjectFile::is64Bit() const {
|
||||||
return getType() == getMachOType(false, true) ||
|
return getType() == getMachOType(false, true) ||
|
||||||
getType() == getMachOType(true, true);
|
getType() == getMachOType(true, true);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
||||||
#include "llvm/ExecutionEngine/ObjectImage.h"
|
#include "llvm/ExecutionEngine/ObjectImage.h"
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "llvm/Object/MachOObject.h"
|
#include "llvm/Object/MachO.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
#include "llvm/Support/Memory.h"
|
#include "llvm/Support/Memory.h"
|
||||||
|
@ -11,9 +11,10 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Object/MachOObject.h"
|
#include "llvm/Object/MachO.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
@ -66,7 +67,8 @@ static void DumpSegmentCommandData(StringRef Name,
|
|||||||
outs() << " ('flags', " << Flags << ")\n";
|
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,
|
StringRef SegmentName, uint64_t Address,
|
||||||
uint64_t Size, uint32_t Offset,
|
uint64_t Size, uint32_t Offset,
|
||||||
uint32_t Align, uint32_t RelocationTableOffset,
|
uint32_t Align, uint32_t RelocationTableOffset,
|
||||||
@ -92,26 +94,22 @@ static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name,
|
|||||||
outs() << " ),\n";
|
outs() << " ),\n";
|
||||||
|
|
||||||
// Dump the relocation entries.
|
// Dump the relocation entries.
|
||||||
int Res = 0;
|
|
||||||
outs() << " ('_relocations', [\n";
|
outs() << " ('_relocations', [\n";
|
||||||
for (unsigned i = 0; i != NumRelocationTableEntries; ++i) {
|
unsigned RelNum = 0;
|
||||||
InMemoryStruct<macho::RelocationEntry> RE;
|
error_code EC;
|
||||||
Obj.ReadRelocationEntry(RelocationTableOffset, i, RE);
|
for (relocation_iterator I = Obj.getSectionRelBegin(Index),
|
||||||
if (!RE) {
|
E = Obj.getSectionRelEnd(Index); I != E; I.increment(EC), ++RelNum) {
|
||||||
Res = Error("unable to read relocation table entry '" + Twine(i) + "'");
|
macho::RelocationEntry RE = Obj.getRelocation(I->getRawDataRefImpl());
|
||||||
break;
|
outs() << " # Relocation " << RelNum << "\n";
|
||||||
}
|
outs() << " (('word-0', " << format("0x%x", RE.Word0) << "),\n";
|
||||||
|
outs() << " ('word-1', " << format("0x%x", RE.Word1) << ")),\n";
|
||||||
outs() << " # Relocation " << i << "\n";
|
|
||||||
outs() << " (('word-0', " << format("0x%x", RE->Word0) << "),\n";
|
|
||||||
outs() << " ('word-1', " << format("0x%x", RE->Word1) << ")),\n";
|
|
||||||
}
|
}
|
||||||
outs() << " ])\n";
|
outs() << " ])\n";
|
||||||
|
|
||||||
// Dump the section data, if requested.
|
// Dump the section data, if requested.
|
||||||
if (ShowSectionData) {
|
if (ShowSectionData) {
|
||||||
outs() << " ('_section_data', '";
|
outs() << " ('_section_data', '";
|
||||||
StringRef Data = Obj.getData(Offset, Size);
|
StringRef Data = Obj.getData().substr(Offset, Size);
|
||||||
for (unsigned i = 0; i != Data.size(); ++i) {
|
for (unsigned i = 0; i != Data.size(); ++i) {
|
||||||
if (i && (i % 4) == 0)
|
if (i && (i % 4) == 0)
|
||||||
outs() << ' ';
|
outs() << ' ';
|
||||||
@ -121,208 +119,162 @@ static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name,
|
|||||||
outs() << "')\n";
|
outs() << "')\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return Res;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DumpSegmentCommand(MachOObject &Obj,
|
static int DumpSegmentCommand(const MachOObjectFile &Obj,
|
||||||
const MachOObject::LoadCommandInfo &LCI) {
|
const MachOObjectFile::LoadCommandInfo &LCI) {
|
||||||
InMemoryStruct<macho::SegmentLoadCommand> SLC;
|
macho::SegmentLoadCommand SLC = Obj.getSegmentLoadCommand(LCI);
|
||||||
Obj.ReadSegmentLoadCommand(LCI, SLC);
|
|
||||||
if (!SLC)
|
|
||||||
return Error("unable to read segment load command");
|
|
||||||
|
|
||||||
DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress,
|
DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress,
|
||||||
SLC->VMSize, SLC->FileOffset, SLC->FileSize,
|
SLC.VMSize, SLC.FileOffset, SLC.FileSize,
|
||||||
SLC->MaxVMProtection, SLC->InitialVMProtection,
|
SLC.MaxVMProtection, SLC.InitialVMProtection,
|
||||||
SLC->NumSections, SLC->Flags);
|
SLC.NumSections, SLC.Flags);
|
||||||
|
|
||||||
// Dump the sections.
|
// Dump the sections.
|
||||||
int Res = 0;
|
|
||||||
outs() << " ('sections', [\n";
|
outs() << " ('sections', [\n";
|
||||||
for (unsigned i = 0; i != SLC->NumSections; ++i) {
|
for (unsigned i = 0; i != SLC.NumSections; ++i) {
|
||||||
InMemoryStruct<macho::Section> Sect;
|
macho::Section Sect = Obj.getSection(LCI, i);
|
||||||
Obj.ReadSection(LCI, i, Sect);
|
DumpSectionData(Obj, i, StringRef(Sect.Name, 16),
|
||||||
if (!SLC) {
|
StringRef(Sect.SegmentName, 16), Sect.Address,
|
||||||
Res = Error("unable to read section '" + Twine(i) + "'");
|
Sect.Size, Sect.Offset, Sect.Align,
|
||||||
break;
|
Sect.RelocationTableOffset,
|
||||||
}
|
Sect.NumRelocationTableEntries, Sect.Flags,
|
||||||
|
Sect.Reserved1, Sect.Reserved2);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
outs() << " ])\n";
|
outs() << " ])\n";
|
||||||
|
|
||||||
return Res;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DumpSegment64Command(MachOObject &Obj,
|
static int DumpSegment64Command(const MachOObjectFile &Obj,
|
||||||
const MachOObject::LoadCommandInfo &LCI) {
|
const MachOObjectFile::LoadCommandInfo &LCI) {
|
||||||
InMemoryStruct<macho::Segment64LoadCommand> SLC;
|
macho::Segment64LoadCommand SLC = Obj.getSegment64LoadCommand(LCI);
|
||||||
Obj.ReadSegment64LoadCommand(LCI, SLC);
|
DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress,
|
||||||
if (!SLC)
|
SLC.VMSize, SLC.FileOffset, SLC.FileSize,
|
||||||
return Error("unable to read segment load command");
|
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.
|
// Dump the sections.
|
||||||
int Res = 0;
|
|
||||||
outs() << " ('sections', [\n";
|
outs() << " ('sections', [\n";
|
||||||
for (unsigned i = 0; i != SLC->NumSections; ++i) {
|
for (unsigned i = 0; i != SLC.NumSections; ++i) {
|
||||||
InMemoryStruct<macho::Section64> Sect;
|
macho::Section64 Sect = Obj.getSection64(LCI, i);
|
||||||
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),
|
DumpSectionData(Obj, i, StringRef(Sect.Name, 16),
|
||||||
StringRef(Sect->SegmentName, 16), Sect->Address,
|
StringRef(Sect.SegmentName, 16), Sect.Address,
|
||||||
Sect->Size, Sect->Offset, Sect->Align,
|
Sect.Size, Sect.Offset, Sect.Align,
|
||||||
Sect->RelocationTableOffset,
|
Sect.RelocationTableOffset,
|
||||||
Sect->NumRelocationTableEntries, Sect->Flags,
|
Sect.NumRelocationTableEntries, Sect.Flags,
|
||||||
Sect->Reserved1, Sect->Reserved2,
|
Sect.Reserved1, Sect.Reserved2,
|
||||||
Sect->Reserved3)))
|
Sect.Reserved3);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
outs() << " ])\n";
|
outs() << " ])\n";
|
||||||
|
|
||||||
return Res;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DumpSymbolTableEntryData(MachOObject &Obj,
|
static void DumpSymbolTableEntryData(const MachOObjectFile &Obj,
|
||||||
unsigned Index, uint32_t StringIndex,
|
unsigned Index, uint32_t StringIndex,
|
||||||
uint8_t Type, uint8_t SectionIndex,
|
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() << " # Symbol " << Index << "\n";
|
||||||
outs() << " (('n_strx', " << StringIndex << ")\n";
|
outs() << " (('n_strx', " << StringIndex << ")\n";
|
||||||
outs() << " ('n_type', " << format("0x%x", Type) << ")\n";
|
outs() << " ('n_type', " << format("0x%x", Type) << ")\n";
|
||||||
outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n";
|
outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n";
|
||||||
outs() << " ('n_desc', " << Flags << ")\n";
|
outs() << " ('n_desc', " << Flags << ")\n";
|
||||||
outs() << " ('n_value', " << Value << ")\n";
|
outs() << " ('n_value', " << Value << ")\n";
|
||||||
outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n";
|
outs() << " ('_string', '" << Name << "')\n";
|
||||||
outs() << " ),\n";
|
outs() << " ),\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DumpSymtabCommand(MachOObject &Obj,
|
static int DumpSymtabCommand(const MachOObjectFile &Obj) {
|
||||||
const MachOObject::LoadCommandInfo &LCI) {
|
macho::SymtabLoadCommand SLC = Obj.getSymtabLoadCommand();
|
||||||
InMemoryStruct<macho::SymtabLoadCommand> SLC;
|
|
||||||
Obj.ReadSymtabLoadCommand(LCI, SLC);
|
|
||||||
if (!SLC)
|
|
||||||
return Error("unable to read segment load command");
|
|
||||||
|
|
||||||
outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n";
|
outs() << " ('symoff', " << SLC.SymbolTableOffset << ")\n";
|
||||||
outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n";
|
outs() << " ('nsyms', " << SLC.NumSymbolTableEntries << ")\n";
|
||||||
outs() << " ('stroff', " << SLC->StringTableOffset << ")\n";
|
outs() << " ('stroff', " << SLC.StringTableOffset << ")\n";
|
||||||
outs() << " ('strsize', " << SLC->StringTableSize << ")\n";
|
outs() << " ('strsize', " << SLC.StringTableSize << ")\n";
|
||||||
|
|
||||||
// Cache the string table data.
|
|
||||||
Obj.RegisterStringTable(*SLC);
|
|
||||||
|
|
||||||
// Dump the string data.
|
// Dump the string data.
|
||||||
outs() << " ('_string_data', '";
|
outs() << " ('_string_data', '";
|
||||||
outs().write_escaped(Obj.getStringTableData(),
|
StringRef StringTable = Obj.getStringTableData();
|
||||||
|
outs().write_escaped(StringTable,
|
||||||
/*UseHexEscapes=*/true) << "')\n";
|
/*UseHexEscapes=*/true) << "')\n";
|
||||||
|
|
||||||
// Dump the symbol table.
|
// Dump the symbol table.
|
||||||
int Res = 0;
|
|
||||||
outs() << " ('_symbols', [\n";
|
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()) {
|
if (Obj.is64Bit()) {
|
||||||
InMemoryStruct<macho::Symbol64TableEntry> STE;
|
macho::Symbol64TableEntry STE = Obj.getSymbol64TableEntry(DRI);
|
||||||
Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE);
|
DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type,
|
||||||
if (!STE) {
|
STE.SectionIndex, STE.Flags, STE.Value,
|
||||||
Res = Error("unable to read symbol: '" + Twine(i) + "'");
|
StringTable);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type,
|
|
||||||
STE->SectionIndex, STE->Flags, STE->Value);
|
|
||||||
} else {
|
} else {
|
||||||
InMemoryStruct<macho::SymbolTableEntry> STE;
|
macho::SymbolTableEntry STE = Obj.getSymbolTableEntry(DRI);
|
||||||
Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE);
|
DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type,
|
||||||
if (!SLC) {
|
STE.SectionIndex, STE.Flags, STE.Value,
|
||||||
Res = Error("unable to read symbol: '" + Twine(i) + "'");
|
StringTable);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type,
|
|
||||||
STE->SectionIndex, STE->Flags, STE->Value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outs() << " ])\n";
|
outs() << " ])\n";
|
||||||
|
|
||||||
return Res;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DumpDysymtabCommand(MachOObject &Obj,
|
static int DumpDysymtabCommand(const MachOObjectFile &Obj) {
|
||||||
const MachOObject::LoadCommandInfo &LCI) {
|
macho::DysymtabLoadCommand DLC = Obj.getDysymtabLoadCommand();
|
||||||
InMemoryStruct<macho::DysymtabLoadCommand> DLC;
|
|
||||||
Obj.ReadDysymtabLoadCommand(LCI, DLC);
|
|
||||||
if (!DLC)
|
|
||||||
return Error("unable to read segment load command");
|
|
||||||
|
|
||||||
outs() << " ('ilocalsym', " << DLC->LocalSymbolsIndex << ")\n";
|
outs() << " ('ilocalsym', " << DLC.LocalSymbolsIndex << ")\n";
|
||||||
outs() << " ('nlocalsym', " << DLC->NumLocalSymbols << ")\n";
|
outs() << " ('nlocalsym', " << DLC.NumLocalSymbols << ")\n";
|
||||||
outs() << " ('iextdefsym', " << DLC->ExternalSymbolsIndex << ")\n";
|
outs() << " ('iextdefsym', " << DLC.ExternalSymbolsIndex << ")\n";
|
||||||
outs() << " ('nextdefsym', " << DLC->NumExternalSymbols << ")\n";
|
outs() << " ('nextdefsym', " << DLC.NumExternalSymbols << ")\n";
|
||||||
outs() << " ('iundefsym', " << DLC->UndefinedSymbolsIndex << ")\n";
|
outs() << " ('iundefsym', " << DLC.UndefinedSymbolsIndex << ")\n";
|
||||||
outs() << " ('nundefsym', " << DLC->NumUndefinedSymbols << ")\n";
|
outs() << " ('nundefsym', " << DLC.NumUndefinedSymbols << ")\n";
|
||||||
outs() << " ('tocoff', " << DLC->TOCOffset << ")\n";
|
outs() << " ('tocoff', " << DLC.TOCOffset << ")\n";
|
||||||
outs() << " ('ntoc', " << DLC->NumTOCEntries << ")\n";
|
outs() << " ('ntoc', " << DLC.NumTOCEntries << ")\n";
|
||||||
outs() << " ('modtaboff', " << DLC->ModuleTableOffset << ")\n";
|
outs() << " ('modtaboff', " << DLC.ModuleTableOffset << ")\n";
|
||||||
outs() << " ('nmodtab', " << DLC->NumModuleTableEntries << ")\n";
|
outs() << " ('nmodtab', " << DLC.NumModuleTableEntries << ")\n";
|
||||||
outs() << " ('extrefsymoff', " << DLC->ReferenceSymbolTableOffset << ")\n";
|
outs() << " ('extrefsymoff', " << DLC.ReferenceSymbolTableOffset << ")\n";
|
||||||
outs() << " ('nextrefsyms', "
|
outs() << " ('nextrefsyms', "
|
||||||
<< DLC->NumReferencedSymbolTableEntries << ")\n";
|
<< DLC.NumReferencedSymbolTableEntries << ")\n";
|
||||||
outs() << " ('indirectsymoff', " << DLC->IndirectSymbolTableOffset << ")\n";
|
outs() << " ('indirectsymoff', " << DLC.IndirectSymbolTableOffset << ")\n";
|
||||||
outs() << " ('nindirectsyms', "
|
outs() << " ('nindirectsyms', "
|
||||||
<< DLC->NumIndirectSymbolTableEntries << ")\n";
|
<< DLC.NumIndirectSymbolTableEntries << ")\n";
|
||||||
outs() << " ('extreloff', " << DLC->ExternalRelocationTableOffset << ")\n";
|
outs() << " ('extreloff', " << DLC.ExternalRelocationTableOffset << ")\n";
|
||||||
outs() << " ('nextrel', " << DLC->NumExternalRelocationTableEntries << ")\n";
|
outs() << " ('nextrel', " << DLC.NumExternalRelocationTableEntries << ")\n";
|
||||||
outs() << " ('locreloff', " << DLC->LocalRelocationTableOffset << ")\n";
|
outs() << " ('locreloff', " << DLC.LocalRelocationTableOffset << ")\n";
|
||||||
outs() << " ('nlocrel', " << DLC->NumLocalRelocationTableEntries << ")\n";
|
outs() << " ('nlocrel', " << DLC.NumLocalRelocationTableEntries << ")\n";
|
||||||
|
|
||||||
// Dump the indirect symbol table.
|
// Dump the indirect symbol table.
|
||||||
int Res = 0;
|
|
||||||
outs() << " ('_indirect_symbols', [\n";
|
outs() << " ('_indirect_symbols', [\n";
|
||||||
for (unsigned i = 0; i != DLC->NumIndirectSymbolTableEntries; ++i) {
|
for (unsigned i = 0; i != DLC.NumIndirectSymbolTableEntries; ++i) {
|
||||||
InMemoryStruct<macho::IndirectSymbolTableEntry> ISTE;
|
macho::IndirectSymbolTableEntry ISTE =
|
||||||
Obj.ReadIndirectSymbolTableEntry(*DLC, i, ISTE);
|
Obj.getIndirectSymbolTableEntry(DLC, i);
|
||||||
if (!ISTE) {
|
|
||||||
Res = Error("unable to read segment load command");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
outs() << " # Indirect Symbol " << i << "\n";
|
outs() << " # Indirect Symbol " << i << "\n";
|
||||||
outs() << " (('symbol_index', "
|
outs() << " (('symbol_index', "
|
||||||
<< format("0x%x", ISTE->Index) << "),),\n";
|
<< format("0x%x", ISTE.Index) << "),),\n";
|
||||||
}
|
}
|
||||||
outs() << " ])\n";
|
outs() << " ])\n";
|
||||||
|
|
||||||
return Res;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DumpLinkeditDataCommand(MachOObject &Obj,
|
static int
|
||||||
const MachOObject::LoadCommandInfo &LCI) {
|
DumpLinkeditDataCommand(const MachOObjectFile &Obj,
|
||||||
InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
|
const MachOObjectFile::LoadCommandInfo &LCI) {
|
||||||
Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
|
macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI);
|
||||||
if (!LLC)
|
outs() << " ('dataoff', " << LLC.DataOffset << ")\n"
|
||||||
return Error("unable to read segment load command");
|
<< " ('datasize', " << LLC.DataSize << ")\n"
|
||||||
|
|
||||||
outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
|
|
||||||
<< " ('datasize', " << LLC->DataSize << ")\n"
|
|
||||||
<< " ('_addresses', [\n";
|
<< " ('_addresses', [\n";
|
||||||
|
|
||||||
SmallVector<uint64_t, 8> Addresses;
|
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)
|
for (unsigned i = 0, e = Addresses.size(); i != e; ++i)
|
||||||
outs() << " # Address " << i << '\n'
|
outs() << " # Address " << i << '\n'
|
||||||
<< " ('address', " << format("0x%x", Addresses[i]) << "),\n";
|
<< " ('address', " << format("0x%x", Addresses[i]) << "),\n";
|
||||||
@ -332,28 +284,22 @@ static int DumpLinkeditDataCommand(MachOObject &Obj,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DumpDataInCodeDataCommand(MachOObject &Obj,
|
static int
|
||||||
const MachOObject::LoadCommandInfo &LCI) {
|
DumpDataInCodeDataCommand(const MachOObjectFile &Obj,
|
||||||
InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
|
const MachOObjectFile::LoadCommandInfo &LCI) {
|
||||||
Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
|
macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI);
|
||||||
if (!LLC)
|
outs() << " ('dataoff', " << LLC.DataOffset << ")\n"
|
||||||
return Error("unable to read data-in-code load command");
|
<< " ('datasize', " << LLC.DataSize << ")\n"
|
||||||
|
|
||||||
outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
|
|
||||||
<< " ('datasize', " << LLC->DataSize << ")\n"
|
|
||||||
<< " ('_data_regions', [\n";
|
<< " ('_data_regions', [\n";
|
||||||
|
|
||||||
|
unsigned NumRegions = LLC.DataSize / 8;
|
||||||
unsigned NumRegions = LLC->DataSize / 8;
|
|
||||||
for (unsigned i = 0; i < NumRegions; ++i) {
|
for (unsigned i = 0; i < NumRegions; ++i) {
|
||||||
InMemoryStruct<macho::DataInCodeTableEntry> DICE;
|
macho::DataInCodeTableEntry DICE =
|
||||||
Obj.ReadDataInCodeTableEntry(LLC->DataOffset, i, DICE);
|
Obj.getDataInCodeTableEntry(LLC.DataOffset, i);
|
||||||
if (!DICE)
|
|
||||||
return Error("unable to read DataInCodeTableEntry");
|
|
||||||
outs() << " # DICE " << i << "\n"
|
outs() << " # DICE " << i << "\n"
|
||||||
<< " ('offset', " << DICE->Offset << ")\n"
|
<< " ('offset', " << DICE.Offset << ")\n"
|
||||||
<< " ('length', " << DICE->Length << ")\n"
|
<< " ('length', " << DICE.Length << ")\n"
|
||||||
<< " ('kind', " << DICE->Kind << ")\n";
|
<< " ('kind', " << DICE.Kind << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
outs() <<" ])\n";
|
outs() <<" ])\n";
|
||||||
@ -361,99 +307,111 @@ static int DumpDataInCodeDataCommand(MachOObject &Obj,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DumpLinkerOptionsCommand(MachOObject &Obj,
|
static int
|
||||||
const MachOObject::LoadCommandInfo &LCI) {
|
DumpLinkerOptionsCommand(const MachOObjectFile &Obj,
|
||||||
InMemoryStruct<macho::LinkerOptionsLoadCommand> LOLC;
|
const MachOObjectFile::LoadCommandInfo &LCI) {
|
||||||
Obj.ReadLinkerOptionsLoadCommand(LCI, LOLC);
|
macho::LinkerOptionsLoadCommand LOLC = Obj.getLinkerOptionsLoadCommand(LCI);
|
||||||
if (!LOLC)
|
outs() << " ('count', " << LOLC.Count << ")\n"
|
||||||
return Error("unable to read linker options load command");
|
<< " ('_strings', [\n";
|
||||||
|
|
||||||
outs() << " ('count', " << LOLC->Count << ")\n"
|
uint64_t DataSize = LOLC.Size - sizeof(macho::LinkerOptionsLoadCommand);
|
||||||
<< " ('_strings', [\n";
|
const char *P = LCI.Ptr + sizeof(macho::LinkerOptionsLoadCommand);
|
||||||
|
StringRef Data(P, DataSize);
|
||||||
uint64_t DataSize = LOLC->Size - sizeof(macho::LinkerOptionsLoadCommand);
|
for (unsigned i = 0; i != LOLC.Count; ++i) {
|
||||||
StringRef Data = Obj.getData(
|
std::pair<StringRef,StringRef> Split = Data.split('\0');
|
||||||
LCI.Offset + sizeof(macho::LinkerOptionsLoadCommand), DataSize);
|
outs() << "\t\"";
|
||||||
for (unsigned i = 0; i != LOLC->Count; ++i) {
|
outs().write_escaped(Split.first);
|
||||||
std::pair<StringRef,StringRef> Split = Data.split('\0');
|
outs() << "\",\n";
|
||||||
outs() << "\t\"";
|
Data = Split.second;
|
||||||
outs().write_escaped(Split.first);
|
}
|
||||||
outs() << "\",\n";
|
outs() <<" ])\n";
|
||||||
Data = Split.second;
|
|
||||||
}
|
|
||||||
outs() <<" ])\n";
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int DumpLoadCommand(const MachOObjectFile &Obj,
|
||||||
static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
|
MachOObjectFile::LoadCommandInfo &LCI) {
|
||||||
const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index);
|
switch (LCI.C.Type) {
|
||||||
int Res = 0;
|
|
||||||
|
|
||||||
outs() << " # Load Command " << Index << "\n"
|
|
||||||
<< " (('command', " << LCI.Command.Type << ")\n"
|
|
||||||
<< " ('size', " << LCI.Command.Size << ")\n";
|
|
||||||
switch (LCI.Command.Type) {
|
|
||||||
case macho::LCT_Segment:
|
case macho::LCT_Segment:
|
||||||
Res = DumpSegmentCommand(Obj, LCI);
|
return DumpSegmentCommand(Obj, LCI);
|
||||||
break;
|
|
||||||
case macho::LCT_Segment64:
|
case macho::LCT_Segment64:
|
||||||
Res = DumpSegment64Command(Obj, LCI);
|
return DumpSegment64Command(Obj, LCI);
|
||||||
break;
|
|
||||||
case macho::LCT_Symtab:
|
case macho::LCT_Symtab:
|
||||||
Res = DumpSymtabCommand(Obj, LCI);
|
return DumpSymtabCommand(Obj);
|
||||||
break;
|
|
||||||
case macho::LCT_Dysymtab:
|
case macho::LCT_Dysymtab:
|
||||||
Res = DumpDysymtabCommand(Obj, LCI);
|
return DumpDysymtabCommand(Obj);
|
||||||
break;
|
|
||||||
case macho::LCT_CodeSignature:
|
case macho::LCT_CodeSignature:
|
||||||
case macho::LCT_SegmentSplitInfo:
|
case macho::LCT_SegmentSplitInfo:
|
||||||
case macho::LCT_FunctionStarts:
|
case macho::LCT_FunctionStarts:
|
||||||
Res = DumpLinkeditDataCommand(Obj, LCI);
|
return DumpLinkeditDataCommand(Obj, LCI);
|
||||||
break;
|
|
||||||
case macho::LCT_DataInCode:
|
case macho::LCT_DataInCode:
|
||||||
Res = DumpDataInCodeDataCommand(Obj, LCI);
|
return DumpDataInCodeDataCommand(Obj, LCI);
|
||||||
break;
|
|
||||||
case macho::LCT_LinkerOptions:
|
case macho::LCT_LinkerOptions:
|
||||||
Res = DumpLinkerOptionsCommand(Obj, LCI);
|
return DumpLinkerOptionsCommand(Obj, LCI);
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
Warning("unknown load command: " + Twine(LCI.Command.Type));
|
Warning("unknown load command: " + Twine(LCI.C.Type));
|
||||||
break;
|
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;
|
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) {
|
int main(int argc, char **argv) {
|
||||||
ProgramName = argv[0];
|
ProgramName = argv[0];
|
||||||
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
|
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
|
||||||
|
|
||||||
cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n");
|
cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n");
|
||||||
|
|
||||||
// Load the input file.
|
OwningPtr<Binary> Binary;
|
||||||
std::string ErrorStr;
|
if (error_code EC = createBinary(InputFile, Binary))
|
||||||
OwningPtr<MemoryBuffer> InputBuffer;
|
return Error("unable to read input: '" + EC.message() + "'");
|
||||||
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer))
|
|
||||||
return Error("unable to read input: '" + ec.message() + "'");
|
|
||||||
|
|
||||||
// Construct the Mach-O wrapper object.
|
const MachOObjectFile *InputObject = dyn_cast<MachOObjectFile>(Binary.get());
|
||||||
OwningPtr<MachOObject> InputObject(
|
|
||||||
MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr));
|
|
||||||
if (!InputObject)
|
if (!InputObject)
|
||||||
return Error("unable to load object: '" + ErrorStr + "'");
|
return Error("Not a MachO object");
|
||||||
|
|
||||||
// Print the header
|
// Print the header
|
||||||
InputObject->printHeader(outs());
|
macho::Header Header = InputObject->getHeader();
|
||||||
|
printHeader(InputObject, Header);
|
||||||
|
|
||||||
// Print the load commands.
|
// Print the load commands.
|
||||||
int Res = 0;
|
int Res = 0;
|
||||||
|
MachOObjectFile::LoadCommandInfo Command =
|
||||||
|
InputObject->getFirstLoadCommandInfo();
|
||||||
outs() << "('load_commands', [\n";
|
outs() << "('load_commands', [\n";
|
||||||
for (unsigned i = 0; i != InputObject->getHeader().NumLoadCommands; ++i)
|
for (unsigned i = 0; ; ++i) {
|
||||||
if ((Res = DumpLoadCommand(*InputObject, i)))
|
if (DumpLoadCommand(*InputObject, i, Command))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (i == Header.NumLoadCommands - 1)
|
||||||
|
break;
|
||||||
|
Command = InputObject->getNextLoadCommandInfo(Command);
|
||||||
|
}
|
||||||
outs() << "])\n";
|
outs() << "])\n";
|
||||||
|
|
||||||
return Res;
|
return Res;
|
||||||
|
Loading…
Reference in New Issue
Block a user