Object: Add isSymbolWeak.
[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::getSymbolType(DataRefImpl Symb,
246                                           SymbolRef::Type &Res) const {
247   uint8_t n_type;
248   if (MachOObj->is64Bit()) {
249     InMemoryStruct<macho::Symbol64TableEntry> Entry;
250     getSymbol64TableEntry(Symb, Entry);
251     n_type = Entry->Type;
252   } else {
253     InMemoryStruct<macho::SymbolTableEntry> Entry;
254     getSymbolTableEntry(Symb, Entry);
255     n_type = Entry->Type;
256   }
257   Res = SymbolRef::ST_Other;
258
259   // If this is a STAB debugging symbol, we can do nothing more.
260   if (n_type & MachO::NlistMaskStab)
261     return object_error::success;
262
263   switch (n_type & MachO::NlistMaskType) {
264     case MachO::NListTypeUndefined :
265       Res = SymbolRef::ST_External;
266       break;
267     case MachO::NListTypeSection :
268       Res = SymbolRef::ST_Function;
269       break;
270   }
271   return object_error::success;
272 }
273
274
275 symbol_iterator MachOObjectFile::begin_symbols() const {
276   // DRI.d.a = segment number; DRI.d.b = symbol index.
277   DataRefImpl DRI;
278   DRI.d.a = DRI.d.b = 0;
279   moveToNextSymbol(DRI);
280   return symbol_iterator(SymbolRef(DRI, this));
281 }
282
283 symbol_iterator MachOObjectFile::end_symbols() const {
284   DataRefImpl DRI;
285   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
286   DRI.d.b = 0;
287   return symbol_iterator(SymbolRef(DRI, this));
288 }
289
290
291 /*===-- Sections ----------------------------------------------------------===*/
292
293 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
294   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
295   while (DRI.d.a < LoadCommandCount) {
296     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
297     if (LCI.Command.Type == macho::LCT_Segment) {
298       InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
299       MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
300       if (DRI.d.b < SegmentLoadCmd->NumSections)
301         return;
302     } else if (LCI.Command.Type == macho::LCT_Segment64) {
303       InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
304       MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
305       if (DRI.d.b < Segment64LoadCmd->NumSections)
306         return;
307     }
308
309     DRI.d.a++;
310     DRI.d.b = 0;
311   }
312 }
313
314 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
315                                            SectionRef &Result) const {
316   DRI.d.b++;
317   moveToNextSection(DRI);
318   Result = SectionRef(DRI, this);
319   return object_error::success;
320 }
321
322 void
323 MachOObjectFile::getSection(DataRefImpl DRI,
324                             InMemoryStruct<macho::Section> &Res) const {
325   InMemoryStruct<macho::SegmentLoadCommand> SLC;
326   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
327   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
328   MachOObj->ReadSection(LCI, DRI.d.b, Res);
329 }
330
331 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
332   SectionList::const_iterator loc =
333     std::find(Sections.begin(), Sections.end(), Sec);
334   assert(loc != Sections.end() && "Sec is not a valid section!");
335   return std::distance(Sections.begin(), loc);
336 }
337
338 void
339 MachOObjectFile::getSection64(DataRefImpl DRI,
340                             InMemoryStruct<macho::Section64> &Res) const {
341   InMemoryStruct<macho::Segment64LoadCommand> SLC;
342   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
343   MachOObj->ReadSegment64LoadCommand(LCI, SLC);
344   MachOObj->ReadSection64(LCI, DRI.d.b, Res);
345 }
346
347 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
348   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
349   if (LCI.Command.Type == macho::LCT_Segment64)
350     return true;
351   assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
352   return false;
353 }
354
355 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
356                                            StringRef &Result) const {
357   // FIXME: thread safety.
358   static char result[34];
359   if (is64BitLoadCommand(MachOObj, DRI)) {
360     InMemoryStruct<macho::Segment64LoadCommand> SLC;
361     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
362     MachOObj->ReadSegment64LoadCommand(LCI, SLC);
363     InMemoryStruct<macho::Section64> Sect;
364     MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
365
366     strcpy(result, Sect->SegmentName);
367     strcat(result, ",");
368     strcat(result, Sect->Name);
369   } else {
370     InMemoryStruct<macho::SegmentLoadCommand> SLC;
371     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
372     MachOObj->ReadSegmentLoadCommand(LCI, SLC);
373     InMemoryStruct<macho::Section> Sect;
374     MachOObj->ReadSection(LCI, DRI.d.b, Sect);
375
376     strcpy(result, Sect->SegmentName);
377     strcat(result, ",");
378     strcat(result, Sect->Name);
379   }
380   Result = StringRef(result);
381   return object_error::success;
382 }
383
384 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
385                                               uint64_t &Result) const {
386   if (is64BitLoadCommand(MachOObj, DRI)) {
387     InMemoryStruct<macho::Section64> Sect;
388     getSection64(DRI, Sect);
389     Result = Sect->Address;
390   } else {
391     InMemoryStruct<macho::Section> Sect;
392     getSection(DRI, Sect);
393     Result = Sect->Address;
394   }
395   return object_error::success;
396 }
397
398 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
399                                            uint64_t &Result) const {
400   if (is64BitLoadCommand(MachOObj, DRI)) {
401     InMemoryStruct<macho::Section64> Sect;
402     getSection64(DRI, Sect);
403     Result = Sect->Size;
404   } else {
405     InMemoryStruct<macho::Section> Sect;
406     getSection(DRI, Sect);
407     Result = Sect->Size;
408   }
409   return object_error::success;
410 }
411
412 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
413                                                StringRef &Result) const {
414   if (is64BitLoadCommand(MachOObj, DRI)) {
415     InMemoryStruct<macho::Section64> Sect;
416     getSection64(DRI, Sect);
417     Result = MachOObj->getData(Sect->Offset, Sect->Size);
418   } else {
419     InMemoryStruct<macho::Section> Sect;
420     getSection(DRI, Sect);
421     Result = MachOObj->getData(Sect->Offset, Sect->Size);
422   }
423   return object_error::success;
424 }
425
426 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
427                                                 uint64_t &Result) const {
428   if (is64BitLoadCommand(MachOObj, DRI)) {
429     InMemoryStruct<macho::Section64> Sect;
430     getSection64(DRI, Sect);
431     Result = uint64_t(1) << Sect->Align;
432   } else {
433     InMemoryStruct<macho::Section> Sect;
434     getSection(DRI, Sect);
435     Result = uint64_t(1) << Sect->Align;
436   }
437   return object_error::success;
438 }
439
440 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
441                                           bool &Result) const {
442   if (is64BitLoadCommand(MachOObj, DRI)) {
443     InMemoryStruct<macho::Section64> Sect;
444     getSection64(DRI, Sect);
445     Result = !strcmp(Sect->Name, "__text");
446   } else {
447     InMemoryStruct<macho::Section> Sect;
448     getSection(DRI, Sect);
449     Result = !strcmp(Sect->Name, "__text");
450   }
451   return object_error::success;
452 }
453
454 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
455                                           bool &Result) const {
456   // FIXME: Unimplemented.
457   Result = false;
458   return object_error::success;
459 }
460
461 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
462                                          bool &Result) const {
463   // FIXME: Unimplemented.
464   Result = false;
465   return object_error::success;
466 }
467
468 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
469                                                   DataRefImpl Symb,
470                                                   bool &Result) const {
471   SymbolRef::Type ST;
472   getSymbolType(Symb, ST);
473   if (ST == SymbolRef::ST_External) {
474     Result = false;
475     return object_error::success;
476   }
477
478   uint64_t SectBegin, SectEnd;
479   getSectionAddress(Sec, SectBegin);
480   getSectionSize(Sec, SectEnd);
481   SectEnd += SectBegin;
482
483   if (MachOObj->is64Bit()) {
484     InMemoryStruct<macho::Symbol64TableEntry> Entry;
485     getSymbol64TableEntry(Symb, Entry);
486     uint64_t SymAddr= Entry->Value;
487     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
488   } else {
489     InMemoryStruct<macho::SymbolTableEntry> Entry;
490     getSymbolTableEntry(Symb, Entry);
491     uint64_t SymAddr= Entry->Value;
492     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
493   }
494
495   return object_error::success;
496 }
497
498 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
499   DataRefImpl ret;
500   ret.d.a = 0;
501   ret.d.b = getSectionIndex(Sec);
502   return relocation_iterator(RelocationRef(ret, this));
503 }
504 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
505   uint32_t last_reloc;
506   if (is64BitLoadCommand(MachOObj, Sec)) {
507     InMemoryStruct<macho::Section64> Sect;
508     getSection64(Sec, Sect);
509     last_reloc = Sect->NumRelocationTableEntries;
510   } else {
511     InMemoryStruct<macho::Section> Sect;
512     getSection(Sec, Sect);
513     last_reloc = Sect->NumRelocationTableEntries;
514   }
515   DataRefImpl ret;
516   ret.d.a = last_reloc;
517   ret.d.b = getSectionIndex(Sec);
518   return relocation_iterator(RelocationRef(ret, this));
519 }
520
521 section_iterator MachOObjectFile::begin_sections() const {
522   DataRefImpl DRI;
523   DRI.d.a = DRI.d.b = 0;
524   moveToNextSection(DRI);
525   return section_iterator(SectionRef(DRI, this));
526 }
527
528 section_iterator MachOObjectFile::end_sections() const {
529   DataRefImpl DRI;
530   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
531   DRI.d.b = 0;
532   return section_iterator(SectionRef(DRI, this));
533 }
534
535 /*===-- Relocations -------------------------------------------------------===*/
536
537 void MachOObjectFile::
538 getRelocation(DataRefImpl Rel,
539               InMemoryStruct<macho::RelocationEntry> &Res) const {
540   uint32_t relOffset;
541   if (MachOObj->is64Bit()) {
542     InMemoryStruct<macho::Section64> Sect;
543     getSection64(Sections[Rel.d.b], Sect);
544     relOffset = Sect->RelocationTableOffset;
545   } else {
546     InMemoryStruct<macho::Section> Sect;
547     getSection(Sections[Rel.d.b], Sect);
548     relOffset = Sect->RelocationTableOffset;
549   }
550   MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
551 }
552 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
553                                               RelocationRef &Res) const {
554   ++Rel.d.a;
555   Res = RelocationRef(Rel, this);
556   return object_error::success;
557 }
558 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
559                                                  uint64_t &Res) const {
560   const uint8_t* sectAddress = base();
561   if (MachOObj->is64Bit()) {
562     InMemoryStruct<macho::Section64> Sect;
563     getSection64(Sections[Rel.d.b], Sect);
564     sectAddress += Sect->Offset;
565   } else {
566     InMemoryStruct<macho::Section> Sect;
567     getSection(Sections[Rel.d.b], Sect);
568     sectAddress += Sect->Offset;
569   }
570   InMemoryStruct<macho::RelocationEntry> RE;
571   getRelocation(Rel, RE);
572   Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
573   return object_error::success;
574 }
575 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
576                                                 SymbolRef &Res) const {
577   InMemoryStruct<macho::RelocationEntry> RE;
578   getRelocation(Rel, RE);
579   uint32_t SymbolIdx = RE->Word1 & 0xffffff;
580   bool isExtern = (RE->Word1 >> 27) & 1;
581
582   DataRefImpl Sym;
583   Sym.d.a = Sym.d.b = 0;
584   moveToNextSymbol(Sym);
585   if (isExtern) {
586     for (unsigned i = 0; i < SymbolIdx; i++) {
587       Sym.d.b++;
588       moveToNextSymbol(Sym);
589       assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
590              "Relocation symbol index out of range!");
591     }
592   }
593   Res = SymbolRef(Sym, this);
594   return object_error::success;
595 }
596 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
597                                               uint32_t &Res) const {
598   InMemoryStruct<macho::RelocationEntry> RE;
599   getRelocation(Rel, RE);
600   Res = RE->Word1;
601   return object_error::success;
602 }
603 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
604                                           SmallVectorImpl<char> &Result) const {
605   return object_error::success;
606 }
607 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
608                                                         int64_t &Res) const {
609   InMemoryStruct<macho::RelocationEntry> RE;
610   getRelocation(Rel, RE);
611   bool isExtern = (RE->Word1 >> 27) & 1;
612   Res = 0;
613   if (!isExtern) {
614     const uint8_t* sectAddress = base();
615     if (MachOObj->is64Bit()) {
616       InMemoryStruct<macho::Section64> Sect;
617       getSection64(Sections[Rel.d.b], Sect);
618       sectAddress += Sect->Offset;
619     } else {
620       InMemoryStruct<macho::Section> Sect;
621       getSection(Sections[Rel.d.b], Sect);
622       sectAddress += Sect->Offset;
623     }
624     Res = reinterpret_cast<uintptr_t>(sectAddress);
625   }
626   return object_error::success;
627 }
628 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
629                                           SmallVectorImpl<char> &Result) const {
630   return object_error::success;
631 }
632
633 /*===-- Miscellaneous -----------------------------------------------------===*/
634
635 uint8_t MachOObjectFile::getBytesInAddress() const {
636   return MachOObj->is64Bit() ? 8 : 4;
637 }
638
639 StringRef MachOObjectFile::getFileFormatName() const {
640   if (!MachOObj->is64Bit()) {
641     switch (MachOObj->getHeader().CPUType) {
642     case llvm::MachO::CPUTypeI386:
643       return "Mach-O 32-bit i386";
644     case llvm::MachO::CPUTypeARM:
645       return "Mach-O arm";
646     case llvm::MachO::CPUTypePowerPC:
647       return "Mach-O 32-bit ppc";
648     default:
649       assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
650              "64-bit object file when we're not 64-bit?");
651       return "Mach-O 32-bit unknown";
652     }
653   }
654
655   switch (MachOObj->getHeader().CPUType) {
656   case llvm::MachO::CPUTypeX86_64:
657     return "Mach-O 64-bit x86-64";
658   case llvm::MachO::CPUTypePowerPC64:
659     return "Mach-O 64-bit ppc64";
660   default:
661     assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
662            "32-bit object file when we're 64-bit?");
663     return "Mach-O 64-bit unknown";
664   }
665 }
666
667 unsigned MachOObjectFile::getArch() const {
668   switch (MachOObj->getHeader().CPUType) {
669   case llvm::MachO::CPUTypeI386:
670     return Triple::x86;
671   case llvm::MachO::CPUTypeX86_64:
672     return Triple::x86_64;
673   case llvm::MachO::CPUTypeARM:
674     return Triple::arm;
675   case llvm::MachO::CPUTypePowerPC:
676     return Triple::ppc;
677   case llvm::MachO::CPUTypePowerPC64:
678     return Triple::ppc64;
679   default:
680     return Triple::UnknownArch;
681   }
682 }
683
684 } // end namespace object
685 } // end namespace llvm