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