xref: /llvm-project/llvm/lib/Object/MachOObjectFile.cpp (revision 2138ef6d3d68e0e844f901732749ac57eb3c503f)
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/Format.h"
19 #include "llvm/Support/MemoryBuffer.h"
20 
21 #include <cctype>
22 #include <cstring>
23 #include <limits>
24 
25 using namespace llvm;
26 using namespace object;
27 
28 namespace llvm {
29 namespace object {
30 
31 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
32                                  error_code &ec)
33     : ObjectFile(Binary::ID_MachO, Object, ec),
34       MachOObj(MOO),
35       RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
36   DataRefImpl DRI;
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::getSymbolFileOffset(DataRefImpl DRI,
128                                                 uint64_t &Result) const {
129   if (MachOObj->is64Bit()) {
130     InMemoryStruct<macho::Symbol64TableEntry> Entry;
131     getSymbol64TableEntry(DRI, Entry);
132     Result = Entry->Value;
133     if (Entry->SectionIndex) {
134       InMemoryStruct<macho::Section64> Section;
135       getSection64(Sections[Entry->SectionIndex-1], Section);
136       Result += Section->Offset - Section->Address;
137     }
138   } else {
139     InMemoryStruct<macho::SymbolTableEntry> Entry;
140     getSymbolTableEntry(DRI, Entry);
141     Result = Entry->Value;
142     if (Entry->SectionIndex) {
143       InMemoryStruct<macho::Section> Section;
144       getSection(Sections[Entry->SectionIndex-1], Section);
145       Result += Section->Offset - Section->Address;
146     }
147   }
148 
149   return object_error::success;
150 }
151 
152 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
153                                              uint64_t &Result) const {
154   if (MachOObj->is64Bit()) {
155     InMemoryStruct<macho::Symbol64TableEntry> Entry;
156     getSymbol64TableEntry(DRI, Entry);
157     Result = Entry->Value;
158   } else {
159     InMemoryStruct<macho::SymbolTableEntry> Entry;
160     getSymbolTableEntry(DRI, Entry);
161     Result = Entry->Value;
162   }
163   return object_error::success;
164 }
165 
166 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
167                                           uint64_t &Result) const {
168   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
169   uint64_t BeginOffset;
170   uint64_t EndOffset = 0;
171   uint8_t SectionIndex;
172   if (MachOObj->is64Bit()) {
173     InMemoryStruct<macho::Symbol64TableEntry> Entry;
174     getSymbol64TableEntry(DRI, Entry);
175     BeginOffset = Entry->Value;
176     SectionIndex = Entry->SectionIndex;
177     if (!SectionIndex) {
178       uint32_t flags = SymbolRef::SF_None;
179       getSymbolFlags(DRI, flags);
180       if (flags & SymbolRef::SF_Common)
181         Result = Entry->Value;
182       else
183         Result = UnknownAddressOrSize;
184       return object_error::success;
185     }
186     // Unfortunately symbols are unsorted so we need to touch all
187     // symbols from load command
188     DRI.d.b = 0;
189     uint32_t Command = DRI.d.a;
190     while (Command == DRI.d.a) {
191       moveToNextSymbol(DRI);
192       if (DRI.d.a < LoadCommandCount) {
193         getSymbol64TableEntry(DRI, Entry);
194         if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
195           if (!EndOffset || Entry->Value < EndOffset)
196             EndOffset = Entry->Value;
197       }
198       DRI.d.b++;
199     }
200   } else {
201     InMemoryStruct<macho::SymbolTableEntry> Entry;
202     getSymbolTableEntry(DRI, Entry);
203     BeginOffset = Entry->Value;
204     SectionIndex = Entry->SectionIndex;
205     if (!SectionIndex) {
206       uint32_t flags = SymbolRef::SF_None;
207       getSymbolFlags(DRI, flags);
208       if (flags & SymbolRef::SF_Common)
209         Result = Entry->Value;
210       else
211         Result = UnknownAddressOrSize;
212       return object_error::success;
213     }
214     // Unfortunately symbols are unsorted so we need to touch all
215     // symbols from load command
216     DRI.d.b = 0;
217     uint32_t Command = DRI.d.a;
218     while (Command == DRI.d.a) {
219       moveToNextSymbol(DRI);
220       if (DRI.d.a < LoadCommandCount) {
221         getSymbolTableEntry(DRI, Entry);
222         if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
223           if (!EndOffset || Entry->Value < EndOffset)
224             EndOffset = Entry->Value;
225       }
226       DRI.d.b++;
227     }
228   }
229   if (!EndOffset) {
230     uint64_t Size;
231     getSectionSize(Sections[SectionIndex-1], Size);
232     getSectionAddress(Sections[SectionIndex-1], EndOffset);
233     EndOffset += Size;
234   }
235   Result = EndOffset - BeginOffset;
236   return object_error::success;
237 }
238 
239 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
240                                                 char &Result) const {
241   uint8_t Type, Flags;
242   if (MachOObj->is64Bit()) {
243     InMemoryStruct<macho::Symbol64TableEntry> Entry;
244     getSymbol64TableEntry(DRI, Entry);
245     Type = Entry->Type;
246     Flags = Entry->Flags;
247   } else {
248     InMemoryStruct<macho::SymbolTableEntry> Entry;
249     getSymbolTableEntry(DRI, Entry);
250     Type = Entry->Type;
251     Flags = Entry->Flags;
252   }
253 
254   char Char;
255   switch (Type & macho::STF_TypeMask) {
256     case macho::STT_Undefined:
257       Char = 'u';
258       break;
259     case macho::STT_Absolute:
260     case macho::STT_Section:
261       Char = 's';
262       break;
263     default:
264       Char = '?';
265       break;
266   }
267 
268   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
269     Char = toupper(Char);
270   Result = Char;
271   return object_error::success;
272 }
273 
274 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
275                                            uint32_t &Result) const {
276   uint16_t MachOFlags;
277   uint8_t MachOType;
278   uint8_t MachOSectionIndex;
279   if (MachOObj->is64Bit()) {
280     InMemoryStruct<macho::Symbol64TableEntry> Entry;
281     getSymbol64TableEntry(DRI, Entry);
282     MachOFlags = Entry->Flags;
283     MachOType = Entry->Type;
284     MachOSectionIndex = Entry->SectionIndex;
285   } else {
286     InMemoryStruct<macho::SymbolTableEntry> Entry;
287     getSymbolTableEntry(DRI, Entry);
288     MachOFlags = Entry->Flags;
289     MachOType = Entry->Type;
290     MachOSectionIndex = Entry->SectionIndex;
291   }
292 
293   // TODO: Correctly set SF_ThreadLocal
294   Result = SymbolRef::SF_None;
295 
296   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
297     Result |= SymbolRef::SF_Undefined;
298 
299   if (MachOFlags & macho::STF_StabsEntryMask)
300     Result |= SymbolRef::SF_FormatSpecific;
301 
302   if (MachOType & MachO::NlistMaskExternal) {
303     Result |= SymbolRef::SF_Global;
304     if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
305       Result |= SymbolRef::SF_Common;
306   }
307 
308   if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
309     Result |= SymbolRef::SF_Weak;
310 
311   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
312     Result |= SymbolRef::SF_Absolute;
313 
314   return object_error::success;
315 }
316 
317 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
318                                              section_iterator &Res) const {
319   uint8_t index;
320   if (MachOObj->is64Bit()) {
321     InMemoryStruct<macho::Symbol64TableEntry> Entry;
322     getSymbol64TableEntry(Symb, Entry);
323     index = Entry->SectionIndex;
324   } else {
325     InMemoryStruct<macho::SymbolTableEntry> Entry;
326     getSymbolTableEntry(Symb, Entry);
327     index = Entry->SectionIndex;
328   }
329 
330   if (index == 0)
331     Res = end_sections();
332   else
333     Res = section_iterator(SectionRef(Sections[index-1], this));
334 
335   return object_error::success;
336 }
337 
338 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
339                                           SymbolRef::Type &Res) const {
340   uint8_t n_type;
341   if (MachOObj->is64Bit()) {
342     InMemoryStruct<macho::Symbol64TableEntry> Entry;
343     getSymbol64TableEntry(Symb, Entry);
344     n_type = Entry->Type;
345   } else {
346     InMemoryStruct<macho::SymbolTableEntry> Entry;
347     getSymbolTableEntry(Symb, Entry);
348     n_type = Entry->Type;
349   }
350   Res = SymbolRef::ST_Other;
351 
352   // If this is a STAB debugging symbol, we can do nothing more.
353   if (n_type & MachO::NlistMaskStab) {
354     Res = SymbolRef::ST_Debug;
355     return object_error::success;
356   }
357 
358   switch (n_type & MachO::NlistMaskType) {
359     case MachO::NListTypeUndefined :
360       Res = SymbolRef::ST_Unknown;
361       break;
362     case MachO::NListTypeSection :
363       Res = SymbolRef::ST_Function;
364       break;
365   }
366   return object_error::success;
367 }
368 
369 
370 symbol_iterator MachOObjectFile::begin_symbols() const {
371   // DRI.d.a = segment number; DRI.d.b = symbol index.
372   DataRefImpl DRI;
373   moveToNextSymbol(DRI);
374   return symbol_iterator(SymbolRef(DRI, this));
375 }
376 
377 symbol_iterator MachOObjectFile::end_symbols() const {
378   DataRefImpl DRI;
379   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
380   return symbol_iterator(SymbolRef(DRI, this));
381 }
382 
383 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
384   // TODO: implement
385   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
386 }
387 
388 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
389   // TODO: implement
390   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
391 }
392 
393 library_iterator MachOObjectFile::begin_libraries_needed() const {
394   // TODO: implement
395   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
396 }
397 
398 library_iterator MachOObjectFile::end_libraries_needed() const {
399   // TODO: implement
400   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
401 }
402 
403 StringRef MachOObjectFile::getLoadName() const {
404   // TODO: Implement
405   report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
406 }
407 
408 /*===-- Sections ----------------------------------------------------------===*/
409 
410 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
411   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
412   while (DRI.d.a < LoadCommandCount) {
413     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
414     if (LCI.Command.Type == macho::LCT_Segment) {
415       InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
416       MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
417       if (DRI.d.b < SegmentLoadCmd->NumSections)
418         return;
419     } else if (LCI.Command.Type == macho::LCT_Segment64) {
420       InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
421       MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
422       if (DRI.d.b < Segment64LoadCmd->NumSections)
423         return;
424     }
425 
426     DRI.d.a++;
427     DRI.d.b = 0;
428   }
429 }
430 
431 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
432                                            SectionRef &Result) const {
433   DRI.d.b++;
434   moveToNextSection(DRI);
435   Result = SectionRef(DRI, this);
436   return object_error::success;
437 }
438 
439 void
440 MachOObjectFile::getSection(DataRefImpl DRI,
441                             InMemoryStruct<macho::Section> &Res) const {
442   InMemoryStruct<macho::SegmentLoadCommand> SLC;
443   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
444   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
445   MachOObj->ReadSection(LCI, DRI.d.b, Res);
446 }
447 
448 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
449   SectionList::const_iterator loc =
450     std::find(Sections.begin(), Sections.end(), Sec);
451   assert(loc != Sections.end() && "Sec is not a valid section!");
452   return std::distance(Sections.begin(), loc);
453 }
454 
455 void
456 MachOObjectFile::getSection64(DataRefImpl DRI,
457                             InMemoryStruct<macho::Section64> &Res) const {
458   InMemoryStruct<macho::Segment64LoadCommand> SLC;
459   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
460   MachOObj->ReadSegment64LoadCommand(LCI, SLC);
461   MachOObj->ReadSection64(LCI, DRI.d.b, Res);
462 }
463 
464 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
465   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
466   if (LCI.Command.Type == macho::LCT_Segment64)
467     return true;
468   assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
469   return false;
470 }
471 
472 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
473                                            StringRef &Result) const {
474   // FIXME: thread safety.
475   static char result[34];
476   if (is64BitLoadCommand(MachOObj, DRI)) {
477     InMemoryStruct<macho::Segment64LoadCommand> SLC;
478     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
479     MachOObj->ReadSegment64LoadCommand(LCI, SLC);
480     InMemoryStruct<macho::Section64> Sect;
481     MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
482 
483     strcpy(result, Sect->SegmentName);
484     strcat(result, ",");
485     strcat(result, Sect->Name);
486   } else {
487     InMemoryStruct<macho::SegmentLoadCommand> SLC;
488     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
489     MachOObj->ReadSegmentLoadCommand(LCI, SLC);
490     InMemoryStruct<macho::Section> Sect;
491     MachOObj->ReadSection(LCI, DRI.d.b, Sect);
492 
493     strcpy(result, Sect->SegmentName);
494     strcat(result, ",");
495     strcat(result, Sect->Name);
496   }
497   Result = StringRef(result);
498   return object_error::success;
499 }
500 
501 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
502                                               uint64_t &Result) const {
503   if (is64BitLoadCommand(MachOObj, DRI)) {
504     InMemoryStruct<macho::Section64> Sect;
505     getSection64(DRI, Sect);
506     Result = Sect->Address;
507   } else {
508     InMemoryStruct<macho::Section> Sect;
509     getSection(DRI, Sect);
510     Result = Sect->Address;
511   }
512   return object_error::success;
513 }
514 
515 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
516                                            uint64_t &Result) const {
517   if (is64BitLoadCommand(MachOObj, DRI)) {
518     InMemoryStruct<macho::Section64> Sect;
519     getSection64(DRI, Sect);
520     Result = Sect->Size;
521   } else {
522     InMemoryStruct<macho::Section> Sect;
523     getSection(DRI, Sect);
524     Result = Sect->Size;
525   }
526   return object_error::success;
527 }
528 
529 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
530                                                StringRef &Result) const {
531   if (is64BitLoadCommand(MachOObj, DRI)) {
532     InMemoryStruct<macho::Section64> Sect;
533     getSection64(DRI, Sect);
534     Result = MachOObj->getData(Sect->Offset, Sect->Size);
535   } else {
536     InMemoryStruct<macho::Section> Sect;
537     getSection(DRI, Sect);
538     Result = MachOObj->getData(Sect->Offset, Sect->Size);
539   }
540   return object_error::success;
541 }
542 
543 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
544                                                 uint64_t &Result) const {
545   if (is64BitLoadCommand(MachOObj, DRI)) {
546     InMemoryStruct<macho::Section64> Sect;
547     getSection64(DRI, Sect);
548     Result = uint64_t(1) << Sect->Align;
549   } else {
550     InMemoryStruct<macho::Section> Sect;
551     getSection(DRI, Sect);
552     Result = uint64_t(1) << Sect->Align;
553   }
554   return object_error::success;
555 }
556 
557 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
558                                           bool &Result) const {
559   if (is64BitLoadCommand(MachOObj, DRI)) {
560     InMemoryStruct<macho::Section64> Sect;
561     getSection64(DRI, Sect);
562     Result = !strcmp(Sect->Name, "__text");
563   } else {
564     InMemoryStruct<macho::Section> Sect;
565     getSection(DRI, Sect);
566     Result = !strcmp(Sect->Name, "__text");
567   }
568   return object_error::success;
569 }
570 
571 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
572                                           bool &Result) const {
573   // FIXME: Unimplemented.
574   Result = false;
575   return object_error::success;
576 }
577 
578 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
579                                          bool &Result) const {
580   // FIXME: Unimplemented.
581   Result = false;
582   return object_error::success;
583 }
584 
585 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
586                                                           bool &Result) const {
587   // FIXME: Unimplemented
588   Result = true;
589   return object_error::success;
590 }
591 
592 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
593                                             bool &Result) const {
594   // FIXME: Unimplemented
595   Result = false;
596   return object_error::success;
597 }
598 
599 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
600                                               bool &Result) const {
601   if (MachOObj->is64Bit()) {
602     InMemoryStruct<macho::Section64> Sect;
603     getSection64(DRI, Sect);
604     Result = (Sect->Flags & MachO::SectionTypeZeroFill ||
605               Sect->Flags & MachO::SectionTypeZeroFillLarge);
606   } else {
607     InMemoryStruct<macho::Section> Sect;
608     getSection(DRI, Sect);
609     Result = (Sect->Flags & MachO::SectionTypeZeroFill ||
610               Sect->Flags & MachO::SectionTypeZeroFillLarge);
611   }
612 
613   return object_error::success;
614 }
615 
616 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
617                                                   DataRefImpl Symb,
618                                                   bool &Result) const {
619   SymbolRef::Type ST;
620   getSymbolType(Symb, ST);
621   if (ST == SymbolRef::ST_Unknown) {
622     Result = false;
623     return object_error::success;
624   }
625 
626   uint64_t SectBegin, SectEnd;
627   getSectionAddress(Sec, SectBegin);
628   getSectionSize(Sec, SectEnd);
629   SectEnd += SectBegin;
630 
631   if (MachOObj->is64Bit()) {
632     InMemoryStruct<macho::Symbol64TableEntry> Entry;
633     getSymbol64TableEntry(Symb, Entry);
634     uint64_t SymAddr= Entry->Value;
635     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
636   } else {
637     InMemoryStruct<macho::SymbolTableEntry> Entry;
638     getSymbolTableEntry(Symb, Entry);
639     uint64_t SymAddr= Entry->Value;
640     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
641   }
642 
643   return object_error::success;
644 }
645 
646 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
647   DataRefImpl ret;
648   ret.d.b = getSectionIndex(Sec);
649   return relocation_iterator(RelocationRef(ret, this));
650 }
651 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
652   uint32_t last_reloc;
653   if (is64BitLoadCommand(MachOObj, Sec)) {
654     InMemoryStruct<macho::Section64> Sect;
655     getSection64(Sec, Sect);
656     last_reloc = Sect->NumRelocationTableEntries;
657   } else {
658     InMemoryStruct<macho::Section> Sect;
659     getSection(Sec, Sect);
660     last_reloc = Sect->NumRelocationTableEntries;
661   }
662   DataRefImpl ret;
663   ret.d.a = last_reloc;
664   ret.d.b = getSectionIndex(Sec);
665   return relocation_iterator(RelocationRef(ret, this));
666 }
667 
668 section_iterator MachOObjectFile::begin_sections() const {
669   DataRefImpl DRI;
670   moveToNextSection(DRI);
671   return section_iterator(SectionRef(DRI, this));
672 }
673 
674 section_iterator MachOObjectFile::end_sections() const {
675   DataRefImpl DRI;
676   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
677   return section_iterator(SectionRef(DRI, this));
678 }
679 
680 /*===-- Relocations -------------------------------------------------------===*/
681 
682 void MachOObjectFile::
683 getRelocation(DataRefImpl Rel,
684               InMemoryStruct<macho::RelocationEntry> &Res) const {
685   uint32_t relOffset;
686   if (MachOObj->is64Bit()) {
687     InMemoryStruct<macho::Section64> Sect;
688     getSection64(Sections[Rel.d.b], Sect);
689     relOffset = Sect->RelocationTableOffset;
690   } else {
691     InMemoryStruct<macho::Section> Sect;
692     getSection(Sections[Rel.d.b], Sect);
693     relOffset = Sect->RelocationTableOffset;
694   }
695   MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
696 }
697 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
698                                               RelocationRef &Res) const {
699   ++Rel.d.a;
700   Res = RelocationRef(Rel, this);
701   return object_error::success;
702 }
703 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
704                                                  uint64_t &Res) const {
705   const uint8_t* sectAddress = 0;
706   if (MachOObj->is64Bit()) {
707     InMemoryStruct<macho::Section64> Sect;
708     getSection64(Sections[Rel.d.b], Sect);
709     sectAddress += Sect->Address;
710   } else {
711     InMemoryStruct<macho::Section> Sect;
712     getSection(Sections[Rel.d.b], Sect);
713     sectAddress += Sect->Address;
714   }
715   InMemoryStruct<macho::RelocationEntry> RE;
716   getRelocation(Rel, RE);
717 
718   unsigned Arch = getArch();
719   bool isScattered = (Arch != Triple::x86_64) &&
720                      (RE->Word0 & macho::RF_Scattered);
721   uint64_t RelAddr = 0;
722   if (isScattered)
723     RelAddr = RE->Word0 & 0xFFFFFF;
724   else
725     RelAddr = RE->Word0;
726 
727   Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
728   return object_error::success;
729 }
730 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
731                                                 uint64_t &Res) const {
732   InMemoryStruct<macho::RelocationEntry> RE;
733   getRelocation(Rel, RE);
734 
735   unsigned Arch = getArch();
736   bool isScattered = (Arch != Triple::x86_64) &&
737                      (RE->Word0 & macho::RF_Scattered);
738   if (isScattered)
739     Res = RE->Word0 & 0xFFFFFF;
740   else
741     Res = RE->Word0;
742   return object_error::success;
743 }
744 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
745                                                 SymbolRef &Res) const {
746   InMemoryStruct<macho::RelocationEntry> RE;
747   getRelocation(Rel, RE);
748   uint32_t SymbolIdx = RE->Word1 & 0xffffff;
749   bool isExtern = (RE->Word1 >> 27) & 1;
750 
751   DataRefImpl Sym;
752   moveToNextSymbol(Sym);
753   if (isExtern) {
754     for (unsigned i = 0; i < SymbolIdx; i++) {
755       Sym.d.b++;
756       moveToNextSymbol(Sym);
757       assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
758              "Relocation symbol index out of range!");
759     }
760   }
761   Res = SymbolRef(Sym, this);
762   return object_error::success;
763 }
764 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
765                                               uint64_t &Res) const {
766   InMemoryStruct<macho::RelocationEntry> RE;
767   getRelocation(Rel, RE);
768   Res = RE->Word0;
769   Res <<= 32;
770   Res |= RE->Word1;
771   return object_error::success;
772 }
773 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
774                                           SmallVectorImpl<char> &Result) const {
775   // TODO: Support scattered relocations.
776   StringRef res;
777   InMemoryStruct<macho::RelocationEntry> RE;
778   getRelocation(Rel, RE);
779 
780   unsigned Arch = getArch();
781   bool isScattered = (Arch != Triple::x86_64) &&
782                      (RE->Word0 & macho::RF_Scattered);
783 
784   unsigned r_type;
785   if (isScattered)
786     r_type = (RE->Word0 >> 24) & 0xF;
787   else
788     r_type = (RE->Word1 >> 28) & 0xF;
789 
790   switch (Arch) {
791     case Triple::x86: {
792       const char* Table[] =  {
793         "GENERIC_RELOC_VANILLA",
794         "GENERIC_RELOC_PAIR",
795         "GENERIC_RELOC_SECTDIFF",
796         "GENERIC_RELOC_PB_LA_PTR",
797         "GENERIC_RELOC_LOCAL_SECTDIFF",
798         "GENERIC_RELOC_TLV" };
799 
800       if (r_type > 6)
801         res = "Unknown";
802       else
803         res = Table[r_type];
804       break;
805     }
806     case Triple::x86_64: {
807       const char* Table[] =  {
808         "X86_64_RELOC_UNSIGNED",
809         "X86_64_RELOC_SIGNED",
810         "X86_64_RELOC_BRANCH",
811         "X86_64_RELOC_GOT_LOAD",
812         "X86_64_RELOC_GOT",
813         "X86_64_RELOC_SUBTRACTOR",
814         "X86_64_RELOC_SIGNED_1",
815         "X86_64_RELOC_SIGNED_2",
816         "X86_64_RELOC_SIGNED_4",
817         "X86_64_RELOC_TLV" };
818 
819       if (r_type > 9)
820         res = "Unknown";
821       else
822         res = Table[r_type];
823       break;
824     }
825     case Triple::arm: {
826       const char* Table[] =  {
827         "ARM_RELOC_VANILLA",
828         "ARM_RELOC_PAIR",
829         "ARM_RELOC_SECTDIFF",
830         "ARM_RELOC_LOCAL_SECTDIFF",
831         "ARM_RELOC_PB_LA_PTR",
832         "ARM_RELOC_BR24",
833         "ARM_THUMB_RELOC_BR22",
834         "ARM_THUMB_32BIT_BRANCH",
835         "ARM_RELOC_HALF",
836         "ARM_RELOC_HALF_SECTDIFF" };
837 
838       if (r_type > 9)
839         res = "Unknown";
840       else
841         res = Table[r_type];
842       break;
843     }
844     case Triple::ppc: {
845       const char* Table[] =  {
846         "PPC_RELOC_VANILLA",
847         "PPC_RELOC_PAIR",
848         "PPC_RELOC_BR14",
849         "PPC_RELOC_BR24",
850         "PPC_RELOC_HI16",
851         "PPC_RELOC_LO16",
852         "PPC_RELOC_HA16",
853         "PPC_RELOC_LO14",
854         "PPC_RELOC_SECTDIFF",
855         "PPC_RELOC_PB_LA_PTR",
856         "PPC_RELOC_HI16_SECTDIFF",
857         "PPC_RELOC_LO16_SECTDIFF",
858         "PPC_RELOC_HA16_SECTDIFF",
859         "PPC_RELOC_JBSR",
860         "PPC_RELOC_LO14_SECTDIFF",
861         "PPC_RELOC_LOCAL_SECTDIFF" };
862 
863       res = Table[r_type];
864       break;
865     }
866     case Triple::UnknownArch:
867       res = "Unknown";
868       break;
869   }
870   Result.append(res.begin(), res.end());
871   return object_error::success;
872 }
873 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
874                                                         int64_t &Res) const {
875   InMemoryStruct<macho::RelocationEntry> RE;
876   getRelocation(Rel, RE);
877   bool isExtern = (RE->Word1 >> 27) & 1;
878   Res = 0;
879   if (!isExtern) {
880     const uint8_t* sectAddress = base();
881     if (MachOObj->is64Bit()) {
882       InMemoryStruct<macho::Section64> Sect;
883       getSection64(Sections[Rel.d.b], Sect);
884       sectAddress += Sect->Offset;
885     } else {
886       InMemoryStruct<macho::Section> Sect;
887       getSection(Sections[Rel.d.b], Sect);
888       sectAddress += Sect->Offset;
889     }
890     Res = reinterpret_cast<uintptr_t>(sectAddress);
891   }
892   return object_error::success;
893 }
894 
895 // Helper to advance a section or symbol iterator multiple increments at a time.
896 template<class T>
897 error_code advance(T &it, size_t Val) {
898   error_code ec;
899   while (Val--) {
900     it.increment(ec);
901   }
902   return ec;
903 }
904 
905 template<class T>
906 void advanceTo(T &it, size_t Val) {
907   if (error_code ec = advance(it, Val))
908     report_fatal_error(ec.message());
909 }
910 
911 void MachOObjectFile::printRelocationTargetName(
912                                      InMemoryStruct<macho::RelocationEntry>& RE,
913                                      raw_string_ostream &fmt) const {
914   unsigned Arch = getArch();
915   bool isScattered = (Arch != Triple::x86_64) &&
916                      (RE->Word0 & macho::RF_Scattered);
917 
918   // Target of a scattered relocation is an address.  In the interest of
919   // generating pretty output, scan through the symbol table looking for a
920   // symbol that aligns with that address.  If we find one, print it.
921   // Otherwise, we just print the hex address of the target.
922   if (isScattered) {
923     uint32_t Val = RE->Word1;
924 
925     error_code ec;
926     for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
927         SI.increment(ec)) {
928       if (ec) report_fatal_error(ec.message());
929 
930       uint64_t Addr;
931       StringRef Name;
932 
933       if ((ec = SI->getAddress(Addr)))
934         report_fatal_error(ec.message());
935       if (Addr != Val) continue;
936       if ((ec = SI->getName(Name)))
937         report_fatal_error(ec.message());
938       fmt << Name;
939       return;
940     }
941 
942     // If we couldn't find a symbol that this relocation refers to, try
943     // to find a section beginning instead.
944     for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
945          SI.increment(ec)) {
946       if (ec) report_fatal_error(ec.message());
947 
948       uint64_t Addr;
949       StringRef Name;
950 
951       if ((ec = SI->getAddress(Addr)))
952         report_fatal_error(ec.message());
953       if (Addr != Val) continue;
954       if ((ec = SI->getName(Name)))
955         report_fatal_error(ec.message());
956       fmt << Name;
957       return;
958     }
959 
960     fmt << format("0x%x", Val);
961     return;
962   }
963 
964   StringRef S;
965   bool isExtern = (RE->Word1 >> 27) & 1;
966   uint32_t Val = RE->Word1 & 0xFFFFFF;
967 
968   if (isExtern) {
969     symbol_iterator SI = begin_symbols();
970     advanceTo(SI, Val);
971     SI->getName(S);
972   } else {
973     section_iterator SI = begin_sections();
974     advanceTo(SI, Val);
975     SI->getName(S);
976   }
977 
978   fmt << S;
979 }
980 
981 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
982                                           SmallVectorImpl<char> &Result) const {
983   InMemoryStruct<macho::RelocationEntry> RE;
984   getRelocation(Rel, RE);
985 
986   unsigned Arch = getArch();
987   bool isScattered = (Arch != Triple::x86_64) &&
988                      (RE->Word0 & macho::RF_Scattered);
989 
990   std::string fmtbuf;
991   raw_string_ostream fmt(fmtbuf);
992 
993   unsigned Type;
994   if (isScattered)
995     Type = (RE->Word0 >> 24) & 0xF;
996   else
997     Type = (RE->Word1 >> 28) & 0xF;
998 
999   bool isPCRel;
1000   if (isScattered)
1001     isPCRel = ((RE->Word0 >> 30) & 1);
1002   else
1003     isPCRel = ((RE->Word1 >> 24) & 1);
1004 
1005   // Determine any addends that should be displayed with the relocation.
1006   // These require decoding the relocation type, which is triple-specific.
1007 
1008   // X86_64 has entirely custom relocation types.
1009   if (Arch == Triple::x86_64) {
1010     bool isPCRel = ((RE->Word1 >> 24) & 1);
1011 
1012     switch (Type) {
1013       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
1014       case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
1015         printRelocationTargetName(RE, fmt);
1016         fmt << "@GOT";
1017         if (isPCRel) fmt << "PCREL";
1018         break;
1019       }
1020       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1021         InMemoryStruct<macho::RelocationEntry> RENext;
1022         DataRefImpl RelNext = Rel;
1023         RelNext.d.a++;
1024         getRelocation(RelNext, RENext);
1025 
1026         // X86_64_SUBTRACTOR must be followed by a relocation of type
1027         // X86_64_RELOC_UNSIGNED.
1028         // NOTE: Scattered relocations don't exist on x86_64.
1029         unsigned RType = (RENext->Word1 >> 28) & 0xF;
1030         if (RType != 0)
1031           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1032                              "X86_64_RELOC_SUBTRACTOR.");
1033 
1034         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1035         // X86_64_SUBTRACTOR contains to the subtrahend.
1036         printRelocationTargetName(RENext, fmt);
1037         fmt << "-";
1038         printRelocationTargetName(RE, fmt);
1039       }
1040       case macho::RIT_X86_64_TLV:
1041         printRelocationTargetName(RE, fmt);
1042         fmt << "@TLV";
1043         if (isPCRel) fmt << "P";
1044         break;
1045       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1046         printRelocationTargetName(RE, fmt);
1047         fmt << "-1";
1048         break;
1049       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1050         printRelocationTargetName(RE, fmt);
1051         fmt << "-2";
1052         break;
1053       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1054         printRelocationTargetName(RE, fmt);
1055         fmt << "-4";
1056         break;
1057       default:
1058         printRelocationTargetName(RE, fmt);
1059         break;
1060     }
1061   // X86 and ARM share some relocation types in common.
1062   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1063     // Generic relocation types...
1064     switch (Type) {
1065       case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1066         return object_error::success;
1067       case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1068         InMemoryStruct<macho::RelocationEntry> RENext;
1069         DataRefImpl RelNext = Rel;
1070         RelNext.d.a++;
1071         getRelocation(RelNext, RENext);
1072 
1073         // X86 sect diff's must be followed by a relocation of type
1074         // GENERIC_RELOC_PAIR.
1075         bool isNextScattered = (Arch != Triple::x86_64) &&
1076                                (RENext->Word0 & macho::RF_Scattered);
1077         unsigned RType;
1078         if (isNextScattered)
1079           RType = (RENext->Word0 >> 24) & 0xF;
1080         else
1081           RType = (RENext->Word1 >> 28) & 0xF;
1082         if (RType != 1)
1083           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1084                              "GENERIC_RELOC_SECTDIFF.");
1085 
1086         printRelocationTargetName(RE, fmt);
1087         fmt << "-";
1088         printRelocationTargetName(RENext, fmt);
1089         break;
1090       }
1091     }
1092 
1093     if (Arch == Triple::x86) {
1094       // All X86 relocations that need special printing were already
1095       // handled in the generic code.
1096       switch (Type) {
1097         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1098           InMemoryStruct<macho::RelocationEntry> RENext;
1099           DataRefImpl RelNext = Rel;
1100           RelNext.d.a++;
1101           getRelocation(RelNext, RENext);
1102 
1103           // X86 sect diff's must be followed by a relocation of type
1104           // GENERIC_RELOC_PAIR.
1105           bool isNextScattered = (Arch != Triple::x86_64) &&
1106                                (RENext->Word0 & macho::RF_Scattered);
1107           unsigned RType;
1108           if (isNextScattered)
1109             RType = (RENext->Word0 >> 24) & 0xF;
1110           else
1111             RType = (RENext->Word1 >> 28) & 0xF;
1112           if (RType != 1)
1113             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1114                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
1115 
1116           printRelocationTargetName(RE, fmt);
1117           fmt << "-";
1118           printRelocationTargetName(RENext, fmt);
1119           break;
1120         }
1121         case macho::RIT_Generic_TLV: {
1122           printRelocationTargetName(RE, fmt);
1123           fmt << "@TLV";
1124           if (isPCRel) fmt << "P";
1125           break;
1126         }
1127         default:
1128           printRelocationTargetName(RE, fmt);
1129       }
1130     } else { // ARM-specific relocations
1131       switch (Type) {
1132         case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
1133         case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1134           // Half relocations steal a bit from the length field to encode
1135           // whether this is an upper16 or a lower16 relocation.
1136           bool isUpper;
1137           if (isScattered)
1138             isUpper = (RE->Word0 >> 28) & 1;
1139           else
1140             isUpper = (RE->Word1 >> 25) & 1;
1141 
1142           if (isUpper)
1143             fmt << ":upper16:(";
1144           else
1145             fmt << ":lower16:(";
1146           printRelocationTargetName(RE, fmt);
1147 
1148           InMemoryStruct<macho::RelocationEntry> RENext;
1149           DataRefImpl RelNext = Rel;
1150           RelNext.d.a++;
1151           getRelocation(RelNext, RENext);
1152 
1153           // ARM half relocs must be followed by a relocation of type
1154           // ARM_RELOC_PAIR.
1155           bool isNextScattered = (Arch != Triple::x86_64) &&
1156                                  (RENext->Word0 & macho::RF_Scattered);
1157           unsigned RType;
1158           if (isNextScattered)
1159             RType = (RENext->Word0 >> 24) & 0xF;
1160           else
1161             RType = (RENext->Word1 >> 28) & 0xF;
1162 
1163           if (RType != 1)
1164             report_fatal_error("Expected ARM_RELOC_PAIR after "
1165                                "GENERIC_RELOC_HALF");
1166 
1167           // NOTE: The half of the target virtual address is stashed in the
1168           // address field of the secondary relocation, but we can't reverse
1169           // engineer the constant offset from it without decoding the movw/movt
1170           // instruction to find the other half in its immediate field.
1171 
1172           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1173           // symbol/section pointer of the follow-on relocation.
1174           if (Type == macho::RIT_ARM_HalfDifference) {
1175             fmt << "-";
1176             printRelocationTargetName(RENext, fmt);
1177           }
1178 
1179           fmt << ")";
1180           break;
1181         }
1182         default: {
1183           printRelocationTargetName(RE, fmt);
1184         }
1185       }
1186     }
1187   } else
1188     printRelocationTargetName(RE, fmt);
1189 
1190   fmt.flush();
1191   Result.append(fmtbuf.begin(), fmtbuf.end());
1192   return object_error::success;
1193 }
1194 
1195 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1196                                                 bool &Result) const {
1197   InMemoryStruct<macho::RelocationEntry> RE;
1198   getRelocation(Rel, RE);
1199 
1200   unsigned Arch = getArch();
1201   bool isScattered = (Arch != Triple::x86_64) &&
1202                      (RE->Word0 & macho::RF_Scattered);
1203   unsigned Type;
1204   if (isScattered)
1205     Type = (RE->Word0 >> 24) & 0xF;
1206   else
1207     Type = (RE->Word1 >> 28) & 0xF;
1208 
1209   Result = false;
1210 
1211   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1212   // is always hidden.
1213   if (Arch == Triple::x86 || Arch == Triple::arm) {
1214     if (Type == macho::RIT_Pair) Result = true;
1215   } else if (Arch == Triple::x86_64) {
1216     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1217     // an X864_64_RELOC_SUBTRACTOR.
1218     if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1219       DataRefImpl RelPrev = Rel;
1220       RelPrev.d.a--;
1221       InMemoryStruct<macho::RelocationEntry> REPrev;
1222       getRelocation(RelPrev, REPrev);
1223 
1224       unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1225 
1226       if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1227     }
1228   }
1229 
1230   return object_error::success;
1231 }
1232 
1233 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1234                                            LibraryRef &Res) const {
1235   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1236 }
1237 
1238 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1239                                            StringRef &Res) const {
1240   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1241 }
1242 
1243 
1244 /*===-- Miscellaneous -----------------------------------------------------===*/
1245 
1246 uint8_t MachOObjectFile::getBytesInAddress() const {
1247   return MachOObj->is64Bit() ? 8 : 4;
1248 }
1249 
1250 StringRef MachOObjectFile::getFileFormatName() const {
1251   if (!MachOObj->is64Bit()) {
1252     switch (MachOObj->getHeader().CPUType) {
1253     case llvm::MachO::CPUTypeI386:
1254       return "Mach-O 32-bit i386";
1255     case llvm::MachO::CPUTypeARM:
1256       return "Mach-O arm";
1257     case llvm::MachO::CPUTypePowerPC:
1258       return "Mach-O 32-bit ppc";
1259     default:
1260       assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1261              "64-bit object file when we're not 64-bit?");
1262       return "Mach-O 32-bit unknown";
1263     }
1264   }
1265 
1266   switch (MachOObj->getHeader().CPUType) {
1267   case llvm::MachO::CPUTypeX86_64:
1268     return "Mach-O 64-bit x86-64";
1269   case llvm::MachO::CPUTypePowerPC64:
1270     return "Mach-O 64-bit ppc64";
1271   default:
1272     assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
1273            "32-bit object file when we're 64-bit?");
1274     return "Mach-O 64-bit unknown";
1275   }
1276 }
1277 
1278 unsigned MachOObjectFile::getArch() const {
1279   switch (MachOObj->getHeader().CPUType) {
1280   case llvm::MachO::CPUTypeI386:
1281     return Triple::x86;
1282   case llvm::MachO::CPUTypeX86_64:
1283     return Triple::x86_64;
1284   case llvm::MachO::CPUTypeARM:
1285     return Triple::arm;
1286   case llvm::MachO::CPUTypePowerPC:
1287     return Triple::ppc;
1288   case llvm::MachO::CPUTypePowerPC64:
1289     return Triple::ppc64;
1290   default:
1291     return Triple::UnknownArch;
1292   }
1293 }
1294 
1295 } // end namespace object
1296 } // end namespace llvm
1297