Change relocation API to be per section.
[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 #include "llvm/ADT/SmallVector.h"
22
23 #include <cctype>
24 #include <cstring>
25 #include <limits>
26
27 using namespace llvm;
28 using namespace object;
29
30 namespace llvm {
31
32 typedef MachOObject::LoadCommandInfo LoadCommandInfo;
33
34 class MachOObjectFile : public ObjectFile {
35 public:
36   MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec);
37
38   virtual symbol_iterator begin_symbols() const;
39   virtual symbol_iterator end_symbols() const;
40   virtual section_iterator begin_sections() const;
41   virtual section_iterator end_sections() const;
42
43   virtual uint8_t getBytesInAddress() const;
44   virtual StringRef getFileFormatName() const;
45   virtual unsigned getArch() const;
46
47 protected:
48   virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
49   virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
50   virtual error_code getSymbolOffset(DataRefImpl Symb, uint64_t &Res) const;
51   virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
52   virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
53   virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
54   virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const;
55   virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const;
56   virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &Res) const;
57
58   virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
59   virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
60   virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
61   virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
62   virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
63   virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
64   virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
65   virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
66   virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S,
67                                            bool &Result) const;
68   virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
69   virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
70
71   virtual error_code getRelocationNext(DataRefImpl Rel,
72                                        RelocationRef &Res) const;
73   virtual error_code getRelocationAddress(DataRefImpl Rel,
74                                           uint64_t &Res) const;
75   virtual error_code getRelocationSymbol(DataRefImpl Rel,
76                                          SymbolRef &Res) const;
77   virtual error_code getRelocationType(DataRefImpl Rel,
78                                        uint32_t &Res) const;
79   virtual error_code getRelocationTypeName(DataRefImpl Rel,
80                                            SmallVectorImpl<char> &Result) const;
81   virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
82                                                  int64_t &Res) const;
83   virtual error_code getRelocationValueString(DataRefImpl Rel,
84                                            SmallVectorImpl<char> &Result) const;
85
86 private:
87   MachOObject *MachOObj;
88   mutable uint32_t RegisteredStringTable;
89   typedef SmallVector<DataRefImpl, 1> SectionList;
90   SectionList Sections;
91
92
93   void moveToNextSection(DataRefImpl &DRI) const;
94   void getSymbolTableEntry(DataRefImpl DRI,
95                            InMemoryStruct<macho::SymbolTableEntry> &Res) const;
96   void getSymbol64TableEntry(DataRefImpl DRI,
97                           InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
98   void moveToNextSymbol(DataRefImpl &DRI) const;
99   void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
100   void getSection64(DataRefImpl DRI,
101                     InMemoryStruct<macho::Section64> &Res) const;
102   void getRelocation(DataRefImpl Rel,
103                      InMemoryStruct<macho::RelocationEntry> &Res) const;
104   std::size_t getSectionIndex(DataRefImpl Sec) const;
105 };
106
107 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
108                                  error_code &ec)
109     : ObjectFile(Binary::isMachO, Object, ec),
110       MachOObj(MOO),
111       RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
112   DataRefImpl DRI;
113   DRI.d.a = DRI.d.b = 0;
114   moveToNextSection(DRI);
115   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
116   while (DRI.d.a < LoadCommandCount) {
117     Sections.push_back(DRI);
118     DRI.d.b++;
119     moveToNextSection(DRI);
120   }
121 }
122
123
124 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
125   error_code ec;
126   std::string Err;
127   MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
128   if (!MachOObj)
129     return NULL;
130   return new MachOObjectFile(Buffer, MachOObj, ec);
131 }
132
133 /*===-- Symbols -----------------------------------------------------------===*/
134
135 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
136   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
137   while (DRI.d.a < LoadCommandCount) {
138     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
139     if (LCI.Command.Type == macho::LCT_Symtab) {
140       InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
141       MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
142       if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
143         return;
144     }
145
146     DRI.d.a++;
147     DRI.d.b = 0;
148   }
149 }
150
151 void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
152     InMemoryStruct<macho::SymbolTableEntry> &Res) const {
153   InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
154   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
155   MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
156
157   if (RegisteredStringTable != DRI.d.a) {
158     MachOObj->RegisterStringTable(*SymtabLoadCmd);
159     RegisteredStringTable = DRI.d.a;
160   }
161
162   MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
163                                  Res);
164 }
165
166 void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
167     InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
168   InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
169   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
170   MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
171
172   if (RegisteredStringTable != DRI.d.a) {
173     MachOObj->RegisterStringTable(*SymtabLoadCmd);
174     RegisteredStringTable = DRI.d.a;
175   }
176
177   MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
178                                    Res);
179 }
180
181
182 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
183                                           SymbolRef &Result) const {
184   DRI.d.b++;
185   moveToNextSymbol(DRI);
186   Result = SymbolRef(DRI, this);
187   return object_error::success;
188 }
189
190 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
191                                           StringRef &Result) const {
192   if (MachOObj->is64Bit()) {
193     InMemoryStruct<macho::Symbol64TableEntry> Entry;
194     getSymbol64TableEntry(DRI, Entry);
195     Result = MachOObj->getStringAtIndex(Entry->StringIndex);
196   } else {
197     InMemoryStruct<macho::SymbolTableEntry> Entry;
198     getSymbolTableEntry(DRI, Entry);
199     Result = MachOObj->getStringAtIndex(Entry->StringIndex);
200   }
201   return object_error::success;
202 }
203
204 error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI,
205                                              uint64_t &Result) const {
206   if (MachOObj->is64Bit()) {
207     InMemoryStruct<macho::Symbol64TableEntry> Entry;
208     getSymbol64TableEntry(DRI, Entry);
209     Result = Entry->Value;
210   } else {
211     InMemoryStruct<macho::SymbolTableEntry> Entry;
212     getSymbolTableEntry(DRI, Entry);
213     Result = Entry->Value;
214   }
215   return object_error::success;
216 }
217
218 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
219                                              uint64_t &Result) const {
220   uint64_t SymbolOffset;
221   uint8_t SectionIndex;
222   if (MachOObj->is64Bit()) {
223     InMemoryStruct<macho::Symbol64TableEntry> Entry;
224     getSymbol64TableEntry(DRI, Entry);
225     SymbolOffset = Entry->Value;
226     SectionIndex = Entry->SectionIndex;
227   } else {
228     InMemoryStruct<macho::SymbolTableEntry> Entry;
229     getSymbolTableEntry(DRI, Entry);
230     SymbolOffset = Entry->Value;
231     SectionIndex = Entry->SectionIndex;
232   }
233   getSectionAddress(Sections[SectionIndex], Result);
234   Result += SymbolOffset;
235
236   return object_error::success;
237 }
238
239 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
240                                           uint64_t &Result) const {
241   Result = UnknownAddressOrSize;
242   return object_error::success;
243 }
244
245 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
246                                                 char &Result) const {
247   uint8_t Type, Flags;
248   if (MachOObj->is64Bit()) {
249     InMemoryStruct<macho::Symbol64TableEntry> Entry;
250     getSymbol64TableEntry(DRI, Entry);
251     Type = Entry->Type;
252     Flags = Entry->Flags;
253   } else {
254     InMemoryStruct<macho::SymbolTableEntry> Entry;
255     getSymbolTableEntry(DRI, Entry);
256     Type = Entry->Type;
257     Flags = Entry->Flags;
258   }
259
260   char Char;
261   switch (Type & macho::STF_TypeMask) {
262     case macho::STT_Undefined:
263       Char = 'u';
264       break;
265     case macho::STT_Absolute:
266     case macho::STT_Section:
267       Char = 's';
268       break;
269     default:
270       Char = '?';
271       break;
272   }
273
274   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
275     Char = toupper(Char);
276   Result = Char;
277   return object_error::success;
278 }
279
280 error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
281                                              bool &Result) const {
282   if (MachOObj->is64Bit()) {
283     InMemoryStruct<macho::Symbol64TableEntry> Entry;
284     getSymbol64TableEntry(DRI, Entry);
285     Result = Entry->Flags & macho::STF_StabsEntryMask;
286   } else {
287     InMemoryStruct<macho::SymbolTableEntry> Entry;
288     getSymbolTableEntry(DRI, Entry);
289     Result = Entry->Flags & macho::STF_StabsEntryMask;
290   }
291   return object_error::success;
292 }
293
294 error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
295
296   if (MachOObj->is64Bit()) {
297     InMemoryStruct<macho::Symbol64TableEntry> Entry;
298     getSymbol64TableEntry(Symb, Entry);
299     Res = Entry->Type & MachO::NlistMaskExternal;
300   } else {
301     InMemoryStruct<macho::SymbolTableEntry> Entry;
302     getSymbolTableEntry(Symb, Entry);
303     Res = Entry->Type & MachO::NlistMaskExternal;
304   }
305   return object_error::success;
306 }
307
308 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
309                                           SymbolRef::SymbolType &Res) const {
310   uint8_t n_type;
311   if (MachOObj->is64Bit()) {
312     InMemoryStruct<macho::Symbol64TableEntry> Entry;
313     getSymbol64TableEntry(Symb, Entry);
314     n_type = Entry->Type;
315   } else {
316     InMemoryStruct<macho::SymbolTableEntry> Entry;
317     getSymbolTableEntry(Symb, Entry);
318     n_type = Entry->Type;
319   }
320   Res = SymbolRef::ST_Other;
321   switch (n_type & MachO::NlistMaskType) {
322     case MachO::NListTypeUndefined :
323       Res = SymbolRef::ST_External;
324       break;
325     case MachO::NListTypeSection :
326       Res = SymbolRef::ST_Function;
327       break;
328   }
329   return object_error::success;
330 }
331
332
333 symbol_iterator MachOObjectFile::begin_symbols() const {
334   // DRI.d.a = segment number; DRI.d.b = symbol index.
335   DataRefImpl DRI;
336   DRI.d.a = DRI.d.b = 0;
337   moveToNextSymbol(DRI);
338   return symbol_iterator(SymbolRef(DRI, this));
339 }
340
341 symbol_iterator MachOObjectFile::end_symbols() const {
342   DataRefImpl DRI;
343   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
344   DRI.d.b = 0;
345   return symbol_iterator(SymbolRef(DRI, this));
346 }
347
348
349 /*===-- Sections ----------------------------------------------------------===*/
350
351 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
352   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
353   while (DRI.d.a < LoadCommandCount) {
354     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
355     if (LCI.Command.Type == macho::LCT_Segment) {
356       InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
357       MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
358       if (DRI.d.b < SegmentLoadCmd->NumSections)
359         return;
360     } else if (LCI.Command.Type == macho::LCT_Segment64) {
361       InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
362       MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
363       if (DRI.d.b < Segment64LoadCmd->NumSections)
364         return;
365     }
366
367     DRI.d.a++;
368     DRI.d.b = 0;
369   }
370 }
371
372 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
373                                            SectionRef &Result) const {
374   DRI.d.b++;
375   moveToNextSection(DRI);
376   Result = SectionRef(DRI, this);
377   return object_error::success;
378 }
379
380 void
381 MachOObjectFile::getSection(DataRefImpl DRI,
382                             InMemoryStruct<macho::Section> &Res) const {
383   InMemoryStruct<macho::SegmentLoadCommand> SLC;
384   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
385   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
386   MachOObj->ReadSection(LCI, DRI.d.b, Res);
387 }
388
389 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
390   SectionList::const_iterator loc =
391     std::find(Sections.begin(), Sections.end(), Sec);
392   assert(loc != Sections.end() && "Sec is not a valid section!");
393   return std::distance(Sections.begin(), loc);
394 }
395
396 void
397 MachOObjectFile::getSection64(DataRefImpl DRI,
398                             InMemoryStruct<macho::Section64> &Res) const {
399   InMemoryStruct<macho::Segment64LoadCommand> SLC;
400   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
401   MachOObj->ReadSegment64LoadCommand(LCI, SLC);
402   MachOObj->ReadSection64(LCI, DRI.d.b, Res);
403 }
404
405 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
406   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
407   if (LCI.Command.Type == macho::LCT_Segment64)
408     return true;
409   assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
410   return false;
411 }
412
413 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
414                                            StringRef &Result) const {
415   // FIXME: thread safety.
416   static char result[34];
417   if (is64BitLoadCommand(MachOObj, DRI)) {
418     InMemoryStruct<macho::Segment64LoadCommand> SLC;
419     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
420     MachOObj->ReadSegment64LoadCommand(LCI, SLC);
421     InMemoryStruct<macho::Section64> Sect;
422     MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
423
424     strcpy(result, Sect->SegmentName);
425     strcat(result, ",");
426     strcat(result, Sect->Name);
427   } else {
428     InMemoryStruct<macho::SegmentLoadCommand> SLC;
429     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
430     MachOObj->ReadSegmentLoadCommand(LCI, SLC);
431     InMemoryStruct<macho::Section> Sect;
432     MachOObj->ReadSection(LCI, DRI.d.b, Sect);
433
434     strcpy(result, Sect->SegmentName);
435     strcat(result, ",");
436     strcat(result, Sect->Name);
437   }
438   Result = StringRef(result);
439   return object_error::success;
440 }
441
442 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
443                                               uint64_t &Result) const {
444   if (is64BitLoadCommand(MachOObj, DRI)) {
445     InMemoryStruct<macho::Section64> Sect;
446     getSection64(DRI, Sect);
447     Result = Sect->Address;
448   } else {
449     InMemoryStruct<macho::Section> Sect;
450     getSection(DRI, Sect);
451     Result = Sect->Address;
452   }
453   return object_error::success;
454 }
455
456 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
457                                            uint64_t &Result) const {
458   if (is64BitLoadCommand(MachOObj, DRI)) {
459     InMemoryStruct<macho::Section64> Sect;
460     getSection64(DRI, Sect);
461     Result = Sect->Size;
462   } else {
463     InMemoryStruct<macho::Section> Sect;
464     getSection(DRI, Sect);
465     Result = Sect->Size;
466   }
467   return object_error::success;
468 }
469
470 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
471                                                StringRef &Result) const {
472   if (is64BitLoadCommand(MachOObj, DRI)) {
473     InMemoryStruct<macho::Section64> Sect;
474     getSection64(DRI, Sect);
475     Result = MachOObj->getData(Sect->Offset, Sect->Size);
476   } else {
477     InMemoryStruct<macho::Section> Sect;
478     getSection(DRI, Sect);
479     Result = MachOObj->getData(Sect->Offset, Sect->Size);
480   }
481   return object_error::success;
482 }
483
484 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
485                                           bool &Result) const {
486   if (is64BitLoadCommand(MachOObj, DRI)) {
487     InMemoryStruct<macho::Section64> Sect;
488     getSection64(DRI, Sect);
489     Result = !strcmp(Sect->Name, "__text");
490   } else {
491     InMemoryStruct<macho::Section> Sect;
492     getSection(DRI, Sect);
493     Result = !strcmp(Sect->Name, "__text");
494   }
495   return object_error::success;
496 }
497
498 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
499                                           bool &Result) const {
500   // FIXME: Unimplemented.
501   Result = false;
502   return object_error::success;
503 }
504
505 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
506                                          bool &Result) const {
507   // FIXME: Unimplemented.
508   Result = false;
509   return object_error::success;
510 }
511
512 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
513                                                   DataRefImpl Symb,
514                                                   bool &Result) const {
515   if (MachOObj->is64Bit()) {
516     InMemoryStruct<macho::Symbol64TableEntry> Entry;
517     getSymbol64TableEntry(Symb, Entry);
518     Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
519   } else {
520     InMemoryStruct<macho::SymbolTableEntry> Entry;
521     getSymbolTableEntry(Symb, Entry);
522     Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
523   }
524   return object_error::success;
525 }
526
527 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
528   DataRefImpl ret;
529   ret.d.a = 0;
530   ret.d.b = getSectionIndex(Sec);
531   return relocation_iterator(RelocationRef(ret, this));
532 }
533 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
534   uint32_t last_reloc;
535   if (is64BitLoadCommand(MachOObj, Sec)) {
536     InMemoryStruct<macho::Section64> Sect;
537     getSection64(Sec, Sect);
538     last_reloc = Sect->NumRelocationTableEntries;
539   } else {
540     InMemoryStruct<macho::Section> Sect;
541     getSection(Sec, Sect);
542     last_reloc = Sect->NumRelocationTableEntries;
543   }
544   DataRefImpl ret;
545   ret.d.a = last_reloc;
546   ret.d.b = getSectionIndex(Sec);
547   return relocation_iterator(RelocationRef(ret, this));
548 }
549
550 section_iterator MachOObjectFile::begin_sections() const {
551   DataRefImpl DRI;
552   DRI.d.a = DRI.d.b = 0;
553   moveToNextSection(DRI);
554   return section_iterator(SectionRef(DRI, this));
555 }
556
557 section_iterator MachOObjectFile::end_sections() const {
558   DataRefImpl DRI;
559   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
560   DRI.d.b = 0;
561   return section_iterator(SectionRef(DRI, this));
562 }
563
564 /*===-- Relocations -------------------------------------------------------===*/
565
566 void MachOObjectFile::
567 getRelocation(DataRefImpl Rel,
568               InMemoryStruct<macho::RelocationEntry> &Res) const {
569   uint32_t relOffset;
570   if (MachOObj->is64Bit()) {
571     InMemoryStruct<macho::Section64> Sect;
572     getSection64(Sections[Rel.d.b], Sect);
573     relOffset = Sect->RelocationTableOffset;
574   } else {
575     InMemoryStruct<macho::Section> Sect;
576     getSection(Sections[Rel.d.b], Sect);
577     relOffset = Sect->RelocationTableOffset;
578   }
579   MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
580 }
581 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
582                                               RelocationRef &Res) const {
583   ++Rel.d.a;
584   Res = RelocationRef(Rel, this);
585   return object_error::success;
586 }
587 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
588                                                  uint64_t &Res) const {
589   const uint8_t* sectAddress = base();
590   if (MachOObj->is64Bit()) {
591     InMemoryStruct<macho::Section64> Sect;
592     getSection64(Sections[Rel.d.b], Sect);
593     sectAddress += Sect->Offset;
594   } else {
595     InMemoryStruct<macho::Section> Sect;
596     getSection(Sections[Rel.d.b], Sect);
597     sectAddress += Sect->Offset;
598   }
599   InMemoryStruct<macho::RelocationEntry> RE;
600   getRelocation(Rel, RE);
601   Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
602   return object_error::success;
603 }
604 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
605                                                 SymbolRef &Res) const {
606   InMemoryStruct<macho::RelocationEntry> RE;
607   getRelocation(Rel, RE);
608   uint32_t SymbolIdx = RE->Word1 & 0xffffff;
609   bool isExtern = (RE->Word1 >> 27) & 1;
610
611   DataRefImpl Sym;
612   Sym.d.a = Sym.d.b = 0;
613   moveToNextSymbol(Sym);
614   if (isExtern) {
615     for (unsigned i = 0; i < SymbolIdx; i++) {
616       Sym.d.b++;
617       moveToNextSymbol(Sym);
618       assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
619              "Relocation symbol index out of range!");
620     }
621   }
622   Res = SymbolRef(Sym, this);
623   return object_error::success;
624 }
625 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
626                                               uint32_t &Res) const {
627   InMemoryStruct<macho::RelocationEntry> RE;
628   getRelocation(Rel, RE);
629   Res = RE->Word1;
630   return object_error::success;
631 }
632 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
633                                           SmallVectorImpl<char> &Result) const {
634   return object_error::success;
635 }
636 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
637                                                         int64_t &Res) const {
638   InMemoryStruct<macho::RelocationEntry> RE;
639   getRelocation(Rel, RE);
640   bool isExtern = (RE->Word1 >> 27) & 1;
641   Res = 0;
642   if (!isExtern) {
643     const uint8_t* sectAddress = base();
644     if (MachOObj->is64Bit()) {
645       InMemoryStruct<macho::Section64> Sect;
646       getSection64(Sections[Rel.d.b], Sect);
647       sectAddress += Sect->Offset;
648     } else {
649       InMemoryStruct<macho::Section> Sect;
650       getSection(Sections[Rel.d.b], Sect);
651       sectAddress += Sect->Offset;
652     }
653     Res = reinterpret_cast<uintptr_t>(sectAddress);
654   }
655   return object_error::success;
656 }
657 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
658                                           SmallVectorImpl<char> &Result) const {
659   return object_error::success;
660 }
661
662 /*===-- Miscellaneous -----------------------------------------------------===*/
663
664 uint8_t MachOObjectFile::getBytesInAddress() const {
665   return MachOObj->is64Bit() ? 8 : 4;
666 }
667
668 StringRef MachOObjectFile::getFileFormatName() const {
669   if (!MachOObj->is64Bit()) {
670     switch (MachOObj->getHeader().CPUType) {
671     case llvm::MachO::CPUTypeI386:
672       return "Mach-O 32-bit i386";
673     case llvm::MachO::CPUTypeARM:
674       return "Mach-O arm";
675     case llvm::MachO::CPUTypePowerPC:
676       return "Mach-O 32-bit ppc";
677     default:
678       assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
679              "64-bit object file when we're not 64-bit?");
680       return "Mach-O 32-bit unknown";
681     }
682   }
683
684   switch (MachOObj->getHeader().CPUType) {
685   case llvm::MachO::CPUTypeX86_64:
686     return "Mach-O 64-bit x86-64";
687   case llvm::MachO::CPUTypePowerPC64:
688     return "Mach-O 64-bit ppc64";
689   default:
690     assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
691            "32-bit object file when we're 64-bit?");
692     return "Mach-O 64-bit unknown";
693   }
694 }
695
696 unsigned MachOObjectFile::getArch() const {
697   switch (MachOObj->getHeader().CPUType) {
698   case llvm::MachO::CPUTypeI386:
699     return Triple::x86;
700   case llvm::MachO::CPUTypeX86_64:
701     return Triple::x86_64;
702   case llvm::MachO::CPUTypeARM:
703     return Triple::arm;
704   case llvm::MachO::CPUTypePowerPC:
705     return Triple::ppc;
706   case llvm::MachO::CPUTypePowerPC64:
707     return Triple::ppc64;
708   default:
709     return Triple::UnknownArch;
710   }
711 }
712
713 } // end namespace llvm