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