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/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include <cctype>
28 #include <cstring>
29 #include <limits>
30
31 using namespace llvm;
32 using namespace object;
33
34 namespace {
35 struct section_base {
36 char sectname[16];
37 char segname[16];
38 };
39 }
40
41 template<typename T>
getStruct(const MachOObjectFile * O,const char * P)42 static T getStruct(const MachOObjectFile *O, const char *P) {
43 T Cmd;
44 memcpy(&Cmd, P, sizeof(T));
45 if (O->isLittleEndian() != sys::IsLittleEndianHost)
46 MachO::swapStruct(Cmd);
47 return Cmd;
48 }
49
50 static uint32_t
getSegmentLoadCommandNumSections(const MachOObjectFile * O,const MachOObjectFile::LoadCommandInfo & L)51 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
52 const MachOObjectFile::LoadCommandInfo &L) {
53 if (O->is64Bit()) {
54 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
55 return S.nsects;
56 }
57 MachO::segment_command S = O->getSegmentLoadCommand(L);
58 return S.nsects;
59 }
60
isPageZeroSegment(const MachOObjectFile * O,const MachOObjectFile::LoadCommandInfo & L)61 static bool isPageZeroSegment(const MachOObjectFile *O,
62 const MachOObjectFile::LoadCommandInfo &L) {
63 if (O->is64Bit()) {
64 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
65 return StringRef("__PAGEZERO").equals(S.segname);
66 }
67 MachO::segment_command S = O->getSegmentLoadCommand(L);
68 return StringRef("__PAGEZERO").equals(S.segname);
69 }
70
71
72 static const char *
getSectionPtr(const MachOObjectFile * O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)73 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
74 unsigned Sec) {
75 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
76
77 bool Is64 = O->is64Bit();
78 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
79 sizeof(MachO::segment_command);
80 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
81 sizeof(MachO::section);
82
83 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
84 return reinterpret_cast<const char*>(SectionAddr);
85 }
86
getPtr(const MachOObjectFile * O,size_t Offset)87 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
88 return O->getData().substr(Offset, 1).data();
89 }
90
91 static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile * O,DataRefImpl DRI)92 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
93 const char *P = reinterpret_cast<const char *>(DRI.p);
94 return getStruct<MachO::nlist_base>(O, P);
95 }
96
parseSegmentOrSectionName(const char * P)97 static StringRef parseSegmentOrSectionName(const char *P) {
98 if (P[15] == 0)
99 // Null terminated.
100 return P;
101 // Not null terminated, so this is a 16 char string.
102 return StringRef(P, 16);
103 }
104
105 // Helper to advance a section or symbol iterator multiple increments at a time.
106 template<class T>
advance(T & it,size_t Val)107 static void advance(T &it, size_t Val) {
108 while (Val--)
109 ++it;
110 }
111
getCPUType(const MachOObjectFile * O)112 static unsigned getCPUType(const MachOObjectFile *O) {
113 return O->getHeader().cputype;
114 }
115
printRelocationTargetName(const MachOObjectFile * O,const MachO::any_relocation_info & RE,raw_string_ostream & fmt)116 static void printRelocationTargetName(const MachOObjectFile *O,
117 const MachO::any_relocation_info &RE,
118 raw_string_ostream &fmt) {
119 bool IsScattered = O->isRelocationScattered(RE);
120
121 // Target of a scattered relocation is an address. In the interest of
122 // generating pretty output, scan through the symbol table looking for a
123 // symbol that aligns with that address. If we find one, print it.
124 // Otherwise, we just print the hex address of the target.
125 if (IsScattered) {
126 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
127
128 for (const SymbolRef &Symbol : O->symbols()) {
129 std::error_code ec;
130 uint64_t Addr;
131 StringRef Name;
132
133 if ((ec = Symbol.getAddress(Addr)))
134 report_fatal_error(ec.message());
135 if (Addr != Val)
136 continue;
137 if ((ec = Symbol.getName(Name)))
138 report_fatal_error(ec.message());
139 fmt << Name;
140 return;
141 }
142
143 // If we couldn't find a symbol that this relocation refers to, try
144 // to find a section beginning instead.
145 for (const SectionRef &Section : O->sections()) {
146 std::error_code ec;
147
148 StringRef Name;
149 uint64_t Addr = Section.getAddress();
150 if (Addr != Val)
151 continue;
152 if ((ec = Section.getName(Name)))
153 report_fatal_error(ec.message());
154 fmt << Name;
155 return;
156 }
157
158 fmt << format("0x%x", Val);
159 return;
160 }
161
162 StringRef S;
163 bool isExtern = O->getPlainRelocationExternal(RE);
164 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
165
166 if (isExtern) {
167 symbol_iterator SI = O->symbol_begin();
168 advance(SI, Val);
169 SI->getName(S);
170 } else {
171 section_iterator SI = O->section_begin();
172 // Adjust for the fact that sections are 1-indexed.
173 advance(SI, Val - 1);
174 SI->getName(S);
175 }
176
177 fmt << S;
178 }
179
180 static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)181 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
182 return RE.r_word0;
183 }
184
185 static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)186 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
187 return RE.r_word0 & 0xffffff;
188 }
189
getPlainRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)190 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
191 const MachO::any_relocation_info &RE) {
192 if (O->isLittleEndian())
193 return (RE.r_word1 >> 24) & 1;
194 return (RE.r_word1 >> 7) & 1;
195 }
196
197 static bool
getScatteredRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)198 getScatteredRelocationPCRel(const MachOObjectFile *O,
199 const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 30) & 1;
201 }
202
getPlainRelocationLength(const MachOObjectFile * O,const MachO::any_relocation_info & RE)203 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
204 const MachO::any_relocation_info &RE) {
205 if (O->isLittleEndian())
206 return (RE.r_word1 >> 25) & 3;
207 return (RE.r_word1 >> 5) & 3;
208 }
209
210 static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)211 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 28) & 3;
213 }
214
getPlainRelocationType(const MachOObjectFile * O,const MachO::any_relocation_info & RE)215 static unsigned getPlainRelocationType(const MachOObjectFile *O,
216 const MachO::any_relocation_info &RE) {
217 if (O->isLittleEndian())
218 return RE.r_word1 >> 28;
219 return RE.r_word1 & 0xf;
220 }
221
getSectionFlags(const MachOObjectFile * O,DataRefImpl Sec)222 static uint32_t getSectionFlags(const MachOObjectFile *O,
223 DataRefImpl Sec) {
224 if (O->is64Bit()) {
225 MachO::section_64 Sect = O->getSection64(Sec);
226 return Sect.flags;
227 }
228 MachO::section Sect = O->getSection(Sec);
229 return Sect.flags;
230 }
231
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,std::error_code & EC)232 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
233 bool Is64bits, std::error_code &EC)
234 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
235 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
236 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
237 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
238 uint32_t LoadCommandCount = this->getHeader().ncmds;
239 if (LoadCommandCount == 0)
240 return;
241
242 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
243 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
244
245 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
246 for (unsigned I = 0; ; ++I) {
247 if (Load.C.cmd == MachO::LC_SYMTAB) {
248 // Multiple symbol tables
249 if (SymtabLoadCmd) {
250 EC = object_error::parse_failed;
251 return;
252 }
253 SymtabLoadCmd = Load.Ptr;
254 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
255 // Multiple dynamic symbol tables
256 if (DysymtabLoadCmd) {
257 EC = object_error::parse_failed;
258 return;
259 }
260 DysymtabLoadCmd = Load.Ptr;
261 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
262 // Multiple data in code tables
263 if (DataInCodeLoadCmd) {
264 EC = object_error::parse_failed;
265 return;
266 }
267 DataInCodeLoadCmd = Load.Ptr;
268 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
269 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
270 // Multiple dyldinfo load commands
271 if (DyldInfoLoadCmd) {
272 EC = object_error::parse_failed;
273 return;
274 }
275 DyldInfoLoadCmd = Load.Ptr;
276 } else if (Load.C.cmd == MachO::LC_UUID) {
277 // Multiple UUID load commands
278 if (UuidLoadCmd) {
279 EC = object_error::parse_failed;
280 return;
281 }
282 UuidLoadCmd = Load.Ptr;
283 } else if (Load.C.cmd == SegmentLoadType) {
284 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
285 for (unsigned J = 0; J < NumSections; ++J) {
286 const char *Sec = getSectionPtr(this, Load, J);
287 Sections.push_back(Sec);
288 }
289 if (isPageZeroSegment(this, Load))
290 HasPageZeroSegment = true;
291 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
292 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
293 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
294 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
295 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
296 Libraries.push_back(Load.Ptr);
297 }
298
299 if (I == LoadCommandCount - 1)
300 break;
301 else
302 Load = getNextLoadCommandInfo(Load);
303 }
304 }
305
moveSymbolNext(DataRefImpl & Symb) const306 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
307 unsigned SymbolTableEntrySize = is64Bit() ?
308 sizeof(MachO::nlist_64) :
309 sizeof(MachO::nlist);
310 Symb.p += SymbolTableEntrySize;
311 }
312
getSymbolName(DataRefImpl Symb,StringRef & Res) const313 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
314 StringRef &Res) const {
315 StringRef StringTable = getStringTableData();
316 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
317 const char *Start = &StringTable.data()[Entry.n_strx];
318 Res = StringRef(Start);
319 return object_error::success;
320 }
321
getSectionType(SectionRef Sec) const322 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
323 DataRefImpl DRI = Sec.getRawDataRefImpl();
324 uint32_t Flags = getSectionFlags(this, DRI);
325 return Flags & MachO::SECTION_TYPE;
326 }
327
328 // getIndirectName() returns the name of the alias'ed symbol who's string table
329 // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const330 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
331 StringRef &Res) const {
332 StringRef StringTable = getStringTableData();
333 uint64_t NValue;
334 if (is64Bit()) {
335 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
336 NValue = Entry.n_value;
337 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
338 return object_error::parse_failed;
339 } else {
340 MachO::nlist Entry = getSymbolTableEntry(Symb);
341 NValue = Entry.n_value;
342 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
343 return object_error::parse_failed;
344 }
345 if (NValue >= StringTable.size())
346 return object_error::parse_failed;
347 const char *Start = &StringTable.data()[NValue];
348 Res = StringRef(Start);
349 return object_error::success;
350 }
351
getSymbolAddress(DataRefImpl Symb,uint64_t & Res) const352 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
353 uint64_t &Res) const {
354 if (is64Bit()) {
355 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
356 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
357 Entry.n_value == 0)
358 Res = UnknownAddressOrSize;
359 else
360 Res = Entry.n_value;
361 } else {
362 MachO::nlist Entry = getSymbolTableEntry(Symb);
363 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
364 Entry.n_value == 0)
365 Res = UnknownAddressOrSize;
366 else
367 Res = Entry.n_value;
368 }
369 return object_error::success;
370 }
371
getSymbolAlignment(DataRefImpl DRI,uint32_t & Result) const372 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
373 uint32_t &Result) const {
374 uint32_t flags = getSymbolFlags(DRI);
375 if (flags & SymbolRef::SF_Common) {
376 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
377 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
378 } else {
379 Result = 0;
380 }
381 return object_error::success;
382 }
383
getSymbolSize(DataRefImpl DRI,uint64_t & Result) const384 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
385 uint64_t &Result) const {
386 uint64_t BeginOffset;
387 uint64_t EndOffset = 0;
388 uint8_t SectionIndex;
389
390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
391 uint64_t Value;
392 getSymbolAddress(DRI, Value);
393 if (Value == UnknownAddressOrSize) {
394 Result = UnknownAddressOrSize;
395 return object_error::success;
396 }
397
398 BeginOffset = Value;
399
400 SectionIndex = Entry.n_sect;
401 if (!SectionIndex) {
402 uint32_t flags = getSymbolFlags(DRI);
403 if (flags & SymbolRef::SF_Common)
404 Result = Value;
405 else
406 Result = UnknownAddressOrSize;
407 return object_error::success;
408 }
409 // Unfortunately symbols are unsorted so we need to touch all
410 // symbols from load command
411 for (const SymbolRef &Symbol : symbols()) {
412 DataRefImpl DRI = Symbol.getRawDataRefImpl();
413 Entry = getSymbolTableEntryBase(this, DRI);
414 getSymbolAddress(DRI, Value);
415 if (Value == UnknownAddressOrSize)
416 continue;
417 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
418 if (!EndOffset || Value < EndOffset)
419 EndOffset = Value;
420 }
421 if (!EndOffset) {
422 DataRefImpl Sec;
423 Sec.d.a = SectionIndex-1;
424 uint64_t Size = getSectionSize(Sec);
425 EndOffset = getSectionAddress(Sec);
426 EndOffset += Size;
427 }
428 Result = EndOffset - BeginOffset;
429 return object_error::success;
430 }
431
getSymbolType(DataRefImpl Symb,SymbolRef::Type & Res) const432 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
433 SymbolRef::Type &Res) const {
434 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
435 uint8_t n_type = Entry.n_type;
436
437 Res = SymbolRef::ST_Other;
438
439 // If this is a STAB debugging symbol, we can do nothing more.
440 if (n_type & MachO::N_STAB) {
441 Res = SymbolRef::ST_Debug;
442 return object_error::success;
443 }
444
445 switch (n_type & MachO::N_TYPE) {
446 case MachO::N_UNDF :
447 Res = SymbolRef::ST_Unknown;
448 break;
449 case MachO::N_SECT :
450 Res = SymbolRef::ST_Function;
451 break;
452 }
453 return object_error::success;
454 }
455
getSymbolFlags(DataRefImpl DRI) const456 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
457 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
458
459 uint8_t MachOType = Entry.n_type;
460 uint16_t MachOFlags = Entry.n_desc;
461
462 uint32_t Result = SymbolRef::SF_None;
463
464 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
465 Result |= SymbolRef::SF_Undefined;
466
467 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
468 Result |= SymbolRef::SF_Indirect;
469
470 if (MachOType & MachO::N_STAB)
471 Result |= SymbolRef::SF_FormatSpecific;
472
473 if (MachOType & MachO::N_EXT) {
474 Result |= SymbolRef::SF_Global;
475 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
476 uint64_t Value;
477 getSymbolAddress(DRI, Value);
478 if (Value && Value != UnknownAddressOrSize)
479 Result |= SymbolRef::SF_Common;
480 }
481 }
482
483 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
484 Result |= SymbolRef::SF_Weak;
485
486 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
487 Result |= SymbolRef::SF_Thumb;
488
489 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
490 Result |= SymbolRef::SF_Absolute;
491
492 return Result;
493 }
494
getSymbolSection(DataRefImpl Symb,section_iterator & Res) const495 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
496 section_iterator &Res) const {
497 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
498 uint8_t index = Entry.n_sect;
499
500 if (index == 0) {
501 Res = section_end();
502 } else {
503 DataRefImpl DRI;
504 DRI.d.a = index - 1;
505 Res = section_iterator(SectionRef(DRI, this));
506 }
507
508 return object_error::success;
509 }
510
moveSectionNext(DataRefImpl & Sec) const511 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
512 Sec.d.a++;
513 }
514
getSectionName(DataRefImpl Sec,StringRef & Result) const515 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
516 StringRef &Result) const {
517 ArrayRef<char> Raw = getSectionRawName(Sec);
518 Result = parseSegmentOrSectionName(Raw.data());
519 return object_error::success;
520 }
521
getSectionAddress(DataRefImpl Sec) const522 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
523 if (is64Bit())
524 return getSection64(Sec).addr;
525 return getSection(Sec).addr;
526 }
527
getSectionSize(DataRefImpl Sec) const528 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
529 if (is64Bit())
530 return getSection64(Sec).size;
531 return getSection(Sec).size;
532 }
533
getSectionContents(DataRefImpl Sec,StringRef & Res) const534 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
535 StringRef &Res) const {
536 uint32_t Offset;
537 uint64_t Size;
538
539 if (is64Bit()) {
540 MachO::section_64 Sect = getSection64(Sec);
541 Offset = Sect.offset;
542 Size = Sect.size;
543 } else {
544 MachO::section Sect = getSection(Sec);
545 Offset = Sect.offset;
546 Size = Sect.size;
547 }
548
549 Res = this->getData().substr(Offset, Size);
550 return object_error::success;
551 }
552
getSectionAlignment(DataRefImpl Sec) const553 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
554 uint32_t Align;
555 if (is64Bit()) {
556 MachO::section_64 Sect = getSection64(Sec);
557 Align = Sect.align;
558 } else {
559 MachO::section Sect = getSection(Sec);
560 Align = Sect.align;
561 }
562
563 return uint64_t(1) << Align;
564 }
565
isSectionText(DataRefImpl Sec) const566 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
567 uint32_t Flags = getSectionFlags(this, Sec);
568 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
569 }
570
isSectionData(DataRefImpl Sec) const571 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
572 uint32_t Flags = getSectionFlags(this, Sec);
573 unsigned SectionType = Flags & MachO::SECTION_TYPE;
574 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
575 !(SectionType == MachO::S_ZEROFILL ||
576 SectionType == MachO::S_GB_ZEROFILL);
577 }
578
isSectionBSS(DataRefImpl Sec) const579 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
580 uint32_t Flags = getSectionFlags(this, Sec);
581 unsigned SectionType = Flags & MachO::SECTION_TYPE;
582 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
583 (SectionType == MachO::S_ZEROFILL ||
584 SectionType == MachO::S_GB_ZEROFILL);
585 }
586
isSectionVirtual(DataRefImpl Sec) const587 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
588 // FIXME: Unimplemented.
589 return false;
590 }
591
sectionContainsSymbol(DataRefImpl Sec,DataRefImpl Symb) const592 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
593 DataRefImpl Symb) const {
594 SymbolRef::Type ST;
595 this->getSymbolType(Symb, ST);
596 if (ST == SymbolRef::ST_Unknown)
597 return false;
598
599 uint64_t SectBegin = getSectionAddress(Sec);
600 uint64_t SectEnd = getSectionSize(Sec);
601 SectEnd += SectBegin;
602
603 uint64_t SymAddr;
604 getSymbolAddress(Symb, SymAddr);
605 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
606 }
607
section_rel_begin(DataRefImpl Sec) const608 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
609 DataRefImpl Ret;
610 Ret.d.a = Sec.d.a;
611 Ret.d.b = 0;
612 return relocation_iterator(RelocationRef(Ret, this));
613 }
614
615 relocation_iterator
section_rel_end(DataRefImpl Sec) const616 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
617 uint32_t Num;
618 if (is64Bit()) {
619 MachO::section_64 Sect = getSection64(Sec);
620 Num = Sect.nreloc;
621 } else {
622 MachO::section Sect = getSection(Sec);
623 Num = Sect.nreloc;
624 }
625
626 DataRefImpl Ret;
627 Ret.d.a = Sec.d.a;
628 Ret.d.b = Num;
629 return relocation_iterator(RelocationRef(Ret, this));
630 }
631
moveRelocationNext(DataRefImpl & Rel) const632 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
633 ++Rel.d.b;
634 }
635
getRelocationAddress(DataRefImpl Rel,uint64_t & Res) const636 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
637 uint64_t &Res) const {
638 uint64_t Offset;
639 getRelocationOffset(Rel, Offset);
640
641 DataRefImpl Sec;
642 Sec.d.a = Rel.d.a;
643 uint64_t SecAddress = getSectionAddress(Sec);
644 Res = SecAddress + Offset;
645 return object_error::success;
646 }
647
getRelocationOffset(DataRefImpl Rel,uint64_t & Res) const648 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
649 uint64_t &Res) const {
650 assert(getHeader().filetype == MachO::MH_OBJECT &&
651 "Only implemented for MH_OBJECT");
652 MachO::any_relocation_info RE = getRelocation(Rel);
653 Res = getAnyRelocationAddress(RE);
654 return object_error::success;
655 }
656
657 symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const658 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
659 MachO::any_relocation_info RE = getRelocation(Rel);
660 if (isRelocationScattered(RE))
661 return symbol_end();
662
663 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
664 bool isExtern = getPlainRelocationExternal(RE);
665 if (!isExtern)
666 return symbol_end();
667
668 MachO::symtab_command S = getSymtabLoadCommand();
669 unsigned SymbolTableEntrySize = is64Bit() ?
670 sizeof(MachO::nlist_64) :
671 sizeof(MachO::nlist);
672 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
673 DataRefImpl Sym;
674 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
675 return symbol_iterator(SymbolRef(Sym, this));
676 }
677
getRelocationType(DataRefImpl Rel,uint64_t & Res) const678 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
679 uint64_t &Res) const {
680 MachO::any_relocation_info RE = getRelocation(Rel);
681 Res = getAnyRelocationType(RE);
682 return object_error::success;
683 }
684
685 std::error_code
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const686 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
687 SmallVectorImpl<char> &Result) const {
688 StringRef res;
689 uint64_t RType;
690 getRelocationType(Rel, RType);
691
692 unsigned Arch = this->getArch();
693
694 switch (Arch) {
695 case Triple::x86: {
696 static const char *const Table[] = {
697 "GENERIC_RELOC_VANILLA",
698 "GENERIC_RELOC_PAIR",
699 "GENERIC_RELOC_SECTDIFF",
700 "GENERIC_RELOC_PB_LA_PTR",
701 "GENERIC_RELOC_LOCAL_SECTDIFF",
702 "GENERIC_RELOC_TLV" };
703
704 if (RType > 5)
705 res = "Unknown";
706 else
707 res = Table[RType];
708 break;
709 }
710 case Triple::x86_64: {
711 static const char *const Table[] = {
712 "X86_64_RELOC_UNSIGNED",
713 "X86_64_RELOC_SIGNED",
714 "X86_64_RELOC_BRANCH",
715 "X86_64_RELOC_GOT_LOAD",
716 "X86_64_RELOC_GOT",
717 "X86_64_RELOC_SUBTRACTOR",
718 "X86_64_RELOC_SIGNED_1",
719 "X86_64_RELOC_SIGNED_2",
720 "X86_64_RELOC_SIGNED_4",
721 "X86_64_RELOC_TLV" };
722
723 if (RType > 9)
724 res = "Unknown";
725 else
726 res = Table[RType];
727 break;
728 }
729 case Triple::arm: {
730 static const char *const Table[] = {
731 "ARM_RELOC_VANILLA",
732 "ARM_RELOC_PAIR",
733 "ARM_RELOC_SECTDIFF",
734 "ARM_RELOC_LOCAL_SECTDIFF",
735 "ARM_RELOC_PB_LA_PTR",
736 "ARM_RELOC_BR24",
737 "ARM_THUMB_RELOC_BR22",
738 "ARM_THUMB_32BIT_BRANCH",
739 "ARM_RELOC_HALF",
740 "ARM_RELOC_HALF_SECTDIFF" };
741
742 if (RType > 9)
743 res = "Unknown";
744 else
745 res = Table[RType];
746 break;
747 }
748 case Triple::aarch64: {
749 static const char *const Table[] = {
750 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
751 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
752 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
753 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
754 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
755 "ARM64_RELOC_ADDEND"
756 };
757
758 if (RType >= array_lengthof(Table))
759 res = "Unknown";
760 else
761 res = Table[RType];
762 break;
763 }
764 case Triple::ppc: {
765 static const char *const Table[] = {
766 "PPC_RELOC_VANILLA",
767 "PPC_RELOC_PAIR",
768 "PPC_RELOC_BR14",
769 "PPC_RELOC_BR24",
770 "PPC_RELOC_HI16",
771 "PPC_RELOC_LO16",
772 "PPC_RELOC_HA16",
773 "PPC_RELOC_LO14",
774 "PPC_RELOC_SECTDIFF",
775 "PPC_RELOC_PB_LA_PTR",
776 "PPC_RELOC_HI16_SECTDIFF",
777 "PPC_RELOC_LO16_SECTDIFF",
778 "PPC_RELOC_HA16_SECTDIFF",
779 "PPC_RELOC_JBSR",
780 "PPC_RELOC_LO14_SECTDIFF",
781 "PPC_RELOC_LOCAL_SECTDIFF" };
782
783 if (RType > 15)
784 res = "Unknown";
785 else
786 res = Table[RType];
787 break;
788 }
789 case Triple::UnknownArch:
790 res = "Unknown";
791 break;
792 }
793 Result.append(res.begin(), res.end());
794 return object_error::success;
795 }
796
797 std::error_code
getRelocationValueString(DataRefImpl Rel,SmallVectorImpl<char> & Result) const798 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
799 SmallVectorImpl<char> &Result) const {
800 MachO::any_relocation_info RE = getRelocation(Rel);
801
802 unsigned Arch = this->getArch();
803
804 std::string fmtbuf;
805 raw_string_ostream fmt(fmtbuf);
806 unsigned Type = this->getAnyRelocationType(RE);
807 bool IsPCRel = this->getAnyRelocationPCRel(RE);
808
809 // Determine any addends that should be displayed with the relocation.
810 // These require decoding the relocation type, which is triple-specific.
811
812 // X86_64 has entirely custom relocation types.
813 if (Arch == Triple::x86_64) {
814 bool isPCRel = getAnyRelocationPCRel(RE);
815
816 switch (Type) {
817 case MachO::X86_64_RELOC_GOT_LOAD:
818 case MachO::X86_64_RELOC_GOT: {
819 printRelocationTargetName(this, RE, fmt);
820 fmt << "@GOT";
821 if (isPCRel) fmt << "PCREL";
822 break;
823 }
824 case MachO::X86_64_RELOC_SUBTRACTOR: {
825 DataRefImpl RelNext = Rel;
826 moveRelocationNext(RelNext);
827 MachO::any_relocation_info RENext = getRelocation(RelNext);
828
829 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
830 // X86_64_RELOC_UNSIGNED.
831 // NOTE: Scattered relocations don't exist on x86_64.
832 unsigned RType = getAnyRelocationType(RENext);
833 if (RType != MachO::X86_64_RELOC_UNSIGNED)
834 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
835 "X86_64_RELOC_SUBTRACTOR.");
836
837 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
838 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
839 printRelocationTargetName(this, RENext, fmt);
840 fmt << "-";
841 printRelocationTargetName(this, RE, fmt);
842 break;
843 }
844 case MachO::X86_64_RELOC_TLV:
845 printRelocationTargetName(this, RE, fmt);
846 fmt << "@TLV";
847 if (isPCRel) fmt << "P";
848 break;
849 case MachO::X86_64_RELOC_SIGNED_1:
850 printRelocationTargetName(this, RE, fmt);
851 fmt << "-1";
852 break;
853 case MachO::X86_64_RELOC_SIGNED_2:
854 printRelocationTargetName(this, RE, fmt);
855 fmt << "-2";
856 break;
857 case MachO::X86_64_RELOC_SIGNED_4:
858 printRelocationTargetName(this, RE, fmt);
859 fmt << "-4";
860 break;
861 default:
862 printRelocationTargetName(this, RE, fmt);
863 break;
864 }
865 // X86 and ARM share some relocation types in common.
866 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
867 Arch == Triple::ppc) {
868 // Generic relocation types...
869 switch (Type) {
870 case MachO::GENERIC_RELOC_PAIR: // prints no info
871 return object_error::success;
872 case MachO::GENERIC_RELOC_SECTDIFF: {
873 DataRefImpl RelNext = Rel;
874 moveRelocationNext(RelNext);
875 MachO::any_relocation_info RENext = getRelocation(RelNext);
876
877 // X86 sect diff's must be followed by a relocation of type
878 // GENERIC_RELOC_PAIR.
879 unsigned RType = getAnyRelocationType(RENext);
880
881 if (RType != MachO::GENERIC_RELOC_PAIR)
882 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
883 "GENERIC_RELOC_SECTDIFF.");
884
885 printRelocationTargetName(this, RE, fmt);
886 fmt << "-";
887 printRelocationTargetName(this, RENext, fmt);
888 break;
889 }
890 }
891
892 if (Arch == Triple::x86 || Arch == Triple::ppc) {
893 switch (Type) {
894 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
895 DataRefImpl RelNext = Rel;
896 moveRelocationNext(RelNext);
897 MachO::any_relocation_info RENext = getRelocation(RelNext);
898
899 // X86 sect diff's must be followed by a relocation of type
900 // GENERIC_RELOC_PAIR.
901 unsigned RType = getAnyRelocationType(RENext);
902 if (RType != MachO::GENERIC_RELOC_PAIR)
903 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
904 "GENERIC_RELOC_LOCAL_SECTDIFF.");
905
906 printRelocationTargetName(this, RE, fmt);
907 fmt << "-";
908 printRelocationTargetName(this, RENext, fmt);
909 break;
910 }
911 case MachO::GENERIC_RELOC_TLV: {
912 printRelocationTargetName(this, RE, fmt);
913 fmt << "@TLV";
914 if (IsPCRel) fmt << "P";
915 break;
916 }
917 default:
918 printRelocationTargetName(this, RE, fmt);
919 }
920 } else { // ARM-specific relocations
921 switch (Type) {
922 case MachO::ARM_RELOC_HALF:
923 case MachO::ARM_RELOC_HALF_SECTDIFF: {
924 // Half relocations steal a bit from the length field to encode
925 // whether this is an upper16 or a lower16 relocation.
926 bool isUpper = getAnyRelocationLength(RE) >> 1;
927
928 if (isUpper)
929 fmt << ":upper16:(";
930 else
931 fmt << ":lower16:(";
932 printRelocationTargetName(this, RE, fmt);
933
934 DataRefImpl RelNext = Rel;
935 moveRelocationNext(RelNext);
936 MachO::any_relocation_info RENext = getRelocation(RelNext);
937
938 // ARM half relocs must be followed by a relocation of type
939 // ARM_RELOC_PAIR.
940 unsigned RType = getAnyRelocationType(RENext);
941 if (RType != MachO::ARM_RELOC_PAIR)
942 report_fatal_error("Expected ARM_RELOC_PAIR after "
943 "ARM_RELOC_HALF");
944
945 // NOTE: The half of the target virtual address is stashed in the
946 // address field of the secondary relocation, but we can't reverse
947 // engineer the constant offset from it without decoding the movw/movt
948 // instruction to find the other half in its immediate field.
949
950 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
951 // symbol/section pointer of the follow-on relocation.
952 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
953 fmt << "-";
954 printRelocationTargetName(this, RENext, fmt);
955 }
956
957 fmt << ")";
958 break;
959 }
960 default: {
961 printRelocationTargetName(this, RE, fmt);
962 }
963 }
964 }
965 } else
966 printRelocationTargetName(this, RE, fmt);
967
968 fmt.flush();
969 Result.append(fmtbuf.begin(), fmtbuf.end());
970 return object_error::success;
971 }
972
getRelocationHidden(DataRefImpl Rel,bool & Result) const973 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
974 bool &Result) const {
975 unsigned Arch = getArch();
976 uint64_t Type;
977 getRelocationType(Rel, Type);
978
979 Result = false;
980
981 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
982 // is always hidden.
983 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
984 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
985 } else if (Arch == Triple::x86_64) {
986 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
987 // an X86_64_RELOC_SUBTRACTOR.
988 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
989 DataRefImpl RelPrev = Rel;
990 RelPrev.d.a--;
991 uint64_t PrevType;
992 getRelocationType(RelPrev, PrevType);
993 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
994 Result = true;
995 }
996 }
997
998 return object_error::success;
999 }
1000
1001 //
1002 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1003 // guess on what the short name is. Then name is returned as a substring of the
1004 // StringRef Name passed in. The name of the dynamic library is recognized as
1005 // a framework if it has one of the two following forms:
1006 // Foo.framework/Versions/A/Foo
1007 // Foo.framework/Foo
1008 // Where A and Foo can be any string. And may contain a trailing suffix
1009 // starting with an underbar. If the Name is recognized as a framework then
1010 // isFramework is set to true else it is set to false. If the Name has a
1011 // suffix then Suffix is set to the substring in Name that contains the suffix
1012 // else it is set to a NULL StringRef.
1013 //
1014 // The Name of the dynamic library is recognized as a library name if it has
1015 // one of the two following forms:
1016 // libFoo.A.dylib
1017 // libFoo.dylib
1018 // The library may have a suffix trailing the name Foo of the form:
1019 // libFoo_profile.A.dylib
1020 // libFoo_profile.dylib
1021 //
1022 // The Name of the dynamic library is also recognized as a library name if it
1023 // has the following form:
1024 // Foo.qtx
1025 //
1026 // If the Name of the dynamic library is none of the forms above then a NULL
1027 // StringRef is returned.
1028 //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)1029 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1030 bool &isFramework,
1031 StringRef &Suffix) {
1032 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1033 size_t a, b, c, d, Idx;
1034
1035 isFramework = false;
1036 Suffix = StringRef();
1037
1038 // Pull off the last component and make Foo point to it
1039 a = Name.rfind('/');
1040 if (a == Name.npos || a == 0)
1041 goto guess_library;
1042 Foo = Name.slice(a+1, Name.npos);
1043
1044 // Look for a suffix starting with a '_'
1045 Idx = Foo.rfind('_');
1046 if (Idx != Foo.npos && Foo.size() >= 2) {
1047 Suffix = Foo.slice(Idx, Foo.npos);
1048 Foo = Foo.slice(0, Idx);
1049 }
1050
1051 // First look for the form Foo.framework/Foo
1052 b = Name.rfind('/', a);
1053 if (b == Name.npos)
1054 Idx = 0;
1055 else
1056 Idx = b+1;
1057 F = Name.slice(Idx, Idx + Foo.size());
1058 DotFramework = Name.slice(Idx + Foo.size(),
1059 Idx + Foo.size() + sizeof(".framework/")-1);
1060 if (F == Foo && DotFramework == ".framework/") {
1061 isFramework = true;
1062 return Foo;
1063 }
1064
1065 // Next look for the form Foo.framework/Versions/A/Foo
1066 if (b == Name.npos)
1067 goto guess_library;
1068 c = Name.rfind('/', b);
1069 if (c == Name.npos || c == 0)
1070 goto guess_library;
1071 V = Name.slice(c+1, Name.npos);
1072 if (!V.startswith("Versions/"))
1073 goto guess_library;
1074 d = Name.rfind('/', c);
1075 if (d == Name.npos)
1076 Idx = 0;
1077 else
1078 Idx = d+1;
1079 F = Name.slice(Idx, Idx + Foo.size());
1080 DotFramework = Name.slice(Idx + Foo.size(),
1081 Idx + Foo.size() + sizeof(".framework/")-1);
1082 if (F == Foo && DotFramework == ".framework/") {
1083 isFramework = true;
1084 return Foo;
1085 }
1086
1087 guess_library:
1088 // pull off the suffix after the "." and make a point to it
1089 a = Name.rfind('.');
1090 if (a == Name.npos || a == 0)
1091 return StringRef();
1092 Dylib = Name.slice(a, Name.npos);
1093 if (Dylib != ".dylib")
1094 goto guess_qtx;
1095
1096 // First pull off the version letter for the form Foo.A.dylib if any.
1097 if (a >= 3) {
1098 Dot = Name.slice(a-2, a-1);
1099 if (Dot == ".")
1100 a = a - 2;
1101 }
1102
1103 b = Name.rfind('/', a);
1104 if (b == Name.npos)
1105 b = 0;
1106 else
1107 b = b+1;
1108 // ignore any suffix after an underbar like Foo_profile.A.dylib
1109 Idx = Name.find('_', b);
1110 if (Idx != Name.npos && Idx != b) {
1111 Lib = Name.slice(b, Idx);
1112 Suffix = Name.slice(Idx, a);
1113 }
1114 else
1115 Lib = Name.slice(b, a);
1116 // There are incorrect library names of the form:
1117 // libATS.A_profile.dylib so check for these.
1118 if (Lib.size() >= 3) {
1119 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1120 if (Dot == ".")
1121 Lib = Lib.slice(0, Lib.size()-2);
1122 }
1123 return Lib;
1124
1125 guess_qtx:
1126 Qtx = Name.slice(a, Name.npos);
1127 if (Qtx != ".qtx")
1128 return StringRef();
1129 b = Name.rfind('/', a);
1130 if (b == Name.npos)
1131 Lib = Name.slice(0, a);
1132 else
1133 Lib = Name.slice(b+1, a);
1134 // There are library names of the form: QT.A.qtx so check for these.
1135 if (Lib.size() >= 3) {
1136 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1137 if (Dot == ".")
1138 Lib = Lib.slice(0, Lib.size()-2);
1139 }
1140 return Lib;
1141 }
1142
1143 // getLibraryShortNameByIndex() is used to get the short name of the library
1144 // for an undefined symbol in a linked Mach-O binary that was linked with the
1145 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1146 // It is passed the index (0 - based) of the library as translated from
1147 // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const1148 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1149 StringRef &Res) const {
1150 if (Index >= Libraries.size())
1151 return object_error::parse_failed;
1152
1153 // If the cache of LibrariesShortNames is not built up do that first for
1154 // all the Libraries.
1155 if (LibrariesShortNames.size() == 0) {
1156 for (unsigned i = 0; i < Libraries.size(); i++) {
1157 MachO::dylib_command D =
1158 getStruct<MachO::dylib_command>(this, Libraries[i]);
1159 if (D.dylib.name >= D.cmdsize)
1160 return object_error::parse_failed;
1161 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1162 StringRef Name = StringRef(P);
1163 if (D.dylib.name+Name.size() >= D.cmdsize)
1164 return object_error::parse_failed;
1165 StringRef Suffix;
1166 bool isFramework;
1167 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1168 if (shortName.empty())
1169 LibrariesShortNames.push_back(Name);
1170 else
1171 LibrariesShortNames.push_back(shortName);
1172 }
1173 }
1174
1175 Res = LibrariesShortNames[Index];
1176 return object_error::success;
1177 }
1178
symbol_begin_impl() const1179 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1180 return getSymbolByIndex(0);
1181 }
1182
symbol_end_impl() const1183 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1184 DataRefImpl DRI;
1185 if (!SymtabLoadCmd)
1186 return basic_symbol_iterator(SymbolRef(DRI, this));
1187
1188 MachO::symtab_command Symtab = getSymtabLoadCommand();
1189 unsigned SymbolTableEntrySize = is64Bit() ?
1190 sizeof(MachO::nlist_64) :
1191 sizeof(MachO::nlist);
1192 unsigned Offset = Symtab.symoff +
1193 Symtab.nsyms * SymbolTableEntrySize;
1194 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1195 return basic_symbol_iterator(SymbolRef(DRI, this));
1196 }
1197
getSymbolByIndex(unsigned Index) const1198 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1199 DataRefImpl DRI;
1200 if (!SymtabLoadCmd)
1201 return basic_symbol_iterator(SymbolRef(DRI, this));
1202
1203 MachO::symtab_command Symtab = getSymtabLoadCommand();
1204 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1205 unsigned SymbolTableEntrySize =
1206 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1207 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1208 DRI.p += Index * SymbolTableEntrySize;
1209 return basic_symbol_iterator(SymbolRef(DRI, this));
1210 }
1211
section_begin() const1212 section_iterator MachOObjectFile::section_begin() const {
1213 DataRefImpl DRI;
1214 return section_iterator(SectionRef(DRI, this));
1215 }
1216
section_end() const1217 section_iterator MachOObjectFile::section_end() const {
1218 DataRefImpl DRI;
1219 DRI.d.a = Sections.size();
1220 return section_iterator(SectionRef(DRI, this));
1221 }
1222
getBytesInAddress() const1223 uint8_t MachOObjectFile::getBytesInAddress() const {
1224 return is64Bit() ? 8 : 4;
1225 }
1226
getFileFormatName() const1227 StringRef MachOObjectFile::getFileFormatName() const {
1228 unsigned CPUType = getCPUType(this);
1229 if (!is64Bit()) {
1230 switch (CPUType) {
1231 case llvm::MachO::CPU_TYPE_I386:
1232 return "Mach-O 32-bit i386";
1233 case llvm::MachO::CPU_TYPE_ARM:
1234 return "Mach-O arm";
1235 case llvm::MachO::CPU_TYPE_POWERPC:
1236 return "Mach-O 32-bit ppc";
1237 default:
1238 return "Mach-O 32-bit unknown";
1239 }
1240 }
1241
1242 switch (CPUType) {
1243 case llvm::MachO::CPU_TYPE_X86_64:
1244 return "Mach-O 64-bit x86-64";
1245 case llvm::MachO::CPU_TYPE_ARM64:
1246 return "Mach-O arm64";
1247 case llvm::MachO::CPU_TYPE_POWERPC64:
1248 return "Mach-O 64-bit ppc64";
1249 default:
1250 return "Mach-O 64-bit unknown";
1251 }
1252 }
1253
getArch(uint32_t CPUType)1254 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1255 switch (CPUType) {
1256 case llvm::MachO::CPU_TYPE_I386:
1257 return Triple::x86;
1258 case llvm::MachO::CPU_TYPE_X86_64:
1259 return Triple::x86_64;
1260 case llvm::MachO::CPU_TYPE_ARM:
1261 return Triple::arm;
1262 case llvm::MachO::CPU_TYPE_ARM64:
1263 return Triple::aarch64;
1264 case llvm::MachO::CPU_TYPE_POWERPC:
1265 return Triple::ppc;
1266 case llvm::MachO::CPU_TYPE_POWERPC64:
1267 return Triple::ppc64;
1268 default:
1269 return Triple::UnknownArch;
1270 }
1271 }
1272
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1273 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1274 const char **McpuDefault) {
1275 if (McpuDefault)
1276 *McpuDefault = nullptr;
1277
1278 switch (CPUType) {
1279 case MachO::CPU_TYPE_I386:
1280 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1281 case MachO::CPU_SUBTYPE_I386_ALL:
1282 return Triple("i386-apple-darwin");
1283 default:
1284 return Triple();
1285 }
1286 case MachO::CPU_TYPE_X86_64:
1287 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1288 case MachO::CPU_SUBTYPE_X86_64_ALL:
1289 return Triple("x86_64-apple-darwin");
1290 case MachO::CPU_SUBTYPE_X86_64_H:
1291 return Triple("x86_64h-apple-darwin");
1292 default:
1293 return Triple();
1294 }
1295 case MachO::CPU_TYPE_ARM:
1296 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1297 case MachO::CPU_SUBTYPE_ARM_V4T:
1298 return Triple("armv4t-apple-darwin");
1299 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1300 return Triple("armv5e-apple-darwin");
1301 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1302 return Triple("xscale-apple-darwin");
1303 case MachO::CPU_SUBTYPE_ARM_V6:
1304 return Triple("armv6-apple-darwin");
1305 case MachO::CPU_SUBTYPE_ARM_V6M:
1306 if (McpuDefault)
1307 *McpuDefault = "cortex-m0";
1308 return Triple("armv6m-apple-darwin");
1309 case MachO::CPU_SUBTYPE_ARM_V7:
1310 return Triple("armv7-apple-darwin");
1311 case MachO::CPU_SUBTYPE_ARM_V7EM:
1312 if (McpuDefault)
1313 *McpuDefault = "cortex-m4";
1314 return Triple("armv7em-apple-darwin");
1315 case MachO::CPU_SUBTYPE_ARM_V7K:
1316 return Triple("armv7k-apple-darwin");
1317 case MachO::CPU_SUBTYPE_ARM_V7M:
1318 if (McpuDefault)
1319 *McpuDefault = "cortex-m3";
1320 return Triple("armv7m-apple-darwin");
1321 case MachO::CPU_SUBTYPE_ARM_V7S:
1322 return Triple("armv7s-apple-darwin");
1323 default:
1324 return Triple();
1325 }
1326 case MachO::CPU_TYPE_ARM64:
1327 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1328 case MachO::CPU_SUBTYPE_ARM64_ALL:
1329 return Triple("arm64-apple-darwin");
1330 default:
1331 return Triple();
1332 }
1333 case MachO::CPU_TYPE_POWERPC:
1334 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1335 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1336 return Triple("ppc-apple-darwin");
1337 default:
1338 return Triple();
1339 }
1340 case MachO::CPU_TYPE_POWERPC64:
1341 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1342 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1343 return Triple("ppc64-apple-darwin");
1344 default:
1345 return Triple();
1346 }
1347 default:
1348 return Triple();
1349 }
1350 }
1351
getThumbArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1352 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1353 const char **McpuDefault) {
1354 if (McpuDefault)
1355 *McpuDefault = nullptr;
1356
1357 switch (CPUType) {
1358 case MachO::CPU_TYPE_ARM:
1359 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1360 case MachO::CPU_SUBTYPE_ARM_V4T:
1361 return Triple("thumbv4t-apple-darwin");
1362 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1363 return Triple("thumbv5e-apple-darwin");
1364 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1365 return Triple("xscale-apple-darwin");
1366 case MachO::CPU_SUBTYPE_ARM_V6:
1367 return Triple("thumbv6-apple-darwin");
1368 case MachO::CPU_SUBTYPE_ARM_V6M:
1369 if (McpuDefault)
1370 *McpuDefault = "cortex-m0";
1371 return Triple("thumbv6m-apple-darwin");
1372 case MachO::CPU_SUBTYPE_ARM_V7:
1373 return Triple("thumbv7-apple-darwin");
1374 case MachO::CPU_SUBTYPE_ARM_V7EM:
1375 if (McpuDefault)
1376 *McpuDefault = "cortex-m4";
1377 return Triple("thumbv7em-apple-darwin");
1378 case MachO::CPU_SUBTYPE_ARM_V7K:
1379 return Triple("thumbv7k-apple-darwin");
1380 case MachO::CPU_SUBTYPE_ARM_V7M:
1381 if (McpuDefault)
1382 *McpuDefault = "cortex-m3";
1383 return Triple("thumbv7m-apple-darwin");
1384 case MachO::CPU_SUBTYPE_ARM_V7S:
1385 return Triple("thumbv7s-apple-darwin");
1386 default:
1387 return Triple();
1388 }
1389 default:
1390 return Triple();
1391 }
1392 }
1393
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,Triple * ThumbTriple)1394 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1395 const char **McpuDefault,
1396 Triple *ThumbTriple) {
1397 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1398 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1399 McpuDefault);
1400 return T;
1401 }
1402
getHostArch()1403 Triple MachOObjectFile::getHostArch() {
1404 return Triple(sys::getDefaultTargetTriple());
1405 }
1406
isValidArch(StringRef ArchFlag)1407 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1408 return StringSwitch<bool>(ArchFlag)
1409 .Case("i386", true)
1410 .Case("x86_64", true)
1411 .Case("x86_64h", true)
1412 .Case("armv4t", true)
1413 .Case("arm", true)
1414 .Case("armv5e", true)
1415 .Case("armv6", true)
1416 .Case("armv6m", true)
1417 .Case("armv7em", true)
1418 .Case("armv7k", true)
1419 .Case("armv7m", true)
1420 .Case("armv7s", true)
1421 .Case("arm64", true)
1422 .Case("ppc", true)
1423 .Case("ppc64", true)
1424 .Default(false);
1425 }
1426
getArch() const1427 unsigned MachOObjectFile::getArch() const {
1428 return getArch(getCPUType(this));
1429 }
1430
getArch(const char ** McpuDefault,Triple * ThumbTriple) const1431 Triple MachOObjectFile::getArch(const char **McpuDefault,
1432 Triple *ThumbTriple) const {
1433 Triple T;
1434 if (is64Bit()) {
1435 MachO::mach_header_64 H_64;
1436 H_64 = getHeader64();
1437 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1438 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1439 McpuDefault);
1440 } else {
1441 MachO::mach_header H;
1442 H = getHeader();
1443 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1444 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1445 McpuDefault);
1446 }
1447 return T;
1448 }
1449
section_rel_begin(unsigned Index) const1450 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1451 DataRefImpl DRI;
1452 DRI.d.a = Index;
1453 return section_rel_begin(DRI);
1454 }
1455
section_rel_end(unsigned Index) const1456 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1457 DataRefImpl DRI;
1458 DRI.d.a = Index;
1459 return section_rel_end(DRI);
1460 }
1461
begin_dices() const1462 dice_iterator MachOObjectFile::begin_dices() const {
1463 DataRefImpl DRI;
1464 if (!DataInCodeLoadCmd)
1465 return dice_iterator(DiceRef(DRI, this));
1466
1467 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1468 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1469 return dice_iterator(DiceRef(DRI, this));
1470 }
1471
end_dices() const1472 dice_iterator MachOObjectFile::end_dices() const {
1473 DataRefImpl DRI;
1474 if (!DataInCodeLoadCmd)
1475 return dice_iterator(DiceRef(DRI, this));
1476
1477 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1478 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1479 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1480 return dice_iterator(DiceRef(DRI, this));
1481 }
1482
ExportEntry(ArrayRef<uint8_t> T)1483 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1484 : Trie(T), Malformed(false), Done(false) { }
1485
moveToFirst()1486 void ExportEntry::moveToFirst() {
1487 pushNode(0);
1488 pushDownUntilBottom();
1489 }
1490
moveToEnd()1491 void ExportEntry::moveToEnd() {
1492 Stack.clear();
1493 Done = true;
1494 }
1495
operator ==(const ExportEntry & Other) const1496 bool ExportEntry::operator==(const ExportEntry &Other) const {
1497 // Common case, one at end, other iterating from begin.
1498 if (Done || Other.Done)
1499 return (Done == Other.Done);
1500 // Not equal if different stack sizes.
1501 if (Stack.size() != Other.Stack.size())
1502 return false;
1503 // Not equal if different cumulative strings.
1504 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1505 return false;
1506 // Equal if all nodes in both stacks match.
1507 for (unsigned i=0; i < Stack.size(); ++i) {
1508 if (Stack[i].Start != Other.Stack[i].Start)
1509 return false;
1510 }
1511 return true;
1512 }
1513
readULEB128(const uint8_t * & Ptr)1514 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1515 unsigned Count;
1516 uint64_t Result = decodeULEB128(Ptr, &Count);
1517 Ptr += Count;
1518 if (Ptr > Trie.end()) {
1519 Ptr = Trie.end();
1520 Malformed = true;
1521 }
1522 return Result;
1523 }
1524
name() const1525 StringRef ExportEntry::name() const {
1526 return CumulativeString.str();
1527 }
1528
flags() const1529 uint64_t ExportEntry::flags() const {
1530 return Stack.back().Flags;
1531 }
1532
address() const1533 uint64_t ExportEntry::address() const {
1534 return Stack.back().Address;
1535 }
1536
other() const1537 uint64_t ExportEntry::other() const {
1538 return Stack.back().Other;
1539 }
1540
otherName() const1541 StringRef ExportEntry::otherName() const {
1542 const char* ImportName = Stack.back().ImportName;
1543 if (ImportName)
1544 return StringRef(ImportName);
1545 return StringRef();
1546 }
1547
nodeOffset() const1548 uint32_t ExportEntry::nodeOffset() const {
1549 return Stack.back().Start - Trie.begin();
1550 }
1551
NodeState(const uint8_t * Ptr)1552 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1553 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1554 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1555 ParentStringLength(0), IsExportNode(false) {
1556 }
1557
pushNode(uint64_t offset)1558 void ExportEntry::pushNode(uint64_t offset) {
1559 const uint8_t *Ptr = Trie.begin() + offset;
1560 NodeState State(Ptr);
1561 uint64_t ExportInfoSize = readULEB128(State.Current);
1562 State.IsExportNode = (ExportInfoSize != 0);
1563 const uint8_t* Children = State.Current + ExportInfoSize;
1564 if (State.IsExportNode) {
1565 State.Flags = readULEB128(State.Current);
1566 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1567 State.Address = 0;
1568 State.Other = readULEB128(State.Current); // dylib ordinal
1569 State.ImportName = reinterpret_cast<const char*>(State.Current);
1570 } else {
1571 State.Address = readULEB128(State.Current);
1572 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1573 State.Other = readULEB128(State.Current);
1574 }
1575 }
1576 State.ChildCount = *Children;
1577 State.Current = Children + 1;
1578 State.NextChildIndex = 0;
1579 State.ParentStringLength = CumulativeString.size();
1580 Stack.push_back(State);
1581 }
1582
pushDownUntilBottom()1583 void ExportEntry::pushDownUntilBottom() {
1584 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1585 NodeState &Top = Stack.back();
1586 CumulativeString.resize(Top.ParentStringLength);
1587 for (;*Top.Current != 0; Top.Current++) {
1588 char C = *Top.Current;
1589 CumulativeString.push_back(C);
1590 }
1591 Top.Current += 1;
1592 uint64_t childNodeIndex = readULEB128(Top.Current);
1593 Top.NextChildIndex += 1;
1594 pushNode(childNodeIndex);
1595 }
1596 if (!Stack.back().IsExportNode) {
1597 Malformed = true;
1598 moveToEnd();
1599 }
1600 }
1601
1602 // We have a trie data structure and need a way to walk it that is compatible
1603 // with the C++ iterator model. The solution is a non-recursive depth first
1604 // traversal where the iterator contains a stack of parent nodes along with a
1605 // string that is the accumulation of all edge strings along the parent chain
1606 // to this point.
1607 //
1608 // There is one "export" node for each exported symbol. But because some
1609 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1610 // node may have child nodes too.
1611 //
1612 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1613 // child until hitting a node with no children (which is an export node or
1614 // else the trie is malformed). On the way down, each node is pushed on the
1615 // stack ivar. If there is no more ways down, it pops up one and tries to go
1616 // down a sibling path until a childless node is reached.
moveNext()1617 void ExportEntry::moveNext() {
1618 if (Stack.empty() || !Stack.back().IsExportNode) {
1619 Malformed = true;
1620 moveToEnd();
1621 return;
1622 }
1623
1624 Stack.pop_back();
1625 while (!Stack.empty()) {
1626 NodeState &Top = Stack.back();
1627 if (Top.NextChildIndex < Top.ChildCount) {
1628 pushDownUntilBottom();
1629 // Now at the next export node.
1630 return;
1631 } else {
1632 if (Top.IsExportNode) {
1633 // This node has no children but is itself an export node.
1634 CumulativeString.resize(Top.ParentStringLength);
1635 return;
1636 }
1637 Stack.pop_back();
1638 }
1639 }
1640 Done = true;
1641 }
1642
1643 iterator_range<export_iterator>
exports(ArrayRef<uint8_t> Trie)1644 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1645 ExportEntry Start(Trie);
1646 if (Trie.size() == 0)
1647 Start.moveToEnd();
1648 else
1649 Start.moveToFirst();
1650
1651 ExportEntry Finish(Trie);
1652 Finish.moveToEnd();
1653
1654 return iterator_range<export_iterator>(export_iterator(Start),
1655 export_iterator(Finish));
1656 }
1657
exports() const1658 iterator_range<export_iterator> MachOObjectFile::exports() const {
1659 return exports(getDyldInfoExportsTrie());
1660 }
1661
1662
MachORebaseEntry(ArrayRef<uint8_t> Bytes,bool is64Bit)1663 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1664 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1665 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1666 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1667
moveToFirst()1668 void MachORebaseEntry::moveToFirst() {
1669 Ptr = Opcodes.begin();
1670 moveNext();
1671 }
1672
moveToEnd()1673 void MachORebaseEntry::moveToEnd() {
1674 Ptr = Opcodes.end();
1675 RemainingLoopCount = 0;
1676 Done = true;
1677 }
1678
moveNext()1679 void MachORebaseEntry::moveNext() {
1680 // If in the middle of some loop, move to next rebasing in loop.
1681 SegmentOffset += AdvanceAmount;
1682 if (RemainingLoopCount) {
1683 --RemainingLoopCount;
1684 return;
1685 }
1686 if (Ptr == Opcodes.end()) {
1687 Done = true;
1688 return;
1689 }
1690 bool More = true;
1691 while (More && !Malformed) {
1692 // Parse next opcode and set up next loop.
1693 uint8_t Byte = *Ptr++;
1694 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1695 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1696 switch (Opcode) {
1697 case MachO::REBASE_OPCODE_DONE:
1698 More = false;
1699 Done = true;
1700 moveToEnd();
1701 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1702 break;
1703 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1704 RebaseType = ImmValue;
1705 DEBUG_WITH_TYPE(
1706 "mach-o-rebase",
1707 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1708 << "RebaseType=" << (int) RebaseType << "\n");
1709 break;
1710 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1711 SegmentIndex = ImmValue;
1712 SegmentOffset = readULEB128();
1713 DEBUG_WITH_TYPE(
1714 "mach-o-rebase",
1715 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1716 << "SegmentIndex=" << SegmentIndex << ", "
1717 << format("SegmentOffset=0x%06X", SegmentOffset)
1718 << "\n");
1719 break;
1720 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1721 SegmentOffset += readULEB128();
1722 DEBUG_WITH_TYPE("mach-o-rebase",
1723 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1724 << format("SegmentOffset=0x%06X",
1725 SegmentOffset) << "\n");
1726 break;
1727 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1728 SegmentOffset += ImmValue * PointerSize;
1729 DEBUG_WITH_TYPE("mach-o-rebase",
1730 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1731 << format("SegmentOffset=0x%06X",
1732 SegmentOffset) << "\n");
1733 break;
1734 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1735 AdvanceAmount = PointerSize;
1736 RemainingLoopCount = ImmValue - 1;
1737 DEBUG_WITH_TYPE(
1738 "mach-o-rebase",
1739 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1740 << format("SegmentOffset=0x%06X", SegmentOffset)
1741 << ", AdvanceAmount=" << AdvanceAmount
1742 << ", RemainingLoopCount=" << RemainingLoopCount
1743 << "\n");
1744 return;
1745 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1746 AdvanceAmount = PointerSize;
1747 RemainingLoopCount = readULEB128() - 1;
1748 DEBUG_WITH_TYPE(
1749 "mach-o-rebase",
1750 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1751 << format("SegmentOffset=0x%06X", SegmentOffset)
1752 << ", AdvanceAmount=" << AdvanceAmount
1753 << ", RemainingLoopCount=" << RemainingLoopCount
1754 << "\n");
1755 return;
1756 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1757 AdvanceAmount = readULEB128() + PointerSize;
1758 RemainingLoopCount = 0;
1759 DEBUG_WITH_TYPE(
1760 "mach-o-rebase",
1761 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1762 << format("SegmentOffset=0x%06X", SegmentOffset)
1763 << ", AdvanceAmount=" << AdvanceAmount
1764 << ", RemainingLoopCount=" << RemainingLoopCount
1765 << "\n");
1766 return;
1767 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1768 RemainingLoopCount = readULEB128() - 1;
1769 AdvanceAmount = readULEB128() + PointerSize;
1770 DEBUG_WITH_TYPE(
1771 "mach-o-rebase",
1772 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1773 << format("SegmentOffset=0x%06X", SegmentOffset)
1774 << ", AdvanceAmount=" << AdvanceAmount
1775 << ", RemainingLoopCount=" << RemainingLoopCount
1776 << "\n");
1777 return;
1778 default:
1779 Malformed = true;
1780 }
1781 }
1782 }
1783
readULEB128()1784 uint64_t MachORebaseEntry::readULEB128() {
1785 unsigned Count;
1786 uint64_t Result = decodeULEB128(Ptr, &Count);
1787 Ptr += Count;
1788 if (Ptr > Opcodes.end()) {
1789 Ptr = Opcodes.end();
1790 Malformed = true;
1791 }
1792 return Result;
1793 }
1794
segmentIndex() const1795 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1796
segmentOffset() const1797 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1798
typeName() const1799 StringRef MachORebaseEntry::typeName() const {
1800 switch (RebaseType) {
1801 case MachO::REBASE_TYPE_POINTER:
1802 return "pointer";
1803 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1804 return "text abs32";
1805 case MachO::REBASE_TYPE_TEXT_PCREL32:
1806 return "text rel32";
1807 }
1808 return "unknown";
1809 }
1810
operator ==(const MachORebaseEntry & Other) const1811 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1812 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1813 return (Ptr == Other.Ptr) &&
1814 (RemainingLoopCount == Other.RemainingLoopCount) &&
1815 (Done == Other.Done);
1816 }
1817
1818 iterator_range<rebase_iterator>
rebaseTable(ArrayRef<uint8_t> Opcodes,bool is64)1819 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1820 MachORebaseEntry Start(Opcodes, is64);
1821 Start.moveToFirst();
1822
1823 MachORebaseEntry Finish(Opcodes, is64);
1824 Finish.moveToEnd();
1825
1826 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1827 rebase_iterator(Finish));
1828 }
1829
rebaseTable() const1830 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1831 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1832 }
1833
1834
MachOBindEntry(ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)1835 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1836 Kind BK)
1837 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1838 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1839 BindType(0), PointerSize(is64Bit ? 8 : 4),
1840 TableKind(BK), Malformed(false), Done(false) {}
1841
moveToFirst()1842 void MachOBindEntry::moveToFirst() {
1843 Ptr = Opcodes.begin();
1844 moveNext();
1845 }
1846
moveToEnd()1847 void MachOBindEntry::moveToEnd() {
1848 Ptr = Opcodes.end();
1849 RemainingLoopCount = 0;
1850 Done = true;
1851 }
1852
moveNext()1853 void MachOBindEntry::moveNext() {
1854 // If in the middle of some loop, move to next binding in loop.
1855 SegmentOffset += AdvanceAmount;
1856 if (RemainingLoopCount) {
1857 --RemainingLoopCount;
1858 return;
1859 }
1860 if (Ptr == Opcodes.end()) {
1861 Done = true;
1862 return;
1863 }
1864 bool More = true;
1865 while (More && !Malformed) {
1866 // Parse next opcode and set up next loop.
1867 uint8_t Byte = *Ptr++;
1868 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1869 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1870 int8_t SignExtended;
1871 const uint8_t *SymStart;
1872 switch (Opcode) {
1873 case MachO::BIND_OPCODE_DONE:
1874 if (TableKind == Kind::Lazy) {
1875 // Lazying bindings have a DONE opcode between entries. Need to ignore
1876 // it to advance to next entry. But need not if this is last entry.
1877 bool NotLastEntry = false;
1878 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1879 if (*P) {
1880 NotLastEntry = true;
1881 }
1882 }
1883 if (NotLastEntry)
1884 break;
1885 }
1886 More = false;
1887 Done = true;
1888 moveToEnd();
1889 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1890 break;
1891 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1892 Ordinal = ImmValue;
1893 DEBUG_WITH_TYPE(
1894 "mach-o-bind",
1895 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1896 << "Ordinal=" << Ordinal << "\n");
1897 break;
1898 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1899 Ordinal = readULEB128();
1900 DEBUG_WITH_TYPE(
1901 "mach-o-bind",
1902 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1903 << "Ordinal=" << Ordinal << "\n");
1904 break;
1905 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1906 if (ImmValue) {
1907 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1908 Ordinal = SignExtended;
1909 } else
1910 Ordinal = 0;
1911 DEBUG_WITH_TYPE(
1912 "mach-o-bind",
1913 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1914 << "Ordinal=" << Ordinal << "\n");
1915 break;
1916 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1917 Flags = ImmValue;
1918 SymStart = Ptr;
1919 while (*Ptr) {
1920 ++Ptr;
1921 }
1922 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1923 Ptr-SymStart);
1924 ++Ptr;
1925 DEBUG_WITH_TYPE(
1926 "mach-o-bind",
1927 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1928 << "SymbolName=" << SymbolName << "\n");
1929 if (TableKind == Kind::Weak) {
1930 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1931 return;
1932 }
1933 break;
1934 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1935 BindType = ImmValue;
1936 DEBUG_WITH_TYPE(
1937 "mach-o-bind",
1938 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1939 << "BindType=" << (int)BindType << "\n");
1940 break;
1941 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1942 Addend = readSLEB128();
1943 if (TableKind == Kind::Lazy)
1944 Malformed = true;
1945 DEBUG_WITH_TYPE(
1946 "mach-o-bind",
1947 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1948 << "Addend=" << Addend << "\n");
1949 break;
1950 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1951 SegmentIndex = ImmValue;
1952 SegmentOffset = readULEB128();
1953 DEBUG_WITH_TYPE(
1954 "mach-o-bind",
1955 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1956 << "SegmentIndex=" << SegmentIndex << ", "
1957 << format("SegmentOffset=0x%06X", SegmentOffset)
1958 << "\n");
1959 break;
1960 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1961 SegmentOffset += readULEB128();
1962 DEBUG_WITH_TYPE("mach-o-bind",
1963 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1964 << format("SegmentOffset=0x%06X",
1965 SegmentOffset) << "\n");
1966 break;
1967 case MachO::BIND_OPCODE_DO_BIND:
1968 AdvanceAmount = PointerSize;
1969 RemainingLoopCount = 0;
1970 DEBUG_WITH_TYPE("mach-o-bind",
1971 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1972 << format("SegmentOffset=0x%06X",
1973 SegmentOffset) << "\n");
1974 return;
1975 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1976 AdvanceAmount = readULEB128() + PointerSize;
1977 RemainingLoopCount = 0;
1978 if (TableKind == Kind::Lazy)
1979 Malformed = true;
1980 DEBUG_WITH_TYPE(
1981 "mach-o-bind",
1982 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1983 << format("SegmentOffset=0x%06X", SegmentOffset)
1984 << ", AdvanceAmount=" << AdvanceAmount
1985 << ", RemainingLoopCount=" << RemainingLoopCount
1986 << "\n");
1987 return;
1988 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1989 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1990 RemainingLoopCount = 0;
1991 if (TableKind == Kind::Lazy)
1992 Malformed = true;
1993 DEBUG_WITH_TYPE("mach-o-bind",
1994 llvm::dbgs()
1995 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1996 << format("SegmentOffset=0x%06X",
1997 SegmentOffset) << "\n");
1998 return;
1999 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2000 RemainingLoopCount = readULEB128() - 1;
2001 AdvanceAmount = readULEB128() + PointerSize;
2002 if (TableKind == Kind::Lazy)
2003 Malformed = true;
2004 DEBUG_WITH_TYPE(
2005 "mach-o-bind",
2006 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2007 << format("SegmentOffset=0x%06X", SegmentOffset)
2008 << ", AdvanceAmount=" << AdvanceAmount
2009 << ", RemainingLoopCount=" << RemainingLoopCount
2010 << "\n");
2011 return;
2012 default:
2013 Malformed = true;
2014 }
2015 }
2016 }
2017
readULEB128()2018 uint64_t MachOBindEntry::readULEB128() {
2019 unsigned Count;
2020 uint64_t Result = decodeULEB128(Ptr, &Count);
2021 Ptr += Count;
2022 if (Ptr > Opcodes.end()) {
2023 Ptr = Opcodes.end();
2024 Malformed = true;
2025 }
2026 return Result;
2027 }
2028
readSLEB128()2029 int64_t MachOBindEntry::readSLEB128() {
2030 unsigned Count;
2031 int64_t Result = decodeSLEB128(Ptr, &Count);
2032 Ptr += Count;
2033 if (Ptr > Opcodes.end()) {
2034 Ptr = Opcodes.end();
2035 Malformed = true;
2036 }
2037 return Result;
2038 }
2039
2040
segmentIndex() const2041 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2042
segmentOffset() const2043 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2044
typeName() const2045 StringRef MachOBindEntry::typeName() const {
2046 switch (BindType) {
2047 case MachO::BIND_TYPE_POINTER:
2048 return "pointer";
2049 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2050 return "text abs32";
2051 case MachO::BIND_TYPE_TEXT_PCREL32:
2052 return "text rel32";
2053 }
2054 return "unknown";
2055 }
2056
symbolName() const2057 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2058
addend() const2059 int64_t MachOBindEntry::addend() const { return Addend; }
2060
flags() const2061 uint32_t MachOBindEntry::flags() const { return Flags; }
2062
ordinal() const2063 int MachOBindEntry::ordinal() const { return Ordinal; }
2064
operator ==(const MachOBindEntry & Other) const2065 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2066 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2067 return (Ptr == Other.Ptr) &&
2068 (RemainingLoopCount == Other.RemainingLoopCount) &&
2069 (Done == Other.Done);
2070 }
2071
2072 iterator_range<bind_iterator>
bindTable(ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)2073 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2074 MachOBindEntry::Kind BKind) {
2075 MachOBindEntry Start(Opcodes, is64, BKind);
2076 Start.moveToFirst();
2077
2078 MachOBindEntry Finish(Opcodes, is64, BKind);
2079 Finish.moveToEnd();
2080
2081 return iterator_range<bind_iterator>(bind_iterator(Start),
2082 bind_iterator(Finish));
2083 }
2084
bindTable() const2085 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2086 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2087 MachOBindEntry::Kind::Regular);
2088 }
2089
lazyBindTable() const2090 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2091 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2092 MachOBindEntry::Kind::Lazy);
2093 }
2094
weakBindTable() const2095 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2096 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2097 MachOBindEntry::Kind::Weak);
2098 }
2099
2100 StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const2101 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2102 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2103 return parseSegmentOrSectionName(Raw.data());
2104 }
2105
2106 ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const2107 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2108 const section_base *Base =
2109 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2110 return makeArrayRef(Base->sectname);
2111 }
2112
2113 ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const2114 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2115 const section_base *Base =
2116 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2117 return makeArrayRef(Base->segname);
2118 }
2119
2120 bool
isRelocationScattered(const MachO::any_relocation_info & RE) const2121 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2122 const {
2123 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2124 return false;
2125 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2126 }
2127
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const2128 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2129 const MachO::any_relocation_info &RE) const {
2130 if (isLittleEndian())
2131 return RE.r_word1 & 0xffffff;
2132 return RE.r_word1 >> 8;
2133 }
2134
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const2135 bool MachOObjectFile::getPlainRelocationExternal(
2136 const MachO::any_relocation_info &RE) const {
2137 if (isLittleEndian())
2138 return (RE.r_word1 >> 27) & 1;
2139 return (RE.r_word1 >> 4) & 1;
2140 }
2141
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const2142 bool MachOObjectFile::getScatteredRelocationScattered(
2143 const MachO::any_relocation_info &RE) const {
2144 return RE.r_word0 >> 31;
2145 }
2146
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const2147 uint32_t MachOObjectFile::getScatteredRelocationValue(
2148 const MachO::any_relocation_info &RE) const {
2149 return RE.r_word1;
2150 }
2151
getScatteredRelocationType(const MachO::any_relocation_info & RE) const2152 uint32_t MachOObjectFile::getScatteredRelocationType(
2153 const MachO::any_relocation_info &RE) const {
2154 return (RE.r_word0 >> 24) & 0xf;
2155 }
2156
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const2157 unsigned MachOObjectFile::getAnyRelocationAddress(
2158 const MachO::any_relocation_info &RE) const {
2159 if (isRelocationScattered(RE))
2160 return getScatteredRelocationAddress(RE);
2161 return getPlainRelocationAddress(RE);
2162 }
2163
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const2164 unsigned MachOObjectFile::getAnyRelocationPCRel(
2165 const MachO::any_relocation_info &RE) const {
2166 if (isRelocationScattered(RE))
2167 return getScatteredRelocationPCRel(this, RE);
2168 return getPlainRelocationPCRel(this, RE);
2169 }
2170
getAnyRelocationLength(const MachO::any_relocation_info & RE) const2171 unsigned MachOObjectFile::getAnyRelocationLength(
2172 const MachO::any_relocation_info &RE) const {
2173 if (isRelocationScattered(RE))
2174 return getScatteredRelocationLength(RE);
2175 return getPlainRelocationLength(this, RE);
2176 }
2177
2178 unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const2179 MachOObjectFile::getAnyRelocationType(
2180 const MachO::any_relocation_info &RE) const {
2181 if (isRelocationScattered(RE))
2182 return getScatteredRelocationType(RE);
2183 return getPlainRelocationType(this, RE);
2184 }
2185
2186 SectionRef
getRelocationSection(const MachO::any_relocation_info & RE) const2187 MachOObjectFile::getRelocationSection(
2188 const MachO::any_relocation_info &RE) const {
2189 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2190 return *section_end();
2191 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2192 DataRefImpl DRI;
2193 DRI.d.a = SecNum;
2194 return SectionRef(DRI, this);
2195 }
2196
2197 MachOObjectFile::LoadCommandInfo
getFirstLoadCommandInfo() const2198 MachOObjectFile::getFirstLoadCommandInfo() const {
2199 MachOObjectFile::LoadCommandInfo Load;
2200
2201 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2202 sizeof(MachO::mach_header);
2203 Load.Ptr = getPtr(this, HeaderSize);
2204 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2205 return Load;
2206 }
2207
2208 MachOObjectFile::LoadCommandInfo
getNextLoadCommandInfo(const LoadCommandInfo & L) const2209 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2210 MachOObjectFile::LoadCommandInfo Next;
2211 Next.Ptr = L.Ptr + L.C.cmdsize;
2212 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2213 return Next;
2214 }
2215
getSection(DataRefImpl DRI) const2216 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2217 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2218 }
2219
getSection64(DataRefImpl DRI) const2220 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2221 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2222 }
2223
getSection(const LoadCommandInfo & L,unsigned Index) const2224 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2225 unsigned Index) const {
2226 const char *Sec = getSectionPtr(this, L, Index);
2227 return getStruct<MachO::section>(this, Sec);
2228 }
2229
getSection64(const LoadCommandInfo & L,unsigned Index) const2230 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2231 unsigned Index) const {
2232 const char *Sec = getSectionPtr(this, L, Index);
2233 return getStruct<MachO::section_64>(this, Sec);
2234 }
2235
2236 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const2237 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2238 const char *P = reinterpret_cast<const char *>(DRI.p);
2239 return getStruct<MachO::nlist>(this, P);
2240 }
2241
2242 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const2243 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2244 const char *P = reinterpret_cast<const char *>(DRI.p);
2245 return getStruct<MachO::nlist_64>(this, P);
2246 }
2247
2248 MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const2249 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2250 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2251 }
2252
2253 MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const2254 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2255 return getStruct<MachO::segment_command>(this, L.Ptr);
2256 }
2257
2258 MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const2259 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2260 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2261 }
2262
2263 MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const2264 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2265 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2266 }
2267
2268 MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const2269 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2270 return getStruct<MachO::version_min_command>(this, L.Ptr);
2271 }
2272
2273 MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const2274 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2275 return getStruct<MachO::dylib_command>(this, L.Ptr);
2276 }
2277
2278 MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const2279 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2280 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2281 }
2282
2283 MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const2284 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2285 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2286 }
2287
2288 MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const2289 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2290 return getStruct<MachO::uuid_command>(this, L.Ptr);
2291 }
2292
2293 MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const2294 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2295 return getStruct<MachO::rpath_command>(this, L.Ptr);
2296 }
2297
2298 MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const2299 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2300 return getStruct<MachO::source_version_command>(this, L.Ptr);
2301 }
2302
2303 MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const2304 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2305 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2306 }
2307
2308 MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const2309 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2310 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2311 }
2312
2313 MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const2314 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2315 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2316 }
2317
2318 MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const2319 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2320 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2321 }
2322
2323 MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const2324 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2325 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2326 }
2327
2328 MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const2329 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2330 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2331 }
2332
2333 MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const2334 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2335 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2336 }
2337
2338 MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const2339 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2340 return getStruct<MachO::routines_command>(this, L.Ptr);
2341 }
2342
2343 MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const2344 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2345 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2346 }
2347
2348 MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const2349 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2350 return getStruct<MachO::thread_command>(this, L.Ptr);
2351 }
2352
2353 MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const2354 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2355 DataRefImpl Sec;
2356 Sec.d.a = Rel.d.a;
2357 uint32_t Offset;
2358 if (is64Bit()) {
2359 MachO::section_64 Sect = getSection64(Sec);
2360 Offset = Sect.reloff;
2361 } else {
2362 MachO::section Sect = getSection(Sec);
2363 Offset = Sect.reloff;
2364 }
2365
2366 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2367 getPtr(this, Offset)) + Rel.d.b;
2368 return getStruct<MachO::any_relocation_info>(
2369 this, reinterpret_cast<const char *>(P));
2370 }
2371
2372 MachO::data_in_code_entry
getDice(DataRefImpl Rel) const2373 MachOObjectFile::getDice(DataRefImpl Rel) const {
2374 const char *P = reinterpret_cast<const char *>(Rel.p);
2375 return getStruct<MachO::data_in_code_entry>(this, P);
2376 }
2377
getHeader() const2378 MachO::mach_header MachOObjectFile::getHeader() const {
2379 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2380 }
2381
getHeader64() const2382 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2383 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2384 }
2385
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const2386 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2387 const MachO::dysymtab_command &DLC,
2388 unsigned Index) const {
2389 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2390 return getStruct<uint32_t>(this, getPtr(this, Offset));
2391 }
2392
2393 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const2394 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2395 unsigned Index) const {
2396 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2397 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2398 }
2399
getSymtabLoadCommand() const2400 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2401 if (SymtabLoadCmd)
2402 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2403
2404 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2405 MachO::symtab_command Cmd;
2406 Cmd.cmd = MachO::LC_SYMTAB;
2407 Cmd.cmdsize = sizeof(MachO::symtab_command);
2408 Cmd.symoff = 0;
2409 Cmd.nsyms = 0;
2410 Cmd.stroff = 0;
2411 Cmd.strsize = 0;
2412 return Cmd;
2413 }
2414
getDysymtabLoadCommand() const2415 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2416 if (DysymtabLoadCmd)
2417 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2418
2419 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2420 MachO::dysymtab_command Cmd;
2421 Cmd.cmd = MachO::LC_DYSYMTAB;
2422 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2423 Cmd.ilocalsym = 0;
2424 Cmd.nlocalsym = 0;
2425 Cmd.iextdefsym = 0;
2426 Cmd.nextdefsym = 0;
2427 Cmd.iundefsym = 0;
2428 Cmd.nundefsym = 0;
2429 Cmd.tocoff = 0;
2430 Cmd.ntoc = 0;
2431 Cmd.modtaboff = 0;
2432 Cmd.nmodtab = 0;
2433 Cmd.extrefsymoff = 0;
2434 Cmd.nextrefsyms = 0;
2435 Cmd.indirectsymoff = 0;
2436 Cmd.nindirectsyms = 0;
2437 Cmd.extreloff = 0;
2438 Cmd.nextrel = 0;
2439 Cmd.locreloff = 0;
2440 Cmd.nlocrel = 0;
2441 return Cmd;
2442 }
2443
2444 MachO::linkedit_data_command
getDataInCodeLoadCommand() const2445 MachOObjectFile::getDataInCodeLoadCommand() const {
2446 if (DataInCodeLoadCmd)
2447 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2448
2449 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2450 MachO::linkedit_data_command Cmd;
2451 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2452 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2453 Cmd.dataoff = 0;
2454 Cmd.datasize = 0;
2455 return Cmd;
2456 }
2457
getDyldInfoRebaseOpcodes() const2458 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2459 if (!DyldInfoLoadCmd)
2460 return ArrayRef<uint8_t>();
2461
2462 MachO::dyld_info_command DyldInfo
2463 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2464 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2465 getPtr(this, DyldInfo.rebase_off));
2466 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2467 }
2468
getDyldInfoBindOpcodes() const2469 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2470 if (!DyldInfoLoadCmd)
2471 return ArrayRef<uint8_t>();
2472
2473 MachO::dyld_info_command DyldInfo
2474 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2475 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2476 getPtr(this, DyldInfo.bind_off));
2477 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2478 }
2479
getDyldInfoWeakBindOpcodes() const2480 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2481 if (!DyldInfoLoadCmd)
2482 return ArrayRef<uint8_t>();
2483
2484 MachO::dyld_info_command DyldInfo
2485 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2486 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2487 getPtr(this, DyldInfo.weak_bind_off));
2488 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2489 }
2490
getDyldInfoLazyBindOpcodes() const2491 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2492 if (!DyldInfoLoadCmd)
2493 return ArrayRef<uint8_t>();
2494
2495 MachO::dyld_info_command DyldInfo
2496 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2497 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2498 getPtr(this, DyldInfo.lazy_bind_off));
2499 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2500 }
2501
getDyldInfoExportsTrie() const2502 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2503 if (!DyldInfoLoadCmd)
2504 return ArrayRef<uint8_t>();
2505
2506 MachO::dyld_info_command DyldInfo
2507 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2508 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2509 getPtr(this, DyldInfo.export_off));
2510 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2511 }
2512
getUuid() const2513 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2514 if (!UuidLoadCmd)
2515 return ArrayRef<uint8_t>();
2516 // Returning a pointer is fine as uuid doesn't need endian swapping.
2517 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2518 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2519 }
2520
getStringTableData() const2521 StringRef MachOObjectFile::getStringTableData() const {
2522 MachO::symtab_command S = getSymtabLoadCommand();
2523 return getData().substr(S.stroff, S.strsize);
2524 }
2525
is64Bit() const2526 bool MachOObjectFile::is64Bit() const {
2527 return getType() == getMachOType(false, true) ||
2528 getType() == getMachOType(true, true);
2529 }
2530
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const2531 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2532 SmallVectorImpl<uint64_t> &Out) const {
2533 DataExtractor extractor(ObjectFile::getData(), true, 0);
2534
2535 uint32_t offset = Index;
2536 uint64_t data = 0;
2537 while (uint64_t delta = extractor.getULEB128(&offset)) {
2538 data += delta;
2539 Out.push_back(data);
2540 }
2541 }
2542
isRelocatableObject() const2543 bool MachOObjectFile::isRelocatableObject() const {
2544 return getHeader().filetype == MachO::MH_OBJECT;
2545 }
2546
2547 ErrorOr<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer)2548 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2549 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2550 std::error_code EC;
2551 std::unique_ptr<MachOObjectFile> Ret;
2552 if (Magic == "\xFE\xED\xFA\xCE")
2553 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2554 else if (Magic == "\xCE\xFA\xED\xFE")
2555 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2556 else if (Magic == "\xFE\xED\xFA\xCF")
2557 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2558 else if (Magic == "\xCF\xFA\xED\xFE")
2559 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2560 else
2561 return object_error::parse_failed;
2562
2563 if (EC)
2564 return EC;
2565 return std::move(Ret);
2566 }
2567
2568