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