• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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