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