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