1 //===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_OBJECT_MACHOOBJECT_H 11 #define LLVM_OBJECT_MACHOOBJECT_H 12 13 #include <string> 14 #include "llvm/ADT/InMemoryStruct.h" 15 #include "llvm/ADT/OwningPtr.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/Object/MachOFormat.h" 18 19 namespace llvm { 20 21 class MemoryBuffer; 22 class raw_ostream; 23 24 namespace object { 25 26 /// \brief Wrapper object for manipulating Mach-O object files. 27 /// 28 /// This class is designed to implement a full-featured, efficient, portable, 29 /// and robust Mach-O interface to Mach-O object files. It does not attempt to 30 /// smooth over rough edges in the Mach-O format or generalize access to object 31 /// independent features. 32 /// 33 /// The class is designed around accessing the Mach-O object which is expected 34 /// to be fully loaded into memory. 35 /// 36 /// This class is *not* suitable for concurrent use. For efficient operation, 37 /// the class uses APIs which rely on the ability to cache the results of 38 /// certain calls in internal objects which are not safe for concurrent 39 /// access. This allows the API to be zero-copy on the common paths. 40 // 41 // FIXME: It would be cool if we supported a "paged" MemoryBuffer 42 // implementation. This would allow us to implement a more sensible version of 43 // MemoryObject which can work like a MemoryBuffer, but be more efficient for 44 // objects which are in the current address space. 45 class MachOObject { 46 public: 47 struct LoadCommandInfo { 48 /// The load command information. 49 macho::LoadCommand Command; 50 51 /// The offset to the start of the load command in memory. 52 uint64_t Offset; 53 }; 54 55 private: 56 OwningPtr<MemoryBuffer> Buffer; 57 58 /// Whether the object is little endian. 59 bool IsLittleEndian; 60 /// Whether the object is 64-bit. 61 bool Is64Bit; 62 /// Whether the object is swapped endianness from the host. 63 bool IsSwappedEndian; 64 /// Whether the string table has been registered. 65 bool HasStringTable; 66 67 /// The cached information on the load commands. 68 LoadCommandInfo *LoadCommands; 69 mutable unsigned NumLoadedCommands; 70 71 /// The cached copy of the header. 72 macho::Header Header; 73 macho::Header64Ext Header64Ext; 74 75 /// Cache string table information. 76 StringRef StringTable; 77 78 private: 79 MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit); 80 81 public: 82 ~MachOObject(); 83 84 /// \brief Load a Mach-O object from a MemoryBuffer object. 85 /// 86 /// \param Buffer - The buffer to load the object from. This routine takes 87 /// exclusive ownership of the buffer (which is passed to the returned object 88 /// on success). 89 /// \param ErrorStr [out] - If given, will be set to a user readable error 90 /// message on failure. 91 /// \returns The loaded object, or null on error. 92 static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer, 93 std::string *ErrorStr = 0); 94 95 /// @name File Information 96 /// @{ 97 isLittleEndian()98 bool isLittleEndian() const { return IsLittleEndian; } isSwappedEndian()99 bool isSwappedEndian() const { return IsSwappedEndian; } is64Bit()100 bool is64Bit() const { return Is64Bit; } 101 getHeaderSize()102 unsigned getHeaderSize() const { 103 return Is64Bit ? macho::Header64Size : macho::Header32Size; 104 } 105 106 StringRef getData(size_t Offset, size_t Size) const; 107 108 /// @} 109 /// @name String Table Data 110 /// @{ 111 getStringTableData()112 StringRef getStringTableData() const { 113 assert(HasStringTable && "String table has not been registered!"); 114 return StringTable; 115 } 116 getStringAtIndex(unsigned Index)117 StringRef getStringAtIndex(unsigned Index) const { 118 size_t End = getStringTableData().find('\0', Index); 119 return getStringTableData().slice(Index, End); 120 } 121 122 void RegisterStringTable(macho::SymtabLoadCommand &SLC); 123 124 /// @} 125 /// @name Object Header Access 126 /// @{ 127 getHeader()128 const macho::Header &getHeader() const { return Header; } getHeader64Ext()129 const macho::Header64Ext &getHeader64Ext() const { 130 assert(is64Bit() && "Invalid access!"); 131 return Header64Ext; 132 } 133 134 /// @} 135 /// @name Object Structure Access 136 /// @{ 137 138 /// \brief Retrieve the information for the given load command. 139 const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; 140 141 void ReadSegmentLoadCommand( 142 const LoadCommandInfo &LCI, 143 InMemoryStruct<macho::SegmentLoadCommand> &Res) const; 144 void ReadSegment64LoadCommand( 145 const LoadCommandInfo &LCI, 146 InMemoryStruct<macho::Segment64LoadCommand> &Res) const; 147 void ReadSymtabLoadCommand( 148 const LoadCommandInfo &LCI, 149 InMemoryStruct<macho::SymtabLoadCommand> &Res) const; 150 void ReadDysymtabLoadCommand( 151 const LoadCommandInfo &LCI, 152 InMemoryStruct<macho::DysymtabLoadCommand> &Res) const; 153 void ReadLinkeditDataLoadCommand( 154 const LoadCommandInfo &LCI, 155 InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const; 156 void ReadIndirectSymbolTableEntry( 157 const macho::DysymtabLoadCommand &DLC, 158 unsigned Index, 159 InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const; 160 void ReadSection( 161 const LoadCommandInfo &LCI, 162 unsigned Index, 163 InMemoryStruct<macho::Section> &Res) const; 164 void ReadSection64( 165 const LoadCommandInfo &LCI, 166 unsigned Index, 167 InMemoryStruct<macho::Section64> &Res) const; 168 void ReadRelocationEntry( 169 uint64_t RelocationTableOffset, unsigned Index, 170 InMemoryStruct<macho::RelocationEntry> &Res) const; 171 void ReadSymbolTableEntry( 172 uint64_t SymbolTableOffset, unsigned Index, 173 InMemoryStruct<macho::SymbolTableEntry> &Res) const; 174 void ReadSymbol64TableEntry( 175 uint64_t SymbolTableOffset, unsigned Index, 176 InMemoryStruct<macho::Symbol64TableEntry> &Res) const; 177 void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; 178 179 /// @} 180 181 /// @name Object Dump Facilities 182 /// @{ 183 /// dump - Support for debugging, callable in GDB: V->dump() 184 // 185 void dump() const; 186 void dumpHeader() const; 187 188 /// print - Implement operator<< on Value. 189 /// 190 void print(raw_ostream &O) const; 191 void printHeader(raw_ostream &O) const; 192 193 /// @} 194 }; 195 196 inline raw_ostream &operator<<(raw_ostream &OS, const MachOObject &V) { 197 V.print(OS); 198 return OS; 199 } 200 201 } // end namespace object 202 } // end namespace llvm 203 204 #endif 205