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