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