Don't read one command past the end.
[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/Object/MachO.h"
16 #include "llvm/ADT/Triple.h"
17 #include "llvm/Object/MachOFormat.h"
18 #include "llvm/Support/DataExtractor.h"
19 #include "llvm/Support/Format.h"
20 #include "llvm/Support/Host.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include <cctype>
23 #include <cstring>
24 #include <limits>
25
26 using namespace llvm;
27 using namespace object;
28
29 namespace llvm {
30 namespace object {
31
32 struct SymbolTableEntryBase {
33   uint32_t StringIndex;
34   uint8_t Type;
35   uint8_t SectionIndex;
36   uint16_t Flags;
37 };
38
39 struct SectionBase {
40   char Name[16];
41   char SegmentName[16];
42 };
43
44 template<typename T>
45 static void SwapValue(T &Value) {
46   Value = sys::SwapByteOrder(Value);
47 }
48
49 template<typename T>
50 static void SwapStruct(T &Value);
51
52 template<>
53 void SwapStruct(macho::RelocationEntry &H) {
54   SwapValue(H.Word0);
55   SwapValue(H.Word1);
56 }
57
58 template<>
59 void SwapStruct(macho::LoadCommand &L) {
60   SwapValue(L.Type);
61   SwapValue(L.Size);
62 }
63
64 template<>
65 void SwapStruct(SymbolTableEntryBase &S) {
66   SwapValue(S.StringIndex);
67   SwapValue(S.Flags);
68 }
69
70 template<>
71 void SwapStruct(macho::Section &S) {
72   SwapValue(S.Address);
73   SwapValue(S.Size);
74   SwapValue(S.Offset);
75   SwapValue(S.Align);
76   SwapValue(S.RelocationTableOffset);
77   SwapValue(S.NumRelocationTableEntries);
78   SwapValue(S.Flags);
79   SwapValue(S.Reserved1);
80   SwapValue(S.Reserved2);
81 }
82
83 template<>
84 void SwapStruct(macho::Section64 &S) {
85   SwapValue(S.Address);
86   SwapValue(S.Size);
87   SwapValue(S.Offset);
88   SwapValue(S.Align);
89   SwapValue(S.RelocationTableOffset);
90   SwapValue(S.NumRelocationTableEntries);
91   SwapValue(S.Flags);
92   SwapValue(S.Reserved1);
93   SwapValue(S.Reserved2);
94   SwapValue(S.Reserved3);
95 }
96
97 template<>
98 void SwapStruct(macho::SymbolTableEntry &S) {
99   SwapValue(S.StringIndex);
100   SwapValue(S.Flags);
101   SwapValue(S.Value);
102 }
103
104 template<>
105 void SwapStruct(macho::Symbol64TableEntry &S) {
106   SwapValue(S.StringIndex);
107   SwapValue(S.Flags);
108   SwapValue(S.Value);
109 }
110
111 template<>
112 void SwapStruct(macho::Header &H) {
113   SwapValue(H.Magic);
114   SwapValue(H.CPUType);
115   SwapValue(H.CPUSubtype);
116   SwapValue(H.FileType);
117   SwapValue(H.NumLoadCommands);
118   SwapValue(H.SizeOfLoadCommands);
119   SwapValue(H.Flags);
120 }
121
122 template<>
123 void SwapStruct(macho::SymtabLoadCommand &C) {
124   SwapValue(C.Type);
125   SwapValue(C.Size);
126   SwapValue(C.SymbolTableOffset);
127   SwapValue(C.NumSymbolTableEntries);
128   SwapValue(C.StringTableOffset);
129   SwapValue(C.StringTableSize);
130 }
131
132 template<>
133 void SwapStruct(macho::LinkeditDataLoadCommand &C) {
134   SwapValue(C.Type);
135   SwapValue(C.Size);
136   SwapValue(C.DataOffset);
137   SwapValue(C.DataSize);
138 }
139
140 template<>
141 void SwapStruct(macho::SegmentLoadCommand &C) {
142   SwapValue(C.Type);
143   SwapValue(C.Size);
144   SwapValue(C.VMAddress);
145   SwapValue(C.VMSize);
146   SwapValue(C.FileOffset);
147   SwapValue(C.FileSize);
148   SwapValue(C.MaxVMProtection);
149   SwapValue(C.InitialVMProtection);
150   SwapValue(C.NumSections);
151   SwapValue(C.Flags);
152 }
153
154 template<>
155 void SwapStruct(macho::Segment64LoadCommand &C) {
156   SwapValue(C.Type);
157   SwapValue(C.Size);
158   SwapValue(C.VMAddress);
159   SwapValue(C.VMSize);
160   SwapValue(C.FileOffset);
161   SwapValue(C.FileSize);
162   SwapValue(C.MaxVMProtection);
163   SwapValue(C.InitialVMProtection);
164   SwapValue(C.NumSections);
165   SwapValue(C.Flags);
166 }
167
168 static bool isSwappedEndian(const MachOObjectFile *O) {
169   return O->isLittleEndian() != sys::IsLittleEndianHost;
170 }
171
172 static macho::SegmentLoadCommand
173 getSegmentLoadCommand(const MachOObjectFile *O,
174                       const MachOObjectFile::LoadCommandInfo &L) {
175   macho::SegmentLoadCommand Cmd;
176   memcpy(&Cmd, L.Ptr, sizeof(macho::SegmentLoadCommand));
177   if (isSwappedEndian(O))
178     SwapStruct(Cmd);
179   return Cmd;
180 }
181
182 static macho::Segment64LoadCommand
183 getSegment64LoadCommand(const MachOObjectFile *O,
184                         const MachOObjectFile::LoadCommandInfo &L) {
185   macho::Segment64LoadCommand Cmd;
186   memcpy(&Cmd, L.Ptr, sizeof(macho::Segment64LoadCommand));
187   if (isSwappedEndian(O))
188     SwapStruct(Cmd);
189   return Cmd;
190 }
191
192 static uint32_t
193 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
194                                  const MachOObjectFile::LoadCommandInfo &L) {
195   if (O->is64Bit()) {
196     macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
197     return S.NumSections;
198   }
199   macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
200   return S.NumSections;
201 }
202
203 static const SectionBase *
204 getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
205                unsigned Sec) {
206   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
207
208   bool Is64 = O->is64Bit();
209   unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
210                                     sizeof(macho::SegmentLoadCommand);
211   unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
212                                 sizeof(macho::Section);
213
214   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
215   return reinterpret_cast<const SectionBase*>(SectionAddr);
216 }
217
218 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
219   return O->getData().substr(Offset, 1).data();
220 }
221
222 static const char *getSymbolTableEntryPtr(const MachOObjectFile *O,
223                                           DataRefImpl DRI) {
224   macho::SymtabLoadCommand S = O->getSymtabLoadCommand();
225
226   unsigned Index = DRI.d.b;
227
228   unsigned SymbolTableEntrySize = O->is64Bit() ?
229     sizeof(macho::Symbol64TableEntry) :
230     sizeof(macho::SymbolTableEntry);
231
232   uint64_t Offset = S.SymbolTableOffset + Index * SymbolTableEntrySize;
233   return getPtr(O, Offset);
234 }
235
236 static SymbolTableEntryBase
237 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
238   const char *P = getSymbolTableEntryPtr(O, DRI);
239   SymbolTableEntryBase Ret;
240   memcpy(&Ret, P, sizeof(SymbolTableEntryBase));
241   if (isSwappedEndian(O))
242     SwapStruct(Ret);
243
244   return Ret;
245 }
246
247 static StringRef parseSegmentOrSectionName(const char *P) {
248   if (P[15] == 0)
249     // Null terminated.
250     return P;
251   // Not null terminated, so this is a 16 char string.
252   return StringRef(P, 16);
253 }
254
255 // Helper to advance a section or symbol iterator multiple increments at a time.
256 template<class T>
257 static error_code advance(T &it, size_t Val) {
258   error_code ec;
259   while (Val--) {
260     it.increment(ec);
261   }
262   return ec;
263 }
264
265 template<class T>
266 static void advanceTo(T &it, size_t Val) {
267   if (error_code ec = advance(it, Val))
268     report_fatal_error(ec.message());
269 }
270
271 static unsigned getCPUType(const MachOObjectFile *O) {
272   return O->getHeader().CPUType;
273 }
274
275 static void printRelocationTargetName(const MachOObjectFile *O,
276                                       const macho::RelocationEntry &RE,
277                                       raw_string_ostream &fmt) {
278   bool IsScattered = O->isRelocationScattered(RE);
279
280   // Target of a scattered relocation is an address.  In the interest of
281   // generating pretty output, scan through the symbol table looking for a
282   // symbol that aligns with that address.  If we find one, print it.
283   // Otherwise, we just print the hex address of the target.
284   if (IsScattered) {
285     uint32_t Val = O->getPlainRelocationSymbolNum(RE);
286
287     error_code ec;
288     for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
289          SI != SE; SI.increment(ec)) {
290       if (ec) report_fatal_error(ec.message());
291
292       uint64_t Addr;
293       StringRef Name;
294
295       if ((ec = SI->getAddress(Addr)))
296         report_fatal_error(ec.message());
297       if (Addr != Val) continue;
298       if ((ec = SI->getName(Name)))
299         report_fatal_error(ec.message());
300       fmt << Name;
301       return;
302     }
303
304     // If we couldn't find a symbol that this relocation refers to, try
305     // to find a section beginning instead.
306     for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
307          SI != SE; SI.increment(ec)) {
308       if (ec) report_fatal_error(ec.message());
309
310       uint64_t Addr;
311       StringRef Name;
312
313       if ((ec = SI->getAddress(Addr)))
314         report_fatal_error(ec.message());
315       if (Addr != Val) continue;
316       if ((ec = SI->getName(Name)))
317         report_fatal_error(ec.message());
318       fmt << Name;
319       return;
320     }
321
322     fmt << format("0x%x", Val);
323     return;
324   }
325
326   StringRef S;
327   bool isExtern = O->getPlainRelocationExternal(RE);
328   uint64_t Val = O->getAnyRelocationAddress(RE);
329
330   if (isExtern) {
331     symbol_iterator SI = O->begin_symbols();
332     advanceTo(SI, Val);
333     SI->getName(S);
334   } else {
335     section_iterator SI = O->begin_sections();
336     advanceTo(SI, Val);
337     SI->getName(S);
338   }
339
340   fmt << S;
341 }
342
343 static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
344   return RE.Word0;
345 }
346
347 static unsigned
348 getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
349   return RE.Word0 & 0xffffff;
350 }
351
352 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
353                                     const macho::RelocationEntry &RE) {
354   if (O->isLittleEndian())
355     return (RE.Word1 >> 24) & 1;
356   return (RE.Word1 >> 7) & 1;
357 }
358
359 static bool
360 getScatteredRelocationPCRel(const MachOObjectFile *O,
361                             const macho::RelocationEntry &RE) {
362   return (RE.Word0 >> 30) & 1;
363 }
364
365 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
366                                          const macho::RelocationEntry &RE) {
367   if (O->isLittleEndian())
368     return (RE.Word1 >> 25) & 3;
369   return (RE.Word1 >> 5) & 3;
370 }
371
372 static unsigned
373 getScatteredRelocationLength(const macho::RelocationEntry &RE) {
374   return (RE.Word0 >> 28) & 3;
375 }
376
377 static unsigned getPlainRelocationType(const MachOObjectFile *O,
378                                        const macho::RelocationEntry &RE) {
379   if (O->isLittleEndian())
380     return RE.Word1 >> 28;
381   return RE.Word1 & 0xf;
382 }
383
384 static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
385   return (RE.Word0 >> 24) & 0xf;
386 }
387
388 static uint32_t getSectionFlags(const MachOObjectFile *O,
389                                 DataRefImpl Sec) {
390   if (O->is64Bit()) {
391     macho::Section64 Sect = O->getSection64(Sec);
392     return Sect.Flags;
393   }
394   macho::Section Sect = O->getSection(Sec);
395   return Sect.Flags;
396 }
397
398 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
399                                  bool IsLittleEndian, bool Is64bits,
400                                  error_code &ec)
401     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
402       SymtabLoadCmd(NULL) {
403   uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
404   macho::LoadCommandType SegmentLoadType = is64Bit() ?
405     macho::LCT_Segment64 : macho::LCT_Segment;
406
407   MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
408   for (unsigned I = 0; ; ++I) {
409     if (Load.C.Type == macho::LCT_Symtab) {
410       assert(!SymtabLoadCmd && "Multiple symbol tables");
411       SymtabLoadCmd = Load.Ptr;
412     }
413
414     if (Load.C.Type == SegmentLoadType) {
415       uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
416       for (unsigned J = 0; J < NumSections; ++J) {
417         const SectionBase *Sec = getSectionBase(this, Load, J);
418         Sections.push_back(reinterpret_cast<const char*>(Sec));
419       }
420     }
421
422     if (I == LoadCommandCount - 1)
423       break;
424     else
425       Load = getNextLoadCommandInfo(Load);
426   }
427 }
428
429 error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
430                                           SymbolRef &Res) const {
431   Symb.d.b++;
432   Res = SymbolRef(Symb, this);
433   return object_error::success;
434 }
435
436 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
437                                           StringRef &Res) const {
438   macho::SymtabLoadCommand S = getSymtabLoadCommand();
439   const char *StringTable = getPtr(this, S.StringTableOffset);
440   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
441   const char *Start = &StringTable[Entry.StringIndex];
442   Res = StringRef(Start);
443   return object_error::success;
444 }
445
446 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
447                                              uint64_t &Res) const {
448   if (is64Bit()) {
449     macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
450     Res = Entry.Value;
451   } else {
452     macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
453     Res = Entry.Value;
454   }
455   return object_error::success;
456 }
457
458 error_code
459 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
460                                      uint64_t &Res) const {
461   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
462   getSymbolAddress(Symb, Res);
463   if (Entry.SectionIndex) {
464     uint64_t Delta;
465     DataRefImpl SecRel;
466     SecRel.d.a = Entry.SectionIndex-1;
467     if (is64Bit()) {
468       macho::Section64 Sec = getSection64(SecRel);
469       Delta = Sec.Offset - Sec.Address;
470     } else {
471       macho::Section Sec = getSection(SecRel);
472       Delta = Sec.Offset - Sec.Address;
473     }
474
475     Res += Delta;
476   }
477
478   return object_error::success;
479 }
480
481 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
482                                           uint64_t &Result) const {
483   uint64_t BeginOffset;
484   uint64_t EndOffset = 0;
485   uint8_t SectionIndex;
486
487   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
488   uint64_t Value;
489   getSymbolAddress(DRI, Value);
490
491   BeginOffset = Value;
492
493   SectionIndex = Entry.SectionIndex;
494   if (!SectionIndex) {
495     uint32_t flags = SymbolRef::SF_None;
496     this->getSymbolFlags(DRI, flags);
497     if (flags & SymbolRef::SF_Common)
498       Result = Value;
499     else
500       Result = UnknownAddressOrSize;
501     return object_error::success;
502   }
503   // Unfortunately symbols are unsorted so we need to touch all
504   // symbols from load command
505   macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
506   DRI.d.b = 0;
507   while (DRI.d.b <= Symtab.NumSymbolTableEntries) {
508     Entry = getSymbolTableEntryBase(this, DRI);
509     getSymbolAddress(DRI, Value);
510     if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
511       if (!EndOffset || Value < EndOffset)
512         EndOffset = Value;
513     DRI.d.b++;
514   }
515   if (!EndOffset) {
516     uint64_t Size;
517     DataRefImpl Sec;
518     Sec.d.a = SectionIndex-1;
519     getSectionSize(Sec, Size);
520     getSectionAddress(Sec, EndOffset);
521     EndOffset += Size;
522   }
523   Result = EndOffset - BeginOffset;
524   return object_error::success;
525 }
526
527 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
528                                           SymbolRef::Type &Res) const {
529   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
530   uint8_t n_type = Entry.Type;
531
532   Res = SymbolRef::ST_Other;
533
534   // If this is a STAB debugging symbol, we can do nothing more.
535   if (n_type & MachO::NlistMaskStab) {
536     Res = SymbolRef::ST_Debug;
537     return object_error::success;
538   }
539
540   switch (n_type & MachO::NlistMaskType) {
541     case MachO::NListTypeUndefined :
542       Res = SymbolRef::ST_Unknown;
543       break;
544     case MachO::NListTypeSection :
545       Res = SymbolRef::ST_Function;
546       break;
547   }
548   return object_error::success;
549 }
550
551 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
552                                                 char &Res) const {
553   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
554   uint8_t Type = Entry.Type;
555   uint16_t Flags = Entry.Flags;
556
557   char Char;
558   switch (Type & macho::STF_TypeMask) {
559     case macho::STT_Undefined:
560       Char = 'u';
561       break;
562     case macho::STT_Absolute:
563     case macho::STT_Section:
564       Char = 's';
565       break;
566     default:
567       Char = '?';
568       break;
569   }
570
571   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
572     Char = toupper(static_cast<unsigned char>(Char));
573   Res = Char;
574   return object_error::success;
575 }
576
577 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
578                                            uint32_t &Result) const {
579   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
580
581   uint8_t MachOType = Entry.Type;
582   uint16_t MachOFlags = Entry.Flags;
583
584   // TODO: Correctly set SF_ThreadLocal
585   Result = SymbolRef::SF_None;
586
587   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
588     Result |= SymbolRef::SF_Undefined;
589
590   if (MachOFlags & macho::STF_StabsEntryMask)
591     Result |= SymbolRef::SF_FormatSpecific;
592
593   if (MachOType & MachO::NlistMaskExternal) {
594     Result |= SymbolRef::SF_Global;
595     if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
596       Result |= SymbolRef::SF_Common;
597   }
598
599   if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
600     Result |= SymbolRef::SF_Weak;
601
602   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
603     Result |= SymbolRef::SF_Absolute;
604
605   return object_error::success;
606 }
607
608 error_code
609 MachOObjectFile::getSymbolSection(DataRefImpl Symb,
610                                   section_iterator &Res) const {
611   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
612   uint8_t index = Entry.SectionIndex;
613
614   if (index == 0) {
615     Res = end_sections();
616   } else {
617     DataRefImpl DRI;
618     DRI.d.a = index - 1;
619     Res = section_iterator(SectionRef(DRI, this));
620   }
621
622   return object_error::success;
623 }
624
625 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
626                                                uint64_t &Val) const {
627   report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
628 }
629
630 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
631                                            SectionRef &Res) const {
632   Sec.d.a++;
633   Res = SectionRef(Sec, this);
634   return object_error::success;
635 }
636
637 error_code
638 MachOObjectFile::getSectionName(DataRefImpl Sec,
639                                     StringRef &Result) const {
640   ArrayRef<char> Raw = getSectionRawName(Sec);
641   Result = parseSegmentOrSectionName(Raw.data());
642   return object_error::success;
643 }
644
645 error_code
646 MachOObjectFile::getSectionAddress(DataRefImpl Sec,
647                                    uint64_t &Res) const {
648   if (is64Bit()) {
649     macho::Section64 Sect = getSection64(Sec);
650     Res = Sect.Address;
651   } else {
652     macho::Section Sect = getSection(Sec);
653     Res = Sect.Address;
654   }
655   return object_error::success;
656 }
657
658 error_code
659 MachOObjectFile::getSectionSize(DataRefImpl Sec,
660                                 uint64_t &Res) const {
661   if (is64Bit()) {
662     macho::Section64 Sect = getSection64(Sec);
663     Res = Sect.Size;
664   } else {
665     macho::Section Sect = getSection(Sec);
666     Res = Sect.Size;
667   }
668
669   return object_error::success;
670 }
671
672 error_code
673 MachOObjectFile::getSectionContents(DataRefImpl Sec,
674                                     StringRef &Res) const {
675   uint32_t Offset;
676   uint64_t Size;
677
678   if (is64Bit()) {
679     macho::Section64 Sect = getSection64(Sec);
680     Offset = Sect.Offset;
681     Size = Sect.Size;
682   } else {
683     macho::Section Sect =getSection(Sec);
684     Offset = Sect.Offset;
685     Size = Sect.Size;
686   }
687
688   Res = this->getData().substr(Offset, Size);
689   return object_error::success;
690 }
691
692 error_code
693 MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
694                                          uint64_t &Res) const {
695   uint32_t Align;
696   if (is64Bit()) {
697     macho::Section64 Sect = getSection64(Sec);
698     Align = Sect.Align;
699   } else {
700     macho::Section Sect = getSection(Sec);
701     Align = Sect.Align;
702   }
703
704   Res = uint64_t(1) << Align;
705   return object_error::success;
706 }
707
708 error_code
709 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
710   uint32_t Flags = getSectionFlags(this, Sec);
711   Res = Flags & macho::SF_PureInstructions;
712   return object_error::success;
713 }
714
715 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
716                                               bool &Result) const {
717   // FIXME: Unimplemented.
718   Result = false;
719   return object_error::success;
720 }
721
722 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
723                                              bool &Result) const {
724   // FIXME: Unimplemented.
725   Result = false;
726   return object_error::success;
727 }
728
729 error_code
730 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
731                                                    bool &Result) const {
732   // FIXME: Unimplemented.
733   Result = true;
734   return object_error::success;
735 }
736
737 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
738                                                  bool &Result) const {
739   // FIXME: Unimplemented.
740   Result = false;
741   return object_error::success;
742 }
743
744 error_code
745 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
746   uint32_t Flags = getSectionFlags(this, Sec);
747   unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
748   Res = SectionType == MachO::SectionTypeZeroFill ||
749     SectionType == MachO::SectionTypeZeroFillLarge;
750   return object_error::success;
751 }
752
753 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
754                                                       bool &Result) const {
755   // Consider using the code from isSectionText to look for __const sections.
756   // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
757   // to use section attributes to distinguish code from data.
758
759   // FIXME: Unimplemented.
760   Result = false;
761   return object_error::success;
762 }
763
764 error_code
765 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
766                                        DataRefImpl Symb,
767                                        bool &Result) const {
768   SymbolRef::Type ST;
769   this->getSymbolType(Symb, ST);
770   if (ST == SymbolRef::ST_Unknown) {
771     Result = false;
772     return object_error::success;
773   }
774
775   uint64_t SectBegin, SectEnd;
776   getSectionAddress(Sec, SectBegin);
777   getSectionSize(Sec, SectEnd);
778   SectEnd += SectBegin;
779
780   uint64_t SymAddr;
781   getSymbolAddress(Symb, SymAddr);
782   Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
783
784   return object_error::success;
785 }
786
787 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
788   DataRefImpl ret;
789   ret.d.b = Sec.d.a;
790   return relocation_iterator(RelocationRef(ret, this));
791 }
792
793 relocation_iterator
794 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
795   uint32_t LastReloc;
796   if (is64Bit()) {
797     macho::Section64 Sect = getSection64(Sec);
798     LastReloc = Sect.NumRelocationTableEntries;
799   } else {
800     macho::Section Sect = getSection(Sec);
801     LastReloc = Sect.NumRelocationTableEntries;
802   }
803
804   DataRefImpl Ret;
805   Ret.d.a = LastReloc;
806   Ret.d.b = Sec.d.a;
807   return relocation_iterator(RelocationRef(Ret, this));
808 }
809
810 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
811                                                   RelocationRef &Res) const {
812   ++Rel.d.a;
813   Res = RelocationRef(Rel, this);
814   return object_error::success;
815 }
816
817 error_code
818 MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
819                                       uint64_t &Res) const {
820   uint64_t SectAddress;
821   DataRefImpl Sec;
822   Sec.d.a = Rel.d.b;
823   if (is64Bit()) {
824     macho::Section64 Sect = getSection64(Sec);
825     SectAddress = Sect.Address;
826   } else {
827     macho::Section Sect = getSection(Sec);
828     SectAddress = Sect.Address;
829   }
830
831   macho::RelocationEntry RE = getRelocation(Rel);
832   uint64_t RelAddr = getAnyRelocationAddress(RE);
833   Res = SectAddress + RelAddr;
834   return object_error::success;
835 }
836
837 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
838                                                     uint64_t &Res) const {
839   macho::RelocationEntry RE = getRelocation(Rel);
840   Res = getAnyRelocationAddress(RE);
841   return object_error::success;
842 }
843
844 error_code
845 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
846                                          SymbolRef &Res) const {
847   macho::RelocationEntry RE = getRelocation(Rel);
848   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
849   bool isExtern = getPlainRelocationExternal(RE);
850
851   DataRefImpl Sym;
852   if (isExtern) {
853     Sym.d.b = SymbolIdx;
854   }
855   Res = SymbolRef(Sym, this);
856   return object_error::success;
857 }
858
859 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
860                                                   uint64_t &Res) const {
861   macho::RelocationEntry RE = getRelocation(Rel);
862   Res = getAnyRelocationType(RE);
863   return object_error::success;
864 }
865
866 error_code
867 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
868                                        SmallVectorImpl<char> &Result) const {
869   StringRef res;
870   uint64_t RType;
871   getRelocationType(Rel, RType);
872
873   unsigned Arch = this->getArch();
874
875   switch (Arch) {
876     case Triple::x86: {
877       static const char *const Table[] =  {
878         "GENERIC_RELOC_VANILLA",
879         "GENERIC_RELOC_PAIR",
880         "GENERIC_RELOC_SECTDIFF",
881         "GENERIC_RELOC_PB_LA_PTR",
882         "GENERIC_RELOC_LOCAL_SECTDIFF",
883         "GENERIC_RELOC_TLV" };
884
885       if (RType > 6)
886         res = "Unknown";
887       else
888         res = Table[RType];
889       break;
890     }
891     case Triple::x86_64: {
892       static const char *const Table[] =  {
893         "X86_64_RELOC_UNSIGNED",
894         "X86_64_RELOC_SIGNED",
895         "X86_64_RELOC_BRANCH",
896         "X86_64_RELOC_GOT_LOAD",
897         "X86_64_RELOC_GOT",
898         "X86_64_RELOC_SUBTRACTOR",
899         "X86_64_RELOC_SIGNED_1",
900         "X86_64_RELOC_SIGNED_2",
901         "X86_64_RELOC_SIGNED_4",
902         "X86_64_RELOC_TLV" };
903
904       if (RType > 9)
905         res = "Unknown";
906       else
907         res = Table[RType];
908       break;
909     }
910     case Triple::arm: {
911       static const char *const Table[] =  {
912         "ARM_RELOC_VANILLA",
913         "ARM_RELOC_PAIR",
914         "ARM_RELOC_SECTDIFF",
915         "ARM_RELOC_LOCAL_SECTDIFF",
916         "ARM_RELOC_PB_LA_PTR",
917         "ARM_RELOC_BR24",
918         "ARM_THUMB_RELOC_BR22",
919         "ARM_THUMB_32BIT_BRANCH",
920         "ARM_RELOC_HALF",
921         "ARM_RELOC_HALF_SECTDIFF" };
922
923       if (RType > 9)
924         res = "Unknown";
925       else
926         res = Table[RType];
927       break;
928     }
929     case Triple::ppc: {
930       static const char *const Table[] =  {
931         "PPC_RELOC_VANILLA",
932         "PPC_RELOC_PAIR",
933         "PPC_RELOC_BR14",
934         "PPC_RELOC_BR24",
935         "PPC_RELOC_HI16",
936         "PPC_RELOC_LO16",
937         "PPC_RELOC_HA16",
938         "PPC_RELOC_LO14",
939         "PPC_RELOC_SECTDIFF",
940         "PPC_RELOC_PB_LA_PTR",
941         "PPC_RELOC_HI16_SECTDIFF",
942         "PPC_RELOC_LO16_SECTDIFF",
943         "PPC_RELOC_HA16_SECTDIFF",
944         "PPC_RELOC_JBSR",
945         "PPC_RELOC_LO14_SECTDIFF",
946         "PPC_RELOC_LOCAL_SECTDIFF" };
947
948       res = Table[RType];
949       break;
950     }
951     case Triple::UnknownArch:
952       res = "Unknown";
953       break;
954   }
955   Result.append(res.begin(), res.end());
956   return object_error::success;
957 }
958
959 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
960                                                         int64_t &Res) const {
961   Res = 0;
962   return object_error::success;
963 }
964
965 error_code
966 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
967                                         SmallVectorImpl<char> &Result) const {
968   macho::RelocationEntry RE = getRelocation(Rel);
969
970   unsigned Arch = this->getArch();
971
972   std::string fmtbuf;
973   raw_string_ostream fmt(fmtbuf);
974   unsigned Type = this->getAnyRelocationType(RE);
975   bool IsPCRel = this->getAnyRelocationPCRel(RE);
976
977   // Determine any addends that should be displayed with the relocation.
978   // These require decoding the relocation type, which is triple-specific.
979
980   // X86_64 has entirely custom relocation types.
981   if (Arch == Triple::x86_64) {
982     bool isPCRel = getAnyRelocationPCRel(RE);
983
984     switch (Type) {
985       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
986       case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
987         printRelocationTargetName(this, RE, fmt);
988         fmt << "@GOT";
989         if (isPCRel) fmt << "PCREL";
990         break;
991       }
992       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
993         DataRefImpl RelNext = Rel;
994         RelNext.d.a++;
995         macho::RelocationEntry RENext = getRelocation(RelNext);
996
997         // X86_64_SUBTRACTOR must be followed by a relocation of type
998         // X86_64_RELOC_UNSIGNED.
999         // NOTE: Scattered relocations don't exist on x86_64.
1000         unsigned RType = getAnyRelocationType(RENext);
1001         if (RType != 0)
1002           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1003                              "X86_64_RELOC_SUBTRACTOR.");
1004
1005         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1006         // X86_64_SUBTRACTOR contains to the subtrahend.
1007         printRelocationTargetName(this, RENext, fmt);
1008         fmt << "-";
1009         printRelocationTargetName(this, RE, fmt);
1010         break;
1011       }
1012       case macho::RIT_X86_64_TLV:
1013         printRelocationTargetName(this, RE, fmt);
1014         fmt << "@TLV";
1015         if (isPCRel) fmt << "P";
1016         break;
1017       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1018         printRelocationTargetName(this, RE, fmt);
1019         fmt << "-1";
1020         break;
1021       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1022         printRelocationTargetName(this, RE, fmt);
1023         fmt << "-2";
1024         break;
1025       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1026         printRelocationTargetName(this, RE, fmt);
1027         fmt << "-4";
1028         break;
1029       default:
1030         printRelocationTargetName(this, RE, fmt);
1031         break;
1032     }
1033   // X86 and ARM share some relocation types in common.
1034   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1035     // Generic relocation types...
1036     switch (Type) {
1037       case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1038         return object_error::success;
1039       case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1040         DataRefImpl RelNext = Rel;
1041         RelNext.d.a++;
1042         macho::RelocationEntry RENext = getRelocation(RelNext);
1043
1044         // X86 sect diff's must be followed by a relocation of type
1045         // GENERIC_RELOC_PAIR.
1046         unsigned RType = getAnyRelocationType(RENext);
1047
1048         if (RType != 1)
1049           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1050                              "GENERIC_RELOC_SECTDIFF.");
1051
1052         printRelocationTargetName(this, RE, fmt);
1053         fmt << "-";
1054         printRelocationTargetName(this, RENext, fmt);
1055         break;
1056       }
1057     }
1058
1059     if (Arch == Triple::x86) {
1060       // All X86 relocations that need special printing were already
1061       // handled in the generic code.
1062       switch (Type) {
1063         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1064           DataRefImpl RelNext = Rel;
1065           RelNext.d.a++;
1066           macho::RelocationEntry RENext = getRelocation(RelNext);
1067
1068           // X86 sect diff's must be followed by a relocation of type
1069           // GENERIC_RELOC_PAIR.
1070           unsigned RType = getAnyRelocationType(RENext);
1071           if (RType != 1)
1072             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1073                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
1074
1075           printRelocationTargetName(this, RE, fmt);
1076           fmt << "-";
1077           printRelocationTargetName(this, RENext, fmt);
1078           break;
1079         }
1080         case macho::RIT_Generic_TLV: {
1081           printRelocationTargetName(this, RE, fmt);
1082           fmt << "@TLV";
1083           if (IsPCRel) fmt << "P";
1084           break;
1085         }
1086         default:
1087           printRelocationTargetName(this, RE, fmt);
1088       }
1089     } else { // ARM-specific relocations
1090       switch (Type) {
1091         case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
1092         case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1093           // Half relocations steal a bit from the length field to encode
1094           // whether this is an upper16 or a lower16 relocation.
1095           bool isUpper = getAnyRelocationLength(RE) >> 1;
1096
1097           if (isUpper)
1098             fmt << ":upper16:(";
1099           else
1100             fmt << ":lower16:(";
1101           printRelocationTargetName(this, RE, fmt);
1102
1103           DataRefImpl RelNext = Rel;
1104           RelNext.d.a++;
1105           macho::RelocationEntry RENext = getRelocation(RelNext);
1106
1107           // ARM half relocs must be followed by a relocation of type
1108           // ARM_RELOC_PAIR.
1109           unsigned RType = getAnyRelocationType(RENext);
1110           if (RType != 1)
1111             report_fatal_error("Expected ARM_RELOC_PAIR after "
1112                                "GENERIC_RELOC_HALF");
1113
1114           // NOTE: The half of the target virtual address is stashed in the
1115           // address field of the secondary relocation, but we can't reverse
1116           // engineer the constant offset from it without decoding the movw/movt
1117           // instruction to find the other half in its immediate field.
1118
1119           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1120           // symbol/section pointer of the follow-on relocation.
1121           if (Type == macho::RIT_ARM_HalfDifference) {
1122             fmt << "-";
1123             printRelocationTargetName(this, RENext, fmt);
1124           }
1125
1126           fmt << ")";
1127           break;
1128         }
1129         default: {
1130           printRelocationTargetName(this, RE, fmt);
1131         }
1132       }
1133     }
1134   } else
1135     printRelocationTargetName(this, RE, fmt);
1136
1137   fmt.flush();
1138   Result.append(fmtbuf.begin(), fmtbuf.end());
1139   return object_error::success;
1140 }
1141
1142 error_code
1143 MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1144                                      bool &Result) const {
1145   unsigned Arch = getArch();
1146   uint64_t Type;
1147   getRelocationType(Rel, Type);
1148
1149   Result = false;
1150
1151   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1152   // is always hidden.
1153   if (Arch == Triple::x86 || Arch == Triple::arm) {
1154     if (Type == macho::RIT_Pair) Result = true;
1155   } else if (Arch == Triple::x86_64) {
1156     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1157     // an X864_64_RELOC_SUBTRACTOR.
1158     if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1159       DataRefImpl RelPrev = Rel;
1160       RelPrev.d.a--;
1161       uint64_t PrevType;
1162       getRelocationType(RelPrev, PrevType);
1163       if (PrevType == macho::RIT_X86_64_Subtractor)
1164         Result = true;
1165     }
1166   }
1167
1168   return object_error::success;
1169 }
1170
1171 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1172                                                LibraryRef &Res) const {
1173   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1174 }
1175
1176 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1177                                                StringRef &Res) const {
1178   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1179 }
1180
1181 symbol_iterator MachOObjectFile::begin_symbols() const {
1182   // DRI.d.a = segment number; DRI.d.b = symbol index.
1183   DataRefImpl DRI;
1184   return symbol_iterator(SymbolRef(DRI, this));
1185 }
1186
1187 symbol_iterator MachOObjectFile::end_symbols() const {
1188   DataRefImpl DRI;
1189   if (SymtabLoadCmd) {
1190     macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1191     DRI.d.b = Symtab.NumSymbolTableEntries;
1192   }
1193   return symbol_iterator(SymbolRef(DRI, this));
1194 }
1195
1196 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1197   // TODO: implement
1198   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1199 }
1200
1201 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1202   // TODO: implement
1203   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1204 }
1205
1206 section_iterator MachOObjectFile::begin_sections() const {
1207   DataRefImpl DRI;
1208   return section_iterator(SectionRef(DRI, this));
1209 }
1210
1211 section_iterator MachOObjectFile::end_sections() const {
1212   DataRefImpl DRI;
1213   DRI.d.a = Sections.size();
1214   return section_iterator(SectionRef(DRI, this));
1215 }
1216
1217 library_iterator MachOObjectFile::begin_libraries_needed() const {
1218   // TODO: implement
1219   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1220 }
1221
1222 library_iterator MachOObjectFile::end_libraries_needed() const {
1223   // TODO: implement
1224   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1225 }
1226
1227 uint8_t MachOObjectFile::getBytesInAddress() const {
1228   return is64Bit() ? 8 : 4;
1229 }
1230
1231 StringRef MachOObjectFile::getFileFormatName() const {
1232   unsigned CPUType = getCPUType(this);
1233   if (!is64Bit()) {
1234     switch (CPUType) {
1235     case llvm::MachO::CPUTypeI386:
1236       return "Mach-O 32-bit i386";
1237     case llvm::MachO::CPUTypeARM:
1238       return "Mach-O arm";
1239     case llvm::MachO::CPUTypePowerPC:
1240       return "Mach-O 32-bit ppc";
1241     default:
1242       assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1243              "64-bit object file when we're not 64-bit?");
1244       return "Mach-O 32-bit unknown";
1245     }
1246   }
1247
1248   // Make sure the cpu type has the correct mask.
1249   assert((CPUType & llvm::MachO::CPUArchABI64)
1250          == llvm::MachO::CPUArchABI64 &&
1251          "32-bit object file when we're 64-bit?");
1252
1253   switch (CPUType) {
1254   case llvm::MachO::CPUTypeX86_64:
1255     return "Mach-O 64-bit x86-64";
1256   case llvm::MachO::CPUTypePowerPC64:
1257     return "Mach-O 64-bit ppc64";
1258   default:
1259     return "Mach-O 64-bit unknown";
1260   }
1261 }
1262
1263 unsigned MachOObjectFile::getArch() const {
1264   switch (getCPUType(this)) {
1265   case llvm::MachO::CPUTypeI386:
1266     return Triple::x86;
1267   case llvm::MachO::CPUTypeX86_64:
1268     return Triple::x86_64;
1269   case llvm::MachO::CPUTypeARM:
1270     return Triple::arm;
1271   case llvm::MachO::CPUTypePowerPC:
1272     return Triple::ppc;
1273   case llvm::MachO::CPUTypePowerPC64:
1274     return Triple::ppc64;
1275   default:
1276     return Triple::UnknownArch;
1277   }
1278 }
1279
1280 StringRef MachOObjectFile::getLoadName() const {
1281   // TODO: Implement
1282   report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1283 }
1284
1285 StringRef
1286 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1287   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1288   return parseSegmentOrSectionName(Raw.data());
1289 }
1290
1291 ArrayRef<char>
1292 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1293   const SectionBase *Base =
1294     reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1295   return ArrayRef<char>(Base->Name);
1296 }
1297
1298 ArrayRef<char>
1299 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1300   const SectionBase *Base =
1301     reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1302   return ArrayRef<char>(Base->SegmentName);
1303 }
1304
1305 bool
1306 MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
1307   const {
1308   if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
1309     return false;
1310   return getPlainRelocationAddress(RE) & macho::RF_Scattered;
1311 }
1312
1313 unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const {
1314   if (isLittleEndian())
1315     return RE.Word1 & 0xffffff;
1316   return RE.Word1 >> 8;
1317 }
1318
1319 bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const {
1320   if (isLittleEndian())
1321     return (RE.Word1 >> 27) & 1;
1322   return (RE.Word1 >> 4) & 1;
1323 }
1324
1325 bool
1326 MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const {
1327   return RE.Word0 >> 31;
1328 }
1329
1330 uint32_t
1331 MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const {
1332   return RE.Word1;
1333 }
1334
1335 unsigned
1336 MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const {
1337   if (isRelocationScattered(RE))
1338     return getScatteredRelocationAddress(RE);
1339   return getPlainRelocationAddress(RE);
1340 }
1341
1342 unsigned
1343 MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
1344   if (isRelocationScattered(RE))
1345     return getScatteredRelocationPCRel(this, RE);
1346   return getPlainRelocationPCRel(this, RE);
1347 }
1348
1349 unsigned
1350 MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const {
1351   if (isRelocationScattered(RE))
1352     return getScatteredRelocationLength(RE);
1353   return getPlainRelocationLength(this, RE);
1354 }
1355
1356 unsigned
1357 MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
1358   if (isRelocationScattered(RE))
1359     return getScatteredRelocationType(RE);
1360   return getPlainRelocationType(this, RE);
1361 }
1362
1363 MachOObjectFile::LoadCommandInfo
1364 MachOObjectFile::getFirstLoadCommandInfo() const {
1365   MachOObjectFile::LoadCommandInfo Load;
1366
1367   unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
1368   Load.Ptr = getPtr(this, HeaderSize);
1369   memcpy(&Load.C, Load.Ptr, sizeof(macho::LoadCommand));
1370   if (isSwappedEndian(this))
1371     SwapStruct(Load.C);
1372   return Load;
1373 }
1374
1375 MachOObjectFile::LoadCommandInfo
1376 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1377   MachOObjectFile::LoadCommandInfo Next;
1378   Next.Ptr = L.Ptr + L.C.Size;
1379   memcpy(&Next.C, Next.Ptr, sizeof(macho::LoadCommand));
1380   if (isSwappedEndian(this))
1381     SwapStruct(Next.C);
1382   return Next;
1383 }
1384
1385 macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
1386   const SectionBase *Addr =
1387     reinterpret_cast<const SectionBase*>(Sections[DRI.d.a]);
1388   macho::Section Ret;
1389   memcpy(&Ret, Addr, sizeof(macho::Section));
1390   if (isSwappedEndian(this))
1391     SwapStruct(Ret);
1392   return Ret;
1393 }
1394
1395 macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1396   const SectionBase *Addr =
1397     reinterpret_cast<const SectionBase*>(Sections[DRI.d.a]);
1398   macho::Section64 Ret;
1399   memcpy(&Ret, Addr, sizeof(macho::Section64));
1400   if (isSwappedEndian(this))
1401     SwapStruct(Ret);
1402   return Ret;
1403 }
1404
1405 macho::SymbolTableEntry
1406 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1407   const char *P = getSymbolTableEntryPtr(this, DRI);
1408   macho::SymbolTableEntry Ret;
1409   memcpy(&Ret, P, sizeof(macho::SymbolTableEntry));
1410   if (isSwappedEndian(this))
1411     SwapStruct(Ret);
1412   return Ret;
1413 }
1414
1415 macho::Symbol64TableEntry
1416 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1417   const char *P = getSymbolTableEntryPtr(this, DRI);
1418   macho::Symbol64TableEntry Ret;
1419   memcpy(&Ret, P, sizeof(macho::Symbol64TableEntry));
1420   if (isSwappedEndian(this))
1421     SwapStruct(Ret);
1422   return Ret;
1423 }
1424
1425 macho::LinkeditDataLoadCommand
1426 MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const {
1427   macho::LinkeditDataLoadCommand Cmd;
1428   memcpy(&Cmd, L.Ptr, sizeof(macho::LinkeditDataLoadCommand));
1429   if (isSwappedEndian(this))
1430     SwapStruct(Cmd);
1431   return Cmd;
1432 }
1433
1434 macho::RelocationEntry
1435 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1436   uint32_t RelOffset;
1437   DataRefImpl Sec;
1438   Sec.d.a = Rel.d.b;
1439   if (is64Bit()) {
1440     macho::Section64 Sect = getSection64(Sec);
1441     RelOffset = Sect.RelocationTableOffset;
1442   } else {
1443     macho::Section Sect = getSection(Sec);
1444     RelOffset = Sect.RelocationTableOffset;
1445   }
1446
1447   uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry);
1448
1449   macho::RelocationEntry Ret;
1450   memcpy(&Ret, getPtr(this, Offset), sizeof(macho::RelocationEntry));
1451   if (isSwappedEndian(this))
1452     SwapStruct(Ret);
1453
1454   return Ret;
1455 }
1456
1457 macho::Header MachOObjectFile::getHeader() const {
1458   macho::Header H;
1459   memcpy(&H, getPtr(this, 0), sizeof(macho::Header));
1460   if (isSwappedEndian(this))
1461     SwapStruct(H);
1462   return H;
1463 }
1464
1465 macho::SymtabLoadCommand
1466 MachOObjectFile::getSymtabLoadCommand() const {
1467   macho::SymtabLoadCommand Cmd;
1468   memcpy(&Cmd, SymtabLoadCmd, sizeof(macho::SymtabLoadCommand));
1469   if (isSwappedEndian(this))
1470     SwapStruct(Cmd);
1471   return Cmd;
1472 }
1473
1474 bool MachOObjectFile::is64Bit() const {
1475   return getType() == getMachOType(false, true) ||
1476     getType() == getMachOType(true, true);
1477 }
1478
1479 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1480                                    SmallVectorImpl<uint64_t> &Out) const {
1481   DataExtractor extractor(ObjectFile::getData(), true, 0);
1482
1483   uint32_t offset = Index;
1484   uint64_t data = 0;
1485   while (uint64_t delta = extractor.getULEB128(&offset)) {
1486     data += delta;
1487     Out.push_back(data);
1488   }
1489 }
1490
1491 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1492   StringRef Magic = Buffer->getBuffer().slice(0, 4);
1493   error_code ec;
1494   ObjectFile *Ret;
1495   if (Magic == "\xFE\xED\xFA\xCE")
1496     Ret = new MachOObjectFile(Buffer, false, false, ec);
1497   else if (Magic == "\xCE\xFA\xED\xFE")
1498     Ret = new MachOObjectFile(Buffer, true, false, ec);
1499   else if (Magic == "\xFE\xED\xFA\xCF")
1500     Ret = new MachOObjectFile(Buffer, false, true, ec);
1501   else if (Magic == "\xCF\xFA\xED\xFE")
1502     Ret = new MachOObjectFile(Buffer, true, true, ec);
1503   else
1504     return NULL;
1505
1506   if (ec)
1507     return NULL;
1508   return Ret;
1509 }
1510
1511 } // end namespace object
1512 } // end namespace llvm