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