Make Binary the parent of ObjectFile and update children to new interface.
[oota-llvm.git] / lib / Object / MachOObjectFile.cpp
1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- 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 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/Object/MachOFormat.h"
17 #include "llvm/Object/MachOObject.h"
18 #include "llvm/Object/ObjectFile.h"
19 #include "llvm/Support/MemoryBuffer.h"
20 #include "llvm/Support/MachO.h"
21
22 #include <cctype>
23 #include <cstring>
24 #include <limits>
25
26 using namespace llvm;
27 using namespace object;
28
29 namespace llvm {
30
31 typedef MachOObject::LoadCommandInfo LoadCommandInfo;
32
33 class MachOObjectFile : public ObjectFile {
34 public:
35   MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec)
36     : ObjectFile(Binary::isMachO, Object, ec),
37       MachOObj(MOO),
38       RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {}
39
40   virtual symbol_iterator begin_symbols() const;
41   virtual symbol_iterator end_symbols() const;
42   virtual section_iterator begin_sections() const;
43   virtual section_iterator end_sections() const;
44
45   virtual uint8_t getBytesInAddress() const;
46   virtual StringRef getFileFormatName() const;
47   virtual unsigned getArch() const;
48
49 protected:
50   virtual SymbolRef getSymbolNext(DataRefImpl Symb) const;
51   virtual StringRef getSymbolName(DataRefImpl Symb) const;
52   virtual uint64_t  getSymbolAddress(DataRefImpl Symb) const;
53   virtual uint64_t  getSymbolSize(DataRefImpl Symb) const;
54   virtual char      getSymbolNMTypeChar(DataRefImpl Symb) const;
55   virtual bool      isSymbolInternal(DataRefImpl Symb) const;
56
57   virtual SectionRef getSectionNext(DataRefImpl Sec) const;
58   virtual StringRef  getSectionName(DataRefImpl Sec) const;
59   virtual uint64_t   getSectionAddress(DataRefImpl Sec) const;
60   virtual uint64_t   getSectionSize(DataRefImpl Sec) const;
61   virtual StringRef  getSectionContents(DataRefImpl Sec) const;
62   virtual bool       isSectionText(DataRefImpl Sec) const;
63
64 private:
65   MachOObject *MachOObj;
66   mutable uint32_t RegisteredStringTable;
67
68   void moveToNextSection(DataRefImpl &DRI) const;
69   void getSymbolTableEntry(DataRefImpl DRI,
70                            InMemoryStruct<macho::SymbolTableEntry> &Res) const;
71   void moveToNextSymbol(DataRefImpl &DRI) const;
72   void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
73 };
74
75 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
76   error_code ec;
77   std::string Err;
78   MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
79   if (!MachOObj)
80     return NULL;
81   return new MachOObjectFile(Buffer, MachOObj, ec);
82 }
83
84 /*===-- Symbols -----------------------------------------------------------===*/
85
86 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
87   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
88   while (DRI.d.a < LoadCommandCount) {
89     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
90     if (LCI.Command.Type == macho::LCT_Symtab) {
91       InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
92       MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
93       if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
94         return;
95     }
96
97     DRI.d.a++;
98     DRI.d.b = 0;
99   }
100 }
101
102 void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
103     InMemoryStruct<macho::SymbolTableEntry> &Res) const {
104   InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
105   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
106   MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
107
108   if (RegisteredStringTable != DRI.d.a) {
109     MachOObj->RegisterStringTable(*SymtabLoadCmd);
110     RegisteredStringTable = DRI.d.a;
111   }
112
113   MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
114                                  Res);
115 }
116
117
118 SymbolRef MachOObjectFile::getSymbolNext(DataRefImpl DRI) const {
119   DRI.d.b++;
120   moveToNextSymbol(DRI);
121   return SymbolRef(DRI, this);
122 }
123
124 StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const {
125   InMemoryStruct<macho::SymbolTableEntry> Entry;
126   getSymbolTableEntry(DRI, Entry);
127   return MachOObj->getStringAtIndex(Entry->StringIndex);
128 }
129
130 uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const {
131   InMemoryStruct<macho::SymbolTableEntry> Entry;
132   getSymbolTableEntry(DRI, Entry);
133   return Entry->Value;
134 }
135
136 uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
137   return UnknownAddressOrSize;
138 }
139
140 char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const {
141   InMemoryStruct<macho::SymbolTableEntry> Entry;
142   getSymbolTableEntry(DRI, Entry);
143
144   char Char;
145   switch (Entry->Type & macho::STF_TypeMask) {
146     case macho::STT_Undefined:
147       Char = 'u';
148       break;
149     case macho::STT_Absolute:
150     case macho::STT_Section:
151       Char = 's';
152       break;
153     default:
154       Char = '?';
155       break;
156   }
157
158   if (Entry->Flags & (macho::STF_External | macho::STF_PrivateExtern))
159     Char = toupper(Char);
160   return Char;
161 }
162
163 bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const {
164   InMemoryStruct<macho::SymbolTableEntry> Entry;
165   getSymbolTableEntry(DRI, Entry);
166   return Entry->Flags & macho::STF_StabsEntryMask;
167 }
168
169 ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const {
170   // DRI.d.a = segment number; DRI.d.b = symbol index.
171   DataRefImpl DRI;
172   DRI.d.a = DRI.d.b = 0;
173   moveToNextSymbol(DRI);
174   return symbol_iterator(SymbolRef(DRI, this));
175 }
176
177 ObjectFile::symbol_iterator MachOObjectFile::end_symbols() const {
178   DataRefImpl DRI;
179   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
180   DRI.d.b = 0;
181   return symbol_iterator(SymbolRef(DRI, this));
182 }
183
184
185 /*===-- Sections ----------------------------------------------------------===*/
186
187 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
188   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
189   while (DRI.d.a < LoadCommandCount) {
190     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
191     if (LCI.Command.Type == macho::LCT_Segment) {
192       InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
193       MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
194       if (DRI.d.b < SegmentLoadCmd->NumSections)
195         return;
196     } else if (LCI.Command.Type == macho::LCT_Segment64) {
197       InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
198       MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
199       if (DRI.d.b < Segment64LoadCmd->NumSections)
200         return;
201     }
202
203     DRI.d.a++;
204     DRI.d.b = 0;
205   }
206 }
207
208 SectionRef MachOObjectFile::getSectionNext(DataRefImpl DRI) const {
209   DRI.d.b++;
210   moveToNextSection(DRI);
211   return SectionRef(DRI, this);
212 }
213
214 void
215 MachOObjectFile::getSection(DataRefImpl DRI,
216                             InMemoryStruct<macho::Section> &Res) const {
217   InMemoryStruct<macho::SegmentLoadCommand> SLC;
218   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
219   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
220   MachOObj->ReadSection(LCI, DRI.d.b, Res);
221 }
222
223 StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const {
224   InMemoryStruct<macho::SegmentLoadCommand> SLC;
225   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
226   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
227   InMemoryStruct<macho::Section> Sect;
228   MachOObj->ReadSection(LCI, DRI.d.b, Sect);
229
230   static char Result[34];
231   strcpy(Result, SLC->Name);
232   strcat(Result, ",");
233   strcat(Result, Sect->Name);
234   return StringRef(Result);
235 }
236
237 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const {
238   InMemoryStruct<macho::Section> Sect;
239   getSection(DRI, Sect);
240   return Sect->Address;
241 }
242
243 uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const {
244   InMemoryStruct<macho::Section> Sect;
245   getSection(DRI, Sect);
246   return Sect->Size;
247 }
248
249 StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const {
250   InMemoryStruct<macho::Section> Sect;
251   getSection(DRI, Sect);
252   return MachOObj->getData(Sect->Offset, Sect->Size);
253 }
254
255 bool MachOObjectFile::isSectionText(DataRefImpl DRI) const {
256   InMemoryStruct<macho::SegmentLoadCommand> SLC;
257   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
258   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
259   return !strcmp(SLC->Name, "__TEXT");
260 }
261
262 ObjectFile::section_iterator MachOObjectFile::begin_sections() const {
263   DataRefImpl DRI;
264   DRI.d.a = DRI.d.b = 0;
265   moveToNextSection(DRI);
266   return section_iterator(SectionRef(DRI, this));
267 }
268
269 ObjectFile::section_iterator MachOObjectFile::end_sections() const {
270   DataRefImpl DRI;
271   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
272   DRI.d.b = 0;
273   return section_iterator(SectionRef(DRI, this));
274 }
275
276 /*===-- Miscellaneous -----------------------------------------------------===*/
277
278 uint8_t MachOObjectFile::getBytesInAddress() const {
279   return MachOObj->is64Bit() ? 8 : 4;
280 }
281
282 StringRef MachOObjectFile::getFileFormatName() const {
283   if (!MachOObj->is64Bit()) {
284     switch (MachOObj->getHeader().CPUType) {
285     case llvm::MachO::CPUTypeI386:
286       return "Mach-O 32-bit i386";
287     case llvm::MachO::CPUTypeARM:
288       return "Mach-O arm";
289     case llvm::MachO::CPUTypePowerPC:
290       return "Mach-O 32-bit ppc";
291     default:
292       assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
293              "64-bit object file when we're not 64-bit?");
294       return "Mach-O 32-bit unknown";
295     }
296   }
297
298   switch (MachOObj->getHeader().CPUType) {
299   case llvm::MachO::CPUTypeX86_64:
300     return "Mach-O 64-bit x86-64";
301   case llvm::MachO::CPUTypePowerPC64:
302     return "Mach-O 64-bit ppc64";
303   default:
304     assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
305            "32-bit object file when we're 64-bit?");
306     return "Mach-O 64-bit unknown";
307   }
308 }
309
310 unsigned MachOObjectFile::getArch() const {
311   switch (MachOObj->getHeader().CPUType) {
312   case llvm::MachO::CPUTypeI386:
313     return Triple::x86;
314   case llvm::MachO::CPUTypeX86_64:
315     return Triple::x86_64;
316   case llvm::MachO::CPUTypeARM:
317     return Triple::arm;
318   case llvm::MachO::CPUTypePowerPC:
319     return Triple::ppc;
320   case llvm::MachO::CPUTypePowerPC64:
321     return Triple::ppc64;
322   default:
323     return Triple::UnknownArch;
324   }
325 }
326
327 } // end namespace llvm
328