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 "llvm/ADT/InMemoryStruct.h" 14 #include "llvm/ADT/OwningPtr.h" 15 #include "llvm/ADT/StringRef.h" 16 #include "llvm/Object/MachOFormat.h" 17 #include <string> 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 98 bool isLittleEndian() const { return IsLittleEndian; } 99 bool isSwappedEndian() const { return IsSwappedEndian; } 100 bool is64Bit() const { return Is64Bit; } 101 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 112 StringRef getStringTableData() const { 113 assert(HasStringTable && "String table has not been registered!"); 114 return StringTable; 115 } 116 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 128 const macho::Header &getHeader() const { return Header; } 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 ReadLinkerOptionsLoadCommand( 157 const LoadCommandInfo &LCI, 158 InMemoryStruct<macho::LinkerOptionsLoadCommand> &Res) const; 159 void ReadIndirectSymbolTableEntry( 160 const macho::DysymtabLoadCommand &DLC, 161 unsigned Index, 162 InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const; 163 void ReadSection( 164 const LoadCommandInfo &LCI, 165 unsigned Index, 166 InMemoryStruct<macho::Section> &Res) const; 167 void ReadSection64( 168 const LoadCommandInfo &LCI, 169 unsigned Index, 170 InMemoryStruct<macho::Section64> &Res) const; 171 void ReadRelocationEntry( 172 uint64_t RelocationTableOffset, unsigned Index, 173 InMemoryStruct<macho::RelocationEntry> &Res) const; 174 void ReadSymbolTableEntry( 175 uint64_t SymbolTableOffset, unsigned Index, 176 InMemoryStruct<macho::SymbolTableEntry> &Res) const; 177 void ReadSymbol64TableEntry( 178 uint64_t SymbolTableOffset, unsigned Index, 179 InMemoryStruct<macho::Symbol64TableEntry> &Res) const; 180 void ReadDataInCodeTableEntry( 181 uint64_t TableOffset, unsigned Index, 182 InMemoryStruct<macho::DataInCodeTableEntry> &Res) const; 183 void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; 184 185 /// @} 186 187 /// @name Object Dump Facilities 188 /// @{ 189 /// dump - Support for debugging, callable in GDB: V->dump() 190 // 191 void dump() const; 192 void dumpHeader() const; 193 194 /// print - Implement operator<< on Value. 195 /// 196 void print(raw_ostream &O) const; 197 void printHeader(raw_ostream &O) const; 198 199 /// @} 200 }; 201 202 inline raw_ostream &operator<<(raw_ostream &OS, const MachOObject &V) { 203 V.print(OS); 204 return OS; 205 } 206 207 } // end namespace object 208 } // end namespace llvm 209 210 #endif 211