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