MachOObjectFile.cpp revision bc884fd9f7bdb64d250be639edc8dc85a20a1975
1//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- 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 defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/Object/MachO.h"
16#include "llvm/ADT/Triple.h"
17#include "llvm/Support/DataExtractor.h"
18#include "llvm/Support/Format.h"
19#include "llvm/Support/Host.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/raw_ostream.h"
22#include <cctype>
23#include <cstring>
24#include <limits>
25
26using namespace llvm;
27using namespace object;
28
29namespace llvm {
30namespace object {
31
32struct nlist_base {
33  uint32_t n_strx;
34  uint8_t n_type;
35  uint8_t n_sect;
36  uint16_t n_desc;
37};
38
39struct section_base {
40  char sectname[16];
41  char segname[16];
42};
43
44template<typename T>
45static void SwapValue(T &Value) {
46  Value = sys::SwapByteOrder(Value);
47}
48
49template<typename T>
50static void SwapStruct(T &Value);
51
52template<>
53void SwapStruct(MachO::any_relocation_info &H) {
54  SwapValue(H.r_word0);
55  SwapValue(H.r_word1);
56}
57
58template<>
59void SwapStruct(MachO::load_command &L) {
60  SwapValue(L.cmd);
61  SwapValue(L.cmdsize);
62}
63
64template<>
65void SwapStruct(nlist_base &S) {
66  SwapValue(S.n_strx);
67  SwapValue(S.n_desc);
68}
69
70template<>
71void SwapStruct(MachO::section &S) {
72  SwapValue(S.addr);
73  SwapValue(S.size);
74  SwapValue(S.offset);
75  SwapValue(S.align);
76  SwapValue(S.reloff);
77  SwapValue(S.nreloc);
78  SwapValue(S.flags);
79  SwapValue(S.reserved1);
80  SwapValue(S.reserved2);
81}
82
83template<>
84void SwapStruct(MachO::section_64 &S) {
85  SwapValue(S.addr);
86  SwapValue(S.size);
87  SwapValue(S.offset);
88  SwapValue(S.align);
89  SwapValue(S.reloff);
90  SwapValue(S.nreloc);
91  SwapValue(S.flags);
92  SwapValue(S.reserved1);
93  SwapValue(S.reserved2);
94  SwapValue(S.reserved3);
95}
96
97template<>
98void SwapStruct(MachO::nlist &S) {
99  SwapValue(S.n_strx);
100  SwapValue(S.n_desc);
101  SwapValue(S.n_value);
102}
103
104template<>
105void SwapStruct(MachO::nlist_64 &S) {
106  SwapValue(S.n_strx);
107  SwapValue(S.n_desc);
108  SwapValue(S.n_value);
109}
110
111template<>
112void SwapStruct(MachO::mach_header &H) {
113  SwapValue(H.magic);
114  SwapValue(H.cputype);
115  SwapValue(H.cpusubtype);
116  SwapValue(H.filetype);
117  SwapValue(H.ncmds);
118  SwapValue(H.sizeofcmds);
119  SwapValue(H.flags);
120}
121
122template<>
123void SwapStruct(MachO::mach_header_64 &H) {
124  SwapValue(H.magic);
125  SwapValue(H.cputype);
126  SwapValue(H.cpusubtype);
127  SwapValue(H.filetype);
128  SwapValue(H.ncmds);
129  SwapValue(H.sizeofcmds);
130  SwapValue(H.flags);
131  SwapValue(H.reserved);
132}
133
134template<>
135void SwapStruct(MachO::symtab_command &C) {
136  SwapValue(C.cmd);
137  SwapValue(C.cmdsize);
138  SwapValue(C.symoff);
139  SwapValue(C.nsyms);
140  SwapValue(C.stroff);
141  SwapValue(C.strsize);
142}
143
144template<>
145void SwapStruct(MachO::dysymtab_command &C) {
146  SwapValue(C.cmd);
147  SwapValue(C.cmdsize);
148  SwapValue(C.ilocalsym);
149  SwapValue(C.nlocalsym);
150  SwapValue(C.iextdefsym);
151  SwapValue(C.nextdefsym);
152  SwapValue(C.iundefsym);
153  SwapValue(C.nundefsym);
154  SwapValue(C.tocoff);
155  SwapValue(C.ntoc);
156  SwapValue(C.modtaboff);
157  SwapValue(C.nmodtab);
158  SwapValue(C.extrefsymoff);
159  SwapValue(C.nextrefsyms);
160  SwapValue(C.indirectsymoff);
161  SwapValue(C.nindirectsyms);
162  SwapValue(C.extreloff);
163  SwapValue(C.nextrel);
164  SwapValue(C.locreloff);
165  SwapValue(C.nlocrel);
166}
167
168template<>
169void SwapStruct(MachO::linkedit_data_command &C) {
170  SwapValue(C.cmd);
171  SwapValue(C.cmdsize);
172  SwapValue(C.dataoff);
173  SwapValue(C.datasize);
174}
175
176template<>
177void SwapStruct(MachO::segment_command &C) {
178  SwapValue(C.cmd);
179  SwapValue(C.cmdsize);
180  SwapValue(C.vmaddr);
181  SwapValue(C.vmsize);
182  SwapValue(C.fileoff);
183  SwapValue(C.filesize);
184  SwapValue(C.maxprot);
185  SwapValue(C.initprot);
186  SwapValue(C.nsects);
187  SwapValue(C.flags);
188}
189
190template<>
191void SwapStruct(MachO::segment_command_64 &C) {
192  SwapValue(C.cmd);
193  SwapValue(C.cmdsize);
194  SwapValue(C.vmaddr);
195  SwapValue(C.vmsize);
196  SwapValue(C.fileoff);
197  SwapValue(C.filesize);
198  SwapValue(C.maxprot);
199  SwapValue(C.initprot);
200  SwapValue(C.nsects);
201  SwapValue(C.flags);
202}
203
204template<>
205void SwapStruct(uint32_t &C) {
206  SwapValue(C);
207}
208
209template<>
210void SwapStruct(MachO::linker_options_command &C) {
211  SwapValue(C.cmd);
212  SwapValue(C.cmdsize);
213  SwapValue(C.count);
214}
215
216template<>
217void SwapStruct(MachO::data_in_code_entry &C) {
218  SwapValue(C.offset);
219  SwapValue(C.length);
220  SwapValue(C.kind);
221}
222
223template<typename T>
224T getStruct(const MachOObjectFile *O, const char *P) {
225  T Cmd;
226  memcpy(&Cmd, P, sizeof(T));
227  if (O->isLittleEndian() != sys::IsLittleEndianHost)
228    SwapStruct(Cmd);
229  return Cmd;
230}
231
232static uint32_t
233getSegmentLoadCommandNumSections(const MachOObjectFile *O,
234                                 const MachOObjectFile::LoadCommandInfo &L) {
235  if (O->is64Bit()) {
236    MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
237    return S.nsects;
238  }
239  MachO::segment_command S = O->getSegmentLoadCommand(L);
240  return S.nsects;
241}
242
243static const char *
244getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
245              unsigned Sec) {
246  uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
247
248  bool Is64 = O->is64Bit();
249  unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
250                                    sizeof(MachO::segment_command);
251  unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
252                                sizeof(MachO::section);
253
254  uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
255  return reinterpret_cast<const char*>(SectionAddr);
256}
257
258static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
259  return O->getData().substr(Offset, 1).data();
260}
261
262static nlist_base
263getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
264  const char *P = reinterpret_cast<const char *>(DRI.p);
265  return getStruct<nlist_base>(O, P);
266}
267
268static StringRef parseSegmentOrSectionName(const char *P) {
269  if (P[15] == 0)
270    // Null terminated.
271    return P;
272  // Not null terminated, so this is a 16 char string.
273  return StringRef(P, 16);
274}
275
276// Helper to advance a section or symbol iterator multiple increments at a time.
277template<class T>
278static error_code advance(T &it, size_t Val) {
279  error_code ec;
280  while (Val--) {
281    it.increment(ec);
282  }
283  return ec;
284}
285
286template<class T>
287static void advanceTo(T &it, size_t Val) {
288  if (error_code ec = advance(it, Val))
289    report_fatal_error(ec.message());
290}
291
292static unsigned getCPUType(const MachOObjectFile *O) {
293  return O->getHeader().cputype;
294}
295
296static void printRelocationTargetName(const MachOObjectFile *O,
297                                      const MachO::any_relocation_info &RE,
298                                      raw_string_ostream &fmt) {
299  bool IsScattered = O->isRelocationScattered(RE);
300
301  // Target of a scattered relocation is an address.  In the interest of
302  // generating pretty output, scan through the symbol table looking for a
303  // symbol that aligns with that address.  If we find one, print it.
304  // Otherwise, we just print the hex address of the target.
305  if (IsScattered) {
306    uint32_t Val = O->getPlainRelocationSymbolNum(RE);
307
308    error_code ec;
309    for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
310         SI != SE; SI.increment(ec)) {
311      if (ec) report_fatal_error(ec.message());
312
313      uint64_t Addr;
314      StringRef Name;
315
316      if ((ec = SI->getAddress(Addr)))
317        report_fatal_error(ec.message());
318      if (Addr != Val) continue;
319      if ((ec = SI->getName(Name)))
320        report_fatal_error(ec.message());
321      fmt << Name;
322      return;
323    }
324
325    // If we couldn't find a symbol that this relocation refers to, try
326    // to find a section beginning instead.
327    for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
328         SI != SE; SI.increment(ec)) {
329      if (ec) report_fatal_error(ec.message());
330
331      uint64_t Addr;
332      StringRef Name;
333
334      if ((ec = SI->getAddress(Addr)))
335        report_fatal_error(ec.message());
336      if (Addr != Val) continue;
337      if ((ec = SI->getName(Name)))
338        report_fatal_error(ec.message());
339      fmt << Name;
340      return;
341    }
342
343    fmt << format("0x%x", Val);
344    return;
345  }
346
347  StringRef S;
348  bool isExtern = O->getPlainRelocationExternal(RE);
349  uint64_t Val = O->getPlainRelocationSymbolNum(RE);
350
351  if (isExtern) {
352    symbol_iterator SI = O->begin_symbols();
353    advanceTo(SI, Val);
354    SI->getName(S);
355  } else {
356    section_iterator SI = O->begin_sections();
357    // Adjust for the fact that sections are 1-indexed.
358    advanceTo(SI, Val - 1);
359    SI->getName(S);
360  }
361
362  fmt << S;
363}
364
365static uint32_t
366getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
367  return RE.r_word0;
368}
369
370static unsigned
371getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
372  return RE.r_word0 & 0xffffff;
373}
374
375static bool getPlainRelocationPCRel(const MachOObjectFile *O,
376                                    const MachO::any_relocation_info &RE) {
377  if (O->isLittleEndian())
378    return (RE.r_word1 >> 24) & 1;
379  return (RE.r_word1 >> 7) & 1;
380}
381
382static bool
383getScatteredRelocationPCRel(const MachOObjectFile *O,
384                            const MachO::any_relocation_info &RE) {
385  return (RE.r_word0 >> 30) & 1;
386}
387
388static unsigned getPlainRelocationLength(const MachOObjectFile *O,
389                                         const MachO::any_relocation_info &RE) {
390  if (O->isLittleEndian())
391    return (RE.r_word1 >> 25) & 3;
392  return (RE.r_word1 >> 5) & 3;
393}
394
395static unsigned
396getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
397  return (RE.r_word0 >> 28) & 3;
398}
399
400static unsigned getPlainRelocationType(const MachOObjectFile *O,
401                                       const MachO::any_relocation_info &RE) {
402  if (O->isLittleEndian())
403    return RE.r_word1 >> 28;
404  return RE.r_word1 & 0xf;
405}
406
407static unsigned
408getScatteredRelocationType(const MachO::any_relocation_info &RE) {
409  return (RE.r_word0 >> 24) & 0xf;
410}
411
412static uint32_t getSectionFlags(const MachOObjectFile *O,
413                                DataRefImpl Sec) {
414  if (O->is64Bit()) {
415    MachO::section_64 Sect = O->getSection64(Sec);
416    return Sect.flags;
417  }
418  MachO::section Sect = O->getSection(Sec);
419  return Sect.flags;
420}
421
422MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
423                                 bool IsLittleEndian, bool Is64bits,
424                                 error_code &ec)
425    : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
426      SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) {
427  uint32_t LoadCommandCount = this->getHeader().ncmds;
428  MachO::LoadCommandType SegmentLoadType = is64Bit() ?
429    MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
430
431  MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
432  for (unsigned I = 0; ; ++I) {
433    if (Load.C.cmd == MachO::LC_SYMTAB) {
434      assert(!SymtabLoadCmd && "Multiple symbol tables");
435      SymtabLoadCmd = Load.Ptr;
436    } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
437      assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
438      DysymtabLoadCmd = Load.Ptr;
439    } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
440      assert(!DataInCodeLoadCmd && "Multiple data in code tables");
441      DataInCodeLoadCmd = Load.Ptr;
442    } else if (Load.C.cmd == SegmentLoadType) {
443      uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
444      for (unsigned J = 0; J < NumSections; ++J) {
445        const char *Sec = getSectionPtr(this, Load, J);
446        Sections.push_back(Sec);
447      }
448    }
449
450    if (I == LoadCommandCount - 1)
451      break;
452    else
453      Load = getNextLoadCommandInfo(Load);
454  }
455}
456
457error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
458                                          SymbolRef &Res) const {
459  unsigned SymbolTableEntrySize = is64Bit() ?
460    sizeof(MachO::nlist_64) :
461    sizeof(MachO::nlist);
462  Symb.p += SymbolTableEntrySize;
463  Res = SymbolRef(Symb, this);
464  return object_error::success;
465}
466
467error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
468                                          StringRef &Res) const {
469  StringRef StringTable = getStringTableData();
470  nlist_base Entry = getSymbolTableEntryBase(this, Symb);
471  const char *Start = &StringTable.data()[Entry.n_strx];
472  Res = StringRef(Start);
473  return object_error::success;
474}
475
476error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
477                                             uint64_t &Res) const {
478  if (is64Bit()) {
479    MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
480    Res = Entry.n_value;
481  } else {
482    MachO::nlist Entry = getSymbolTableEntry(Symb);
483    Res = Entry.n_value;
484  }
485  return object_error::success;
486}
487
488error_code
489MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
490                                     uint64_t &Res) const {
491  nlist_base Entry = getSymbolTableEntryBase(this, Symb);
492  getSymbolAddress(Symb, Res);
493  if (Entry.n_sect) {
494    uint64_t Delta;
495    DataRefImpl SecRel;
496    SecRel.d.a = Entry.n_sect-1;
497    if (is64Bit()) {
498      MachO::section_64 Sec = getSection64(SecRel);
499      Delta = Sec.offset - Sec.addr;
500    } else {
501      MachO::section Sec = getSection(SecRel);
502      Delta = Sec.offset - Sec.addr;
503    }
504
505    Res += Delta;
506  }
507
508  return object_error::success;
509}
510
511error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
512                                               uint32_t &Result) const {
513  uint32_t flags;
514  this->getSymbolFlags(DRI, flags);
515  if (flags & SymbolRef::SF_Common) {
516    nlist_base Entry = getSymbolTableEntryBase(this, DRI);
517    Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
518  } else {
519    Result = 0;
520  }
521  return object_error::success;
522}
523
524error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
525                                          uint64_t &Result) const {
526  uint64_t BeginOffset;
527  uint64_t EndOffset = 0;
528  uint8_t SectionIndex;
529
530  nlist_base Entry = getSymbolTableEntryBase(this, DRI);
531  uint64_t Value;
532  getSymbolAddress(DRI, Value);
533
534  BeginOffset = Value;
535
536  SectionIndex = Entry.n_sect;
537  if (!SectionIndex) {
538    uint32_t flags = SymbolRef::SF_None;
539    this->getSymbolFlags(DRI, flags);
540    if (flags & SymbolRef::SF_Common)
541      Result = Value;
542    else
543      Result = UnknownAddressOrSize;
544    return object_error::success;
545  }
546  // Unfortunately symbols are unsorted so we need to touch all
547  // symbols from load command
548  error_code ec;
549  for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E;
550       I.increment(ec)) {
551    DataRefImpl DRI = I->getRawDataRefImpl();
552    Entry = getSymbolTableEntryBase(this, DRI);
553    getSymbolAddress(DRI, Value);
554    if (Entry.n_sect == SectionIndex && Value > BeginOffset)
555      if (!EndOffset || Value < EndOffset)
556        EndOffset = Value;
557  }
558  if (!EndOffset) {
559    uint64_t Size;
560    DataRefImpl Sec;
561    Sec.d.a = SectionIndex-1;
562    getSectionSize(Sec, Size);
563    getSectionAddress(Sec, EndOffset);
564    EndOffset += Size;
565  }
566  Result = EndOffset - BeginOffset;
567  return object_error::success;
568}
569
570error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
571                                          SymbolRef::Type &Res) const {
572  nlist_base Entry = getSymbolTableEntryBase(this, Symb);
573  uint8_t n_type = Entry.n_type;
574
575  Res = SymbolRef::ST_Other;
576
577  // If this is a STAB debugging symbol, we can do nothing more.
578  if (n_type & MachO::N_STAB) {
579    Res = SymbolRef::ST_Debug;
580    return object_error::success;
581  }
582
583  switch (n_type & MachO::N_TYPE) {
584    case MachO::N_UNDF :
585      Res = SymbolRef::ST_Unknown;
586      break;
587    case MachO::N_SECT :
588      Res = SymbolRef::ST_Function;
589      break;
590  }
591  return object_error::success;
592}
593
594error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
595                                           uint32_t &Result) const {
596  nlist_base Entry = getSymbolTableEntryBase(this, DRI);
597
598  uint8_t MachOType = Entry.n_type;
599  uint16_t MachOFlags = Entry.n_desc;
600
601  // TODO: Correctly set SF_ThreadLocal
602  Result = SymbolRef::SF_None;
603
604  if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
605    Result |= SymbolRef::SF_Undefined;
606
607  if (MachOType & MachO::N_STAB)
608    Result |= SymbolRef::SF_FormatSpecific;
609
610  if (MachOType & MachO::N_EXT) {
611    Result |= SymbolRef::SF_Global;
612    if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
613      uint64_t Value;
614      getSymbolAddress(DRI, Value);
615      if (Value)
616        Result |= SymbolRef::SF_Common;
617    }
618  }
619
620  if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
621    Result |= SymbolRef::SF_Weak;
622
623  if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
624    Result |= SymbolRef::SF_Absolute;
625
626  return object_error::success;
627}
628
629error_code
630MachOObjectFile::getSymbolSection(DataRefImpl Symb,
631                                  section_iterator &Res) const {
632  nlist_base Entry = getSymbolTableEntryBase(this, Symb);
633  uint8_t index = Entry.n_sect;
634
635  if (index == 0) {
636    Res = end_sections();
637  } else {
638    DataRefImpl DRI;
639    DRI.d.a = index - 1;
640    Res = section_iterator(SectionRef(DRI, this));
641  }
642
643  return object_error::success;
644}
645
646error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
647                                           uint64_t &Val) const {
648  report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
649}
650
651error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
652                                           SectionRef &Res) const {
653  Sec.d.a++;
654  Res = SectionRef(Sec, this);
655  return object_error::success;
656}
657
658error_code
659MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const {
660  ArrayRef<char> Raw = getSectionRawName(Sec);
661  Result = parseSegmentOrSectionName(Raw.data());
662  return object_error::success;
663}
664
665error_code
666MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {
667  if (is64Bit()) {
668    MachO::section_64 Sect = getSection64(Sec);
669    Res = Sect.addr;
670  } else {
671    MachO::section Sect = getSection(Sec);
672    Res = Sect.addr;
673  }
674  return object_error::success;
675}
676
677error_code
678MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {
679  if (is64Bit()) {
680    MachO::section_64 Sect = getSection64(Sec);
681    Res = Sect.size;
682  } else {
683    MachO::section Sect = getSection(Sec);
684    Res = Sect.size;
685  }
686
687  return object_error::success;
688}
689
690error_code
691MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {
692  uint32_t Offset;
693  uint64_t Size;
694
695  if (is64Bit()) {
696    MachO::section_64 Sect = getSection64(Sec);
697    Offset = Sect.offset;
698    Size = Sect.size;
699  } else {
700    MachO::section Sect = getSection(Sec);
701    Offset = Sect.offset;
702    Size = Sect.size;
703  }
704
705  Res = this->getData().substr(Offset, Size);
706  return object_error::success;
707}
708
709error_code
710MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {
711  uint32_t Align;
712  if (is64Bit()) {
713    MachO::section_64 Sect = getSection64(Sec);
714    Align = Sect.align;
715  } else {
716    MachO::section Sect = getSection(Sec);
717    Align = Sect.align;
718  }
719
720  Res = uint64_t(1) << Align;
721  return object_error::success;
722}
723
724error_code
725MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
726  uint32_t Flags = getSectionFlags(this, Sec);
727  Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
728  return object_error::success;
729}
730
731error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const {
732  // FIXME: Unimplemented.
733  Result = false;
734  return object_error::success;
735}
736
737error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const {
738  // FIXME: Unimplemented.
739  Result = false;
740  return object_error::success;
741}
742
743error_code
744MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
745                                               bool &Result) const {
746  // FIXME: Unimplemented.
747  Result = true;
748  return object_error::success;
749}
750
751error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
752                                             bool &Result) const {
753  // FIXME: Unimplemented.
754  Result = false;
755  return object_error::success;
756}
757
758error_code
759MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
760  uint32_t Flags = getSectionFlags(this, Sec);
761  unsigned SectionType = Flags & MachO::SECTION_TYPE;
762  Res = SectionType == MachO::S_ZEROFILL ||
763    SectionType == MachO::S_GB_ZEROFILL;
764  return object_error::success;
765}
766
767error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
768                                                  bool &Result) const {
769  // Consider using the code from isSectionText to look for __const sections.
770  // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
771  // to use section attributes to distinguish code from data.
772
773  // FIXME: Unimplemented.
774  Result = false;
775  return object_error::success;
776}
777
778error_code
779MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
780                                       bool &Result) const {
781  SymbolRef::Type ST;
782  this->getSymbolType(Symb, ST);
783  if (ST == SymbolRef::ST_Unknown) {
784    Result = false;
785    return object_error::success;
786  }
787
788  uint64_t SectBegin, SectEnd;
789  getSectionAddress(Sec, SectBegin);
790  getSectionSize(Sec, SectEnd);
791  SectEnd += SectBegin;
792
793  uint64_t SymAddr;
794  getSymbolAddress(Symb, SymAddr);
795  Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
796
797  return object_error::success;
798}
799
800relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
801  uint32_t Offset;
802  if (is64Bit()) {
803    MachO::section_64 Sect = getSection64(Sec);
804    Offset = Sect.reloff;
805  } else {
806    MachO::section Sect = getSection(Sec);
807    Offset = Sect.reloff;
808  }
809
810  DataRefImpl Ret;
811  Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
812  return relocation_iterator(RelocationRef(Ret, this));
813}
814
815relocation_iterator
816MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
817  uint32_t Offset;
818  uint32_t Num;
819  if (is64Bit()) {
820    MachO::section_64 Sect = getSection64(Sec);
821    Offset = Sect.reloff;
822    Num = Sect.nreloc;
823  } else {
824    MachO::section Sect = getSection(Sec);
825    Offset = Sect.reloff;
826    Num = Sect.nreloc;
827  }
828
829  const MachO::any_relocation_info *P =
830    reinterpret_cast<const MachO::any_relocation_info *>(getPtr(this, Offset));
831
832  DataRefImpl Ret;
833  Ret.p = reinterpret_cast<uintptr_t>(P + Num);
834  return relocation_iterator(RelocationRef(Ret, this));
835}
836
837error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
838                                              RelocationRef &Res) const {
839  const MachO::any_relocation_info *P =
840    reinterpret_cast<const MachO::any_relocation_info *>(Rel.p);
841  Rel.p = reinterpret_cast<uintptr_t>(P + 1);
842  Res = RelocationRef(Rel, this);
843  return object_error::success;
844}
845
846error_code
847MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const {
848  report_fatal_error("getRelocationAddress not implemented in MachOObjectFile");
849}
850
851error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
852                                                uint64_t &Res) const {
853  MachO::any_relocation_info RE = getRelocation(Rel);
854  Res = getAnyRelocationAddress(RE);
855  return object_error::success;
856}
857
858symbol_iterator
859MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
860  MachO::any_relocation_info RE = getRelocation(Rel);
861  uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
862  bool isExtern = getPlainRelocationExternal(RE);
863  if (!isExtern)
864    return end_symbols();
865
866  MachO::symtab_command S = getSymtabLoadCommand();
867  unsigned SymbolTableEntrySize = is64Bit() ?
868    sizeof(MachO::nlist_64) :
869    sizeof(MachO::nlist);
870  uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
871  DataRefImpl Sym;
872  Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
873  return symbol_iterator(SymbolRef(Sym, this));
874}
875
876error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
877                                              uint64_t &Res) const {
878  MachO::any_relocation_info RE = getRelocation(Rel);
879  Res = getAnyRelocationType(RE);
880  return object_error::success;
881}
882
883error_code
884MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
885                                       SmallVectorImpl<char> &Result) const {
886  StringRef res;
887  uint64_t RType;
888  getRelocationType(Rel, RType);
889
890  unsigned Arch = this->getArch();
891
892  switch (Arch) {
893    case Triple::x86: {
894      static const char *const Table[] =  {
895        "GENERIC_RELOC_VANILLA",
896        "GENERIC_RELOC_PAIR",
897        "GENERIC_RELOC_SECTDIFF",
898        "GENERIC_RELOC_PB_LA_PTR",
899        "GENERIC_RELOC_LOCAL_SECTDIFF",
900        "GENERIC_RELOC_TLV" };
901
902      if (RType > 6)
903        res = "Unknown";
904      else
905        res = Table[RType];
906      break;
907    }
908    case Triple::x86_64: {
909      static const char *const Table[] =  {
910        "X86_64_RELOC_UNSIGNED",
911        "X86_64_RELOC_SIGNED",
912        "X86_64_RELOC_BRANCH",
913        "X86_64_RELOC_GOT_LOAD",
914        "X86_64_RELOC_GOT",
915        "X86_64_RELOC_SUBTRACTOR",
916        "X86_64_RELOC_SIGNED_1",
917        "X86_64_RELOC_SIGNED_2",
918        "X86_64_RELOC_SIGNED_4",
919        "X86_64_RELOC_TLV" };
920
921      if (RType > 9)
922        res = "Unknown";
923      else
924        res = Table[RType];
925      break;
926    }
927    case Triple::arm: {
928      static const char *const Table[] =  {
929        "ARM_RELOC_VANILLA",
930        "ARM_RELOC_PAIR",
931        "ARM_RELOC_SECTDIFF",
932        "ARM_RELOC_LOCAL_SECTDIFF",
933        "ARM_RELOC_PB_LA_PTR",
934        "ARM_RELOC_BR24",
935        "ARM_THUMB_RELOC_BR22",
936        "ARM_THUMB_32BIT_BRANCH",
937        "ARM_RELOC_HALF",
938        "ARM_RELOC_HALF_SECTDIFF" };
939
940      if (RType > 9)
941        res = "Unknown";
942      else
943        res = Table[RType];
944      break;
945    }
946    case Triple::ppc: {
947      static const char *const Table[] =  {
948        "PPC_RELOC_VANILLA",
949        "PPC_RELOC_PAIR",
950        "PPC_RELOC_BR14",
951        "PPC_RELOC_BR24",
952        "PPC_RELOC_HI16",
953        "PPC_RELOC_LO16",
954        "PPC_RELOC_HA16",
955        "PPC_RELOC_LO14",
956        "PPC_RELOC_SECTDIFF",
957        "PPC_RELOC_PB_LA_PTR",
958        "PPC_RELOC_HI16_SECTDIFF",
959        "PPC_RELOC_LO16_SECTDIFF",
960        "PPC_RELOC_HA16_SECTDIFF",
961        "PPC_RELOC_JBSR",
962        "PPC_RELOC_LO14_SECTDIFF",
963        "PPC_RELOC_LOCAL_SECTDIFF" };
964
965      res = Table[RType];
966      break;
967    }
968    case Triple::UnknownArch:
969      res = "Unknown";
970      break;
971  }
972  Result.append(res.begin(), res.end());
973  return object_error::success;
974}
975
976error_code
977MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
978                                          SmallVectorImpl<char> &Result) const {
979  MachO::any_relocation_info RE = getRelocation(Rel);
980
981  unsigned Arch = this->getArch();
982
983  std::string fmtbuf;
984  raw_string_ostream fmt(fmtbuf);
985  unsigned Type = this->getAnyRelocationType(RE);
986  bool IsPCRel = this->getAnyRelocationPCRel(RE);
987
988  // Determine any addends that should be displayed with the relocation.
989  // These require decoding the relocation type, which is triple-specific.
990
991  // X86_64 has entirely custom relocation types.
992  if (Arch == Triple::x86_64) {
993    bool isPCRel = getAnyRelocationPCRel(RE);
994
995    switch (Type) {
996      case MachO::X86_64_RELOC_GOT_LOAD:
997      case MachO::X86_64_RELOC_GOT: {
998        printRelocationTargetName(this, RE, fmt);
999        fmt << "@GOT";
1000        if (isPCRel) fmt << "PCREL";
1001        break;
1002      }
1003      case MachO::X86_64_RELOC_SUBTRACTOR: {
1004        DataRefImpl RelNext = Rel;
1005        RelNext.d.a++;
1006        MachO::any_relocation_info RENext = getRelocation(RelNext);
1007
1008        // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
1009        // X86_64_RELOC_UNSIGNED.
1010        // NOTE: Scattered relocations don't exist on x86_64.
1011        unsigned RType = getAnyRelocationType(RENext);
1012        if (RType != MachO::X86_64_RELOC_UNSIGNED)
1013          report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1014                             "X86_64_RELOC_SUBTRACTOR.");
1015
1016        // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
1017        // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
1018        printRelocationTargetName(this, RENext, fmt);
1019        fmt << "-";
1020        printRelocationTargetName(this, RE, fmt);
1021        break;
1022      }
1023      case MachO::X86_64_RELOC_TLV:
1024        printRelocationTargetName(this, RE, fmt);
1025        fmt << "@TLV";
1026        if (isPCRel) fmt << "P";
1027        break;
1028      case MachO::X86_64_RELOC_SIGNED_1:
1029        printRelocationTargetName(this, RE, fmt);
1030        fmt << "-1";
1031        break;
1032      case MachO::X86_64_RELOC_SIGNED_2:
1033        printRelocationTargetName(this, RE, fmt);
1034        fmt << "-2";
1035        break;
1036      case MachO::X86_64_RELOC_SIGNED_4:
1037        printRelocationTargetName(this, RE, fmt);
1038        fmt << "-4";
1039        break;
1040      default:
1041        printRelocationTargetName(this, RE, fmt);
1042        break;
1043    }
1044  // X86 and ARM share some relocation types in common.
1045  } else if (Arch == Triple::x86 || Arch == Triple::arm ||
1046             Arch == Triple::ppc) {
1047    // Generic relocation types...
1048    switch (Type) {
1049      case MachO::GENERIC_RELOC_PAIR: // prints no info
1050        return object_error::success;
1051      case MachO::GENERIC_RELOC_SECTDIFF: {
1052        DataRefImpl RelNext = Rel;
1053        RelNext.d.a++;
1054        MachO::any_relocation_info RENext = getRelocation(RelNext);
1055
1056        // X86 sect diff's must be followed by a relocation of type
1057        // GENERIC_RELOC_PAIR.
1058        unsigned RType = getAnyRelocationType(RENext);
1059
1060        if (RType != MachO::GENERIC_RELOC_PAIR)
1061          report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1062                             "GENERIC_RELOC_SECTDIFF.");
1063
1064        printRelocationTargetName(this, RE, fmt);
1065        fmt << "-";
1066        printRelocationTargetName(this, RENext, fmt);
1067        break;
1068      }
1069    }
1070
1071    if (Arch == Triple::x86 || Arch == Triple::ppc) {
1072      switch (Type) {
1073        case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
1074          DataRefImpl RelNext = Rel;
1075          RelNext.d.a++;
1076          MachO::any_relocation_info RENext = getRelocation(RelNext);
1077
1078          // X86 sect diff's must be followed by a relocation of type
1079          // GENERIC_RELOC_PAIR.
1080          unsigned RType = getAnyRelocationType(RENext);
1081          if (RType != MachO::GENERIC_RELOC_PAIR)
1082            report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1083                               "GENERIC_RELOC_LOCAL_SECTDIFF.");
1084
1085          printRelocationTargetName(this, RE, fmt);
1086          fmt << "-";
1087          printRelocationTargetName(this, RENext, fmt);
1088          break;
1089        }
1090        case MachO::GENERIC_RELOC_TLV: {
1091          printRelocationTargetName(this, RE, fmt);
1092          fmt << "@TLV";
1093          if (IsPCRel) fmt << "P";
1094          break;
1095        }
1096        default:
1097          printRelocationTargetName(this, RE, fmt);
1098      }
1099    } else { // ARM-specific relocations
1100      switch (Type) {
1101        case MachO::ARM_RELOC_HALF:
1102        case MachO::ARM_RELOC_HALF_SECTDIFF: {
1103          // Half relocations steal a bit from the length field to encode
1104          // whether this is an upper16 or a lower16 relocation.
1105          bool isUpper = getAnyRelocationLength(RE) >> 1;
1106
1107          if (isUpper)
1108            fmt << ":upper16:(";
1109          else
1110            fmt << ":lower16:(";
1111          printRelocationTargetName(this, RE, fmt);
1112
1113          DataRefImpl RelNext = Rel;
1114          RelNext.d.a++;
1115          MachO::any_relocation_info RENext = getRelocation(RelNext);
1116
1117          // ARM half relocs must be followed by a relocation of type
1118          // ARM_RELOC_PAIR.
1119          unsigned RType = getAnyRelocationType(RENext);
1120          if (RType != MachO::ARM_RELOC_PAIR)
1121            report_fatal_error("Expected ARM_RELOC_PAIR after "
1122                               "ARM_RELOC_HALF");
1123
1124          // NOTE: The half of the target virtual address is stashed in the
1125          // address field of the secondary relocation, but we can't reverse
1126          // engineer the constant offset from it without decoding the movw/movt
1127          // instruction to find the other half in its immediate field.
1128
1129          // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1130          // symbol/section pointer of the follow-on relocation.
1131          if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
1132            fmt << "-";
1133            printRelocationTargetName(this, RENext, fmt);
1134          }
1135
1136          fmt << ")";
1137          break;
1138        }
1139        default: {
1140          printRelocationTargetName(this, RE, fmt);
1141        }
1142      }
1143    }
1144  } else
1145    printRelocationTargetName(this, RE, fmt);
1146
1147  fmt.flush();
1148  Result.append(fmtbuf.begin(), fmtbuf.end());
1149  return object_error::success;
1150}
1151
1152error_code
1153MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
1154  unsigned Arch = getArch();
1155  uint64_t Type;
1156  getRelocationType(Rel, Type);
1157
1158  Result = false;
1159
1160  // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1161  // is always hidden.
1162  if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
1163    if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
1164  } else if (Arch == Triple::x86_64) {
1165    // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1166    // an X86_64_RELOC_SUBTRACTOR.
1167    if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1168      DataRefImpl RelPrev = Rel;
1169      RelPrev.d.a--;
1170      uint64_t PrevType;
1171      getRelocationType(RelPrev, PrevType);
1172      if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1173        Result = true;
1174    }
1175  }
1176
1177  return object_error::success;
1178}
1179
1180error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1181                                           LibraryRef &Res) const {
1182  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1183}
1184
1185error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1186                                           StringRef &Res) const {
1187  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1188}
1189
1190symbol_iterator MachOObjectFile::begin_symbols() const {
1191  DataRefImpl DRI;
1192  if (!SymtabLoadCmd)
1193    return symbol_iterator(SymbolRef(DRI, this));
1194
1195  MachO::symtab_command Symtab = getSymtabLoadCommand();
1196  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1197  return symbol_iterator(SymbolRef(DRI, this));
1198}
1199
1200symbol_iterator MachOObjectFile::end_symbols() const {
1201  DataRefImpl DRI;
1202  if (!SymtabLoadCmd)
1203    return symbol_iterator(SymbolRef(DRI, this));
1204
1205  MachO::symtab_command Symtab = getSymtabLoadCommand();
1206  unsigned SymbolTableEntrySize = is64Bit() ?
1207    sizeof(MachO::nlist_64) :
1208    sizeof(MachO::nlist);
1209  unsigned Offset = Symtab.symoff +
1210    Symtab.nsyms * SymbolTableEntrySize;
1211  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1212  return symbol_iterator(SymbolRef(DRI, this));
1213}
1214
1215symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1216  // TODO: implement
1217  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1218}
1219
1220symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1221  // TODO: implement
1222  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1223}
1224
1225section_iterator MachOObjectFile::begin_sections() const {
1226  DataRefImpl DRI;
1227  return section_iterator(SectionRef(DRI, this));
1228}
1229
1230section_iterator MachOObjectFile::end_sections() const {
1231  DataRefImpl DRI;
1232  DRI.d.a = Sections.size();
1233  return section_iterator(SectionRef(DRI, this));
1234}
1235
1236library_iterator MachOObjectFile::begin_libraries_needed() const {
1237  // TODO: implement
1238  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1239}
1240
1241library_iterator MachOObjectFile::end_libraries_needed() const {
1242  // TODO: implement
1243  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1244}
1245
1246uint8_t MachOObjectFile::getBytesInAddress() const {
1247  return is64Bit() ? 8 : 4;
1248}
1249
1250StringRef MachOObjectFile::getFileFormatName() const {
1251  unsigned CPUType = getCPUType(this);
1252  if (!is64Bit()) {
1253    switch (CPUType) {
1254    case llvm::MachO::CPU_TYPE_I386:
1255      return "Mach-O 32-bit i386";
1256    case llvm::MachO::CPU_TYPE_ARM:
1257      return "Mach-O arm";
1258    case llvm::MachO::CPU_TYPE_POWERPC:
1259      return "Mach-O 32-bit ppc";
1260    default:
1261      assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1262             "64-bit object file when we're not 64-bit?");
1263      return "Mach-O 32-bit unknown";
1264    }
1265  }
1266
1267  // Make sure the cpu type has the correct mask.
1268  assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1269         == llvm::MachO::CPU_ARCH_ABI64 &&
1270         "32-bit object file when we're 64-bit?");
1271
1272  switch (CPUType) {
1273  case llvm::MachO::CPU_TYPE_X86_64:
1274    return "Mach-O 64-bit x86-64";
1275  case llvm::MachO::CPU_TYPE_POWERPC64:
1276    return "Mach-O 64-bit ppc64";
1277  default:
1278    return "Mach-O 64-bit unknown";
1279  }
1280}
1281
1282Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1283  switch (CPUType) {
1284  case llvm::MachO::CPU_TYPE_I386:
1285    return Triple::x86;
1286  case llvm::MachO::CPU_TYPE_X86_64:
1287    return Triple::x86_64;
1288  case llvm::MachO::CPU_TYPE_ARM:
1289    return Triple::arm;
1290  case llvm::MachO::CPU_TYPE_POWERPC:
1291    return Triple::ppc;
1292  case llvm::MachO::CPU_TYPE_POWERPC64:
1293    return Triple::ppc64;
1294  default:
1295    return Triple::UnknownArch;
1296  }
1297}
1298
1299unsigned MachOObjectFile::getArch() const {
1300  return getArch(getCPUType(this));
1301}
1302
1303StringRef MachOObjectFile::getLoadName() const {
1304  // TODO: Implement
1305  report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1306}
1307
1308relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1309  DataRefImpl DRI;
1310  DRI.d.a = Index;
1311  return section_rel_begin(DRI);
1312}
1313
1314relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1315  DataRefImpl DRI;
1316  DRI.d.a = Index;
1317  return section_rel_end(DRI);
1318}
1319
1320dice_iterator MachOObjectFile::begin_dices() const {
1321  DataRefImpl DRI;
1322  if (!DataInCodeLoadCmd)
1323    return dice_iterator(DiceRef(DRI, this));
1324
1325  MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1326  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1327  return dice_iterator(DiceRef(DRI, this));
1328}
1329
1330dice_iterator MachOObjectFile::end_dices() const {
1331  DataRefImpl DRI;
1332  if (!DataInCodeLoadCmd)
1333    return dice_iterator(DiceRef(DRI, this));
1334
1335  MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1336  unsigned Offset = DicLC.dataoff + DicLC.datasize;
1337  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1338  return dice_iterator(DiceRef(DRI, this));
1339}
1340
1341StringRef
1342MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1343  ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1344  return parseSegmentOrSectionName(Raw.data());
1345}
1346
1347ArrayRef<char>
1348MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1349  const section_base *Base =
1350    reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1351  return ArrayRef<char>(Base->sectname);
1352}
1353
1354ArrayRef<char>
1355MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1356  const section_base *Base =
1357    reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1358  return ArrayRef<char>(Base->segname);
1359}
1360
1361bool
1362MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1363  const {
1364  if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1365    return false;
1366  return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1367}
1368
1369unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1370    const MachO::any_relocation_info &RE) const {
1371  if (isLittleEndian())
1372    return RE.r_word1 & 0xffffff;
1373  return RE.r_word1 >> 8;
1374}
1375
1376bool MachOObjectFile::getPlainRelocationExternal(
1377    const MachO::any_relocation_info &RE) const {
1378  if (isLittleEndian())
1379    return (RE.r_word1 >> 27) & 1;
1380  return (RE.r_word1 >> 4) & 1;
1381}
1382
1383bool MachOObjectFile::getScatteredRelocationScattered(
1384    const MachO::any_relocation_info &RE) const {
1385  return RE.r_word0 >> 31;
1386}
1387
1388uint32_t MachOObjectFile::getScatteredRelocationValue(
1389    const MachO::any_relocation_info &RE) const {
1390  return RE.r_word1;
1391}
1392
1393unsigned MachOObjectFile::getAnyRelocationAddress(
1394    const MachO::any_relocation_info &RE) const {
1395  if (isRelocationScattered(RE))
1396    return getScatteredRelocationAddress(RE);
1397  return getPlainRelocationAddress(RE);
1398}
1399
1400unsigned MachOObjectFile::getAnyRelocationPCRel(
1401    const MachO::any_relocation_info &RE) const {
1402  if (isRelocationScattered(RE))
1403    return getScatteredRelocationPCRel(this, RE);
1404  return getPlainRelocationPCRel(this, RE);
1405}
1406
1407unsigned MachOObjectFile::getAnyRelocationLength(
1408    const MachO::any_relocation_info &RE) const {
1409  if (isRelocationScattered(RE))
1410    return getScatteredRelocationLength(RE);
1411  return getPlainRelocationLength(this, RE);
1412}
1413
1414unsigned
1415MachOObjectFile::getAnyRelocationType(
1416                                   const MachO::any_relocation_info &RE) const {
1417  if (isRelocationScattered(RE))
1418    return getScatteredRelocationType(RE);
1419  return getPlainRelocationType(this, RE);
1420}
1421
1422SectionRef
1423MachOObjectFile::getRelocationSection(
1424                                   const MachO::any_relocation_info &RE) const {
1425  if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1426    return *end_sections();
1427  unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1428  DataRefImpl DRI;
1429  DRI.d.a = SecNum;
1430  return SectionRef(DRI, this);
1431}
1432
1433MachOObjectFile::LoadCommandInfo
1434MachOObjectFile::getFirstLoadCommandInfo() const {
1435  MachOObjectFile::LoadCommandInfo Load;
1436
1437  unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1438                                    sizeof(MachO::mach_header);
1439  Load.Ptr = getPtr(this, HeaderSize);
1440  Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
1441  return Load;
1442}
1443
1444MachOObjectFile::LoadCommandInfo
1445MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1446  MachOObjectFile::LoadCommandInfo Next;
1447  Next.Ptr = L.Ptr + L.C.cmdsize;
1448  Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
1449  return Next;
1450}
1451
1452MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1453  return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1454}
1455
1456MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1457  return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1458}
1459
1460MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1461                                           unsigned Index) const {
1462  const char *Sec = getSectionPtr(this, L, Index);
1463  return getStruct<MachO::section>(this, Sec);
1464}
1465
1466MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1467                                                unsigned Index) const {
1468  const char *Sec = getSectionPtr(this, L, Index);
1469  return getStruct<MachO::section_64>(this, Sec);
1470}
1471
1472MachO::nlist
1473MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1474  const char *P = reinterpret_cast<const char *>(DRI.p);
1475  return getStruct<MachO::nlist>(this, P);
1476}
1477
1478MachO::nlist_64
1479MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1480  const char *P = reinterpret_cast<const char *>(DRI.p);
1481  return getStruct<MachO::nlist_64>(this, P);
1482}
1483
1484MachO::linkedit_data_command
1485MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1486  return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1487}
1488
1489MachO::segment_command
1490MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1491  return getStruct<MachO::segment_command>(this, L.Ptr);
1492}
1493
1494MachO::segment_command_64
1495MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1496  return getStruct<MachO::segment_command_64>(this, L.Ptr);
1497}
1498
1499MachO::linker_options_command
1500MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
1501  return getStruct<MachO::linker_options_command>(this, L.Ptr);
1502}
1503
1504MachO::any_relocation_info
1505MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1506  const char *P = reinterpret_cast<const char *>(Rel.p);
1507  return getStruct<MachO::any_relocation_info>(this, P);
1508}
1509
1510MachO::data_in_code_entry
1511MachOObjectFile::getDice(DataRefImpl Rel) const {
1512  const char *P = reinterpret_cast<const char *>(Rel.p);
1513  return getStruct<MachO::data_in_code_entry>(this, P);
1514}
1515
1516MachO::mach_header MachOObjectFile::getHeader() const {
1517  return getStruct<MachO::mach_header>(this, getPtr(this, 0));
1518}
1519
1520MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1521  return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
1522}
1523
1524uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1525                                             const MachO::dysymtab_command &DLC,
1526                                             unsigned Index) const {
1527  uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1528  return getStruct<uint32_t>(this, getPtr(this, Offset));
1529}
1530
1531MachO::data_in_code_entry
1532MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1533                                         unsigned Index) const {
1534  uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1535  return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
1536}
1537
1538MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1539  return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1540}
1541
1542MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1543  return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1544}
1545
1546MachO::linkedit_data_command
1547MachOObjectFile::getDataInCodeLoadCommand() const {
1548  if (DataInCodeLoadCmd)
1549    return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
1550
1551  // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
1552  MachO::linkedit_data_command Cmd;
1553  Cmd.cmd = MachO::LC_DATA_IN_CODE;
1554  Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1555  Cmd.dataoff = 0;
1556  Cmd.datasize = 0;
1557  return Cmd;
1558}
1559
1560StringRef MachOObjectFile::getStringTableData() const {
1561  MachO::symtab_command S = getSymtabLoadCommand();
1562  return getData().substr(S.stroff, S.strsize);
1563}
1564
1565bool MachOObjectFile::is64Bit() const {
1566  return getType() == getMachOType(false, true) ||
1567    getType() == getMachOType(true, true);
1568}
1569
1570void MachOObjectFile::ReadULEB128s(uint64_t Index,
1571                                   SmallVectorImpl<uint64_t> &Out) const {
1572  DataExtractor extractor(ObjectFile::getData(), true, 0);
1573
1574  uint32_t offset = Index;
1575  uint64_t data = 0;
1576  while (uint64_t delta = extractor.getULEB128(&offset)) {
1577    data += delta;
1578    Out.push_back(data);
1579  }
1580}
1581
1582ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1583  StringRef Magic = Buffer->getBuffer().slice(0, 4);
1584  error_code ec;
1585  OwningPtr<ObjectFile> Ret;
1586  if (Magic == "\xFE\xED\xFA\xCE")
1587    Ret.reset(new MachOObjectFile(Buffer, false, false, ec));
1588  else if (Magic == "\xCE\xFA\xED\xFE")
1589    Ret.reset(new MachOObjectFile(Buffer, true, false, ec));
1590  else if (Magic == "\xFE\xED\xFA\xCF")
1591    Ret.reset(new MachOObjectFile(Buffer, false, true, ec));
1592  else if (Magic == "\xCF\xFA\xED\xFE")
1593    Ret.reset(new MachOObjectFile(Buffer, true, true, ec));
1594  else {
1595    delete Buffer;
1596    return NULL;
1597  }
1598
1599  if (ec)
1600    return NULL;
1601  return Ret.take();
1602}
1603
1604} // end namespace object
1605} // end namespace llvm
1606