Stub out some of the MachO relocation decoding hooks.
[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/MemoryBuffer.h"
19
20 #include <cctype>
21 #include <cstring>
22 #include <limits>
23
24 using namespace llvm;
25 using namespace object;
26
27 namespace llvm {
28 namespace object {
29
30 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
31                                  error_code &ec)
32     : ObjectFile(Binary::isMachO, Object, ec),
33       MachOObj(MOO),
34       RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
35   DataRefImpl DRI;
36   DRI.d.a = DRI.d.b = 0;
37   moveToNextSection(DRI);
38   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
39   while (DRI.d.a < LoadCommandCount) {
40     Sections.push_back(DRI);
41     DRI.d.b++;
42     moveToNextSection(DRI);
43   }
44 }
45
46
47 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
48   error_code ec;
49   std::string Err;
50   MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
51   if (!MachOObj)
52     return NULL;
53   return new MachOObjectFile(Buffer, MachOObj, ec);
54 }
55
56 /*===-- Symbols -----------------------------------------------------------===*/
57
58 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
59   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
60   while (DRI.d.a < LoadCommandCount) {
61     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
62     if (LCI.Command.Type == macho::LCT_Symtab) {
63       InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
64       MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
65       if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
66         return;
67     }
68
69     DRI.d.a++;
70     DRI.d.b = 0;
71   }
72 }
73
74 void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
75     InMemoryStruct<macho::SymbolTableEntry> &Res) const {
76   InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
77   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
78   MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
79
80   if (RegisteredStringTable != DRI.d.a) {
81     MachOObj->RegisterStringTable(*SymtabLoadCmd);
82     RegisteredStringTable = DRI.d.a;
83   }
84
85   MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
86                                  Res);
87 }
88
89 void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
90     InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
91   InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
92   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
93   MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
94
95   if (RegisteredStringTable != DRI.d.a) {
96     MachOObj->RegisterStringTable(*SymtabLoadCmd);
97     RegisteredStringTable = DRI.d.a;
98   }
99
100   MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
101                                    Res);
102 }
103
104
105 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
106                                           SymbolRef &Result) const {
107   DRI.d.b++;
108   moveToNextSymbol(DRI);
109   Result = SymbolRef(DRI, this);
110   return object_error::success;
111 }
112
113 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
114                                           StringRef &Result) const {
115   if (MachOObj->is64Bit()) {
116     InMemoryStruct<macho::Symbol64TableEntry> Entry;
117     getSymbol64TableEntry(DRI, Entry);
118     Result = MachOObj->getStringAtIndex(Entry->StringIndex);
119   } else {
120     InMemoryStruct<macho::SymbolTableEntry> Entry;
121     getSymbolTableEntry(DRI, Entry);
122     Result = MachOObj->getStringAtIndex(Entry->StringIndex);
123   }
124   return object_error::success;
125 }
126
127 error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI,
128                                              uint64_t &Result) const {
129   uint64_t SectionOffset;
130   uint8_t SectionIndex;
131   if (MachOObj->is64Bit()) {
132     InMemoryStruct<macho::Symbol64TableEntry> Entry;
133     getSymbol64TableEntry(DRI, Entry);
134     Result = Entry->Value;
135     SectionIndex = Entry->SectionIndex;
136   } else {
137     InMemoryStruct<macho::SymbolTableEntry> Entry;
138     getSymbolTableEntry(DRI, Entry);
139     Result = Entry->Value;
140     SectionIndex = Entry->SectionIndex;
141   }
142   getSectionAddress(Sections[SectionIndex-1], SectionOffset);
143   Result -= SectionOffset;
144
145   return object_error::success;
146 }
147
148 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
149                                              uint64_t &Result) const {
150   if (MachOObj->is64Bit()) {
151     InMemoryStruct<macho::Symbol64TableEntry> Entry;
152     getSymbol64TableEntry(DRI, Entry);
153     Result = Entry->Value;
154   } else {
155     InMemoryStruct<macho::SymbolTableEntry> Entry;
156     getSymbolTableEntry(DRI, Entry);
157     Result = Entry->Value;
158   }
159   return object_error::success;
160 }
161
162 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
163                                           uint64_t &Result) const {
164   Result = UnknownAddressOrSize;
165   return object_error::success;
166 }
167
168 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
169                                                 char &Result) const {
170   uint8_t Type, Flags;
171   if (MachOObj->is64Bit()) {
172     InMemoryStruct<macho::Symbol64TableEntry> Entry;
173     getSymbol64TableEntry(DRI, Entry);
174     Type = Entry->Type;
175     Flags = Entry->Flags;
176   } else {
177     InMemoryStruct<macho::SymbolTableEntry> Entry;
178     getSymbolTableEntry(DRI, Entry);
179     Type = Entry->Type;
180     Flags = Entry->Flags;
181   }
182
183   char Char;
184   switch (Type & macho::STF_TypeMask) {
185     case macho::STT_Undefined:
186       Char = 'u';
187       break;
188     case macho::STT_Absolute:
189     case macho::STT_Section:
190       Char = 's';
191       break;
192     default:
193       Char = '?';
194       break;
195   }
196
197   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
198     Char = toupper(Char);
199   Result = Char;
200   return object_error::success;
201 }
202
203 error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
204                                              bool &Result) const {
205   if (MachOObj->is64Bit()) {
206     InMemoryStruct<macho::Symbol64TableEntry> Entry;
207     getSymbol64TableEntry(DRI, Entry);
208     Result = Entry->Flags & macho::STF_StabsEntryMask;
209   } else {
210     InMemoryStruct<macho::SymbolTableEntry> Entry;
211     getSymbolTableEntry(DRI, Entry);
212     Result = Entry->Flags & macho::STF_StabsEntryMask;
213   }
214   return object_error::success;
215 }
216
217 error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
218
219   if (MachOObj->is64Bit()) {
220     InMemoryStruct<macho::Symbol64TableEntry> Entry;
221     getSymbol64TableEntry(Symb, Entry);
222     Res = Entry->Type & MachO::NlistMaskExternal;
223   } else {
224     InMemoryStruct<macho::SymbolTableEntry> Entry;
225     getSymbolTableEntry(Symb, Entry);
226     Res = Entry->Type & MachO::NlistMaskExternal;
227   }
228   return object_error::success;
229 }
230
231 error_code MachOObjectFile::isSymbolWeak(DataRefImpl Symb, bool &Res) const {
232
233   if (MachOObj->is64Bit()) {
234     InMemoryStruct<macho::Symbol64TableEntry> Entry;
235     getSymbol64TableEntry(Symb, Entry);
236     Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
237   } else {
238     InMemoryStruct<macho::SymbolTableEntry> Entry;
239     getSymbolTableEntry(Symb, Entry);
240     Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
241   }
242   return object_error::success;
243 }
244
245 error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{
246   uint8_t n_type;
247   if (MachOObj->is64Bit()) {
248     InMemoryStruct<macho::Symbol64TableEntry> Entry;
249     getSymbol64TableEntry(Symb, Entry);
250     n_type = Entry->Type;
251   } else {
252     InMemoryStruct<macho::SymbolTableEntry> Entry;
253     getSymbolTableEntry(Symb, Entry);
254     n_type = Entry->Type;
255   }
256
257   Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute;
258   return object_error::success;
259 }
260
261 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
262                                              section_iterator &Res) const {
263   uint8_t index;
264   if (MachOObj->is64Bit()) {
265     InMemoryStruct<macho::Symbol64TableEntry> Entry;
266     getSymbol64TableEntry(Symb, Entry);
267     index = Entry->SectionIndex;
268   } else {
269     InMemoryStruct<macho::SymbolTableEntry> Entry;
270     getSymbolTableEntry(Symb, Entry);
271     index = Entry->SectionIndex;
272   }
273
274   if (index == 0)
275     Res = end_sections();
276   else
277     Res = section_iterator(SectionRef(Sections[index], this));
278
279   return object_error::success;
280 }
281
282 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
283                                           SymbolRef::Type &Res) const {
284   uint8_t n_type;
285   if (MachOObj->is64Bit()) {
286     InMemoryStruct<macho::Symbol64TableEntry> Entry;
287     getSymbol64TableEntry(Symb, Entry);
288     n_type = Entry->Type;
289   } else {
290     InMemoryStruct<macho::SymbolTableEntry> Entry;
291     getSymbolTableEntry(Symb, Entry);
292     n_type = Entry->Type;
293   }
294   Res = SymbolRef::ST_Other;
295
296   // If this is a STAB debugging symbol, we can do nothing more.
297   if (n_type & MachO::NlistMaskStab) {
298     Res = SymbolRef::ST_Debug;
299     return object_error::success;
300   }
301
302   switch (n_type & MachO::NlistMaskType) {
303     case MachO::NListTypeUndefined :
304       Res = SymbolRef::ST_External;
305       break;
306     case MachO::NListTypeSection :
307       Res = SymbolRef::ST_Function;
308       break;
309   }
310   return object_error::success;
311 }
312
313
314 symbol_iterator MachOObjectFile::begin_symbols() const {
315   // DRI.d.a = segment number; DRI.d.b = symbol index.
316   DataRefImpl DRI;
317   DRI.d.a = DRI.d.b = 0;
318   moveToNextSymbol(DRI);
319   return symbol_iterator(SymbolRef(DRI, this));
320 }
321
322 symbol_iterator MachOObjectFile::end_symbols() const {
323   DataRefImpl DRI;
324   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
325   DRI.d.b = 0;
326   return symbol_iterator(SymbolRef(DRI, this));
327 }
328
329
330 /*===-- Sections ----------------------------------------------------------===*/
331
332 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
333   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
334   while (DRI.d.a < LoadCommandCount) {
335     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
336     if (LCI.Command.Type == macho::LCT_Segment) {
337       InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
338       MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
339       if (DRI.d.b < SegmentLoadCmd->NumSections)
340         return;
341     } else if (LCI.Command.Type == macho::LCT_Segment64) {
342       InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
343       MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
344       if (DRI.d.b < Segment64LoadCmd->NumSections)
345         return;
346     }
347
348     DRI.d.a++;
349     DRI.d.b = 0;
350   }
351 }
352
353 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
354                                            SectionRef &Result) const {
355   DRI.d.b++;
356   moveToNextSection(DRI);
357   Result = SectionRef(DRI, this);
358   return object_error::success;
359 }
360
361 void
362 MachOObjectFile::getSection(DataRefImpl DRI,
363                             InMemoryStruct<macho::Section> &Res) const {
364   InMemoryStruct<macho::SegmentLoadCommand> SLC;
365   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
366   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
367   MachOObj->ReadSection(LCI, DRI.d.b, Res);
368 }
369
370 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
371   SectionList::const_iterator loc =
372     std::find(Sections.begin(), Sections.end(), Sec);
373   assert(loc != Sections.end() && "Sec is not a valid section!");
374   return std::distance(Sections.begin(), loc);
375 }
376
377 void
378 MachOObjectFile::getSection64(DataRefImpl DRI,
379                             InMemoryStruct<macho::Section64> &Res) const {
380   InMemoryStruct<macho::Segment64LoadCommand> SLC;
381   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
382   MachOObj->ReadSegment64LoadCommand(LCI, SLC);
383   MachOObj->ReadSection64(LCI, DRI.d.b, Res);
384 }
385
386 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
387   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
388   if (LCI.Command.Type == macho::LCT_Segment64)
389     return true;
390   assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
391   return false;
392 }
393
394 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
395                                            StringRef &Result) const {
396   // FIXME: thread safety.
397   static char result[34];
398   if (is64BitLoadCommand(MachOObj, DRI)) {
399     InMemoryStruct<macho::Segment64LoadCommand> SLC;
400     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
401     MachOObj->ReadSegment64LoadCommand(LCI, SLC);
402     InMemoryStruct<macho::Section64> Sect;
403     MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
404
405     strcpy(result, Sect->SegmentName);
406     strcat(result, ",");
407     strcat(result, Sect->Name);
408   } else {
409     InMemoryStruct<macho::SegmentLoadCommand> SLC;
410     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
411     MachOObj->ReadSegmentLoadCommand(LCI, SLC);
412     InMemoryStruct<macho::Section> Sect;
413     MachOObj->ReadSection(LCI, DRI.d.b, Sect);
414
415     strcpy(result, Sect->SegmentName);
416     strcat(result, ",");
417     strcat(result, Sect->Name);
418   }
419   Result = StringRef(result);
420   return object_error::success;
421 }
422
423 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
424                                               uint64_t &Result) const {
425   if (is64BitLoadCommand(MachOObj, DRI)) {
426     InMemoryStruct<macho::Section64> Sect;
427     getSection64(DRI, Sect);
428     Result = Sect->Address;
429   } else {
430     InMemoryStruct<macho::Section> Sect;
431     getSection(DRI, Sect);
432     Result = Sect->Address;
433   }
434   return object_error::success;
435 }
436
437 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
438                                            uint64_t &Result) const {
439   if (is64BitLoadCommand(MachOObj, DRI)) {
440     InMemoryStruct<macho::Section64> Sect;
441     getSection64(DRI, Sect);
442     Result = Sect->Size;
443   } else {
444     InMemoryStruct<macho::Section> Sect;
445     getSection(DRI, Sect);
446     Result = Sect->Size;
447   }
448   return object_error::success;
449 }
450
451 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
452                                                StringRef &Result) const {
453   if (is64BitLoadCommand(MachOObj, DRI)) {
454     InMemoryStruct<macho::Section64> Sect;
455     getSection64(DRI, Sect);
456     Result = MachOObj->getData(Sect->Offset, Sect->Size);
457   } else {
458     InMemoryStruct<macho::Section> Sect;
459     getSection(DRI, Sect);
460     Result = MachOObj->getData(Sect->Offset, Sect->Size);
461   }
462   return object_error::success;
463 }
464
465 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
466                                                 uint64_t &Result) const {
467   if (is64BitLoadCommand(MachOObj, DRI)) {
468     InMemoryStruct<macho::Section64> Sect;
469     getSection64(DRI, Sect);
470     Result = uint64_t(1) << Sect->Align;
471   } else {
472     InMemoryStruct<macho::Section> Sect;
473     getSection(DRI, Sect);
474     Result = uint64_t(1) << Sect->Align;
475   }
476   return object_error::success;
477 }
478
479 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
480                                           bool &Result) const {
481   if (is64BitLoadCommand(MachOObj, DRI)) {
482     InMemoryStruct<macho::Section64> Sect;
483     getSection64(DRI, Sect);
484     Result = !strcmp(Sect->Name, "__text");
485   } else {
486     InMemoryStruct<macho::Section> Sect;
487     getSection(DRI, Sect);
488     Result = !strcmp(Sect->Name, "__text");
489   }
490   return object_error::success;
491 }
492
493 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
494                                           bool &Result) const {
495   // FIXME: Unimplemented.
496   Result = false;
497   return object_error::success;
498 }
499
500 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
501                                          bool &Result) const {
502   // FIXME: Unimplemented.
503   Result = false;
504   return object_error::success;
505 }
506
507 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
508                                                   DataRefImpl Symb,
509                                                   bool &Result) const {
510   SymbolRef::Type ST;
511   getSymbolType(Symb, ST);
512   if (ST == SymbolRef::ST_External) {
513     Result = false;
514     return object_error::success;
515   }
516
517   uint64_t SectBegin, SectEnd;
518   getSectionAddress(Sec, SectBegin);
519   getSectionSize(Sec, SectEnd);
520   SectEnd += SectBegin;
521
522   if (MachOObj->is64Bit()) {
523     InMemoryStruct<macho::Symbol64TableEntry> Entry;
524     getSymbol64TableEntry(Symb, Entry);
525     uint64_t SymAddr= Entry->Value;
526     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
527   } else {
528     InMemoryStruct<macho::SymbolTableEntry> Entry;
529     getSymbolTableEntry(Symb, Entry);
530     uint64_t SymAddr= Entry->Value;
531     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
532   }
533
534   return object_error::success;
535 }
536
537 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
538   DataRefImpl ret;
539   ret.d.a = 0;
540   ret.d.b = getSectionIndex(Sec);
541   return relocation_iterator(RelocationRef(ret, this));
542 }
543 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
544   uint32_t last_reloc;
545   if (is64BitLoadCommand(MachOObj, Sec)) {
546     InMemoryStruct<macho::Section64> Sect;
547     getSection64(Sec, Sect);
548     last_reloc = Sect->NumRelocationTableEntries;
549   } else {
550     InMemoryStruct<macho::Section> Sect;
551     getSection(Sec, Sect);
552     last_reloc = Sect->NumRelocationTableEntries;
553   }
554   DataRefImpl ret;
555   ret.d.a = last_reloc;
556   ret.d.b = getSectionIndex(Sec);
557   return relocation_iterator(RelocationRef(ret, this));
558 }
559
560 section_iterator MachOObjectFile::begin_sections() const {
561   DataRefImpl DRI;
562   DRI.d.a = DRI.d.b = 0;
563   moveToNextSection(DRI);
564   return section_iterator(SectionRef(DRI, this));
565 }
566
567 section_iterator MachOObjectFile::end_sections() const {
568   DataRefImpl DRI;
569   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
570   DRI.d.b = 0;
571   return section_iterator(SectionRef(DRI, this));
572 }
573
574 /*===-- Relocations -------------------------------------------------------===*/
575
576 void MachOObjectFile::
577 getRelocation(DataRefImpl Rel,
578               InMemoryStruct<macho::RelocationEntry> &Res) const {
579   uint32_t relOffset;
580   if (MachOObj->is64Bit()) {
581     InMemoryStruct<macho::Section64> Sect;
582     getSection64(Sections[Rel.d.b], Sect);
583     relOffset = Sect->RelocationTableOffset;
584   } else {
585     InMemoryStruct<macho::Section> Sect;
586     getSection(Sections[Rel.d.b], Sect);
587     relOffset = Sect->RelocationTableOffset;
588   }
589   MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
590 }
591 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
592                                               RelocationRef &Res) const {
593   ++Rel.d.a;
594   Res = RelocationRef(Rel, this);
595   return object_error::success;
596 }
597 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
598                                                  uint64_t &Res) const {
599   const uint8_t* sectAddress = base();
600   if (MachOObj->is64Bit()) {
601     InMemoryStruct<macho::Section64> Sect;
602     getSection64(Sections[Rel.d.b], Sect);
603     sectAddress += Sect->Offset;
604   } else {
605     InMemoryStruct<macho::Section> Sect;
606     getSection(Sections[Rel.d.b], Sect);
607     sectAddress += Sect->Offset;
608   }
609   InMemoryStruct<macho::RelocationEntry> RE;
610   getRelocation(Rel, RE);
611   Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
612   return object_error::success;
613 }
614 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
615                                                 SymbolRef &Res) const {
616   InMemoryStruct<macho::RelocationEntry> RE;
617   getRelocation(Rel, RE);
618   uint32_t SymbolIdx = RE->Word1 & 0xffffff;
619   bool isExtern = (RE->Word1 >> 27) & 1;
620
621   DataRefImpl Sym;
622   Sym.d.a = Sym.d.b = 0;
623   moveToNextSymbol(Sym);
624   if (isExtern) {
625     for (unsigned i = 0; i < SymbolIdx; i++) {
626       Sym.d.b++;
627       moveToNextSymbol(Sym);
628       assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
629              "Relocation symbol index out of range!");
630     }
631   }
632   Res = SymbolRef(Sym, this);
633   return object_error::success;
634 }
635 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
636                                               uint32_t &Res) const {
637   InMemoryStruct<macho::RelocationEntry> RE;
638   getRelocation(Rel, RE);
639   Res = RE->Word1;
640   return object_error::success;
641 }
642 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
643                                           SmallVectorImpl<char> &Result) const {
644   StringRef res = "Unknown";
645   Result.append(res.begin(), res.end());
646   return object_error::success;
647 }
648 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
649                                                         int64_t &Res) const {
650   InMemoryStruct<macho::RelocationEntry> RE;
651   getRelocation(Rel, RE);
652   bool isExtern = (RE->Word1 >> 27) & 1;
653   Res = 0;
654   if (!isExtern) {
655     const uint8_t* sectAddress = base();
656     if (MachOObj->is64Bit()) {
657       InMemoryStruct<macho::Section64> Sect;
658       getSection64(Sections[Rel.d.b], Sect);
659       sectAddress += Sect->Offset;
660     } else {
661       InMemoryStruct<macho::Section> Sect;
662       getSection(Sections[Rel.d.b], Sect);
663       sectAddress += Sect->Offset;
664     }
665     Res = reinterpret_cast<uintptr_t>(sectAddress);
666   }
667   return object_error::success;
668 }
669 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
670                                           SmallVectorImpl<char> &Result) const {
671   StringRef res = "Unknown";
672   Result.append(res.begin(), res.end());
673   return object_error::success;
674 }
675
676 /*===-- Miscellaneous -----------------------------------------------------===*/
677
678 uint8_t MachOObjectFile::getBytesInAddress() const {
679   return MachOObj->is64Bit() ? 8 : 4;
680 }
681
682 StringRef MachOObjectFile::getFileFormatName() const {
683   if (!MachOObj->is64Bit()) {
684     switch (MachOObj->getHeader().CPUType) {
685     case llvm::MachO::CPUTypeI386:
686       return "Mach-O 32-bit i386";
687     case llvm::MachO::CPUTypeARM:
688       return "Mach-O arm";
689     case llvm::MachO::CPUTypePowerPC:
690       return "Mach-O 32-bit ppc";
691     default:
692       assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
693              "64-bit object file when we're not 64-bit?");
694       return "Mach-O 32-bit unknown";
695     }
696   }
697
698   switch (MachOObj->getHeader().CPUType) {
699   case llvm::MachO::CPUTypeX86_64:
700     return "Mach-O 64-bit x86-64";
701   case llvm::MachO::CPUTypePowerPC64:
702     return "Mach-O 64-bit ppc64";
703   default:
704     assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
705            "32-bit object file when we're 64-bit?");
706     return "Mach-O 64-bit unknown";
707   }
708 }
709
710 unsigned MachOObjectFile::getArch() const {
711   switch (MachOObj->getHeader().CPUType) {
712   case llvm::MachO::CPUTypeI386:
713     return Triple::x86;
714   case llvm::MachO::CPUTypeX86_64:
715     return Triple::x86_64;
716   case llvm::MachO::CPUTypeARM:
717     return Triple::arm;
718   case llvm::MachO::CPUTypePowerPC:
719     return Triple::ppc;
720   case llvm::MachO::CPUTypePowerPC64:
721     return Triple::ppc64;
722   default:
723     return Triple::UnknownArch;
724   }
725 }
726
727 } // end namespace object
728 } // end namespace llvm