Add 179294 back, but don't use bit fields so that it works on big endian hosts.
[oota-llvm.git] / include / llvm / Object / MachO.h
1 //===- MachO.h - MachO object file implementation ---------------*- 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 declares the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_OBJECT_MACHO_H
16 #define LLVM_OBJECT_MACHO_H
17
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/Triple.h"
21 #include "llvm/Object/MachOFormat.h"
22 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/raw_ostream.h"
26
27 namespace llvm {
28 namespace object {
29
30 using support::endianness;
31
32 template<endianness E, bool B>
33 struct MachOType {
34   static const endianness TargetEndianness = E;
35   static const bool Is64Bits = B;
36 };
37
38 template<endianness TargetEndianness>
39 struct MachODataTypeTypedefHelperCommon {
40   typedef support::detail::packed_endian_specific_integral
41     <uint16_t, TargetEndianness, support::unaligned> MachOInt16;
42   typedef support::detail::packed_endian_specific_integral
43     <uint32_t, TargetEndianness, support::unaligned> MachOInt32;
44   typedef support::detail::packed_endian_specific_integral
45     <uint64_t, TargetEndianness, support::unaligned> MachOInt64;
46 };
47
48 #define LLVM_MACHOB_IMPORT_TYPES(E)                                          \
49 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \
50 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \
51 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64;
52
53 template<class MachOT>
54 struct MachODataTypeTypedefHelper;
55
56 template<endianness TargetEndianness>
57 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, false> > {
58   typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
59   typedef typename Base::MachOInt32 MachOIntPtr;
60 };
61
62 template<endianness TargetEndianness>
63 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, true> > {
64   typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
65   typedef typename Base::MachOInt64 MachOIntPtr;
66 };
67
68 #define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B)                        \
69 LLVM_MACHOB_IMPORT_TYPES(E)                                          \
70 typedef typename                                                     \
71   MachODataTypeTypedefHelper <MachOT<E, B> >::MachOIntPtr MachOIntPtr;
72
73 namespace MachOFormat {
74   struct SectionBase {
75     char Name[16];
76     char SegmentName[16];
77   };
78
79   template<class MachOT>
80   struct Section;
81
82   template<endianness TargetEndianness>
83   struct Section<MachOType<TargetEndianness, false> > {
84     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
85     char Name[16];
86     char SegmentName[16];
87     MachOInt32 Address;
88     MachOInt32 Size;
89     MachOInt32 Offset;
90     MachOInt32 Align;
91     MachOInt32 RelocationTableOffset;
92     MachOInt32 NumRelocationTableEntries;
93     MachOInt32 Flags;
94     MachOInt32 Reserved1;
95     MachOInt32 Reserved2;
96   };
97
98   template<endianness TargetEndianness>
99   struct Section<MachOType<TargetEndianness, true> > {
100     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
101     char Name[16];
102     char SegmentName[16];
103     MachOInt64 Address;
104     MachOInt64 Size;
105     MachOInt32 Offset;
106     MachOInt32 Align;
107     MachOInt32 RelocationTableOffset;
108     MachOInt32 NumRelocationTableEntries;
109     MachOInt32 Flags;
110     MachOInt32 Reserved1;
111     MachOInt32 Reserved2;
112     MachOInt32 Reserved3;
113   };
114
115   struct MachOInt24 {
116     uint8_t bytes[3];
117     operator uint32_t() const {
118       return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
119     }
120   };
121
122   template<endianness TargetEndianness>
123   struct RelocationEntry {
124     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
125     MachOInt32 Address;
126     MachOInt24 SymbolNum;
127     uint8_t Bits;
128
129     unsigned getPCRel() const {
130       return Bits & 0x1;
131     }
132     unsigned getLength() const {
133       return (Bits >> 1) & 0x3;
134     }
135     unsigned getExternal() const {
136       return (Bits >> 3) & 0x1;
137     }
138     unsigned getType() const {
139       return Bits >> 4;
140     }
141   };
142
143   template<endianness TargetEndianness>
144   struct ScatteredRelocationEntry {
145     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
146     MachOInt24 Address;
147     uint8_t Bits;
148     MachOInt32 Value;
149
150     unsigned getType() const {
151       return Bits & 0xf;
152     }
153     unsigned getLength() const {
154       return (Bits >> 4) & 0x3;
155     }
156     unsigned getPCRel() const {
157       return (Bits >> 6) & 0x1;
158     }
159     unsigned getScattered() const {
160       return Bits >> 7;
161     }
162   };
163
164   template<endianness TargetEndianness>
165   struct SymbolTableEntryBase {
166     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
167     MachOInt32 StringIndex;
168     uint8_t Type;
169     uint8_t SectionIndex;
170     MachOInt16 Flags;
171   };
172
173   template<class MachOT>
174   struct SymbolTableEntry;
175
176   template<endianness TargetEndianness, bool Is64Bits>
177   struct SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > {
178     LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
179     MachOInt32 StringIndex;
180     uint8_t Type;
181     uint8_t SectionIndex;
182     MachOInt16 Flags;
183     MachOIntPtr Value;
184   };
185
186   template<endianness TargetEndianness>
187   struct LoadCommand {
188     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
189     MachOInt32 Type;
190     MachOInt32 Size;
191   };
192
193   template<endianness TargetEndianness>
194   struct SymtabLoadCommand {
195     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
196     MachOInt32 Type;
197     MachOInt32 Size;
198     MachOInt32 SymbolTableOffset;
199     MachOInt32 NumSymbolTableEntries;
200     MachOInt32 StringTableOffset;
201     MachOInt32 StringTableSize;
202   };
203
204   template<class MachOT>
205   struct SegmentLoadCommand;
206
207   template<endianness TargetEndianness, bool Is64Bits>
208   struct SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > {
209     LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
210     MachOInt32 Type;
211     MachOInt32 Size;
212     char Name[16];
213     MachOIntPtr VMAddress;
214     MachOIntPtr VMSize;
215     MachOIntPtr FileOffset;
216     MachOIntPtr FileSize;
217     MachOInt32 MaxVMProtection;
218     MachOInt32 InitialVMProtection;
219     MachOInt32 NumSections;
220     MachOInt32 Flags;
221   };
222
223   template<endianness TargetEndianness>
224   struct LinkeditDataLoadCommand {
225     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
226     MachOInt32 Type;
227     MachOInt32 Size;
228     MachOInt32 DataOffset;
229     MachOInt32 DataSize;
230   };
231
232   template<endianness TargetEndianness>
233   struct Header {
234     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
235     MachOInt32 Magic;
236     MachOInt32 CPUType;
237     MachOInt32 CPUSubtype;
238     MachOInt32 FileType;
239     MachOInt32 NumLoadCommands;
240     MachOInt32 SizeOfLoadCommands;
241     MachOInt32 Flags;
242   };
243 }
244
245 class MachOObjectFileBase : public ObjectFile {
246 public:
247   typedef MachOFormat::SymbolTableEntryBase<support::little>
248     SymbolTableEntryBase;
249   typedef MachOFormat::SymtabLoadCommand<support::little> SymtabLoadCommand;
250   typedef MachOFormat::RelocationEntry<support::little> RelocationEntry;
251   typedef MachOFormat::ScatteredRelocationEntry<support::little>
252     ScatteredRelocationEntry;
253   typedef MachOFormat::SectionBase SectionBase;
254   typedef MachOFormat::LoadCommand<support::little> LoadCommand;
255   typedef MachOFormat::Header<support::little> Header;
256   typedef MachOFormat::LinkeditDataLoadCommand<support::little>
257     LinkeditDataLoadCommand;
258
259   MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec);
260
261   virtual symbol_iterator begin_symbols() const;
262   virtual symbol_iterator end_symbols() const;
263   virtual symbol_iterator begin_dynamic_symbols() const;
264   virtual symbol_iterator end_dynamic_symbols() const;
265   virtual library_iterator begin_libraries_needed() const;
266   virtual library_iterator end_libraries_needed() const;
267   virtual section_iterator end_sections() const;
268
269   virtual uint8_t getBytesInAddress() const;
270   virtual StringRef getFileFormatName() const;
271   virtual unsigned getArch() const;
272   virtual StringRef getLoadName() const;
273
274   // In a MachO file, sections have a segment name. This is used in the .o
275   // files. They have a single segment, but this field specifies which segment
276   // a section should be put in in the final object.
277   StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
278
279   // Names are stored as 16 bytes. These returns the raw 16 bytes without
280   // interpreting them as a C string.
281   ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
282   ArrayRef<char>getSectionRawFinalSegmentName(DataRefImpl Sec) const;
283
284   bool is64Bit() const;
285   const LoadCommand *getLoadCommandInfo(unsigned Index) const;
286   void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
287   const Header *getHeader() const;
288   unsigned getHeaderSize() const;
289   StringRef getData(size_t Offset, size_t Size) const;
290   const RelocationEntry *getRelocation(DataRefImpl Rel) const;
291   bool isScattered(const RelocationEntry *RE) const;
292   bool isPCRel(const RelocationEntry *RE) const;
293   unsigned getLength(const RelocationEntry *RE) const;
294   unsigned getType(const RelocationEntry *RE) const;
295
296   static inline bool classof(const Binary *v) {
297     return v->isMachO();
298   }
299
300 protected:
301   virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
302   virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
303   virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
304   virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const;
305   virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const;
306   virtual error_code getSymbolSection(DataRefImpl Symb,
307                                       section_iterator &Res) const;
308   virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
309   virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
310   virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
311   virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
312   virtual error_code isSectionRequiredForExecution(DataRefImpl Sec,
313                                                    bool &Res) const;
314   virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const;
315   virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const;
316   virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
317
318   virtual error_code getRelocationNext(DataRefImpl Rel,
319                                        RelocationRef &Res) const;
320
321   virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const;
322   virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const;
323   virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
324                                                  int64_t &Res) const;
325
326   std::size_t getSectionIndex(DataRefImpl Sec) const;
327
328   typedef SmallVector<DataRefImpl, 1> SectionList;
329   SectionList Sections;
330
331   void moveToNextSymbol(DataRefImpl &DRI) const;
332   void printRelocationTargetName(const RelocationEntry *RE,
333                                  raw_string_ostream &fmt) const;
334   const SectionBase *getSectionBase(DataRefImpl DRI) const;
335   const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const;
336
337 private:
338
339   const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI,
340                                   const SymtabLoadCommand *SymtabLoadCmd) const;
341 };
342
343 template<class MachOT>
344 struct MachOObjectFileHelperCommon;
345
346 template<endianness TargetEndianness, bool Is64Bits>
347 struct MachOObjectFileHelperCommon<MachOType<TargetEndianness, Is64Bits> > {
348   typedef
349     MachOFormat::SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> >
350     SegmentLoadCommand;
351   typedef MachOFormat::SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> >
352     SymbolTableEntry;
353   typedef MachOFormat::Section<MachOType<TargetEndianness, Is64Bits> > Section;
354 };
355
356 template<class MachOT>
357 struct MachOObjectFileHelper;
358
359 template<endianness TargetEndianness>
360 struct MachOObjectFileHelper<MachOType<TargetEndianness, false> > :
361     public MachOObjectFileHelperCommon<MachOType<TargetEndianness, false> > {
362   static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment;
363 };
364
365 template<endianness TargetEndianness>
366 struct MachOObjectFileHelper<MachOType<TargetEndianness, true> > :
367     public MachOObjectFileHelperCommon<MachOType<TargetEndianness, true> > {
368   static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64;
369 };
370
371 template<class MachOT>
372 class MachOObjectFile : public MachOObjectFileBase {
373 public:
374   static const endianness TargetEndianness = MachOT::TargetEndianness;
375   static const bool Is64Bits = MachOT::Is64Bits;
376
377   typedef MachOObjectFileHelper<MachOT> Helper;
378   static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType;
379   typedef typename Helper::SegmentLoadCommand SegmentLoadCommand;
380   typedef typename Helper::SymbolTableEntry SymbolTableEntry;
381   typedef typename Helper::Section Section;
382
383   MachOObjectFile(MemoryBuffer *Object, error_code &ec);
384   static bool classof(const Binary *v);
385
386   const Section *getSection(DataRefImpl DRI) const;
387   const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const;
388   const RelocationEntry *getRelocation(DataRefImpl Rel) const;
389
390   virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
391   virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
392   virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
393   virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
394   virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
395   virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const;
396   virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
397   virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const;
398   virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const;
399   virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const;
400   virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const;
401   virtual error_code getRelocationTypeName(DataRefImpl Rel,
402                                            SmallVectorImpl<char> &Result) const;
403   virtual error_code getRelocationValueString(DataRefImpl Rel,
404                                            SmallVectorImpl<char> &Result) const;
405   virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const;
406   virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const;
407   virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
408                                            bool &Result) const;
409   virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
410   virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
411   virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
412   virtual section_iterator begin_sections() const;
413   void moveToNextSection(DataRefImpl &DRI) const;
414 };
415
416 template<class MachOT>
417 MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object,
418                                          error_code &ec) :
419   MachOObjectFileBase(Object, Is64Bits, ec) {
420   DataRefImpl DRI;
421   moveToNextSection(DRI);
422   uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
423   while (DRI.d.a < LoadCommandCount) {
424     Sections.push_back(DRI);
425     DRI.d.b++;
426     moveToNextSection(DRI);
427   }
428 }
429
430 template<class MachOT>
431 bool MachOObjectFile<MachOT>::classof(const Binary *v) {
432   return v->getType() == getMachOType(true, Is64Bits);
433 }
434
435 template<class MachOT>
436 const typename MachOObjectFile<MachOT>::Section *
437 MachOObjectFile<MachOT>::getSection(DataRefImpl DRI) const {
438   const SectionBase *Addr = getSectionBase(DRI);
439   return reinterpret_cast<const Section*>(Addr);
440 }
441
442 template<class MachOT>
443 const typename MachOObjectFile<MachOT>::SymbolTableEntry *
444 MachOObjectFile<MachOT>::getSymbolTableEntry(DataRefImpl DRI) const {
445   const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
446   return reinterpret_cast<const SymbolTableEntry*>(Base);
447 }
448
449 template<class MachOT>
450 const typename MachOObjectFile<MachOT>::RelocationEntry *
451 MachOObjectFile<MachOT>::getRelocation(DataRefImpl Rel) const {
452   const Section *Sect = getSection(Sections[Rel.d.b]);
453   uint32_t RelOffset = Sect->RelocationTableOffset;
454   uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry);
455   StringRef Data = getData(Offset, sizeof(RelocationEntry));
456   return reinterpret_cast<const RelocationEntry*>(Data.data());
457 }
458
459 template<class MachOT>
460 error_code
461 MachOObjectFile<MachOT>::getSectionAddress(DataRefImpl Sec,
462                                            uint64_t &Res) const {
463   const Section *Sect = getSection(Sec);
464   Res = Sect->Address;
465   return object_error::success;
466 }
467
468 template<class MachOT>
469 error_code
470 MachOObjectFile<MachOT>::getSectionSize(DataRefImpl Sec,
471                                         uint64_t &Res) const {
472   const Section *Sect = getSection(Sec);
473   Res = Sect->Size;
474   return object_error::success;
475 }
476
477 template<class MachOT>
478 error_code
479 MachOObjectFile<MachOT>::getSectionContents(DataRefImpl Sec,
480                                             StringRef &Res) const {
481   const Section *Sect = getSection(Sec);
482   Res = getData(Sect->Offset, Sect->Size);
483   return object_error::success;
484 }
485
486 template<class MachOT>
487 error_code
488 MachOObjectFile<MachOT>::getSectionAlignment(DataRefImpl Sec,
489                                              uint64_t &Res) const {
490   const Section *Sect = getSection(Sec);
491   Res = uint64_t(1) << Sect->Align;
492   return object_error::success;
493 }
494
495 template<class MachOT>
496 error_code
497 MachOObjectFile<MachOT>::isSectionText(DataRefImpl Sec, bool &Res) const {
498   const Section *Sect = getSection(Sec);
499   Res = Sect->Flags & macho::SF_PureInstructions;
500   return object_error::success;
501 }
502
503 template<class MachOT>
504 error_code
505 MachOObjectFile<MachOT>::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
506   const Section *Sect = getSection(Sec);
507   unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
508   Res = SectionType == MachO::SectionTypeZeroFill ||
509     SectionType == MachO::SectionTypeZeroFillLarge;
510   return object_error::success;
511 }
512
513 template<class MachOT>
514 relocation_iterator
515 MachOObjectFile<MachOT>::getSectionRelEnd(DataRefImpl Sec) const {
516   const Section *Sect = getSection(Sec);
517   uint32_t LastReloc = Sect->NumRelocationTableEntries;
518   DataRefImpl Ret;
519   Ret.d.a = LastReloc;
520   Ret.d.b = getSectionIndex(Sec);
521   return relocation_iterator(RelocationRef(Ret, this));
522 }
523
524 template<class MachOT>
525 error_code
526 MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel,
527                                               uint64_t &Res) const {
528   const Section *Sect = getSection(Sections[Rel.d.b]);
529   uint64_t SectAddress = Sect->Address;
530   const RelocationEntry *RE = getRelocation(Rel);
531
532   uint64_t RelAddr;
533   if (isScattered(RE))
534     RelAddr = RE->Address & 0xFFFFFF;
535   else
536     RelAddr = RE->Address;
537
538   Res = SectAddress + RelAddr;
539   return object_error::success;
540 }
541
542 template<class MachOT>
543 error_code
544 MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel,
545                                              uint64_t &Res) const {
546   const RelocationEntry *RE = getRelocation(Rel);
547   if (isScattered(RE))
548     Res = RE->Address & 0xFFFFFF;
549   else
550     Res = RE->Address;
551   return object_error::success;
552 }
553
554 template<class MachOT>
555 error_code
556 MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel,
557                                              SymbolRef &Res) const {
558   const RelocationEntry *RE = getRelocation(Rel);
559   uint32_t SymbolIdx = RE->SymbolNum;
560   bool isExtern = RE->getExternal();
561
562   DataRefImpl Sym;
563   moveToNextSymbol(Sym);
564   if (isExtern) {
565     for (unsigned i = 0; i < SymbolIdx; i++) {
566       Sym.d.b++;
567       moveToNextSymbol(Sym);
568       assert(Sym.d.a < getHeader()->NumLoadCommands &&
569              "Relocation symbol index out of range!");
570     }
571   }
572   Res = SymbolRef(Sym, this);
573   return object_error::success;
574 }
575
576 template<class MachOT>
577 error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel,
578                                                       uint64_t &Res) const {
579   const RelocationEntry *RE = getRelocation(Rel);
580   Res = getType(RE);
581   return object_error::success;
582 }
583
584 template<class MachOT>
585 error_code
586 MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel,
587                                           SmallVectorImpl<char> &Result) const {
588     // TODO: Support scattered relocations.
589   StringRef res;
590   const RelocationEntry *RE = getRelocation(Rel);
591
592   unsigned Arch = getArch();
593
594   unsigned r_type = getType(RE);
595
596   switch (Arch) {
597     case Triple::x86: {
598       static const char *const Table[] =  {
599         "GENERIC_RELOC_VANILLA",
600         "GENERIC_RELOC_PAIR",
601         "GENERIC_RELOC_SECTDIFF",
602         "GENERIC_RELOC_PB_LA_PTR",
603         "GENERIC_RELOC_LOCAL_SECTDIFF",
604         "GENERIC_RELOC_TLV" };
605
606       if (r_type > 6)
607         res = "Unknown";
608       else
609         res = Table[r_type];
610       break;
611     }
612     case Triple::x86_64: {
613       static const char *const Table[] =  {
614         "X86_64_RELOC_UNSIGNED",
615         "X86_64_RELOC_SIGNED",
616         "X86_64_RELOC_BRANCH",
617         "X86_64_RELOC_GOT_LOAD",
618         "X86_64_RELOC_GOT",
619         "X86_64_RELOC_SUBTRACTOR",
620         "X86_64_RELOC_SIGNED_1",
621         "X86_64_RELOC_SIGNED_2",
622         "X86_64_RELOC_SIGNED_4",
623         "X86_64_RELOC_TLV" };
624
625       if (r_type > 9)
626         res = "Unknown";
627       else
628         res = Table[r_type];
629       break;
630     }
631     case Triple::arm: {
632       static const char *const Table[] =  {
633         "ARM_RELOC_VANILLA",
634         "ARM_RELOC_PAIR",
635         "ARM_RELOC_SECTDIFF",
636         "ARM_RELOC_LOCAL_SECTDIFF",
637         "ARM_RELOC_PB_LA_PTR",
638         "ARM_RELOC_BR24",
639         "ARM_THUMB_RELOC_BR22",
640         "ARM_THUMB_32BIT_BRANCH",
641         "ARM_RELOC_HALF",
642         "ARM_RELOC_HALF_SECTDIFF" };
643
644       if (r_type > 9)
645         res = "Unknown";
646       else
647         res = Table[r_type];
648       break;
649     }
650     case Triple::ppc: {
651       static const char *const Table[] =  {
652         "PPC_RELOC_VANILLA",
653         "PPC_RELOC_PAIR",
654         "PPC_RELOC_BR14",
655         "PPC_RELOC_BR24",
656         "PPC_RELOC_HI16",
657         "PPC_RELOC_LO16",
658         "PPC_RELOC_HA16",
659         "PPC_RELOC_LO14",
660         "PPC_RELOC_SECTDIFF",
661         "PPC_RELOC_PB_LA_PTR",
662         "PPC_RELOC_HI16_SECTDIFF",
663         "PPC_RELOC_LO16_SECTDIFF",
664         "PPC_RELOC_HA16_SECTDIFF",
665         "PPC_RELOC_JBSR",
666         "PPC_RELOC_LO14_SECTDIFF",
667         "PPC_RELOC_LOCAL_SECTDIFF" };
668
669       res = Table[r_type];
670       break;
671     }
672     case Triple::UnknownArch:
673       res = "Unknown";
674       break;
675   }
676   Result.append(res.begin(), res.end());
677   return object_error::success;
678 }
679
680 template<class MachOT>
681 error_code
682 MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
683                                           SmallVectorImpl<char> &Result) const {
684   const RelocationEntry *RE = getRelocation(Rel);
685
686   unsigned Arch = getArch();
687   bool IsScattered = isScattered(RE);
688
689   std::string fmtbuf;
690   raw_string_ostream fmt(fmtbuf);
691
692   unsigned Type = getType(RE);
693   bool IsPCRel = isPCRel(RE);
694
695   // Determine any addends that should be displayed with the relocation.
696   // These require decoding the relocation type, which is triple-specific.
697
698   // X86_64 has entirely custom relocation types.
699   if (Arch == Triple::x86_64) {
700     bool isPCRel = RE->getPCRel();
701
702     switch (Type) {
703       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
704       case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
705         printRelocationTargetName(RE, fmt);
706         fmt << "@GOT";
707         if (isPCRel) fmt << "PCREL";
708         break;
709       }
710       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
711         DataRefImpl RelNext = Rel;
712         RelNext.d.a++;
713         const RelocationEntry *RENext = getRelocation(RelNext);
714
715         // X86_64_SUBTRACTOR must be followed by a relocation of type
716         // X86_64_RELOC_UNSIGNED.
717         // NOTE: Scattered relocations don't exist on x86_64.
718         unsigned RType = RENext->getType();
719         if (RType != 0)
720           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
721                              "X86_64_RELOC_SUBTRACTOR.");
722
723         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
724         // X86_64_SUBTRACTOR contains to the subtrahend.
725         printRelocationTargetName(RENext, fmt);
726         fmt << "-";
727         printRelocationTargetName(RE, fmt);
728         break;
729       }
730       case macho::RIT_X86_64_TLV:
731         printRelocationTargetName(RE, fmt);
732         fmt << "@TLV";
733         if (isPCRel) fmt << "P";
734         break;
735       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
736         printRelocationTargetName(RE, fmt);
737         fmt << "-1";
738         break;
739       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
740         printRelocationTargetName(RE, fmt);
741         fmt << "-2";
742         break;
743       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
744         printRelocationTargetName(RE, fmt);
745         fmt << "-4";
746         break;
747       default:
748         printRelocationTargetName(RE, fmt);
749         break;
750     }
751   // X86 and ARM share some relocation types in common.
752   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
753     // Generic relocation types...
754     switch (Type) {
755       case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
756         return object_error::success;
757       case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
758         DataRefImpl RelNext = Rel;
759         RelNext.d.a++;
760         const RelocationEntry *RENext = getRelocation(RelNext);
761
762         // X86 sect diff's must be followed by a relocation of type
763         // GENERIC_RELOC_PAIR.
764         bool isNextScattered = (Arch != Triple::x86_64) &&
765                                (RENext->Address & macho::RF_Scattered);
766         unsigned RType;
767         if (isNextScattered)
768           RType = (RENext->Address >> 24) & 0xF;
769         else
770           RType = RENext->getType();
771         if (RType != 1)
772           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
773                              "GENERIC_RELOC_SECTDIFF.");
774
775         printRelocationTargetName(RE, fmt);
776         fmt << "-";
777         printRelocationTargetName(RENext, fmt);
778         break;
779       }
780     }
781
782     if (Arch == Triple::x86) {
783       // All X86 relocations that need special printing were already
784       // handled in the generic code.
785       switch (Type) {
786         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
787           DataRefImpl RelNext = Rel;
788           RelNext.d.a++;
789           const RelocationEntry *RENext = getRelocation(RelNext);
790
791           // X86 sect diff's must be followed by a relocation of type
792           // GENERIC_RELOC_PAIR.
793           bool isNextScattered = (Arch != Triple::x86_64) &&
794                                (RENext->Address & macho::RF_Scattered);
795           unsigned RType;
796           if (isNextScattered)
797             RType = (RENext->Address >> 24) & 0xF;
798           else
799             RType = RENext->getType();
800           if (RType != 1)
801             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
802                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
803
804           printRelocationTargetName(RE, fmt);
805           fmt << "-";
806           printRelocationTargetName(RENext, fmt);
807           break;
808         }
809         case macho::RIT_Generic_TLV: {
810           printRelocationTargetName(RE, fmt);
811           fmt << "@TLV";
812           if (IsPCRel) fmt << "P";
813           break;
814         }
815         default:
816           printRelocationTargetName(RE, fmt);
817       }
818     } else { // ARM-specific relocations
819       switch (Type) {
820         case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
821         case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
822           // Half relocations steal a bit from the length field to encode
823           // whether this is an upper16 or a lower16 relocation.
824           bool isUpper;
825           if (IsScattered)
826             isUpper = (RE->Address >> 28) & 1;
827           else
828             isUpper = (RE->getLength() >> 1) & 1;
829
830           if (isUpper)
831             fmt << ":upper16:(";
832           else
833             fmt << ":lower16:(";
834           printRelocationTargetName(RE, fmt);
835
836           DataRefImpl RelNext = Rel;
837           RelNext.d.a++;
838           const RelocationEntry *RENext = getRelocation(RelNext);
839
840           // ARM half relocs must be followed by a relocation of type
841           // ARM_RELOC_PAIR.
842           bool isNextScattered = (Arch != Triple::x86_64) &&
843                                  (RENext->Address & macho::RF_Scattered);
844           unsigned RType;
845           if (isNextScattered)
846             RType = (RENext->Address >> 24) & 0xF;
847           else
848             RType = RENext->getType();
849
850           if (RType != 1)
851             report_fatal_error("Expected ARM_RELOC_PAIR after "
852                                "GENERIC_RELOC_HALF");
853
854           // NOTE: The half of the target virtual address is stashed in the
855           // address field of the secondary relocation, but we can't reverse
856           // engineer the constant offset from it without decoding the movw/movt
857           // instruction to find the other half in its immediate field.
858
859           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
860           // symbol/section pointer of the follow-on relocation.
861           if (Type == macho::RIT_ARM_HalfDifference) {
862             fmt << "-";
863             printRelocationTargetName(RENext, fmt);
864           }
865
866           fmt << ")";
867           break;
868         }
869         default: {
870           printRelocationTargetName(RE, fmt);
871         }
872       }
873     }
874   } else
875     printRelocationTargetName(RE, fmt);
876
877   fmt.flush();
878   Result.append(fmtbuf.begin(), fmtbuf.end());
879   return object_error::success;
880 }
881
882 template<class MachOT>
883 error_code
884 MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
885                                              bool &Result) const {
886   const RelocationEntry *RE = getRelocation(Rel);
887   unsigned Arch = getArch();
888   unsigned Type = getType(RE);
889
890   Result = false;
891
892   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
893   // is always hidden.
894   if (Arch == Triple::x86 || Arch == Triple::arm) {
895     if (Type == macho::RIT_Pair) Result = true;
896   } else if (Arch == Triple::x86_64) {
897     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
898     // an X864_64_RELOC_SUBTRACTOR.
899     if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
900       DataRefImpl RelPrev = Rel;
901       RelPrev.d.a--;
902       const RelocationEntry *REPrev = getRelocation(RelPrev);
903
904       unsigned PrevType = REPrev->getType();
905
906       if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
907     }
908   }
909
910   return object_error::success;
911 }
912
913 template<class MachOT>
914 error_code
915 MachOObjectFile<MachOT>::getSymbolFileOffset(DataRefImpl Symb,
916                                              uint64_t &Res) const {
917   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
918   Res = Entry->Value;
919   if (Entry->SectionIndex) {
920     const Section *Sec = getSection(Sections[Entry->SectionIndex-1]);
921     Res += Sec->Offset - Sec->Address;
922   }
923
924   return object_error::success;
925 }
926
927 template<class MachOT>
928 error_code
929 MachOObjectFile<MachOT>::sectionContainsSymbol(DataRefImpl Sec,
930                                                DataRefImpl Symb,
931                                                bool &Result) const {
932   SymbolRef::Type ST;
933   getSymbolType(Symb, ST);
934   if (ST == SymbolRef::ST_Unknown) {
935     Result = false;
936     return object_error::success;
937   }
938
939   uint64_t SectBegin, SectEnd;
940   getSectionAddress(Sec, SectBegin);
941   getSectionSize(Sec, SectEnd);
942   SectEnd += SectBegin;
943
944   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
945   uint64_t SymAddr= Entry->Value;
946   Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
947
948   return object_error::success;
949 }
950
951 template<class MachOT>
952 error_code MachOObjectFile<MachOT>::getSymbolAddress(DataRefImpl Symb,
953                                                      uint64_t &Res) const {
954   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
955   Res = Entry->Value;
956   return object_error::success;
957 }
958
959 template<class MachOT>
960 error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI,
961                                                     uint64_t &Result) const {
962   uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
963   uint64_t BeginOffset;
964   uint64_t EndOffset = 0;
965   uint8_t SectionIndex;
966
967   const SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
968   BeginOffset = Entry->Value;
969   SectionIndex = Entry->SectionIndex;
970   if (!SectionIndex) {
971     uint32_t flags = SymbolRef::SF_None;
972     getSymbolFlags(DRI, flags);
973     if (flags & SymbolRef::SF_Common)
974       Result = Entry->Value;
975     else
976       Result = UnknownAddressOrSize;
977     return object_error::success;
978   }
979   // Unfortunately symbols are unsorted so we need to touch all
980   // symbols from load command
981   DRI.d.b = 0;
982   uint32_t Command = DRI.d.a;
983   while (Command == DRI.d.a) {
984     moveToNextSymbol(DRI);
985     if (DRI.d.a < LoadCommandCount) {
986       Entry = getSymbolTableEntry(DRI);
987       if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
988         if (!EndOffset || Entry->Value < EndOffset)
989           EndOffset = Entry->Value;
990     }
991     DRI.d.b++;
992   }
993   if (!EndOffset) {
994     uint64_t Size;
995     getSectionSize(Sections[SectionIndex-1], Size);
996     getSectionAddress(Sections[SectionIndex-1], EndOffset);
997     EndOffset += Size;
998   }
999   Result = EndOffset - BeginOffset;
1000   return object_error::success;
1001 }
1002
1003 template<class MachOT>
1004 error_code MachOObjectFile<MachOT>::getSectionNext(DataRefImpl Sec,
1005                                                    SectionRef &Res) const {
1006   Sec.d.b++;
1007   moveToNextSection(Sec);
1008   Res = SectionRef(Sec, this);
1009   return object_error::success;
1010 }
1011
1012 template<class MachOT>
1013 section_iterator MachOObjectFile<MachOT>::begin_sections() const {
1014   DataRefImpl DRI;
1015   moveToNextSection(DRI);
1016   return section_iterator(SectionRef(DRI, this));
1017 }
1018
1019 template<class MachOT>
1020 void MachOObjectFile<MachOT>::moveToNextSection(DataRefImpl &DRI) const {
1021   uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
1022   while (DRI.d.a < LoadCommandCount) {
1023     const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
1024     if (Command->Type == SegmentLoadType) {
1025       const SegmentLoadCommand *SegmentLoadCmd =
1026         reinterpret_cast<const SegmentLoadCommand*>(Command);
1027       if (DRI.d.b < SegmentLoadCmd->NumSections)
1028         return;
1029     }
1030
1031     DRI.d.a++;
1032     DRI.d.b = 0;
1033   }
1034 }
1035
1036   typedef MachOObjectFile<MachOType<support::little, false> >
1037     MachOObjectFile32Le;
1038   typedef MachOObjectFile<MachOType<support::little, true> >
1039     MachOObjectFile64Le;
1040 }
1041 }
1042
1043 #endif
1044