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