MachOObjectFile.cpp revision 87d0b9ed1462705dd9bf1cb7f67d0bf03af776c8
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/Format.h"
19#include "llvm/Support/MemoryBuffer.h"
20#include <cctype>
21#include <cstring>
22#include <limits>
23
24using namespace llvm;
25using namespace object;
26
27namespace llvm {
28namespace object {
29
30MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
31                                 error_code &ec)
32    : ObjectFile(Binary::ID_MachO, Object, ec),
33      MachOObj(MOO),
34      RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
35  DataRefImpl DRI;
36  moveToNextSection(DRI);
37  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
38  while (DRI.d.a < LoadCommandCount) {
39    Sections.push_back(DRI);
40    DRI.d.b++;
41    moveToNextSection(DRI);
42  }
43}
44
45
46ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
47  error_code ec;
48  std::string Err;
49  MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
50  if (!MachOObj)
51    return NULL;
52  // MachOObject takes ownership of the Buffer we passed to it, and
53  // MachOObjectFile does, too, so we need to make sure they don't get the
54  // same object. A MemoryBuffer is cheap (it's just a reference to memory,
55  // not a copy of the memory itself), so just make a new copy here for
56  // the MachOObjectFile.
57  MemoryBuffer *NewBuffer =
58    MemoryBuffer::getMemBuffer(Buffer->getBuffer(),
59                               Buffer->getBufferIdentifier(), false);
60  return new MachOObjectFile(NewBuffer, MachOObj, ec);
61}
62
63/*===-- Symbols -----------------------------------------------------------===*/
64
65void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
66  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
67  while (DRI.d.a < LoadCommandCount) {
68    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
69    if (LCI.Command.Type == macho::LCT_Symtab) {
70      InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
71      MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
72      if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
73        return;
74    }
75
76    DRI.d.a++;
77    DRI.d.b = 0;
78  }
79}
80
81void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
82    InMemoryStruct<macho::SymbolTableEntry> &Res) const {
83  InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
84  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
85  MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
86
87  if (RegisteredStringTable != DRI.d.a) {
88    MachOObj->RegisterStringTable(*SymtabLoadCmd);
89    RegisteredStringTable = DRI.d.a;
90  }
91
92  MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
93                                 Res);
94}
95
96void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
97    InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
98  InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
99  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
100  MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
101
102  if (RegisteredStringTable != DRI.d.a) {
103    MachOObj->RegisterStringTable(*SymtabLoadCmd);
104    RegisteredStringTable = DRI.d.a;
105  }
106
107  MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
108                                   Res);
109}
110
111
112error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
113                                          SymbolRef &Result) const {
114  DRI.d.b++;
115  moveToNextSymbol(DRI);
116  Result = SymbolRef(DRI, this);
117  return object_error::success;
118}
119
120error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
121                                          StringRef &Result) const {
122  if (MachOObj->is64Bit()) {
123    InMemoryStruct<macho::Symbol64TableEntry> Entry;
124    getSymbol64TableEntry(DRI, Entry);
125    Result = MachOObj->getStringAtIndex(Entry->StringIndex);
126  } else {
127    InMemoryStruct<macho::SymbolTableEntry> Entry;
128    getSymbolTableEntry(DRI, Entry);
129    Result = MachOObj->getStringAtIndex(Entry->StringIndex);
130  }
131  return object_error::success;
132}
133
134error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
135                                                uint64_t &Result) const {
136  if (MachOObj->is64Bit()) {
137    InMemoryStruct<macho::Symbol64TableEntry> Entry;
138    getSymbol64TableEntry(DRI, Entry);
139    Result = Entry->Value;
140    if (Entry->SectionIndex) {
141      InMemoryStruct<macho::Section64> Section;
142      getSection64(Sections[Entry->SectionIndex-1], Section);
143      Result += Section->Offset - Section->Address;
144    }
145  } else {
146    InMemoryStruct<macho::SymbolTableEntry> Entry;
147    getSymbolTableEntry(DRI, Entry);
148    Result = Entry->Value;
149    if (Entry->SectionIndex) {
150      InMemoryStruct<macho::Section> Section;
151      getSection(Sections[Entry->SectionIndex-1], Section);
152      Result += Section->Offset - Section->Address;
153    }
154  }
155
156  return object_error::success;
157}
158
159error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
160                                             uint64_t &Result) const {
161  if (MachOObj->is64Bit()) {
162    InMemoryStruct<macho::Symbol64TableEntry> Entry;
163    getSymbol64TableEntry(DRI, Entry);
164    Result = Entry->Value;
165  } else {
166    InMemoryStruct<macho::SymbolTableEntry> Entry;
167    getSymbolTableEntry(DRI, Entry);
168    Result = Entry->Value;
169  }
170  return object_error::success;
171}
172
173error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
174                                          uint64_t &Result) const {
175  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
176  uint64_t BeginOffset;
177  uint64_t EndOffset = 0;
178  uint8_t SectionIndex;
179  if (MachOObj->is64Bit()) {
180    InMemoryStruct<macho::Symbol64TableEntry> Entry;
181    getSymbol64TableEntry(DRI, Entry);
182    BeginOffset = Entry->Value;
183    SectionIndex = Entry->SectionIndex;
184    if (!SectionIndex) {
185      uint32_t flags = SymbolRef::SF_None;
186      getSymbolFlags(DRI, flags);
187      if (flags & SymbolRef::SF_Common)
188        Result = Entry->Value;
189      else
190        Result = UnknownAddressOrSize;
191      return object_error::success;
192    }
193    // Unfortunately symbols are unsorted so we need to touch all
194    // symbols from load command
195    DRI.d.b = 0;
196    uint32_t Command = DRI.d.a;
197    while (Command == DRI.d.a) {
198      moveToNextSymbol(DRI);
199      if (DRI.d.a < LoadCommandCount) {
200        getSymbol64TableEntry(DRI, Entry);
201        if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
202          if (!EndOffset || Entry->Value < EndOffset)
203            EndOffset = Entry->Value;
204      }
205      DRI.d.b++;
206    }
207  } else {
208    InMemoryStruct<macho::SymbolTableEntry> Entry;
209    getSymbolTableEntry(DRI, Entry);
210    BeginOffset = Entry->Value;
211    SectionIndex = Entry->SectionIndex;
212    if (!SectionIndex) {
213      uint32_t flags = SymbolRef::SF_None;
214      getSymbolFlags(DRI, flags);
215      if (flags & SymbolRef::SF_Common)
216        Result = Entry->Value;
217      else
218        Result = UnknownAddressOrSize;
219      return object_error::success;
220    }
221    // Unfortunately symbols are unsorted so we need to touch all
222    // symbols from load command
223    DRI.d.b = 0;
224    uint32_t Command = DRI.d.a;
225    while (Command == DRI.d.a) {
226      moveToNextSymbol(DRI);
227      if (DRI.d.a < LoadCommandCount) {
228        getSymbolTableEntry(DRI, Entry);
229        if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
230          if (!EndOffset || Entry->Value < EndOffset)
231            EndOffset = Entry->Value;
232      }
233      DRI.d.b++;
234    }
235  }
236  if (!EndOffset) {
237    uint64_t Size;
238    getSectionSize(Sections[SectionIndex-1], Size);
239    getSectionAddress(Sections[SectionIndex-1], EndOffset);
240    EndOffset += Size;
241  }
242  Result = EndOffset - BeginOffset;
243  return object_error::success;
244}
245
246error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
247                                                char &Result) const {
248  uint8_t Type, Flags;
249  if (MachOObj->is64Bit()) {
250    InMemoryStruct<macho::Symbol64TableEntry> Entry;
251    getSymbol64TableEntry(DRI, Entry);
252    Type = Entry->Type;
253    Flags = Entry->Flags;
254  } else {
255    InMemoryStruct<macho::SymbolTableEntry> Entry;
256    getSymbolTableEntry(DRI, Entry);
257    Type = Entry->Type;
258    Flags = Entry->Flags;
259  }
260
261  char Char;
262  switch (Type & macho::STF_TypeMask) {
263    case macho::STT_Undefined:
264      Char = 'u';
265      break;
266    case macho::STT_Absolute:
267    case macho::STT_Section:
268      Char = 's';
269      break;
270    default:
271      Char = '?';
272      break;
273  }
274
275  if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
276    Char = toupper(static_cast<unsigned char>(Char));
277  Result = Char;
278  return object_error::success;
279}
280
281error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
282                                           uint32_t &Result) const {
283  uint16_t MachOFlags;
284  uint8_t MachOType;
285  if (MachOObj->is64Bit()) {
286    InMemoryStruct<macho::Symbol64TableEntry> Entry;
287    getSymbol64TableEntry(DRI, Entry);
288    MachOFlags = Entry->Flags;
289    MachOType = Entry->Type;
290  } else {
291    InMemoryStruct<macho::SymbolTableEntry> Entry;
292    getSymbolTableEntry(DRI, Entry);
293    MachOFlags = Entry->Flags;
294    MachOType = Entry->Type;
295  }
296
297  // TODO: Correctly set SF_ThreadLocal
298  Result = SymbolRef::SF_None;
299
300  if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
301    Result |= SymbolRef::SF_Undefined;
302
303  if (MachOFlags & macho::STF_StabsEntryMask)
304    Result |= SymbolRef::SF_FormatSpecific;
305
306  if (MachOType & MachO::NlistMaskExternal) {
307    Result |= SymbolRef::SF_Global;
308    if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
309      Result |= SymbolRef::SF_Common;
310  }
311
312  if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
313    Result |= SymbolRef::SF_Weak;
314
315  if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
316    Result |= SymbolRef::SF_Absolute;
317
318  return object_error::success;
319}
320
321error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
322                                             section_iterator &Res) const {
323  uint8_t index;
324  if (MachOObj->is64Bit()) {
325    InMemoryStruct<macho::Symbol64TableEntry> Entry;
326    getSymbol64TableEntry(Symb, Entry);
327    index = Entry->SectionIndex;
328  } else {
329    InMemoryStruct<macho::SymbolTableEntry> Entry;
330    getSymbolTableEntry(Symb, Entry);
331    index = Entry->SectionIndex;
332  }
333
334  if (index == 0)
335    Res = end_sections();
336  else
337    Res = section_iterator(SectionRef(Sections[index-1], this));
338
339  return object_error::success;
340}
341
342error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
343                                          SymbolRef::Type &Res) const {
344  uint8_t n_type;
345  if (MachOObj->is64Bit()) {
346    InMemoryStruct<macho::Symbol64TableEntry> Entry;
347    getSymbol64TableEntry(Symb, Entry);
348    n_type = Entry->Type;
349  } else {
350    InMemoryStruct<macho::SymbolTableEntry> Entry;
351    getSymbolTableEntry(Symb, Entry);
352    n_type = Entry->Type;
353  }
354  Res = SymbolRef::ST_Other;
355
356  // If this is a STAB debugging symbol, we can do nothing more.
357  if (n_type & MachO::NlistMaskStab) {
358    Res = SymbolRef::ST_Debug;
359    return object_error::success;
360  }
361
362  switch (n_type & MachO::NlistMaskType) {
363    case MachO::NListTypeUndefined :
364      Res = SymbolRef::ST_Unknown;
365      break;
366    case MachO::NListTypeSection :
367      Res = SymbolRef::ST_Function;
368      break;
369  }
370  return object_error::success;
371}
372
373error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
374                                           uint64_t &Val) const {
375  report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
376}
377
378symbol_iterator MachOObjectFile::begin_symbols() const {
379  // DRI.d.a = segment number; DRI.d.b = symbol index.
380  DataRefImpl DRI;
381  moveToNextSymbol(DRI);
382  return symbol_iterator(SymbolRef(DRI, this));
383}
384
385symbol_iterator MachOObjectFile::end_symbols() const {
386  DataRefImpl DRI;
387  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
388  return symbol_iterator(SymbolRef(DRI, this));
389}
390
391symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
392  // TODO: implement
393  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
394}
395
396symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
397  // TODO: implement
398  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
399}
400
401library_iterator MachOObjectFile::begin_libraries_needed() const {
402  // TODO: implement
403  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
404}
405
406library_iterator MachOObjectFile::end_libraries_needed() const {
407  // TODO: implement
408  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
409}
410
411StringRef MachOObjectFile::getLoadName() const {
412  // TODO: Implement
413  report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
414}
415
416/*===-- Sections ----------------------------------------------------------===*/
417
418void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
419  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
420  while (DRI.d.a < LoadCommandCount) {
421    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
422    if (LCI.Command.Type == macho::LCT_Segment) {
423      InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
424      MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
425      if (DRI.d.b < SegmentLoadCmd->NumSections)
426        return;
427    } else if (LCI.Command.Type == macho::LCT_Segment64) {
428      InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
429      MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
430      if (DRI.d.b < Segment64LoadCmd->NumSections)
431        return;
432    }
433
434    DRI.d.a++;
435    DRI.d.b = 0;
436  }
437}
438
439error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
440                                           SectionRef &Result) const {
441  DRI.d.b++;
442  moveToNextSection(DRI);
443  Result = SectionRef(DRI, this);
444  return object_error::success;
445}
446
447void
448MachOObjectFile::getSection(DataRefImpl DRI,
449                            InMemoryStruct<macho::Section> &Res) const {
450  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
451  MachOObj->ReadSection(LCI, DRI.d.b, Res);
452}
453
454std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
455  SectionList::const_iterator loc =
456    std::find(Sections.begin(), Sections.end(), Sec);
457  assert(loc != Sections.end() && "Sec is not a valid section!");
458  return std::distance(Sections.begin(), loc);
459}
460
461void
462MachOObjectFile::getSection64(DataRefImpl DRI,
463                            InMemoryStruct<macho::Section64> &Res) const {
464  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
465  MachOObj->ReadSection64(LCI, DRI.d.b, Res);
466}
467
468static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
469  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
470  if (LCI.Command.Type == macho::LCT_Segment64)
471    return true;
472  assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
473  return false;
474}
475
476static StringRef parseSegmentOrSectionName(const char *P) {
477  if (P[15] == 0)
478    // Null terminated.
479    return P;
480  // Not null terminated, so this is a 16 char string.
481  return StringRef(P, 16);
482}
483
484error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
485                                           StringRef &Result) const {
486  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
487    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
488    unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) +
489      DRI.d.b * sizeof(macho::Section64);
490    StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64));
491    const macho::Section64 *sec =
492      reinterpret_cast<const macho::Section64*>(Data.data());
493    Result = parseSegmentOrSectionName(sec->Name);
494  } else {
495    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
496    unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) +
497      DRI.d.b * sizeof(macho::Section);
498    StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section));
499    const macho::Section *sec =
500      reinterpret_cast<const macho::Section*>(Data.data());
501    Result = parseSegmentOrSectionName(sec->Name);
502  }
503  return object_error::success;
504}
505
506error_code MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec,
507                                                       StringRef &Res) const {
508  if (is64BitLoadCommand(MachOObj.get(), Sec)) {
509    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(Sec.d.a);
510    unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) +
511      Sec.d.b * sizeof(macho::Section64);
512    StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64));
513    const macho::Section64 *sec =
514      reinterpret_cast<const macho::Section64*>(Data.data());
515    Res = parseSegmentOrSectionName(sec->SegmentName);
516  } else {
517    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(Sec.d.a);
518    unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) +
519      Sec.d.b * sizeof(macho::Section);
520    StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section));
521    const macho::Section *sec =
522      reinterpret_cast<const macho::Section*>(Data.data());
523    Res = parseSegmentOrSectionName(sec->SegmentName);
524  }
525  return object_error::success;
526}
527
528error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
529                                              uint64_t &Result) const {
530  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
531    InMemoryStruct<macho::Section64> Sect;
532    getSection64(DRI, Sect);
533    Result = Sect->Address;
534  } else {
535    InMemoryStruct<macho::Section> Sect;
536    getSection(DRI, Sect);
537    Result = Sect->Address;
538  }
539  return object_error::success;
540}
541
542error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
543                                           uint64_t &Result) const {
544  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
545    InMemoryStruct<macho::Section64> Sect;
546    getSection64(DRI, Sect);
547    Result = Sect->Size;
548  } else {
549    InMemoryStruct<macho::Section> Sect;
550    getSection(DRI, Sect);
551    Result = Sect->Size;
552  }
553  return object_error::success;
554}
555
556error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
557                                               StringRef &Result) const {
558  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
559    InMemoryStruct<macho::Section64> Sect;
560    getSection64(DRI, Sect);
561    Result = MachOObj->getData(Sect->Offset, Sect->Size);
562  } else {
563    InMemoryStruct<macho::Section> Sect;
564    getSection(DRI, Sect);
565    Result = MachOObj->getData(Sect->Offset, Sect->Size);
566  }
567  return object_error::success;
568}
569
570error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
571                                                uint64_t &Result) const {
572  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
573    InMemoryStruct<macho::Section64> Sect;
574    getSection64(DRI, Sect);
575    Result = uint64_t(1) << Sect->Align;
576  } else {
577    InMemoryStruct<macho::Section> Sect;
578    getSection(DRI, Sect);
579    Result = uint64_t(1) << Sect->Align;
580  }
581  return object_error::success;
582}
583
584error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
585                                          bool &Result) const {
586  if (is64BitLoadCommand(MachOObj.get(), DRI)) {
587    InMemoryStruct<macho::Section64> Sect;
588    getSection64(DRI, Sect);
589    Result = Sect->Flags & macho::SF_PureInstructions;
590  } else {
591    InMemoryStruct<macho::Section> Sect;
592    getSection(DRI, Sect);
593    Result = Sect->Flags & macho::SF_PureInstructions;
594  }
595  return object_error::success;
596}
597
598error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
599                                          bool &Result) const {
600  // FIXME: Unimplemented.
601  Result = false;
602  return object_error::success;
603}
604
605error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
606                                         bool &Result) const {
607  // FIXME: Unimplemented.
608  Result = false;
609  return object_error::success;
610}
611
612error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
613                                                          bool &Result) const {
614  // FIXME: Unimplemented.
615  Result = true;
616  return object_error::success;
617}
618
619error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
620                                             bool &Result) const {
621  // FIXME: Unimplemented.
622  Result = false;
623  return object_error::success;
624}
625
626error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
627                                              bool &Result) const {
628  if (MachOObj->is64Bit()) {
629    InMemoryStruct<macho::Section64> Sect;
630    getSection64(DRI, Sect);
631    unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
632    Result = (SectionType == MachO::SectionTypeZeroFill ||
633              SectionType == MachO::SectionTypeZeroFillLarge);
634  } else {
635    InMemoryStruct<macho::Section> Sect;
636    getSection(DRI, Sect);
637    unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
638    Result = (SectionType == MachO::SectionTypeZeroFill ||
639              SectionType == MachO::SectionTypeZeroFillLarge);
640  }
641
642  return object_error::success;
643}
644
645error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
646                                                  bool &Result) const {
647  // Consider using the code from isSectionText to look for __const sections.
648  // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
649  // to use section attributes to distinguish code from data.
650
651  // FIXME: Unimplemented.
652  Result = false;
653  return object_error::success;
654}
655
656error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
657                                                  DataRefImpl Symb,
658                                                  bool &Result) const {
659  SymbolRef::Type ST;
660  getSymbolType(Symb, ST);
661  if (ST == SymbolRef::ST_Unknown) {
662    Result = false;
663    return object_error::success;
664  }
665
666  uint64_t SectBegin, SectEnd;
667  getSectionAddress(Sec, SectBegin);
668  getSectionSize(Sec, SectEnd);
669  SectEnd += SectBegin;
670
671  if (MachOObj->is64Bit()) {
672    InMemoryStruct<macho::Symbol64TableEntry> Entry;
673    getSymbol64TableEntry(Symb, Entry);
674    uint64_t SymAddr= Entry->Value;
675    Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
676  } else {
677    InMemoryStruct<macho::SymbolTableEntry> Entry;
678    getSymbolTableEntry(Symb, Entry);
679    uint64_t SymAddr= Entry->Value;
680    Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
681  }
682
683  return object_error::success;
684}
685
686relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
687  DataRefImpl ret;
688  ret.d.b = getSectionIndex(Sec);
689  return relocation_iterator(RelocationRef(ret, this));
690}
691relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
692  uint32_t last_reloc;
693  if (is64BitLoadCommand(MachOObj.get(), Sec)) {
694    InMemoryStruct<macho::Section64> Sect;
695    getSection64(Sec, Sect);
696    last_reloc = Sect->NumRelocationTableEntries;
697  } else {
698    InMemoryStruct<macho::Section> Sect;
699    getSection(Sec, Sect);
700    last_reloc = Sect->NumRelocationTableEntries;
701  }
702  DataRefImpl ret;
703  ret.d.a = last_reloc;
704  ret.d.b = getSectionIndex(Sec);
705  return relocation_iterator(RelocationRef(ret, this));
706}
707
708section_iterator MachOObjectFile::begin_sections() const {
709  DataRefImpl DRI;
710  moveToNextSection(DRI);
711  return section_iterator(SectionRef(DRI, this));
712}
713
714section_iterator MachOObjectFile::end_sections() const {
715  DataRefImpl DRI;
716  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
717  return section_iterator(SectionRef(DRI, this));
718}
719
720/*===-- Relocations -------------------------------------------------------===*/
721
722void MachOObjectFile::
723getRelocation(DataRefImpl Rel,
724              InMemoryStruct<macho::RelocationEntry> &Res) const {
725  uint32_t relOffset;
726  if (MachOObj->is64Bit()) {
727    InMemoryStruct<macho::Section64> Sect;
728    getSection64(Sections[Rel.d.b], Sect);
729    relOffset = Sect->RelocationTableOffset;
730  } else {
731    InMemoryStruct<macho::Section> Sect;
732    getSection(Sections[Rel.d.b], Sect);
733    relOffset = Sect->RelocationTableOffset;
734  }
735  MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
736}
737error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
738                                              RelocationRef &Res) const {
739  ++Rel.d.a;
740  Res = RelocationRef(Rel, this);
741  return object_error::success;
742}
743error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
744                                                 uint64_t &Res) const {
745  const uint8_t* sectAddress = 0;
746  if (MachOObj->is64Bit()) {
747    InMemoryStruct<macho::Section64> Sect;
748    getSection64(Sections[Rel.d.b], Sect);
749    sectAddress += Sect->Address;
750  } else {
751    InMemoryStruct<macho::Section> Sect;
752    getSection(Sections[Rel.d.b], Sect);
753    sectAddress += Sect->Address;
754  }
755  InMemoryStruct<macho::RelocationEntry> RE;
756  getRelocation(Rel, RE);
757
758  unsigned Arch = getArch();
759  bool isScattered = (Arch != Triple::x86_64) &&
760                     (RE->Word0 & macho::RF_Scattered);
761  uint64_t RelAddr = 0;
762  if (isScattered)
763    RelAddr = RE->Word0 & 0xFFFFFF;
764  else
765    RelAddr = RE->Word0;
766
767  Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
768  return object_error::success;
769}
770error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
771                                                uint64_t &Res) const {
772  InMemoryStruct<macho::RelocationEntry> RE;
773  getRelocation(Rel, RE);
774
775  unsigned Arch = getArch();
776  bool isScattered = (Arch != Triple::x86_64) &&
777                     (RE->Word0 & macho::RF_Scattered);
778  if (isScattered)
779    Res = RE->Word0 & 0xFFFFFF;
780  else
781    Res = RE->Word0;
782  return object_error::success;
783}
784error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
785                                                SymbolRef &Res) const {
786  InMemoryStruct<macho::RelocationEntry> RE;
787  getRelocation(Rel, RE);
788  uint32_t SymbolIdx = RE->Word1 & 0xffffff;
789  bool isExtern = (RE->Word1 >> 27) & 1;
790
791  DataRefImpl Sym;
792  moveToNextSymbol(Sym);
793  if (isExtern) {
794    for (unsigned i = 0; i < SymbolIdx; i++) {
795      Sym.d.b++;
796      moveToNextSymbol(Sym);
797      assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
798             "Relocation symbol index out of range!");
799    }
800  }
801  Res = SymbolRef(Sym, this);
802  return object_error::success;
803}
804error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
805                                              uint64_t &Res) const {
806  InMemoryStruct<macho::RelocationEntry> RE;
807  getRelocation(Rel, RE);
808  Res = RE->Word0;
809  Res <<= 32;
810  Res |= RE->Word1;
811  return object_error::success;
812}
813error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
814                                          SmallVectorImpl<char> &Result) const {
815  // TODO: Support scattered relocations.
816  StringRef res;
817  InMemoryStruct<macho::RelocationEntry> RE;
818  getRelocation(Rel, RE);
819
820  unsigned Arch = getArch();
821  bool isScattered = (Arch != Triple::x86_64) &&
822                     (RE->Word0 & macho::RF_Scattered);
823
824  unsigned r_type;
825  if (isScattered)
826    r_type = (RE->Word0 >> 24) & 0xF;
827  else
828    r_type = (RE->Word1 >> 28) & 0xF;
829
830  switch (Arch) {
831    case Triple::x86: {
832      static const char *const Table[] =  {
833        "GENERIC_RELOC_VANILLA",
834        "GENERIC_RELOC_PAIR",
835        "GENERIC_RELOC_SECTDIFF",
836        "GENERIC_RELOC_PB_LA_PTR",
837        "GENERIC_RELOC_LOCAL_SECTDIFF",
838        "GENERIC_RELOC_TLV" };
839
840      if (r_type > 6)
841        res = "Unknown";
842      else
843        res = Table[r_type];
844      break;
845    }
846    case Triple::x86_64: {
847      static const char *const Table[] =  {
848        "X86_64_RELOC_UNSIGNED",
849        "X86_64_RELOC_SIGNED",
850        "X86_64_RELOC_BRANCH",
851        "X86_64_RELOC_GOT_LOAD",
852        "X86_64_RELOC_GOT",
853        "X86_64_RELOC_SUBTRACTOR",
854        "X86_64_RELOC_SIGNED_1",
855        "X86_64_RELOC_SIGNED_2",
856        "X86_64_RELOC_SIGNED_4",
857        "X86_64_RELOC_TLV" };
858
859      if (r_type > 9)
860        res = "Unknown";
861      else
862        res = Table[r_type];
863      break;
864    }
865    case Triple::arm: {
866      static const char *const Table[] =  {
867        "ARM_RELOC_VANILLA",
868        "ARM_RELOC_PAIR",
869        "ARM_RELOC_SECTDIFF",
870        "ARM_RELOC_LOCAL_SECTDIFF",
871        "ARM_RELOC_PB_LA_PTR",
872        "ARM_RELOC_BR24",
873        "ARM_THUMB_RELOC_BR22",
874        "ARM_THUMB_32BIT_BRANCH",
875        "ARM_RELOC_HALF",
876        "ARM_RELOC_HALF_SECTDIFF" };
877
878      if (r_type > 9)
879        res = "Unknown";
880      else
881        res = Table[r_type];
882      break;
883    }
884    case Triple::ppc: {
885      static const char *const Table[] =  {
886        "PPC_RELOC_VANILLA",
887        "PPC_RELOC_PAIR",
888        "PPC_RELOC_BR14",
889        "PPC_RELOC_BR24",
890        "PPC_RELOC_HI16",
891        "PPC_RELOC_LO16",
892        "PPC_RELOC_HA16",
893        "PPC_RELOC_LO14",
894        "PPC_RELOC_SECTDIFF",
895        "PPC_RELOC_PB_LA_PTR",
896        "PPC_RELOC_HI16_SECTDIFF",
897        "PPC_RELOC_LO16_SECTDIFF",
898        "PPC_RELOC_HA16_SECTDIFF",
899        "PPC_RELOC_JBSR",
900        "PPC_RELOC_LO14_SECTDIFF",
901        "PPC_RELOC_LOCAL_SECTDIFF" };
902
903      res = Table[r_type];
904      break;
905    }
906    case Triple::UnknownArch:
907      res = "Unknown";
908      break;
909  }
910  Result.append(res.begin(), res.end());
911  return object_error::success;
912}
913error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
914                                                        int64_t &Res) const {
915  InMemoryStruct<macho::RelocationEntry> RE;
916  getRelocation(Rel, RE);
917  bool isExtern = (RE->Word1 >> 27) & 1;
918  Res = 0;
919  if (!isExtern) {
920    const uint8_t* sectAddress = base();
921    if (MachOObj->is64Bit()) {
922      InMemoryStruct<macho::Section64> Sect;
923      getSection64(Sections[Rel.d.b], Sect);
924      sectAddress += Sect->Offset;
925    } else {
926      InMemoryStruct<macho::Section> Sect;
927      getSection(Sections[Rel.d.b], Sect);
928      sectAddress += Sect->Offset;
929    }
930    Res = reinterpret_cast<uintptr_t>(sectAddress);
931  }
932  return object_error::success;
933}
934
935// Helper to advance a section or symbol iterator multiple increments at a time.
936template<class T>
937error_code advance(T &it, size_t Val) {
938  error_code ec;
939  while (Val--) {
940    it.increment(ec);
941  }
942  return ec;
943}
944
945template<class T>
946void advanceTo(T &it, size_t Val) {
947  if (error_code ec = advance(it, Val))
948    report_fatal_error(ec.message());
949}
950
951void MachOObjectFile::printRelocationTargetName(
952                                     InMemoryStruct<macho::RelocationEntry>& RE,
953                                     raw_string_ostream &fmt) const {
954  unsigned Arch = getArch();
955  bool isScattered = (Arch != Triple::x86_64) &&
956                     (RE->Word0 & macho::RF_Scattered);
957
958  // Target of a scattered relocation is an address.  In the interest of
959  // generating pretty output, scan through the symbol table looking for a
960  // symbol that aligns with that address.  If we find one, print it.
961  // Otherwise, we just print the hex address of the target.
962  if (isScattered) {
963    uint32_t Val = RE->Word1;
964
965    error_code ec;
966    for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
967        SI.increment(ec)) {
968      if (ec) report_fatal_error(ec.message());
969
970      uint64_t Addr;
971      StringRef Name;
972
973      if ((ec = SI->getAddress(Addr)))
974        report_fatal_error(ec.message());
975      if (Addr != Val) continue;
976      if ((ec = SI->getName(Name)))
977        report_fatal_error(ec.message());
978      fmt << Name;
979      return;
980    }
981
982    // If we couldn't find a symbol that this relocation refers to, try
983    // to find a section beginning instead.
984    for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
985         SI.increment(ec)) {
986      if (ec) report_fatal_error(ec.message());
987
988      uint64_t Addr;
989      StringRef Name;
990
991      if ((ec = SI->getAddress(Addr)))
992        report_fatal_error(ec.message());
993      if (Addr != Val) continue;
994      if ((ec = SI->getName(Name)))
995        report_fatal_error(ec.message());
996      fmt << Name;
997      return;
998    }
999
1000    fmt << format("0x%x", Val);
1001    return;
1002  }
1003
1004  StringRef S;
1005  bool isExtern = (RE->Word1 >> 27) & 1;
1006  uint32_t Val = RE->Word1 & 0xFFFFFF;
1007
1008  if (isExtern) {
1009    symbol_iterator SI = begin_symbols();
1010    advanceTo(SI, Val);
1011    SI->getName(S);
1012  } else {
1013    section_iterator SI = begin_sections();
1014    advanceTo(SI, Val);
1015    SI->getName(S);
1016  }
1017
1018  fmt << S;
1019}
1020
1021error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1022                                          SmallVectorImpl<char> &Result) const {
1023  InMemoryStruct<macho::RelocationEntry> RE;
1024  getRelocation(Rel, RE);
1025
1026  unsigned Arch = getArch();
1027  bool isScattered = (Arch != Triple::x86_64) &&
1028                     (RE->Word0 & macho::RF_Scattered);
1029
1030  std::string fmtbuf;
1031  raw_string_ostream fmt(fmtbuf);
1032
1033  unsigned Type;
1034  if (isScattered)
1035    Type = (RE->Word0 >> 24) & 0xF;
1036  else
1037    Type = (RE->Word1 >> 28) & 0xF;
1038
1039  bool isPCRel;
1040  if (isScattered)
1041    isPCRel = ((RE->Word0 >> 30) & 1);
1042  else
1043    isPCRel = ((RE->Word1 >> 24) & 1);
1044
1045  // Determine any addends that should be displayed with the relocation.
1046  // These require decoding the relocation type, which is triple-specific.
1047
1048  // X86_64 has entirely custom relocation types.
1049  if (Arch == Triple::x86_64) {
1050    bool isPCRel = ((RE->Word1 >> 24) & 1);
1051
1052    switch (Type) {
1053      case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
1054      case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
1055        printRelocationTargetName(RE, fmt);
1056        fmt << "@GOT";
1057        if (isPCRel) fmt << "PCREL";
1058        break;
1059      }
1060      case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1061        InMemoryStruct<macho::RelocationEntry> RENext;
1062        DataRefImpl RelNext = Rel;
1063        RelNext.d.a++;
1064        getRelocation(RelNext, RENext);
1065
1066        // X86_64_SUBTRACTOR must be followed by a relocation of type
1067        // X86_64_RELOC_UNSIGNED.
1068        // NOTE: Scattered relocations don't exist on x86_64.
1069        unsigned RType = (RENext->Word1 >> 28) & 0xF;
1070        if (RType != 0)
1071          report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1072                             "X86_64_RELOC_SUBTRACTOR.");
1073
1074        // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1075        // X86_64_SUBTRACTOR contains to the subtrahend.
1076        printRelocationTargetName(RENext, fmt);
1077        fmt << "-";
1078        printRelocationTargetName(RE, fmt);
1079        break;
1080      }
1081      case macho::RIT_X86_64_TLV:
1082        printRelocationTargetName(RE, fmt);
1083        fmt << "@TLV";
1084        if (isPCRel) fmt << "P";
1085        break;
1086      case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1087        printRelocationTargetName(RE, fmt);
1088        fmt << "-1";
1089        break;
1090      case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1091        printRelocationTargetName(RE, fmt);
1092        fmt << "-2";
1093        break;
1094      case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1095        printRelocationTargetName(RE, fmt);
1096        fmt << "-4";
1097        break;
1098      default:
1099        printRelocationTargetName(RE, fmt);
1100        break;
1101    }
1102  // X86 and ARM share some relocation types in common.
1103  } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1104    // Generic relocation types...
1105    switch (Type) {
1106      case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1107        return object_error::success;
1108      case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1109        InMemoryStruct<macho::RelocationEntry> RENext;
1110        DataRefImpl RelNext = Rel;
1111        RelNext.d.a++;
1112        getRelocation(RelNext, RENext);
1113
1114        // X86 sect diff's must be followed by a relocation of type
1115        // GENERIC_RELOC_PAIR.
1116        bool isNextScattered = (Arch != Triple::x86_64) &&
1117                               (RENext->Word0 & macho::RF_Scattered);
1118        unsigned RType;
1119        if (isNextScattered)
1120          RType = (RENext->Word0 >> 24) & 0xF;
1121        else
1122          RType = (RENext->Word1 >> 28) & 0xF;
1123        if (RType != 1)
1124          report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1125                             "GENERIC_RELOC_SECTDIFF.");
1126
1127        printRelocationTargetName(RE, fmt);
1128        fmt << "-";
1129        printRelocationTargetName(RENext, fmt);
1130        break;
1131      }
1132    }
1133
1134    if (Arch == Triple::x86) {
1135      // All X86 relocations that need special printing were already
1136      // handled in the generic code.
1137      switch (Type) {
1138        case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1139          InMemoryStruct<macho::RelocationEntry> RENext;
1140          DataRefImpl RelNext = Rel;
1141          RelNext.d.a++;
1142          getRelocation(RelNext, RENext);
1143
1144          // X86 sect diff's must be followed by a relocation of type
1145          // GENERIC_RELOC_PAIR.
1146          bool isNextScattered = (Arch != Triple::x86_64) &&
1147                               (RENext->Word0 & macho::RF_Scattered);
1148          unsigned RType;
1149          if (isNextScattered)
1150            RType = (RENext->Word0 >> 24) & 0xF;
1151          else
1152            RType = (RENext->Word1 >> 28) & 0xF;
1153          if (RType != 1)
1154            report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1155                               "GENERIC_RELOC_LOCAL_SECTDIFF.");
1156
1157          printRelocationTargetName(RE, fmt);
1158          fmt << "-";
1159          printRelocationTargetName(RENext, fmt);
1160          break;
1161        }
1162        case macho::RIT_Generic_TLV: {
1163          printRelocationTargetName(RE, fmt);
1164          fmt << "@TLV";
1165          if (isPCRel) fmt << "P";
1166          break;
1167        }
1168        default:
1169          printRelocationTargetName(RE, fmt);
1170      }
1171    } else { // ARM-specific relocations
1172      switch (Type) {
1173        case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
1174        case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1175          // Half relocations steal a bit from the length field to encode
1176          // whether this is an upper16 or a lower16 relocation.
1177          bool isUpper;
1178          if (isScattered)
1179            isUpper = (RE->Word0 >> 28) & 1;
1180          else
1181            isUpper = (RE->Word1 >> 25) & 1;
1182
1183          if (isUpper)
1184            fmt << ":upper16:(";
1185          else
1186            fmt << ":lower16:(";
1187          printRelocationTargetName(RE, fmt);
1188
1189          InMemoryStruct<macho::RelocationEntry> RENext;
1190          DataRefImpl RelNext = Rel;
1191          RelNext.d.a++;
1192          getRelocation(RelNext, RENext);
1193
1194          // ARM half relocs must be followed by a relocation of type
1195          // ARM_RELOC_PAIR.
1196          bool isNextScattered = (Arch != Triple::x86_64) &&
1197                                 (RENext->Word0 & macho::RF_Scattered);
1198          unsigned RType;
1199          if (isNextScattered)
1200            RType = (RENext->Word0 >> 24) & 0xF;
1201          else
1202            RType = (RENext->Word1 >> 28) & 0xF;
1203
1204          if (RType != 1)
1205            report_fatal_error("Expected ARM_RELOC_PAIR after "
1206                               "GENERIC_RELOC_HALF");
1207
1208          // NOTE: The half of the target virtual address is stashed in the
1209          // address field of the secondary relocation, but we can't reverse
1210          // engineer the constant offset from it without decoding the movw/movt
1211          // instruction to find the other half in its immediate field.
1212
1213          // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1214          // symbol/section pointer of the follow-on relocation.
1215          if (Type == macho::RIT_ARM_HalfDifference) {
1216            fmt << "-";
1217            printRelocationTargetName(RENext, fmt);
1218          }
1219
1220          fmt << ")";
1221          break;
1222        }
1223        default: {
1224          printRelocationTargetName(RE, fmt);
1225        }
1226      }
1227    }
1228  } else
1229    printRelocationTargetName(RE, fmt);
1230
1231  fmt.flush();
1232  Result.append(fmtbuf.begin(), fmtbuf.end());
1233  return object_error::success;
1234}
1235
1236error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1237                                                bool &Result) const {
1238  InMemoryStruct<macho::RelocationEntry> RE;
1239  getRelocation(Rel, RE);
1240
1241  unsigned Arch = getArch();
1242  bool isScattered = (Arch != Triple::x86_64) &&
1243                     (RE->Word0 & macho::RF_Scattered);
1244  unsigned Type;
1245  if (isScattered)
1246    Type = (RE->Word0 >> 24) & 0xF;
1247  else
1248    Type = (RE->Word1 >> 28) & 0xF;
1249
1250  Result = false;
1251
1252  // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1253  // is always hidden.
1254  if (Arch == Triple::x86 || Arch == Triple::arm) {
1255    if (Type == macho::RIT_Pair) Result = true;
1256  } else if (Arch == Triple::x86_64) {
1257    // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1258    // an X864_64_RELOC_SUBTRACTOR.
1259    if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1260      DataRefImpl RelPrev = Rel;
1261      RelPrev.d.a--;
1262      InMemoryStruct<macho::RelocationEntry> REPrev;
1263      getRelocation(RelPrev, REPrev);
1264
1265      unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1266
1267      if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1268    }
1269  }
1270
1271  return object_error::success;
1272}
1273
1274error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1275                                           LibraryRef &Res) const {
1276  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1277}
1278
1279error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1280                                           StringRef &Res) const {
1281  report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1282}
1283
1284
1285/*===-- Miscellaneous -----------------------------------------------------===*/
1286
1287uint8_t MachOObjectFile::getBytesInAddress() const {
1288  return MachOObj->is64Bit() ? 8 : 4;
1289}
1290
1291StringRef MachOObjectFile::getFileFormatName() const {
1292  if (!MachOObj->is64Bit()) {
1293    switch (MachOObj->getHeader().CPUType) {
1294    case llvm::MachO::CPUTypeI386:
1295      return "Mach-O 32-bit i386";
1296    case llvm::MachO::CPUTypeARM:
1297      return "Mach-O arm";
1298    case llvm::MachO::CPUTypePowerPC:
1299      return "Mach-O 32-bit ppc";
1300    default:
1301      assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1302             "64-bit object file when we're not 64-bit?");
1303      return "Mach-O 32-bit unknown";
1304    }
1305  }
1306
1307  switch (MachOObj->getHeader().CPUType) {
1308  case llvm::MachO::CPUTypeX86_64:
1309    return "Mach-O 64-bit x86-64";
1310  case llvm::MachO::CPUTypePowerPC64:
1311    return "Mach-O 64-bit ppc64";
1312  default:
1313    assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
1314           "32-bit object file when we're 64-bit?");
1315    return "Mach-O 64-bit unknown";
1316  }
1317}
1318
1319unsigned MachOObjectFile::getArch() const {
1320  switch (MachOObj->getHeader().CPUType) {
1321  case llvm::MachO::CPUTypeI386:
1322    return Triple::x86;
1323  case llvm::MachO::CPUTypeX86_64:
1324    return Triple::x86_64;
1325  case llvm::MachO::CPUTypeARM:
1326    return Triple::arm;
1327  case llvm::MachO::CPUTypePowerPC:
1328    return Triple::ppc;
1329  case llvm::MachO::CPUTypePowerPC64:
1330    return Triple::ppc64;
1331  default:
1332    return Triple::UnknownArch;
1333  }
1334}
1335
1336} // end namespace object
1337} // end namespace llvm
1338