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 // FIXME: Replace all uses of this function with getStructOrErr.
42 template <typename T>
getStruct(const MachOObjectFile * O,const char * P)43 static T getStruct(const MachOObjectFile *O, const char *P) {
44 // Don't read before the beginning or past the end of the file
45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46 report_fatal_error("Malformed MachO file.");
47
48 T Cmd;
49 memcpy(&Cmd, P, sizeof(T));
50 if (O->isLittleEndian() != sys::IsLittleEndianHost)
51 MachO::swapStruct(Cmd);
52 return Cmd;
53 }
54
55 template <typename T>
getStructOrErr(const MachOObjectFile * O,const char * P)56 static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57 // Don't read before the beginning or past the end of the file
58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59 return object_error::parse_failed;
60
61 T Cmd;
62 memcpy(&Cmd, P, sizeof(T));
63 if (O->isLittleEndian() != sys::IsLittleEndianHost)
64 MachO::swapStruct(Cmd);
65 return Cmd;
66 }
67
68 static const char *
getSectionPtr(const MachOObjectFile * O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)69 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
70 unsigned Sec) {
71 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
72
73 bool Is64 = O->is64Bit();
74 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75 sizeof(MachO::segment_command);
76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77 sizeof(MachO::section);
78
79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
80 return reinterpret_cast<const char*>(SectionAddr);
81 }
82
getPtr(const MachOObjectFile * O,size_t Offset)83 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84 return O->getData().substr(Offset, 1).data();
85 }
86
87 static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile * O,DataRefImpl DRI)88 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
89 const char *P = reinterpret_cast<const char *>(DRI.p);
90 return getStruct<MachO::nlist_base>(O, P);
91 }
92
parseSegmentOrSectionName(const char * P)93 static StringRef parseSegmentOrSectionName(const char *P) {
94 if (P[15] == 0)
95 // Null terminated.
96 return P;
97 // Not null terminated, so this is a 16 char string.
98 return StringRef(P, 16);
99 }
100
101 // Helper to advance a section or symbol iterator multiple increments at a time.
102 template<class T>
advance(T & it,size_t Val)103 static void advance(T &it, size_t Val) {
104 while (Val--)
105 ++it;
106 }
107
getCPUType(const MachOObjectFile * O)108 static unsigned getCPUType(const MachOObjectFile *O) {
109 return O->getHeader().cputype;
110 }
111
112 static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)113 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
114 return RE.r_word0;
115 }
116
117 static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)118 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119 return RE.r_word0 & 0xffffff;
120 }
121
getPlainRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)122 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
123 const MachO::any_relocation_info &RE) {
124 if (O->isLittleEndian())
125 return (RE.r_word1 >> 24) & 1;
126 return (RE.r_word1 >> 7) & 1;
127 }
128
129 static bool
getScatteredRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)130 getScatteredRelocationPCRel(const MachOObjectFile *O,
131 const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
133 }
134
getPlainRelocationLength(const MachOObjectFile * O,const MachO::any_relocation_info & RE)135 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
136 const MachO::any_relocation_info &RE) {
137 if (O->isLittleEndian())
138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
140 }
141
142 static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
145 }
146
getPlainRelocationType(const MachOObjectFile * O,const MachO::any_relocation_info & RE)147 static unsigned getPlainRelocationType(const MachOObjectFile *O,
148 const MachO::any_relocation_info &RE) {
149 if (O->isLittleEndian())
150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
152 }
153
getSectionFlags(const MachOObjectFile * O,DataRefImpl Sec)154 static uint32_t getSectionFlags(const MachOObjectFile *O,
155 DataRefImpl Sec) {
156 if (O->is64Bit()) {
157 MachO::section_64 Sect = O->getSection64(Sec);
158 return Sect.flags;
159 }
160 MachO::section Sect = O->getSection(Sec);
161 return Sect.flags;
162 }
163
164 static ErrorOr<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile * Obj,const char * Ptr)165 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
167 if (!CmdOrErr)
168 return CmdOrErr.getError();
169 if (CmdOrErr->cmdsize < 8)
170 return object_error::macho_small_load_command;
171 MachOObjectFile::LoadCommandInfo Load;
172 Load.Ptr = Ptr;
173 Load.C = CmdOrErr.get();
174 return Load;
175 }
176
177 static ErrorOr<MachOObjectFile::LoadCommandInfo>
getFirstLoadCommandInfo(const MachOObjectFile * Obj)178 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180 : sizeof(MachO::mach_header);
181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
182 }
183
184 static ErrorOr<MachOObjectFile::LoadCommandInfo>
getNextLoadCommandInfo(const MachOObjectFile * Obj,const MachOObjectFile::LoadCommandInfo & L)185 getNextLoadCommandInfo(const MachOObjectFile *Obj,
186 const MachOObjectFile::LoadCommandInfo &L) {
187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
188 }
189
190 template <typename T>
parseHeader(const MachOObjectFile * Obj,T & Header,std::error_code & EC)191 static void parseHeader(const MachOObjectFile *Obj, T &Header,
192 std::error_code &EC) {
193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
194 if (HeaderOrErr)
195 Header = HeaderOrErr.get();
196 else
197 EC = HeaderOrErr.getError();
198 }
199
200 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201 // sections to \param Sections, and optionally sets
202 // \param IsPageZeroSegment to true.
203 template <typename SegmentCmd>
parseSegmentLoadCommand(const MachOObjectFile * Obj,const MachOObjectFile::LoadCommandInfo & Load,SmallVectorImpl<const char * > & Sections,bool & IsPageZeroSegment)204 static std::error_code parseSegmentLoadCommand(
205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208 if (Load.C.cmdsize < SegmentLoadSize)
209 return object_error::macho_load_segment_too_small;
210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
211 if (!SegOrErr)
212 return SegOrErr.getError();
213 SegmentCmd S = SegOrErr.get();
214 const unsigned SectionSize =
215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218 return object_error::macho_load_segment_too_many_sections;
219 for (unsigned J = 0; J < S.nsects; ++J) {
220 const char *Sec = getSectionPtr(Obj, Load, J);
221 Sections.push_back(Sec);
222 }
223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
224 return std::error_code();
225 }
226
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,std::error_code & EC)227 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
234 if (is64Bit())
235 parseHeader(this, Header64, EC);
236 else
237 parseHeader(this, Header, EC);
238 if (EC)
239 return;
240
241 uint32_t LoadCommandCount = getHeader().ncmds;
242 if (LoadCommandCount == 0)
243 return;
244
245 auto LoadOrErr = getFirstLoadCommandInfo(this);
246 if (!LoadOrErr) {
247 EC = LoadOrErr.getError();
248 return;
249 }
250 LoadCommandInfo Load = LoadOrErr.get();
251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
253 if (Load.C.cmd == MachO::LC_SYMTAB) {
254 // Multiple symbol tables
255 if (SymtabLoadCmd) {
256 EC = object_error::parse_failed;
257 return;
258 }
259 SymtabLoadCmd = Load.Ptr;
260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
264 return;
265 }
266 DysymtabLoadCmd = Load.Ptr;
267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
271 return;
272 }
273 DataInCodeLoadCmd = Load.Ptr;
274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
278 return;
279 }
280 LinkOptHintsLoadCmd = Load.Ptr;
281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
286 return;
287 }
288 DyldInfoLoadCmd = Load.Ptr;
289 } else if (Load.C.cmd == MachO::LC_UUID) {
290 // Multiple UUID load commands
291 if (UuidLoadCmd) {
292 EC = object_error::parse_failed;
293 return;
294 }
295 UuidLoadCmd = Load.Ptr;
296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
299 return;
300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
303 return;
304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
310 }
311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
313 if (!LoadOrErr) {
314 EC = LoadOrErr.getError();
315 return;
316 }
317 Load = LoadOrErr.get();
318 }
319 }
320 assert(LoadCommands.size() == LoadCommandCount);
321 }
322
moveSymbolNext(DataRefImpl & Symb) const323 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
324 unsigned SymbolTableEntrySize = is64Bit() ?
325 sizeof(MachO::nlist_64) :
326 sizeof(MachO::nlist);
327 Symb.p += SymbolTableEntrySize;
328 }
329
getSymbolName(DataRefImpl Symb) const330 ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
331 StringRef StringTable = getStringTableData();
332 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
333 const char *Start = &StringTable.data()[Entry.n_strx];
334 if (Start < getData().begin() || Start >= getData().end())
335 report_fatal_error(
336 "Symbol name entry points before beginning or past end of file.");
337 return StringRef(Start);
338 }
339
getSectionType(SectionRef Sec) const340 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
341 DataRefImpl DRI = Sec.getRawDataRefImpl();
342 uint32_t Flags = getSectionFlags(this, DRI);
343 return Flags & MachO::SECTION_TYPE;
344 }
345
getNValue(DataRefImpl Sym) const346 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
347 if (is64Bit()) {
348 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
349 return Entry.n_value;
350 }
351 MachO::nlist Entry = getSymbolTableEntry(Sym);
352 return Entry.n_value;
353 }
354
355 // getIndirectName() returns the name of the alias'ed symbol who's string table
356 // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const357 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
358 StringRef &Res) const {
359 StringRef StringTable = getStringTableData();
360 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
361 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362 return object_error::parse_failed;
363 uint64_t NValue = getNValue(Symb);
364 if (NValue >= StringTable.size())
365 return object_error::parse_failed;
366 const char *Start = &StringTable.data()[NValue];
367 Res = StringRef(Start);
368 return std::error_code();
369 }
370
getSymbolValueImpl(DataRefImpl Sym) const371 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
372 return getNValue(Sym);
373 }
374
getSymbolAddress(DataRefImpl Sym) const375 ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
376 return getSymbolValue(Sym);
377 }
378
getSymbolAlignment(DataRefImpl DRI) const379 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
380 uint32_t flags = getSymbolFlags(DRI);
381 if (flags & SymbolRef::SF_Common) {
382 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
383 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
384 }
385 return 0;
386 }
387
getCommonSymbolSizeImpl(DataRefImpl DRI) const388 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
389 return getNValue(DRI);
390 }
391
getSymbolType(DataRefImpl Symb) const392 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
393 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
394 uint8_t n_type = Entry.n_type;
395
396 // If this is a STAB debugging symbol, we can do nothing more.
397 if (n_type & MachO::N_STAB)
398 return SymbolRef::ST_Debug;
399
400 switch (n_type & MachO::N_TYPE) {
401 case MachO::N_UNDF :
402 return SymbolRef::ST_Unknown;
403 case MachO::N_SECT :
404 return SymbolRef::ST_Function;
405 }
406 return SymbolRef::ST_Other;
407 }
408
getSymbolFlags(DataRefImpl DRI) const409 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
411
412 uint8_t MachOType = Entry.n_type;
413 uint16_t MachOFlags = Entry.n_desc;
414
415 uint32_t Result = SymbolRef::SF_None;
416
417 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
418 Result |= SymbolRef::SF_Indirect;
419
420 if (MachOType & MachO::N_STAB)
421 Result |= SymbolRef::SF_FormatSpecific;
422
423 if (MachOType & MachO::N_EXT) {
424 Result |= SymbolRef::SF_Global;
425 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
426 if (getNValue(DRI))
427 Result |= SymbolRef::SF_Common;
428 else
429 Result |= SymbolRef::SF_Undefined;
430 }
431
432 if (!(MachOType & MachO::N_PEXT))
433 Result |= SymbolRef::SF_Exported;
434 }
435
436 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
437 Result |= SymbolRef::SF_Weak;
438
439 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
440 Result |= SymbolRef::SF_Thumb;
441
442 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
443 Result |= SymbolRef::SF_Absolute;
444
445 return Result;
446 }
447
getSymbolSection(DataRefImpl Symb,section_iterator & Res) const448 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
449 section_iterator &Res) const {
450 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
451 uint8_t index = Entry.n_sect;
452
453 if (index == 0) {
454 Res = section_end();
455 } else {
456 DataRefImpl DRI;
457 DRI.d.a = index - 1;
458 if (DRI.d.a >= Sections.size())
459 report_fatal_error("getSymbolSection: Invalid section index.");
460 Res = section_iterator(SectionRef(DRI, this));
461 }
462
463 return std::error_code();
464 }
465
getSymbolSectionID(SymbolRef Sym) const466 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
467 MachO::nlist_base Entry =
468 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
469 return Entry.n_sect - 1;
470 }
471
moveSectionNext(DataRefImpl & Sec) const472 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
473 Sec.d.a++;
474 }
475
getSectionName(DataRefImpl Sec,StringRef & Result) const476 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
477 StringRef &Result) const {
478 ArrayRef<char> Raw = getSectionRawName(Sec);
479 Result = parseSegmentOrSectionName(Raw.data());
480 return std::error_code();
481 }
482
getSectionAddress(DataRefImpl Sec) const483 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
484 if (is64Bit())
485 return getSection64(Sec).addr;
486 return getSection(Sec).addr;
487 }
488
getSectionSize(DataRefImpl Sec) const489 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
490 if (is64Bit())
491 return getSection64(Sec).size;
492 return getSection(Sec).size;
493 }
494
getSectionContents(DataRefImpl Sec,StringRef & Res) const495 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
496 StringRef &Res) const {
497 uint32_t Offset;
498 uint64_t Size;
499
500 if (is64Bit()) {
501 MachO::section_64 Sect = getSection64(Sec);
502 Offset = Sect.offset;
503 Size = Sect.size;
504 } else {
505 MachO::section Sect = getSection(Sec);
506 Offset = Sect.offset;
507 Size = Sect.size;
508 }
509
510 Res = this->getData().substr(Offset, Size);
511 return std::error_code();
512 }
513
getSectionAlignment(DataRefImpl Sec) const514 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
515 uint32_t Align;
516 if (is64Bit()) {
517 MachO::section_64 Sect = getSection64(Sec);
518 Align = Sect.align;
519 } else {
520 MachO::section Sect = getSection(Sec);
521 Align = Sect.align;
522 }
523
524 return uint64_t(1) << Align;
525 }
526
isSectionText(DataRefImpl Sec) const527 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
528 uint32_t Flags = getSectionFlags(this, Sec);
529 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
530 }
531
isSectionData(DataRefImpl Sec) const532 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
533 uint32_t Flags = getSectionFlags(this, Sec);
534 unsigned SectionType = Flags & MachO::SECTION_TYPE;
535 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
536 !(SectionType == MachO::S_ZEROFILL ||
537 SectionType == MachO::S_GB_ZEROFILL);
538 }
539
isSectionBSS(DataRefImpl Sec) const540 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
541 uint32_t Flags = getSectionFlags(this, Sec);
542 unsigned SectionType = Flags & MachO::SECTION_TYPE;
543 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
544 (SectionType == MachO::S_ZEROFILL ||
545 SectionType == MachO::S_GB_ZEROFILL);
546 }
547
getSectionID(SectionRef Sec) const548 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
549 return Sec.getRawDataRefImpl().d.a;
550 }
551
isSectionVirtual(DataRefImpl Sec) const552 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
553 // FIXME: Unimplemented.
554 return false;
555 }
556
section_rel_begin(DataRefImpl Sec) const557 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
558 DataRefImpl Ret;
559 Ret.d.a = Sec.d.a;
560 Ret.d.b = 0;
561 return relocation_iterator(RelocationRef(Ret, this));
562 }
563
564 relocation_iterator
section_rel_end(DataRefImpl Sec) const565 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
566 uint32_t Num;
567 if (is64Bit()) {
568 MachO::section_64 Sect = getSection64(Sec);
569 Num = Sect.nreloc;
570 } else {
571 MachO::section Sect = getSection(Sec);
572 Num = Sect.nreloc;
573 }
574
575 DataRefImpl Ret;
576 Ret.d.a = Sec.d.a;
577 Ret.d.b = Num;
578 return relocation_iterator(RelocationRef(Ret, this));
579 }
580
moveRelocationNext(DataRefImpl & Rel) const581 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
582 ++Rel.d.b;
583 }
584
getRelocationOffset(DataRefImpl Rel) const585 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
586 assert(getHeader().filetype == MachO::MH_OBJECT &&
587 "Only implemented for MH_OBJECT");
588 MachO::any_relocation_info RE = getRelocation(Rel);
589 return getAnyRelocationAddress(RE);
590 }
591
592 symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const593 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
594 MachO::any_relocation_info RE = getRelocation(Rel);
595 if (isRelocationScattered(RE))
596 return symbol_end();
597
598 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
599 bool isExtern = getPlainRelocationExternal(RE);
600 if (!isExtern)
601 return symbol_end();
602
603 MachO::symtab_command S = getSymtabLoadCommand();
604 unsigned SymbolTableEntrySize = is64Bit() ?
605 sizeof(MachO::nlist_64) :
606 sizeof(MachO::nlist);
607 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
608 DataRefImpl Sym;
609 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
610 return symbol_iterator(SymbolRef(Sym, this));
611 }
612
613 section_iterator
getRelocationSection(DataRefImpl Rel) const614 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
615 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
616 }
617
getRelocationType(DataRefImpl Rel) const618 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
619 MachO::any_relocation_info RE = getRelocation(Rel);
620 return getAnyRelocationType(RE);
621 }
622
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const623 void MachOObjectFile::getRelocationTypeName(
624 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
625 StringRef res;
626 uint64_t RType = getRelocationType(Rel);
627
628 unsigned Arch = this->getArch();
629
630 switch (Arch) {
631 case Triple::x86: {
632 static const char *const Table[] = {
633 "GENERIC_RELOC_VANILLA",
634 "GENERIC_RELOC_PAIR",
635 "GENERIC_RELOC_SECTDIFF",
636 "GENERIC_RELOC_PB_LA_PTR",
637 "GENERIC_RELOC_LOCAL_SECTDIFF",
638 "GENERIC_RELOC_TLV" };
639
640 if (RType > 5)
641 res = "Unknown";
642 else
643 res = Table[RType];
644 break;
645 }
646 case Triple::x86_64: {
647 static const char *const Table[] = {
648 "X86_64_RELOC_UNSIGNED",
649 "X86_64_RELOC_SIGNED",
650 "X86_64_RELOC_BRANCH",
651 "X86_64_RELOC_GOT_LOAD",
652 "X86_64_RELOC_GOT",
653 "X86_64_RELOC_SUBTRACTOR",
654 "X86_64_RELOC_SIGNED_1",
655 "X86_64_RELOC_SIGNED_2",
656 "X86_64_RELOC_SIGNED_4",
657 "X86_64_RELOC_TLV" };
658
659 if (RType > 9)
660 res = "Unknown";
661 else
662 res = Table[RType];
663 break;
664 }
665 case Triple::arm: {
666 static const char *const Table[] = {
667 "ARM_RELOC_VANILLA",
668 "ARM_RELOC_PAIR",
669 "ARM_RELOC_SECTDIFF",
670 "ARM_RELOC_LOCAL_SECTDIFF",
671 "ARM_RELOC_PB_LA_PTR",
672 "ARM_RELOC_BR24",
673 "ARM_THUMB_RELOC_BR22",
674 "ARM_THUMB_32BIT_BRANCH",
675 "ARM_RELOC_HALF",
676 "ARM_RELOC_HALF_SECTDIFF" };
677
678 if (RType > 9)
679 res = "Unknown";
680 else
681 res = Table[RType];
682 break;
683 }
684 case Triple::aarch64: {
685 static const char *const Table[] = {
686 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
687 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
688 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
689 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
690 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
691 "ARM64_RELOC_ADDEND"
692 };
693
694 if (RType >= array_lengthof(Table))
695 res = "Unknown";
696 else
697 res = Table[RType];
698 break;
699 }
700 case Triple::ppc: {
701 static const char *const Table[] = {
702 "PPC_RELOC_VANILLA",
703 "PPC_RELOC_PAIR",
704 "PPC_RELOC_BR14",
705 "PPC_RELOC_BR24",
706 "PPC_RELOC_HI16",
707 "PPC_RELOC_LO16",
708 "PPC_RELOC_HA16",
709 "PPC_RELOC_LO14",
710 "PPC_RELOC_SECTDIFF",
711 "PPC_RELOC_PB_LA_PTR",
712 "PPC_RELOC_HI16_SECTDIFF",
713 "PPC_RELOC_LO16_SECTDIFF",
714 "PPC_RELOC_HA16_SECTDIFF",
715 "PPC_RELOC_JBSR",
716 "PPC_RELOC_LO14_SECTDIFF",
717 "PPC_RELOC_LOCAL_SECTDIFF" };
718
719 if (RType > 15)
720 res = "Unknown";
721 else
722 res = Table[RType];
723 break;
724 }
725 case Triple::UnknownArch:
726 res = "Unknown";
727 break;
728 }
729 Result.append(res.begin(), res.end());
730 }
731
getRelocationLength(DataRefImpl Rel) const732 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
733 MachO::any_relocation_info RE = getRelocation(Rel);
734 return getAnyRelocationLength(RE);
735 }
736
737 //
738 // guessLibraryShortName() is passed a name of a dynamic library and returns a
739 // guess on what the short name is. Then name is returned as a substring of the
740 // StringRef Name passed in. The name of the dynamic library is recognized as
741 // a framework if it has one of the two following forms:
742 // Foo.framework/Versions/A/Foo
743 // Foo.framework/Foo
744 // Where A and Foo can be any string. And may contain a trailing suffix
745 // starting with an underbar. If the Name is recognized as a framework then
746 // isFramework is set to true else it is set to false. If the Name has a
747 // suffix then Suffix is set to the substring in Name that contains the suffix
748 // else it is set to a NULL StringRef.
749 //
750 // The Name of the dynamic library is recognized as a library name if it has
751 // one of the two following forms:
752 // libFoo.A.dylib
753 // libFoo.dylib
754 // The library may have a suffix trailing the name Foo of the form:
755 // libFoo_profile.A.dylib
756 // libFoo_profile.dylib
757 //
758 // The Name of the dynamic library is also recognized as a library name if it
759 // has the following form:
760 // Foo.qtx
761 //
762 // If the Name of the dynamic library is none of the forms above then a NULL
763 // StringRef is returned.
764 //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)765 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
766 bool &isFramework,
767 StringRef &Suffix) {
768 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
769 size_t a, b, c, d, Idx;
770
771 isFramework = false;
772 Suffix = StringRef();
773
774 // Pull off the last component and make Foo point to it
775 a = Name.rfind('/');
776 if (a == Name.npos || a == 0)
777 goto guess_library;
778 Foo = Name.slice(a+1, Name.npos);
779
780 // Look for a suffix starting with a '_'
781 Idx = Foo.rfind('_');
782 if (Idx != Foo.npos && Foo.size() >= 2) {
783 Suffix = Foo.slice(Idx, Foo.npos);
784 Foo = Foo.slice(0, Idx);
785 }
786
787 // First look for the form Foo.framework/Foo
788 b = Name.rfind('/', a);
789 if (b == Name.npos)
790 Idx = 0;
791 else
792 Idx = b+1;
793 F = Name.slice(Idx, Idx + Foo.size());
794 DotFramework = Name.slice(Idx + Foo.size(),
795 Idx + Foo.size() + sizeof(".framework/")-1);
796 if (F == Foo && DotFramework == ".framework/") {
797 isFramework = true;
798 return Foo;
799 }
800
801 // Next look for the form Foo.framework/Versions/A/Foo
802 if (b == Name.npos)
803 goto guess_library;
804 c = Name.rfind('/', b);
805 if (c == Name.npos || c == 0)
806 goto guess_library;
807 V = Name.slice(c+1, Name.npos);
808 if (!V.startswith("Versions/"))
809 goto guess_library;
810 d = Name.rfind('/', c);
811 if (d == Name.npos)
812 Idx = 0;
813 else
814 Idx = d+1;
815 F = Name.slice(Idx, Idx + Foo.size());
816 DotFramework = Name.slice(Idx + Foo.size(),
817 Idx + Foo.size() + sizeof(".framework/")-1);
818 if (F == Foo && DotFramework == ".framework/") {
819 isFramework = true;
820 return Foo;
821 }
822
823 guess_library:
824 // pull off the suffix after the "." and make a point to it
825 a = Name.rfind('.');
826 if (a == Name.npos || a == 0)
827 return StringRef();
828 Dylib = Name.slice(a, Name.npos);
829 if (Dylib != ".dylib")
830 goto guess_qtx;
831
832 // First pull off the version letter for the form Foo.A.dylib if any.
833 if (a >= 3) {
834 Dot = Name.slice(a-2, a-1);
835 if (Dot == ".")
836 a = a - 2;
837 }
838
839 b = Name.rfind('/', a);
840 if (b == Name.npos)
841 b = 0;
842 else
843 b = b+1;
844 // ignore any suffix after an underbar like Foo_profile.A.dylib
845 Idx = Name.find('_', b);
846 if (Idx != Name.npos && Idx != b) {
847 Lib = Name.slice(b, Idx);
848 Suffix = Name.slice(Idx, a);
849 }
850 else
851 Lib = Name.slice(b, a);
852 // There are incorrect library names of the form:
853 // libATS.A_profile.dylib so check for these.
854 if (Lib.size() >= 3) {
855 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
856 if (Dot == ".")
857 Lib = Lib.slice(0, Lib.size()-2);
858 }
859 return Lib;
860
861 guess_qtx:
862 Qtx = Name.slice(a, Name.npos);
863 if (Qtx != ".qtx")
864 return StringRef();
865 b = Name.rfind('/', a);
866 if (b == Name.npos)
867 Lib = Name.slice(0, a);
868 else
869 Lib = Name.slice(b+1, a);
870 // There are library names of the form: QT.A.qtx so check for these.
871 if (Lib.size() >= 3) {
872 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
873 if (Dot == ".")
874 Lib = Lib.slice(0, Lib.size()-2);
875 }
876 return Lib;
877 }
878
879 // getLibraryShortNameByIndex() is used to get the short name of the library
880 // for an undefined symbol in a linked Mach-O binary that was linked with the
881 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
882 // It is passed the index (0 - based) of the library as translated from
883 // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const884 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
885 StringRef &Res) const {
886 if (Index >= Libraries.size())
887 return object_error::parse_failed;
888
889 // If the cache of LibrariesShortNames is not built up do that first for
890 // all the Libraries.
891 if (LibrariesShortNames.size() == 0) {
892 for (unsigned i = 0; i < Libraries.size(); i++) {
893 MachO::dylib_command D =
894 getStruct<MachO::dylib_command>(this, Libraries[i]);
895 if (D.dylib.name >= D.cmdsize)
896 return object_error::parse_failed;
897 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
898 StringRef Name = StringRef(P);
899 if (D.dylib.name+Name.size() >= D.cmdsize)
900 return object_error::parse_failed;
901 StringRef Suffix;
902 bool isFramework;
903 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
904 if (shortName.empty())
905 LibrariesShortNames.push_back(Name);
906 else
907 LibrariesShortNames.push_back(shortName);
908 }
909 }
910
911 Res = LibrariesShortNames[Index];
912 return std::error_code();
913 }
914
915 section_iterator
getRelocationRelocatedSection(relocation_iterator Rel) const916 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
917 DataRefImpl Sec;
918 Sec.d.a = Rel->getRawDataRefImpl().d.a;
919 return section_iterator(SectionRef(Sec, this));
920 }
921
symbol_begin_impl() const922 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
923 return getSymbolByIndex(0);
924 }
925
symbol_end_impl() const926 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
927 DataRefImpl DRI;
928 if (!SymtabLoadCmd)
929 return basic_symbol_iterator(SymbolRef(DRI, this));
930
931 MachO::symtab_command Symtab = getSymtabLoadCommand();
932 unsigned SymbolTableEntrySize = is64Bit() ?
933 sizeof(MachO::nlist_64) :
934 sizeof(MachO::nlist);
935 unsigned Offset = Symtab.symoff +
936 Symtab.nsyms * SymbolTableEntrySize;
937 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
938 return basic_symbol_iterator(SymbolRef(DRI, this));
939 }
940
getSymbolByIndex(unsigned Index) const941 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
942 DataRefImpl DRI;
943 if (!SymtabLoadCmd)
944 return basic_symbol_iterator(SymbolRef(DRI, this));
945
946 MachO::symtab_command Symtab = getSymtabLoadCommand();
947 if (Index >= Symtab.nsyms)
948 report_fatal_error("Requested symbol index is out of range.");
949 unsigned SymbolTableEntrySize =
950 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
951 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
952 DRI.p += Index * SymbolTableEntrySize;
953 return basic_symbol_iterator(SymbolRef(DRI, this));
954 }
955
section_begin() const956 section_iterator MachOObjectFile::section_begin() const {
957 DataRefImpl DRI;
958 return section_iterator(SectionRef(DRI, this));
959 }
960
section_end() const961 section_iterator MachOObjectFile::section_end() const {
962 DataRefImpl DRI;
963 DRI.d.a = Sections.size();
964 return section_iterator(SectionRef(DRI, this));
965 }
966
getBytesInAddress() const967 uint8_t MachOObjectFile::getBytesInAddress() const {
968 return is64Bit() ? 8 : 4;
969 }
970
getFileFormatName() const971 StringRef MachOObjectFile::getFileFormatName() const {
972 unsigned CPUType = getCPUType(this);
973 if (!is64Bit()) {
974 switch (CPUType) {
975 case llvm::MachO::CPU_TYPE_I386:
976 return "Mach-O 32-bit i386";
977 case llvm::MachO::CPU_TYPE_ARM:
978 return "Mach-O arm";
979 case llvm::MachO::CPU_TYPE_POWERPC:
980 return "Mach-O 32-bit ppc";
981 default:
982 return "Mach-O 32-bit unknown";
983 }
984 }
985
986 switch (CPUType) {
987 case llvm::MachO::CPU_TYPE_X86_64:
988 return "Mach-O 64-bit x86-64";
989 case llvm::MachO::CPU_TYPE_ARM64:
990 return "Mach-O arm64";
991 case llvm::MachO::CPU_TYPE_POWERPC64:
992 return "Mach-O 64-bit ppc64";
993 default:
994 return "Mach-O 64-bit unknown";
995 }
996 }
997
getArch(uint32_t CPUType)998 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
999 switch (CPUType) {
1000 case llvm::MachO::CPU_TYPE_I386:
1001 return Triple::x86;
1002 case llvm::MachO::CPU_TYPE_X86_64:
1003 return Triple::x86_64;
1004 case llvm::MachO::CPU_TYPE_ARM:
1005 return Triple::arm;
1006 case llvm::MachO::CPU_TYPE_ARM64:
1007 return Triple::aarch64;
1008 case llvm::MachO::CPU_TYPE_POWERPC:
1009 return Triple::ppc;
1010 case llvm::MachO::CPU_TYPE_POWERPC64:
1011 return Triple::ppc64;
1012 default:
1013 return Triple::UnknownArch;
1014 }
1015 }
1016
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1017 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1018 const char **McpuDefault) {
1019 if (McpuDefault)
1020 *McpuDefault = nullptr;
1021
1022 switch (CPUType) {
1023 case MachO::CPU_TYPE_I386:
1024 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1025 case MachO::CPU_SUBTYPE_I386_ALL:
1026 return Triple("i386-apple-darwin");
1027 default:
1028 return Triple();
1029 }
1030 case MachO::CPU_TYPE_X86_64:
1031 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1032 case MachO::CPU_SUBTYPE_X86_64_ALL:
1033 return Triple("x86_64-apple-darwin");
1034 case MachO::CPU_SUBTYPE_X86_64_H:
1035 return Triple("x86_64h-apple-darwin");
1036 default:
1037 return Triple();
1038 }
1039 case MachO::CPU_TYPE_ARM:
1040 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1041 case MachO::CPU_SUBTYPE_ARM_V4T:
1042 return Triple("armv4t-apple-darwin");
1043 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1044 return Triple("armv5e-apple-darwin");
1045 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1046 return Triple("xscale-apple-darwin");
1047 case MachO::CPU_SUBTYPE_ARM_V6:
1048 return Triple("armv6-apple-darwin");
1049 case MachO::CPU_SUBTYPE_ARM_V6M:
1050 if (McpuDefault)
1051 *McpuDefault = "cortex-m0";
1052 return Triple("armv6m-apple-darwin");
1053 case MachO::CPU_SUBTYPE_ARM_V7:
1054 return Triple("armv7-apple-darwin");
1055 case MachO::CPU_SUBTYPE_ARM_V7EM:
1056 if (McpuDefault)
1057 *McpuDefault = "cortex-m4";
1058 return Triple("armv7em-apple-darwin");
1059 case MachO::CPU_SUBTYPE_ARM_V7K:
1060 return Triple("armv7k-apple-darwin");
1061 case MachO::CPU_SUBTYPE_ARM_V7M:
1062 if (McpuDefault)
1063 *McpuDefault = "cortex-m3";
1064 return Triple("armv7m-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V7S:
1066 return Triple("armv7s-apple-darwin");
1067 default:
1068 return Triple();
1069 }
1070 case MachO::CPU_TYPE_ARM64:
1071 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1072 case MachO::CPU_SUBTYPE_ARM64_ALL:
1073 return Triple("arm64-apple-darwin");
1074 default:
1075 return Triple();
1076 }
1077 case MachO::CPU_TYPE_POWERPC:
1078 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1079 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1080 return Triple("ppc-apple-darwin");
1081 default:
1082 return Triple();
1083 }
1084 case MachO::CPU_TYPE_POWERPC64:
1085 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1086 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1087 return Triple("ppc64-apple-darwin");
1088 default:
1089 return Triple();
1090 }
1091 default:
1092 return Triple();
1093 }
1094 }
1095
getThumbArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1096 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1097 const char **McpuDefault) {
1098 if (McpuDefault)
1099 *McpuDefault = nullptr;
1100
1101 switch (CPUType) {
1102 case MachO::CPU_TYPE_ARM:
1103 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1104 case MachO::CPU_SUBTYPE_ARM_V4T:
1105 return Triple("thumbv4t-apple-darwin");
1106 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1107 return Triple("thumbv5e-apple-darwin");
1108 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1109 return Triple("xscale-apple-darwin");
1110 case MachO::CPU_SUBTYPE_ARM_V6:
1111 return Triple("thumbv6-apple-darwin");
1112 case MachO::CPU_SUBTYPE_ARM_V6M:
1113 if (McpuDefault)
1114 *McpuDefault = "cortex-m0";
1115 return Triple("thumbv6m-apple-darwin");
1116 case MachO::CPU_SUBTYPE_ARM_V7:
1117 return Triple("thumbv7-apple-darwin");
1118 case MachO::CPU_SUBTYPE_ARM_V7EM:
1119 if (McpuDefault)
1120 *McpuDefault = "cortex-m4";
1121 return Triple("thumbv7em-apple-darwin");
1122 case MachO::CPU_SUBTYPE_ARM_V7K:
1123 return Triple("thumbv7k-apple-darwin");
1124 case MachO::CPU_SUBTYPE_ARM_V7M:
1125 if (McpuDefault)
1126 *McpuDefault = "cortex-m3";
1127 return Triple("thumbv7m-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V7S:
1129 return Triple("thumbv7s-apple-darwin");
1130 default:
1131 return Triple();
1132 }
1133 default:
1134 return Triple();
1135 }
1136 }
1137
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,Triple * ThumbTriple)1138 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1139 const char **McpuDefault,
1140 Triple *ThumbTriple) {
1141 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1142 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1143 McpuDefault);
1144 return T;
1145 }
1146
getHostArch()1147 Triple MachOObjectFile::getHostArch() {
1148 return Triple(sys::getDefaultTargetTriple());
1149 }
1150
isValidArch(StringRef ArchFlag)1151 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1152 return StringSwitch<bool>(ArchFlag)
1153 .Case("i386", true)
1154 .Case("x86_64", true)
1155 .Case("x86_64h", true)
1156 .Case("armv4t", true)
1157 .Case("arm", true)
1158 .Case("armv5e", true)
1159 .Case("armv6", true)
1160 .Case("armv6m", true)
1161 .Case("armv7", true)
1162 .Case("armv7em", true)
1163 .Case("armv7k", true)
1164 .Case("armv7m", true)
1165 .Case("armv7s", true)
1166 .Case("arm64", true)
1167 .Case("ppc", true)
1168 .Case("ppc64", true)
1169 .Default(false);
1170 }
1171
getArch() const1172 unsigned MachOObjectFile::getArch() const {
1173 return getArch(getCPUType(this));
1174 }
1175
getArch(const char ** McpuDefault,Triple * ThumbTriple) const1176 Triple MachOObjectFile::getArch(const char **McpuDefault,
1177 Triple *ThumbTriple) const {
1178 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1179 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1180 }
1181
section_rel_begin(unsigned Index) const1182 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1183 DataRefImpl DRI;
1184 DRI.d.a = Index;
1185 return section_rel_begin(DRI);
1186 }
1187
section_rel_end(unsigned Index) const1188 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1189 DataRefImpl DRI;
1190 DRI.d.a = Index;
1191 return section_rel_end(DRI);
1192 }
1193
begin_dices() const1194 dice_iterator MachOObjectFile::begin_dices() const {
1195 DataRefImpl DRI;
1196 if (!DataInCodeLoadCmd)
1197 return dice_iterator(DiceRef(DRI, this));
1198
1199 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1200 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1201 return dice_iterator(DiceRef(DRI, this));
1202 }
1203
end_dices() const1204 dice_iterator MachOObjectFile::end_dices() const {
1205 DataRefImpl DRI;
1206 if (!DataInCodeLoadCmd)
1207 return dice_iterator(DiceRef(DRI, this));
1208
1209 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1210 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1211 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1212 return dice_iterator(DiceRef(DRI, this));
1213 }
1214
ExportEntry(ArrayRef<uint8_t> T)1215 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1216 : Trie(T), Malformed(false), Done(false) { }
1217
moveToFirst()1218 void ExportEntry::moveToFirst() {
1219 pushNode(0);
1220 pushDownUntilBottom();
1221 }
1222
moveToEnd()1223 void ExportEntry::moveToEnd() {
1224 Stack.clear();
1225 Done = true;
1226 }
1227
operator ==(const ExportEntry & Other) const1228 bool ExportEntry::operator==(const ExportEntry &Other) const {
1229 // Common case, one at end, other iterating from begin.
1230 if (Done || Other.Done)
1231 return (Done == Other.Done);
1232 // Not equal if different stack sizes.
1233 if (Stack.size() != Other.Stack.size())
1234 return false;
1235 // Not equal if different cumulative strings.
1236 if (!CumulativeString.equals(Other.CumulativeString))
1237 return false;
1238 // Equal if all nodes in both stacks match.
1239 for (unsigned i=0; i < Stack.size(); ++i) {
1240 if (Stack[i].Start != Other.Stack[i].Start)
1241 return false;
1242 }
1243 return true;
1244 }
1245
readULEB128(const uint8_t * & Ptr)1246 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1247 unsigned Count;
1248 uint64_t Result = decodeULEB128(Ptr, &Count);
1249 Ptr += Count;
1250 if (Ptr > Trie.end()) {
1251 Ptr = Trie.end();
1252 Malformed = true;
1253 }
1254 return Result;
1255 }
1256
name() const1257 StringRef ExportEntry::name() const {
1258 return CumulativeString;
1259 }
1260
flags() const1261 uint64_t ExportEntry::flags() const {
1262 return Stack.back().Flags;
1263 }
1264
address() const1265 uint64_t ExportEntry::address() const {
1266 return Stack.back().Address;
1267 }
1268
other() const1269 uint64_t ExportEntry::other() const {
1270 return Stack.back().Other;
1271 }
1272
otherName() const1273 StringRef ExportEntry::otherName() const {
1274 const char* ImportName = Stack.back().ImportName;
1275 if (ImportName)
1276 return StringRef(ImportName);
1277 return StringRef();
1278 }
1279
nodeOffset() const1280 uint32_t ExportEntry::nodeOffset() const {
1281 return Stack.back().Start - Trie.begin();
1282 }
1283
NodeState(const uint8_t * Ptr)1284 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1285 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1286 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1287 ParentStringLength(0), IsExportNode(false) {
1288 }
1289
pushNode(uint64_t offset)1290 void ExportEntry::pushNode(uint64_t offset) {
1291 const uint8_t *Ptr = Trie.begin() + offset;
1292 NodeState State(Ptr);
1293 uint64_t ExportInfoSize = readULEB128(State.Current);
1294 State.IsExportNode = (ExportInfoSize != 0);
1295 const uint8_t* Children = State.Current + ExportInfoSize;
1296 if (State.IsExportNode) {
1297 State.Flags = readULEB128(State.Current);
1298 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1299 State.Address = 0;
1300 State.Other = readULEB128(State.Current); // dylib ordinal
1301 State.ImportName = reinterpret_cast<const char*>(State.Current);
1302 } else {
1303 State.Address = readULEB128(State.Current);
1304 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1305 State.Other = readULEB128(State.Current);
1306 }
1307 }
1308 State.ChildCount = *Children;
1309 State.Current = Children + 1;
1310 State.NextChildIndex = 0;
1311 State.ParentStringLength = CumulativeString.size();
1312 Stack.push_back(State);
1313 }
1314
pushDownUntilBottom()1315 void ExportEntry::pushDownUntilBottom() {
1316 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1317 NodeState &Top = Stack.back();
1318 CumulativeString.resize(Top.ParentStringLength);
1319 for (;*Top.Current != 0; Top.Current++) {
1320 char C = *Top.Current;
1321 CumulativeString.push_back(C);
1322 }
1323 Top.Current += 1;
1324 uint64_t childNodeIndex = readULEB128(Top.Current);
1325 Top.NextChildIndex += 1;
1326 pushNode(childNodeIndex);
1327 }
1328 if (!Stack.back().IsExportNode) {
1329 Malformed = true;
1330 moveToEnd();
1331 }
1332 }
1333
1334 // We have a trie data structure and need a way to walk it that is compatible
1335 // with the C++ iterator model. The solution is a non-recursive depth first
1336 // traversal where the iterator contains a stack of parent nodes along with a
1337 // string that is the accumulation of all edge strings along the parent chain
1338 // to this point.
1339 //
1340 // There is one "export" node for each exported symbol. But because some
1341 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1342 // node may have child nodes too.
1343 //
1344 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1345 // child until hitting a node with no children (which is an export node or
1346 // else the trie is malformed). On the way down, each node is pushed on the
1347 // stack ivar. If there is no more ways down, it pops up one and tries to go
1348 // down a sibling path until a childless node is reached.
moveNext()1349 void ExportEntry::moveNext() {
1350 if (Stack.empty() || !Stack.back().IsExportNode) {
1351 Malformed = true;
1352 moveToEnd();
1353 return;
1354 }
1355
1356 Stack.pop_back();
1357 while (!Stack.empty()) {
1358 NodeState &Top = Stack.back();
1359 if (Top.NextChildIndex < Top.ChildCount) {
1360 pushDownUntilBottom();
1361 // Now at the next export node.
1362 return;
1363 } else {
1364 if (Top.IsExportNode) {
1365 // This node has no children but is itself an export node.
1366 CumulativeString.resize(Top.ParentStringLength);
1367 return;
1368 }
1369 Stack.pop_back();
1370 }
1371 }
1372 Done = true;
1373 }
1374
1375 iterator_range<export_iterator>
exports(ArrayRef<uint8_t> Trie)1376 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1377 ExportEntry Start(Trie);
1378 if (Trie.size() == 0)
1379 Start.moveToEnd();
1380 else
1381 Start.moveToFirst();
1382
1383 ExportEntry Finish(Trie);
1384 Finish.moveToEnd();
1385
1386 return iterator_range<export_iterator>(export_iterator(Start),
1387 export_iterator(Finish));
1388 }
1389
exports() const1390 iterator_range<export_iterator> MachOObjectFile::exports() const {
1391 return exports(getDyldInfoExportsTrie());
1392 }
1393
1394
MachORebaseEntry(ArrayRef<uint8_t> Bytes,bool is64Bit)1395 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1396 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1397 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1398 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1399
moveToFirst()1400 void MachORebaseEntry::moveToFirst() {
1401 Ptr = Opcodes.begin();
1402 moveNext();
1403 }
1404
moveToEnd()1405 void MachORebaseEntry::moveToEnd() {
1406 Ptr = Opcodes.end();
1407 RemainingLoopCount = 0;
1408 Done = true;
1409 }
1410
moveNext()1411 void MachORebaseEntry::moveNext() {
1412 // If in the middle of some loop, move to next rebasing in loop.
1413 SegmentOffset += AdvanceAmount;
1414 if (RemainingLoopCount) {
1415 --RemainingLoopCount;
1416 return;
1417 }
1418 if (Ptr == Opcodes.end()) {
1419 Done = true;
1420 return;
1421 }
1422 bool More = true;
1423 while (More && !Malformed) {
1424 // Parse next opcode and set up next loop.
1425 uint8_t Byte = *Ptr++;
1426 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1427 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1428 switch (Opcode) {
1429 case MachO::REBASE_OPCODE_DONE:
1430 More = false;
1431 Done = true;
1432 moveToEnd();
1433 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1434 break;
1435 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1436 RebaseType = ImmValue;
1437 DEBUG_WITH_TYPE(
1438 "mach-o-rebase",
1439 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1440 << "RebaseType=" << (int) RebaseType << "\n");
1441 break;
1442 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1443 SegmentIndex = ImmValue;
1444 SegmentOffset = readULEB128();
1445 DEBUG_WITH_TYPE(
1446 "mach-o-rebase",
1447 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1448 << "SegmentIndex=" << SegmentIndex << ", "
1449 << format("SegmentOffset=0x%06X", SegmentOffset)
1450 << "\n");
1451 break;
1452 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1453 SegmentOffset += readULEB128();
1454 DEBUG_WITH_TYPE("mach-o-rebase",
1455 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1456 << format("SegmentOffset=0x%06X",
1457 SegmentOffset) << "\n");
1458 break;
1459 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1460 SegmentOffset += ImmValue * PointerSize;
1461 DEBUG_WITH_TYPE("mach-o-rebase",
1462 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1463 << format("SegmentOffset=0x%06X",
1464 SegmentOffset) << "\n");
1465 break;
1466 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1467 AdvanceAmount = PointerSize;
1468 RemainingLoopCount = ImmValue - 1;
1469 DEBUG_WITH_TYPE(
1470 "mach-o-rebase",
1471 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1472 << format("SegmentOffset=0x%06X", SegmentOffset)
1473 << ", AdvanceAmount=" << AdvanceAmount
1474 << ", RemainingLoopCount=" << RemainingLoopCount
1475 << "\n");
1476 return;
1477 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1478 AdvanceAmount = PointerSize;
1479 RemainingLoopCount = readULEB128() - 1;
1480 DEBUG_WITH_TYPE(
1481 "mach-o-rebase",
1482 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1483 << format("SegmentOffset=0x%06X", SegmentOffset)
1484 << ", AdvanceAmount=" << AdvanceAmount
1485 << ", RemainingLoopCount=" << RemainingLoopCount
1486 << "\n");
1487 return;
1488 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1489 AdvanceAmount = readULEB128() + PointerSize;
1490 RemainingLoopCount = 0;
1491 DEBUG_WITH_TYPE(
1492 "mach-o-rebase",
1493 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1494 << format("SegmentOffset=0x%06X", SegmentOffset)
1495 << ", AdvanceAmount=" << AdvanceAmount
1496 << ", RemainingLoopCount=" << RemainingLoopCount
1497 << "\n");
1498 return;
1499 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1500 RemainingLoopCount = readULEB128() - 1;
1501 AdvanceAmount = readULEB128() + PointerSize;
1502 DEBUG_WITH_TYPE(
1503 "mach-o-rebase",
1504 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1505 << format("SegmentOffset=0x%06X", SegmentOffset)
1506 << ", AdvanceAmount=" << AdvanceAmount
1507 << ", RemainingLoopCount=" << RemainingLoopCount
1508 << "\n");
1509 return;
1510 default:
1511 Malformed = true;
1512 }
1513 }
1514 }
1515
readULEB128()1516 uint64_t MachORebaseEntry::readULEB128() {
1517 unsigned Count;
1518 uint64_t Result = decodeULEB128(Ptr, &Count);
1519 Ptr += Count;
1520 if (Ptr > Opcodes.end()) {
1521 Ptr = Opcodes.end();
1522 Malformed = true;
1523 }
1524 return Result;
1525 }
1526
segmentIndex() const1527 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1528
segmentOffset() const1529 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1530
typeName() const1531 StringRef MachORebaseEntry::typeName() const {
1532 switch (RebaseType) {
1533 case MachO::REBASE_TYPE_POINTER:
1534 return "pointer";
1535 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1536 return "text abs32";
1537 case MachO::REBASE_TYPE_TEXT_PCREL32:
1538 return "text rel32";
1539 }
1540 return "unknown";
1541 }
1542
operator ==(const MachORebaseEntry & Other) const1543 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1544 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1545 return (Ptr == Other.Ptr) &&
1546 (RemainingLoopCount == Other.RemainingLoopCount) &&
1547 (Done == Other.Done);
1548 }
1549
1550 iterator_range<rebase_iterator>
rebaseTable(ArrayRef<uint8_t> Opcodes,bool is64)1551 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1552 MachORebaseEntry Start(Opcodes, is64);
1553 Start.moveToFirst();
1554
1555 MachORebaseEntry Finish(Opcodes, is64);
1556 Finish.moveToEnd();
1557
1558 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1559 rebase_iterator(Finish));
1560 }
1561
rebaseTable() const1562 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1563 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1564 }
1565
1566
MachOBindEntry(ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)1567 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1568 Kind BK)
1569 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1570 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1571 BindType(0), PointerSize(is64Bit ? 8 : 4),
1572 TableKind(BK), Malformed(false), Done(false) {}
1573
moveToFirst()1574 void MachOBindEntry::moveToFirst() {
1575 Ptr = Opcodes.begin();
1576 moveNext();
1577 }
1578
moveToEnd()1579 void MachOBindEntry::moveToEnd() {
1580 Ptr = Opcodes.end();
1581 RemainingLoopCount = 0;
1582 Done = true;
1583 }
1584
moveNext()1585 void MachOBindEntry::moveNext() {
1586 // If in the middle of some loop, move to next binding in loop.
1587 SegmentOffset += AdvanceAmount;
1588 if (RemainingLoopCount) {
1589 --RemainingLoopCount;
1590 return;
1591 }
1592 if (Ptr == Opcodes.end()) {
1593 Done = true;
1594 return;
1595 }
1596 bool More = true;
1597 while (More && !Malformed) {
1598 // Parse next opcode and set up next loop.
1599 uint8_t Byte = *Ptr++;
1600 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1601 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1602 int8_t SignExtended;
1603 const uint8_t *SymStart;
1604 switch (Opcode) {
1605 case MachO::BIND_OPCODE_DONE:
1606 if (TableKind == Kind::Lazy) {
1607 // Lazying bindings have a DONE opcode between entries. Need to ignore
1608 // it to advance to next entry. But need not if this is last entry.
1609 bool NotLastEntry = false;
1610 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1611 if (*P) {
1612 NotLastEntry = true;
1613 }
1614 }
1615 if (NotLastEntry)
1616 break;
1617 }
1618 More = false;
1619 Done = true;
1620 moveToEnd();
1621 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1622 break;
1623 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1624 Ordinal = ImmValue;
1625 DEBUG_WITH_TYPE(
1626 "mach-o-bind",
1627 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1628 << "Ordinal=" << Ordinal << "\n");
1629 break;
1630 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1631 Ordinal = readULEB128();
1632 DEBUG_WITH_TYPE(
1633 "mach-o-bind",
1634 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1635 << "Ordinal=" << Ordinal << "\n");
1636 break;
1637 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1638 if (ImmValue) {
1639 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1640 Ordinal = SignExtended;
1641 } else
1642 Ordinal = 0;
1643 DEBUG_WITH_TYPE(
1644 "mach-o-bind",
1645 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1646 << "Ordinal=" << Ordinal << "\n");
1647 break;
1648 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1649 Flags = ImmValue;
1650 SymStart = Ptr;
1651 while (*Ptr) {
1652 ++Ptr;
1653 }
1654 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1655 Ptr-SymStart);
1656 ++Ptr;
1657 DEBUG_WITH_TYPE(
1658 "mach-o-bind",
1659 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1660 << "SymbolName=" << SymbolName << "\n");
1661 if (TableKind == Kind::Weak) {
1662 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1663 return;
1664 }
1665 break;
1666 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1667 BindType = ImmValue;
1668 DEBUG_WITH_TYPE(
1669 "mach-o-bind",
1670 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1671 << "BindType=" << (int)BindType << "\n");
1672 break;
1673 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1674 Addend = readSLEB128();
1675 if (TableKind == Kind::Lazy)
1676 Malformed = true;
1677 DEBUG_WITH_TYPE(
1678 "mach-o-bind",
1679 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1680 << "Addend=" << Addend << "\n");
1681 break;
1682 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1683 SegmentIndex = ImmValue;
1684 SegmentOffset = readULEB128();
1685 DEBUG_WITH_TYPE(
1686 "mach-o-bind",
1687 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1688 << "SegmentIndex=" << SegmentIndex << ", "
1689 << format("SegmentOffset=0x%06X", SegmentOffset)
1690 << "\n");
1691 break;
1692 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1693 SegmentOffset += readULEB128();
1694 DEBUG_WITH_TYPE("mach-o-bind",
1695 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1696 << format("SegmentOffset=0x%06X",
1697 SegmentOffset) << "\n");
1698 break;
1699 case MachO::BIND_OPCODE_DO_BIND:
1700 AdvanceAmount = PointerSize;
1701 RemainingLoopCount = 0;
1702 DEBUG_WITH_TYPE("mach-o-bind",
1703 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1704 << format("SegmentOffset=0x%06X",
1705 SegmentOffset) << "\n");
1706 return;
1707 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1708 AdvanceAmount = readULEB128() + PointerSize;
1709 RemainingLoopCount = 0;
1710 if (TableKind == Kind::Lazy)
1711 Malformed = true;
1712 DEBUG_WITH_TYPE(
1713 "mach-o-bind",
1714 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1715 << format("SegmentOffset=0x%06X", SegmentOffset)
1716 << ", AdvanceAmount=" << AdvanceAmount
1717 << ", RemainingLoopCount=" << RemainingLoopCount
1718 << "\n");
1719 return;
1720 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1721 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1722 RemainingLoopCount = 0;
1723 if (TableKind == Kind::Lazy)
1724 Malformed = true;
1725 DEBUG_WITH_TYPE("mach-o-bind",
1726 llvm::dbgs()
1727 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1728 << format("SegmentOffset=0x%06X",
1729 SegmentOffset) << "\n");
1730 return;
1731 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1732 RemainingLoopCount = readULEB128() - 1;
1733 AdvanceAmount = readULEB128() + PointerSize;
1734 if (TableKind == Kind::Lazy)
1735 Malformed = true;
1736 DEBUG_WITH_TYPE(
1737 "mach-o-bind",
1738 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1739 << format("SegmentOffset=0x%06X", SegmentOffset)
1740 << ", AdvanceAmount=" << AdvanceAmount
1741 << ", RemainingLoopCount=" << RemainingLoopCount
1742 << "\n");
1743 return;
1744 default:
1745 Malformed = true;
1746 }
1747 }
1748 }
1749
readULEB128()1750 uint64_t MachOBindEntry::readULEB128() {
1751 unsigned Count;
1752 uint64_t Result = decodeULEB128(Ptr, &Count);
1753 Ptr += Count;
1754 if (Ptr > Opcodes.end()) {
1755 Ptr = Opcodes.end();
1756 Malformed = true;
1757 }
1758 return Result;
1759 }
1760
readSLEB128()1761 int64_t MachOBindEntry::readSLEB128() {
1762 unsigned Count;
1763 int64_t Result = decodeSLEB128(Ptr, &Count);
1764 Ptr += Count;
1765 if (Ptr > Opcodes.end()) {
1766 Ptr = Opcodes.end();
1767 Malformed = true;
1768 }
1769 return Result;
1770 }
1771
1772
segmentIndex() const1773 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1774
segmentOffset() const1775 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1776
typeName() const1777 StringRef MachOBindEntry::typeName() const {
1778 switch (BindType) {
1779 case MachO::BIND_TYPE_POINTER:
1780 return "pointer";
1781 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1782 return "text abs32";
1783 case MachO::BIND_TYPE_TEXT_PCREL32:
1784 return "text rel32";
1785 }
1786 return "unknown";
1787 }
1788
symbolName() const1789 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1790
addend() const1791 int64_t MachOBindEntry::addend() const { return Addend; }
1792
flags() const1793 uint32_t MachOBindEntry::flags() const { return Flags; }
1794
ordinal() const1795 int MachOBindEntry::ordinal() const { return Ordinal; }
1796
operator ==(const MachOBindEntry & Other) const1797 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1798 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1799 return (Ptr == Other.Ptr) &&
1800 (RemainingLoopCount == Other.RemainingLoopCount) &&
1801 (Done == Other.Done);
1802 }
1803
1804 iterator_range<bind_iterator>
bindTable(ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)1805 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1806 MachOBindEntry::Kind BKind) {
1807 MachOBindEntry Start(Opcodes, is64, BKind);
1808 Start.moveToFirst();
1809
1810 MachOBindEntry Finish(Opcodes, is64, BKind);
1811 Finish.moveToEnd();
1812
1813 return iterator_range<bind_iterator>(bind_iterator(Start),
1814 bind_iterator(Finish));
1815 }
1816
bindTable() const1817 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1818 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1819 MachOBindEntry::Kind::Regular);
1820 }
1821
lazyBindTable() const1822 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1823 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1824 MachOBindEntry::Kind::Lazy);
1825 }
1826
weakBindTable() const1827 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1828 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1829 MachOBindEntry::Kind::Weak);
1830 }
1831
1832 MachOObjectFile::load_command_iterator
begin_load_commands() const1833 MachOObjectFile::begin_load_commands() const {
1834 return LoadCommands.begin();
1835 }
1836
1837 MachOObjectFile::load_command_iterator
end_load_commands() const1838 MachOObjectFile::end_load_commands() const {
1839 return LoadCommands.end();
1840 }
1841
1842 iterator_range<MachOObjectFile::load_command_iterator>
load_commands() const1843 MachOObjectFile::load_commands() const {
1844 return iterator_range<load_command_iterator>(begin_load_commands(),
1845 end_load_commands());
1846 }
1847
1848 StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const1849 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1850 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1851 return parseSegmentOrSectionName(Raw.data());
1852 }
1853
1854 ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const1855 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1856 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1857 const section_base *Base =
1858 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1859 return makeArrayRef(Base->sectname);
1860 }
1861
1862 ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const1863 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1864 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1865 const section_base *Base =
1866 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1867 return makeArrayRef(Base->segname);
1868 }
1869
1870 bool
isRelocationScattered(const MachO::any_relocation_info & RE) const1871 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1872 const {
1873 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1874 return false;
1875 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1876 }
1877
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const1878 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1879 const MachO::any_relocation_info &RE) const {
1880 if (isLittleEndian())
1881 return RE.r_word1 & 0xffffff;
1882 return RE.r_word1 >> 8;
1883 }
1884
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const1885 bool MachOObjectFile::getPlainRelocationExternal(
1886 const MachO::any_relocation_info &RE) const {
1887 if (isLittleEndian())
1888 return (RE.r_word1 >> 27) & 1;
1889 return (RE.r_word1 >> 4) & 1;
1890 }
1891
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const1892 bool MachOObjectFile::getScatteredRelocationScattered(
1893 const MachO::any_relocation_info &RE) const {
1894 return RE.r_word0 >> 31;
1895 }
1896
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const1897 uint32_t MachOObjectFile::getScatteredRelocationValue(
1898 const MachO::any_relocation_info &RE) const {
1899 return RE.r_word1;
1900 }
1901
getScatteredRelocationType(const MachO::any_relocation_info & RE) const1902 uint32_t MachOObjectFile::getScatteredRelocationType(
1903 const MachO::any_relocation_info &RE) const {
1904 return (RE.r_word0 >> 24) & 0xf;
1905 }
1906
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const1907 unsigned MachOObjectFile::getAnyRelocationAddress(
1908 const MachO::any_relocation_info &RE) const {
1909 if (isRelocationScattered(RE))
1910 return getScatteredRelocationAddress(RE);
1911 return getPlainRelocationAddress(RE);
1912 }
1913
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const1914 unsigned MachOObjectFile::getAnyRelocationPCRel(
1915 const MachO::any_relocation_info &RE) const {
1916 if (isRelocationScattered(RE))
1917 return getScatteredRelocationPCRel(this, RE);
1918 return getPlainRelocationPCRel(this, RE);
1919 }
1920
getAnyRelocationLength(const MachO::any_relocation_info & RE) const1921 unsigned MachOObjectFile::getAnyRelocationLength(
1922 const MachO::any_relocation_info &RE) const {
1923 if (isRelocationScattered(RE))
1924 return getScatteredRelocationLength(RE);
1925 return getPlainRelocationLength(this, RE);
1926 }
1927
1928 unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const1929 MachOObjectFile::getAnyRelocationType(
1930 const MachO::any_relocation_info &RE) const {
1931 if (isRelocationScattered(RE))
1932 return getScatteredRelocationType(RE);
1933 return getPlainRelocationType(this, RE);
1934 }
1935
1936 SectionRef
getAnyRelocationSection(const MachO::any_relocation_info & RE) const1937 MachOObjectFile::getAnyRelocationSection(
1938 const MachO::any_relocation_info &RE) const {
1939 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1940 return *section_end();
1941 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1942 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1943 return *section_end();
1944 DataRefImpl DRI;
1945 DRI.d.a = SecNum - 1;
1946 return SectionRef(DRI, this);
1947 }
1948
getSection(DataRefImpl DRI) const1949 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1950 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1951 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1952 }
1953
getSection64(DataRefImpl DRI) const1954 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1955 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1956 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1957 }
1958
getSection(const LoadCommandInfo & L,unsigned Index) const1959 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1960 unsigned Index) const {
1961 const char *Sec = getSectionPtr(this, L, Index);
1962 return getStruct<MachO::section>(this, Sec);
1963 }
1964
getSection64(const LoadCommandInfo & L,unsigned Index) const1965 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1966 unsigned Index) const {
1967 const char *Sec = getSectionPtr(this, L, Index);
1968 return getStruct<MachO::section_64>(this, Sec);
1969 }
1970
1971 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const1972 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1973 const char *P = reinterpret_cast<const char *>(DRI.p);
1974 return getStruct<MachO::nlist>(this, P);
1975 }
1976
1977 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const1978 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1979 const char *P = reinterpret_cast<const char *>(DRI.p);
1980 return getStruct<MachO::nlist_64>(this, P);
1981 }
1982
1983 MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const1984 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1985 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1986 }
1987
1988 MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const1989 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1990 return getStruct<MachO::segment_command>(this, L.Ptr);
1991 }
1992
1993 MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const1994 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1995 return getStruct<MachO::segment_command_64>(this, L.Ptr);
1996 }
1997
1998 MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const1999 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2000 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2001 }
2002
2003 MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const2004 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2005 return getStruct<MachO::version_min_command>(this, L.Ptr);
2006 }
2007
2008 MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const2009 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2010 return getStruct<MachO::dylib_command>(this, L.Ptr);
2011 }
2012
2013 MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const2014 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2015 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2016 }
2017
2018 MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const2019 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2020 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2021 }
2022
2023 MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const2024 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2025 return getStruct<MachO::uuid_command>(this, L.Ptr);
2026 }
2027
2028 MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const2029 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2030 return getStruct<MachO::rpath_command>(this, L.Ptr);
2031 }
2032
2033 MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const2034 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2035 return getStruct<MachO::source_version_command>(this, L.Ptr);
2036 }
2037
2038 MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const2039 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2040 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2041 }
2042
2043 MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const2044 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2045 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2046 }
2047
2048 MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const2049 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2050 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2051 }
2052
2053 MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const2054 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2055 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2056 }
2057
2058 MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const2059 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2060 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2061 }
2062
2063 MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const2064 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2065 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2066 }
2067
2068 MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const2069 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2070 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2071 }
2072
2073 MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const2074 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2075 return getStruct<MachO::routines_command>(this, L.Ptr);
2076 }
2077
2078 MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const2079 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2080 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2081 }
2082
2083 MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const2084 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2085 return getStruct<MachO::thread_command>(this, L.Ptr);
2086 }
2087
2088 MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const2089 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2090 DataRefImpl Sec;
2091 Sec.d.a = Rel.d.a;
2092 uint32_t Offset;
2093 if (is64Bit()) {
2094 MachO::section_64 Sect = getSection64(Sec);
2095 Offset = Sect.reloff;
2096 } else {
2097 MachO::section Sect = getSection(Sec);
2098 Offset = Sect.reloff;
2099 }
2100
2101 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2102 getPtr(this, Offset)) + Rel.d.b;
2103 return getStruct<MachO::any_relocation_info>(
2104 this, reinterpret_cast<const char *>(P));
2105 }
2106
2107 MachO::data_in_code_entry
getDice(DataRefImpl Rel) const2108 MachOObjectFile::getDice(DataRefImpl Rel) const {
2109 const char *P = reinterpret_cast<const char *>(Rel.p);
2110 return getStruct<MachO::data_in_code_entry>(this, P);
2111 }
2112
getHeader() const2113 const MachO::mach_header &MachOObjectFile::getHeader() const {
2114 return Header;
2115 }
2116
getHeader64() const2117 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2118 assert(is64Bit());
2119 return Header64;
2120 }
2121
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const2122 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2123 const MachO::dysymtab_command &DLC,
2124 unsigned Index) const {
2125 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2126 return getStruct<uint32_t>(this, getPtr(this, Offset));
2127 }
2128
2129 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const2130 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2131 unsigned Index) const {
2132 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2133 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2134 }
2135
getSymtabLoadCommand() const2136 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2137 if (SymtabLoadCmd)
2138 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2139
2140 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2141 MachO::symtab_command Cmd;
2142 Cmd.cmd = MachO::LC_SYMTAB;
2143 Cmd.cmdsize = sizeof(MachO::symtab_command);
2144 Cmd.symoff = 0;
2145 Cmd.nsyms = 0;
2146 Cmd.stroff = 0;
2147 Cmd.strsize = 0;
2148 return Cmd;
2149 }
2150
getDysymtabLoadCommand() const2151 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2152 if (DysymtabLoadCmd)
2153 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2154
2155 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2156 MachO::dysymtab_command Cmd;
2157 Cmd.cmd = MachO::LC_DYSYMTAB;
2158 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2159 Cmd.ilocalsym = 0;
2160 Cmd.nlocalsym = 0;
2161 Cmd.iextdefsym = 0;
2162 Cmd.nextdefsym = 0;
2163 Cmd.iundefsym = 0;
2164 Cmd.nundefsym = 0;
2165 Cmd.tocoff = 0;
2166 Cmd.ntoc = 0;
2167 Cmd.modtaboff = 0;
2168 Cmd.nmodtab = 0;
2169 Cmd.extrefsymoff = 0;
2170 Cmd.nextrefsyms = 0;
2171 Cmd.indirectsymoff = 0;
2172 Cmd.nindirectsyms = 0;
2173 Cmd.extreloff = 0;
2174 Cmd.nextrel = 0;
2175 Cmd.locreloff = 0;
2176 Cmd.nlocrel = 0;
2177 return Cmd;
2178 }
2179
2180 MachO::linkedit_data_command
getDataInCodeLoadCommand() const2181 MachOObjectFile::getDataInCodeLoadCommand() const {
2182 if (DataInCodeLoadCmd)
2183 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2184
2185 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2186 MachO::linkedit_data_command Cmd;
2187 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2188 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2189 Cmd.dataoff = 0;
2190 Cmd.datasize = 0;
2191 return Cmd;
2192 }
2193
2194 MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const2195 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2196 if (LinkOptHintsLoadCmd)
2197 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2198
2199 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2200 // fields.
2201 MachO::linkedit_data_command Cmd;
2202 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2203 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2204 Cmd.dataoff = 0;
2205 Cmd.datasize = 0;
2206 return Cmd;
2207 }
2208
getDyldInfoRebaseOpcodes() const2209 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2210 if (!DyldInfoLoadCmd)
2211 return ArrayRef<uint8_t>();
2212
2213 MachO::dyld_info_command DyldInfo
2214 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2215 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2216 getPtr(this, DyldInfo.rebase_off));
2217 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2218 }
2219
getDyldInfoBindOpcodes() const2220 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2221 if (!DyldInfoLoadCmd)
2222 return ArrayRef<uint8_t>();
2223
2224 MachO::dyld_info_command DyldInfo
2225 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2226 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2227 getPtr(this, DyldInfo.bind_off));
2228 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2229 }
2230
getDyldInfoWeakBindOpcodes() const2231 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2232 if (!DyldInfoLoadCmd)
2233 return ArrayRef<uint8_t>();
2234
2235 MachO::dyld_info_command DyldInfo
2236 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2237 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2238 getPtr(this, DyldInfo.weak_bind_off));
2239 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2240 }
2241
getDyldInfoLazyBindOpcodes() const2242 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2243 if (!DyldInfoLoadCmd)
2244 return ArrayRef<uint8_t>();
2245
2246 MachO::dyld_info_command DyldInfo
2247 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2248 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2249 getPtr(this, DyldInfo.lazy_bind_off));
2250 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2251 }
2252
getDyldInfoExportsTrie() const2253 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2254 if (!DyldInfoLoadCmd)
2255 return ArrayRef<uint8_t>();
2256
2257 MachO::dyld_info_command DyldInfo
2258 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2259 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2260 getPtr(this, DyldInfo.export_off));
2261 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2262 }
2263
getUuid() const2264 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2265 if (!UuidLoadCmd)
2266 return ArrayRef<uint8_t>();
2267 // Returning a pointer is fine as uuid doesn't need endian swapping.
2268 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2269 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2270 }
2271
getStringTableData() const2272 StringRef MachOObjectFile::getStringTableData() const {
2273 MachO::symtab_command S = getSymtabLoadCommand();
2274 return getData().substr(S.stroff, S.strsize);
2275 }
2276
is64Bit() const2277 bool MachOObjectFile::is64Bit() const {
2278 return getType() == getMachOType(false, true) ||
2279 getType() == getMachOType(true, true);
2280 }
2281
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const2282 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2283 SmallVectorImpl<uint64_t> &Out) const {
2284 DataExtractor extractor(ObjectFile::getData(), true, 0);
2285
2286 uint32_t offset = Index;
2287 uint64_t data = 0;
2288 while (uint64_t delta = extractor.getULEB128(&offset)) {
2289 data += delta;
2290 Out.push_back(data);
2291 }
2292 }
2293
isRelocatableObject() const2294 bool MachOObjectFile::isRelocatableObject() const {
2295 return getHeader().filetype == MachO::MH_OBJECT;
2296 }
2297
2298 ErrorOr<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer)2299 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2300 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2301 std::error_code EC;
2302 std::unique_ptr<MachOObjectFile> Ret;
2303 if (Magic == "\xFE\xED\xFA\xCE")
2304 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2305 else if (Magic == "\xCE\xFA\xED\xFE")
2306 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2307 else if (Magic == "\xFE\xED\xFA\xCF")
2308 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2309 else if (Magic == "\xCF\xFA\xED\xFE")
2310 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2311 else
2312 return object_error::parse_failed;
2313
2314 if (EC)
2315 return EC;
2316 return std::move(Ret);
2317 }
2318
2319