mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +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;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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 "llvm/ADT/IndexedMap.h"
|
||||
#include "llvm/Object/MachOObject.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -4,7 +4,6 @@ add_llvm_library(LLVMObject
|
||||
COFFObjectFile.cpp
|
||||
ELFObjectFile.cpp
|
||||
Error.cpp
|
||||
MachOObject.cpp
|
||||
MachOObjectFile.cpp
|
||||
Object.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);
|
||||
}
|
||||
|
||||
template<>
|
||||
void SwapStruct(macho::Header64Ext &E) {
|
||||
SwapValue(E.Reserved);
|
||||
}
|
||||
|
||||
template<>
|
||||
void SwapStruct(macho::SymtabLoadCommand &C) {
|
||||
SwapValue(C.Type);
|
||||
@ -129,6 +134,30 @@ void SwapStruct(macho::SymtabLoadCommand &C) {
|
||||
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<>
|
||||
void SwapStruct(macho::LinkeditDataLoadCommand &C) {
|
||||
SwapValue(C.Type);
|
||||
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
for (unsigned i = 0; i != SLC.NumSections; ++i) {
|
||||
macho::Section64 Sect = Obj.getSection64(LCI, i);
|
||||
|
||||
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;
|
||||
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");
|
||||
static int DumpSymtabCommand(const MachOObjectFile &Obj) {
|
||||
macho::SymtabLoadCommand SLC = Obj.getSymtabLoadCommand();
|
||||
|
||||
outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n";
|
||||
outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n";
|
||||
outs() << " ('stroff', " << SLC->StringTableOffset << ")\n";
|
||||
outs() << " ('strsize', " << SLC->StringTableSize << ")\n";
|
||||
|
||||
// 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");
|
||||
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() << " ('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");
|
||||
static int
|
||||
DumpLinkerOptionsCommand(const MachOObjectFile &Obj,
|
||||
const MachOObjectFile::LoadCommandInfo &LCI) {
|
||||
macho::LinkerOptionsLoadCommand LOLC = Obj.getLinkerOptionsLoadCommand(LCI);
|
||||
outs() << " ('count', " << LOLC.Count << ")\n"
|
||||
<< " ('_strings', [\n";
|
||||
|
||||
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";
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user