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