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