1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
|
//===- 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 <string>
#include "llvm/ADT/InMemoryStruct.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/MachOFormat.h"
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
/// @{
/// \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 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 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
|