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 section_iterator Sec = *getSymbolSection(Symb);
405 if (Sec->isData() || Sec->isBSS())
406 return SymbolRef::ST_Data;
407 return SymbolRef::ST_Function;
408 }
409 return SymbolRef::ST_Other;
410 }
411
getSymbolFlags(DataRefImpl DRI) const412 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
414
415 uint8_t MachOType = Entry.n_type;
416 uint16_t MachOFlags = Entry.n_desc;
417
418 uint32_t Result = SymbolRef::SF_None;
419
420 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
421 Result |= SymbolRef::SF_Indirect;
422
423 if (MachOType & MachO::N_STAB)
424 Result |= SymbolRef::SF_FormatSpecific;
425
426 if (MachOType & MachO::N_EXT) {
427 Result |= SymbolRef::SF_Global;
428 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
429 if (getNValue(DRI))
430 Result |= SymbolRef::SF_Common;
431 else
432 Result |= SymbolRef::SF_Undefined;
433 }
434
435 if (!(MachOType & MachO::N_PEXT))
436 Result |= SymbolRef::SF_Exported;
437 }
438
439 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
440 Result |= SymbolRef::SF_Weak;
441
442 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
443 Result |= SymbolRef::SF_Thumb;
444
445 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
446 Result |= SymbolRef::SF_Absolute;
447
448 return Result;
449 }
450
451 ErrorOr<section_iterator>
getSymbolSection(DataRefImpl Symb) const452 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
453 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
454 uint8_t index = Entry.n_sect;
455
456 if (index == 0)
457 return section_end();
458 DataRefImpl DRI;
459 DRI.d.a = index - 1;
460 if (DRI.d.a >= Sections.size())
461 report_fatal_error("getSymbolSection: Invalid section index.");
462 return section_iterator(SectionRef(DRI, this));
463 }
464
getSymbolSectionID(SymbolRef Sym) const465 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
466 MachO::nlist_base Entry =
467 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
468 return Entry.n_sect - 1;
469 }
470
moveSectionNext(DataRefImpl & Sec) const471 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
472 Sec.d.a++;
473 }
474
getSectionName(DataRefImpl Sec,StringRef & Result) const475 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
476 StringRef &Result) const {
477 ArrayRef<char> Raw = getSectionRawName(Sec);
478 Result = parseSegmentOrSectionName(Raw.data());
479 return std::error_code();
480 }
481
getSectionAddress(DataRefImpl Sec) const482 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
483 if (is64Bit())
484 return getSection64(Sec).addr;
485 return getSection(Sec).addr;
486 }
487
getSectionSize(DataRefImpl Sec) const488 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
489 // In the case if a malformed Mach-O file where the section offset is past
490 // the end of the file or some part of the section size is past the end of
491 // the file return a size of zero or a size that covers the rest of the file
492 // but does not extend past the end of the file.
493 uint32_t SectOffset, SectType;
494 uint64_t SectSize;
495
496 if (is64Bit()) {
497 MachO::section_64 Sect = getSection64(Sec);
498 SectOffset = Sect.offset;
499 SectSize = Sect.size;
500 SectType = Sect.flags & MachO::SECTION_TYPE;
501 } else {
502 MachO::section Sect = getSection(Sec);
503 SectOffset = Sect.offset;
504 SectSize = Sect.size;
505 SectType = Sect.flags & MachO::SECTION_TYPE;
506 }
507 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
508 return SectSize;
509 uint64_t FileSize = getData().size();
510 if (SectOffset > FileSize)
511 return 0;
512 if (FileSize - SectOffset < SectSize)
513 return FileSize - SectOffset;
514 return SectSize;
515 }
516
getSectionContents(DataRefImpl Sec,StringRef & Res) const517 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
518 StringRef &Res) const {
519 uint32_t Offset;
520 uint64_t Size;
521
522 if (is64Bit()) {
523 MachO::section_64 Sect = getSection64(Sec);
524 Offset = Sect.offset;
525 Size = Sect.size;
526 } else {
527 MachO::section Sect = getSection(Sec);
528 Offset = Sect.offset;
529 Size = Sect.size;
530 }
531
532 Res = this->getData().substr(Offset, Size);
533 return std::error_code();
534 }
535
getSectionAlignment(DataRefImpl Sec) const536 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
537 uint32_t Align;
538 if (is64Bit()) {
539 MachO::section_64 Sect = getSection64(Sec);
540 Align = Sect.align;
541 } else {
542 MachO::section Sect = getSection(Sec);
543 Align = Sect.align;
544 }
545
546 return uint64_t(1) << Align;
547 }
548
isSectionText(DataRefImpl Sec) const549 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
550 uint32_t Flags = getSectionFlags(this, Sec);
551 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
552 }
553
isSectionData(DataRefImpl Sec) const554 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
555 uint32_t Flags = getSectionFlags(this, Sec);
556 unsigned SectionType = Flags & MachO::SECTION_TYPE;
557 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
558 !(SectionType == MachO::S_ZEROFILL ||
559 SectionType == MachO::S_GB_ZEROFILL);
560 }
561
isSectionBSS(DataRefImpl Sec) const562 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
563 uint32_t Flags = getSectionFlags(this, Sec);
564 unsigned SectionType = Flags & MachO::SECTION_TYPE;
565 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
566 (SectionType == MachO::S_ZEROFILL ||
567 SectionType == MachO::S_GB_ZEROFILL);
568 }
569
getSectionID(SectionRef Sec) const570 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
571 return Sec.getRawDataRefImpl().d.a;
572 }
573
isSectionVirtual(DataRefImpl Sec) const574 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
575 // FIXME: Unimplemented.
576 return false;
577 }
578
section_rel_begin(DataRefImpl Sec) const579 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
580 DataRefImpl Ret;
581 Ret.d.a = Sec.d.a;
582 Ret.d.b = 0;
583 return relocation_iterator(RelocationRef(Ret, this));
584 }
585
586 relocation_iterator
section_rel_end(DataRefImpl Sec) const587 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
588 uint32_t Num;
589 if (is64Bit()) {
590 MachO::section_64 Sect = getSection64(Sec);
591 Num = Sect.nreloc;
592 } else {
593 MachO::section Sect = getSection(Sec);
594 Num = Sect.nreloc;
595 }
596
597 DataRefImpl Ret;
598 Ret.d.a = Sec.d.a;
599 Ret.d.b = Num;
600 return relocation_iterator(RelocationRef(Ret, this));
601 }
602
moveRelocationNext(DataRefImpl & Rel) const603 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
604 ++Rel.d.b;
605 }
606
getRelocationOffset(DataRefImpl Rel) const607 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
608 assert(getHeader().filetype == MachO::MH_OBJECT &&
609 "Only implemented for MH_OBJECT");
610 MachO::any_relocation_info RE = getRelocation(Rel);
611 return getAnyRelocationAddress(RE);
612 }
613
614 symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const615 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
616 MachO::any_relocation_info RE = getRelocation(Rel);
617 if (isRelocationScattered(RE))
618 return symbol_end();
619
620 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
621 bool isExtern = getPlainRelocationExternal(RE);
622 if (!isExtern)
623 return symbol_end();
624
625 MachO::symtab_command S = getSymtabLoadCommand();
626 unsigned SymbolTableEntrySize = is64Bit() ?
627 sizeof(MachO::nlist_64) :
628 sizeof(MachO::nlist);
629 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
630 DataRefImpl Sym;
631 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
632 return symbol_iterator(SymbolRef(Sym, this));
633 }
634
635 section_iterator
getRelocationSection(DataRefImpl Rel) const636 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
637 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
638 }
639
getRelocationType(DataRefImpl Rel) const640 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
641 MachO::any_relocation_info RE = getRelocation(Rel);
642 return getAnyRelocationType(RE);
643 }
644
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const645 void MachOObjectFile::getRelocationTypeName(
646 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
647 StringRef res;
648 uint64_t RType = getRelocationType(Rel);
649
650 unsigned Arch = this->getArch();
651
652 switch (Arch) {
653 case Triple::x86: {
654 static const char *const Table[] = {
655 "GENERIC_RELOC_VANILLA",
656 "GENERIC_RELOC_PAIR",
657 "GENERIC_RELOC_SECTDIFF",
658 "GENERIC_RELOC_PB_LA_PTR",
659 "GENERIC_RELOC_LOCAL_SECTDIFF",
660 "GENERIC_RELOC_TLV" };
661
662 if (RType > 5)
663 res = "Unknown";
664 else
665 res = Table[RType];
666 break;
667 }
668 case Triple::x86_64: {
669 static const char *const Table[] = {
670 "X86_64_RELOC_UNSIGNED",
671 "X86_64_RELOC_SIGNED",
672 "X86_64_RELOC_BRANCH",
673 "X86_64_RELOC_GOT_LOAD",
674 "X86_64_RELOC_GOT",
675 "X86_64_RELOC_SUBTRACTOR",
676 "X86_64_RELOC_SIGNED_1",
677 "X86_64_RELOC_SIGNED_2",
678 "X86_64_RELOC_SIGNED_4",
679 "X86_64_RELOC_TLV" };
680
681 if (RType > 9)
682 res = "Unknown";
683 else
684 res = Table[RType];
685 break;
686 }
687 case Triple::arm: {
688 static const char *const Table[] = {
689 "ARM_RELOC_VANILLA",
690 "ARM_RELOC_PAIR",
691 "ARM_RELOC_SECTDIFF",
692 "ARM_RELOC_LOCAL_SECTDIFF",
693 "ARM_RELOC_PB_LA_PTR",
694 "ARM_RELOC_BR24",
695 "ARM_THUMB_RELOC_BR22",
696 "ARM_THUMB_32BIT_BRANCH",
697 "ARM_RELOC_HALF",
698 "ARM_RELOC_HALF_SECTDIFF" };
699
700 if (RType > 9)
701 res = "Unknown";
702 else
703 res = Table[RType];
704 break;
705 }
706 case Triple::aarch64: {
707 static const char *const Table[] = {
708 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
709 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
710 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
711 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
712 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
713 "ARM64_RELOC_ADDEND"
714 };
715
716 if (RType >= array_lengthof(Table))
717 res = "Unknown";
718 else
719 res = Table[RType];
720 break;
721 }
722 case Triple::ppc: {
723 static const char *const Table[] = {
724 "PPC_RELOC_VANILLA",
725 "PPC_RELOC_PAIR",
726 "PPC_RELOC_BR14",
727 "PPC_RELOC_BR24",
728 "PPC_RELOC_HI16",
729 "PPC_RELOC_LO16",
730 "PPC_RELOC_HA16",
731 "PPC_RELOC_LO14",
732 "PPC_RELOC_SECTDIFF",
733 "PPC_RELOC_PB_LA_PTR",
734 "PPC_RELOC_HI16_SECTDIFF",
735 "PPC_RELOC_LO16_SECTDIFF",
736 "PPC_RELOC_HA16_SECTDIFF",
737 "PPC_RELOC_JBSR",
738 "PPC_RELOC_LO14_SECTDIFF",
739 "PPC_RELOC_LOCAL_SECTDIFF" };
740
741 if (RType > 15)
742 res = "Unknown";
743 else
744 res = Table[RType];
745 break;
746 }
747 case Triple::UnknownArch:
748 res = "Unknown";
749 break;
750 }
751 Result.append(res.begin(), res.end());
752 }
753
getRelocationLength(DataRefImpl Rel) const754 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
755 MachO::any_relocation_info RE = getRelocation(Rel);
756 return getAnyRelocationLength(RE);
757 }
758
759 //
760 // guessLibraryShortName() is passed a name of a dynamic library and returns a
761 // guess on what the short name is. Then name is returned as a substring of the
762 // StringRef Name passed in. The name of the dynamic library is recognized as
763 // a framework if it has one of the two following forms:
764 // Foo.framework/Versions/A/Foo
765 // Foo.framework/Foo
766 // Where A and Foo can be any string. And may contain a trailing suffix
767 // starting with an underbar. If the Name is recognized as a framework then
768 // isFramework is set to true else it is set to false. If the Name has a
769 // suffix then Suffix is set to the substring in Name that contains the suffix
770 // else it is set to a NULL StringRef.
771 //
772 // The Name of the dynamic library is recognized as a library name if it has
773 // one of the two following forms:
774 // libFoo.A.dylib
775 // libFoo.dylib
776 // The library may have a suffix trailing the name Foo of the form:
777 // libFoo_profile.A.dylib
778 // libFoo_profile.dylib
779 //
780 // The Name of the dynamic library is also recognized as a library name if it
781 // has the following form:
782 // Foo.qtx
783 //
784 // If the Name of the dynamic library is none of the forms above then a NULL
785 // StringRef is returned.
786 //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)787 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
788 bool &isFramework,
789 StringRef &Suffix) {
790 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
791 size_t a, b, c, d, Idx;
792
793 isFramework = false;
794 Suffix = StringRef();
795
796 // Pull off the last component and make Foo point to it
797 a = Name.rfind('/');
798 if (a == Name.npos || a == 0)
799 goto guess_library;
800 Foo = Name.slice(a+1, Name.npos);
801
802 // Look for a suffix starting with a '_'
803 Idx = Foo.rfind('_');
804 if (Idx != Foo.npos && Foo.size() >= 2) {
805 Suffix = Foo.slice(Idx, Foo.npos);
806 Foo = Foo.slice(0, Idx);
807 }
808
809 // First look for the form Foo.framework/Foo
810 b = Name.rfind('/', a);
811 if (b == Name.npos)
812 Idx = 0;
813 else
814 Idx = b+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 // Next look for the form Foo.framework/Versions/A/Foo
824 if (b == Name.npos)
825 goto guess_library;
826 c = Name.rfind('/', b);
827 if (c == Name.npos || c == 0)
828 goto guess_library;
829 V = Name.slice(c+1, Name.npos);
830 if (!V.startswith("Versions/"))
831 goto guess_library;
832 d = Name.rfind('/', c);
833 if (d == Name.npos)
834 Idx = 0;
835 else
836 Idx = d+1;
837 F = Name.slice(Idx, Idx + Foo.size());
838 DotFramework = Name.slice(Idx + Foo.size(),
839 Idx + Foo.size() + sizeof(".framework/")-1);
840 if (F == Foo && DotFramework == ".framework/") {
841 isFramework = true;
842 return Foo;
843 }
844
845 guess_library:
846 // pull off the suffix after the "." and make a point to it
847 a = Name.rfind('.');
848 if (a == Name.npos || a == 0)
849 return StringRef();
850 Dylib = Name.slice(a, Name.npos);
851 if (Dylib != ".dylib")
852 goto guess_qtx;
853
854 // First pull off the version letter for the form Foo.A.dylib if any.
855 if (a >= 3) {
856 Dot = Name.slice(a-2, a-1);
857 if (Dot == ".")
858 a = a - 2;
859 }
860
861 b = Name.rfind('/', a);
862 if (b == Name.npos)
863 b = 0;
864 else
865 b = b+1;
866 // ignore any suffix after an underbar like Foo_profile.A.dylib
867 Idx = Name.find('_', b);
868 if (Idx != Name.npos && Idx != b) {
869 Lib = Name.slice(b, Idx);
870 Suffix = Name.slice(Idx, a);
871 }
872 else
873 Lib = Name.slice(b, a);
874 // There are incorrect library names of the form:
875 // libATS.A_profile.dylib so check for these.
876 if (Lib.size() >= 3) {
877 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
878 if (Dot == ".")
879 Lib = Lib.slice(0, Lib.size()-2);
880 }
881 return Lib;
882
883 guess_qtx:
884 Qtx = Name.slice(a, Name.npos);
885 if (Qtx != ".qtx")
886 return StringRef();
887 b = Name.rfind('/', a);
888 if (b == Name.npos)
889 Lib = Name.slice(0, a);
890 else
891 Lib = Name.slice(b+1, a);
892 // There are library names of the form: QT.A.qtx so check for these.
893 if (Lib.size() >= 3) {
894 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
895 if (Dot == ".")
896 Lib = Lib.slice(0, Lib.size()-2);
897 }
898 return Lib;
899 }
900
901 // getLibraryShortNameByIndex() is used to get the short name of the library
902 // for an undefined symbol in a linked Mach-O binary that was linked with the
903 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
904 // It is passed the index (0 - based) of the library as translated from
905 // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const906 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
907 StringRef &Res) const {
908 if (Index >= Libraries.size())
909 return object_error::parse_failed;
910
911 // If the cache of LibrariesShortNames is not built up do that first for
912 // all the Libraries.
913 if (LibrariesShortNames.size() == 0) {
914 for (unsigned i = 0; i < Libraries.size(); i++) {
915 MachO::dylib_command D =
916 getStruct<MachO::dylib_command>(this, Libraries[i]);
917 if (D.dylib.name >= D.cmdsize)
918 return object_error::parse_failed;
919 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
920 StringRef Name = StringRef(P);
921 if (D.dylib.name+Name.size() >= D.cmdsize)
922 return object_error::parse_failed;
923 StringRef Suffix;
924 bool isFramework;
925 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
926 if (shortName.empty())
927 LibrariesShortNames.push_back(Name);
928 else
929 LibrariesShortNames.push_back(shortName);
930 }
931 }
932
933 Res = LibrariesShortNames[Index];
934 return std::error_code();
935 }
936
937 section_iterator
getRelocationRelocatedSection(relocation_iterator Rel) const938 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
939 DataRefImpl Sec;
940 Sec.d.a = Rel->getRawDataRefImpl().d.a;
941 return section_iterator(SectionRef(Sec, this));
942 }
943
symbol_begin_impl() const944 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
945 return getSymbolByIndex(0);
946 }
947
symbol_end_impl() const948 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
949 DataRefImpl DRI;
950 if (!SymtabLoadCmd)
951 return basic_symbol_iterator(SymbolRef(DRI, this));
952
953 MachO::symtab_command Symtab = getSymtabLoadCommand();
954 unsigned SymbolTableEntrySize = is64Bit() ?
955 sizeof(MachO::nlist_64) :
956 sizeof(MachO::nlist);
957 unsigned Offset = Symtab.symoff +
958 Symtab.nsyms * SymbolTableEntrySize;
959 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
960 return basic_symbol_iterator(SymbolRef(DRI, this));
961 }
962
getSymbolByIndex(unsigned Index) const963 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
964 DataRefImpl DRI;
965 if (!SymtabLoadCmd)
966 return basic_symbol_iterator(SymbolRef(DRI, this));
967
968 MachO::symtab_command Symtab = getSymtabLoadCommand();
969 if (Index >= Symtab.nsyms)
970 report_fatal_error("Requested symbol index is out of range.");
971 unsigned SymbolTableEntrySize =
972 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
973 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
974 DRI.p += Index * SymbolTableEntrySize;
975 return basic_symbol_iterator(SymbolRef(DRI, this));
976 }
977
section_begin() const978 section_iterator MachOObjectFile::section_begin() const {
979 DataRefImpl DRI;
980 return section_iterator(SectionRef(DRI, this));
981 }
982
section_end() const983 section_iterator MachOObjectFile::section_end() const {
984 DataRefImpl DRI;
985 DRI.d.a = Sections.size();
986 return section_iterator(SectionRef(DRI, this));
987 }
988
getBytesInAddress() const989 uint8_t MachOObjectFile::getBytesInAddress() const {
990 return is64Bit() ? 8 : 4;
991 }
992
getFileFormatName() const993 StringRef MachOObjectFile::getFileFormatName() const {
994 unsigned CPUType = getCPUType(this);
995 if (!is64Bit()) {
996 switch (CPUType) {
997 case llvm::MachO::CPU_TYPE_I386:
998 return "Mach-O 32-bit i386";
999 case llvm::MachO::CPU_TYPE_ARM:
1000 return "Mach-O arm";
1001 case llvm::MachO::CPU_TYPE_POWERPC:
1002 return "Mach-O 32-bit ppc";
1003 default:
1004 return "Mach-O 32-bit unknown";
1005 }
1006 }
1007
1008 switch (CPUType) {
1009 case llvm::MachO::CPU_TYPE_X86_64:
1010 return "Mach-O 64-bit x86-64";
1011 case llvm::MachO::CPU_TYPE_ARM64:
1012 return "Mach-O arm64";
1013 case llvm::MachO::CPU_TYPE_POWERPC64:
1014 return "Mach-O 64-bit ppc64";
1015 default:
1016 return "Mach-O 64-bit unknown";
1017 }
1018 }
1019
getArch(uint32_t CPUType)1020 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1021 switch (CPUType) {
1022 case llvm::MachO::CPU_TYPE_I386:
1023 return Triple::x86;
1024 case llvm::MachO::CPU_TYPE_X86_64:
1025 return Triple::x86_64;
1026 case llvm::MachO::CPU_TYPE_ARM:
1027 return Triple::arm;
1028 case llvm::MachO::CPU_TYPE_ARM64:
1029 return Triple::aarch64;
1030 case llvm::MachO::CPU_TYPE_POWERPC:
1031 return Triple::ppc;
1032 case llvm::MachO::CPU_TYPE_POWERPC64:
1033 return Triple::ppc64;
1034 default:
1035 return Triple::UnknownArch;
1036 }
1037 }
1038
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1039 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1040 const char **McpuDefault) {
1041 if (McpuDefault)
1042 *McpuDefault = nullptr;
1043
1044 switch (CPUType) {
1045 case MachO::CPU_TYPE_I386:
1046 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1047 case MachO::CPU_SUBTYPE_I386_ALL:
1048 return Triple("i386-apple-darwin");
1049 default:
1050 return Triple();
1051 }
1052 case MachO::CPU_TYPE_X86_64:
1053 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1054 case MachO::CPU_SUBTYPE_X86_64_ALL:
1055 return Triple("x86_64-apple-darwin");
1056 case MachO::CPU_SUBTYPE_X86_64_H:
1057 return Triple("x86_64h-apple-darwin");
1058 default:
1059 return Triple();
1060 }
1061 case MachO::CPU_TYPE_ARM:
1062 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1063 case MachO::CPU_SUBTYPE_ARM_V4T:
1064 return Triple("armv4t-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1066 return Triple("armv5e-apple-darwin");
1067 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1068 return Triple("xscale-apple-darwin");
1069 case MachO::CPU_SUBTYPE_ARM_V6:
1070 return Triple("armv6-apple-darwin");
1071 case MachO::CPU_SUBTYPE_ARM_V6M:
1072 if (McpuDefault)
1073 *McpuDefault = "cortex-m0";
1074 return Triple("armv6m-apple-darwin");
1075 case MachO::CPU_SUBTYPE_ARM_V7:
1076 return Triple("armv7-apple-darwin");
1077 case MachO::CPU_SUBTYPE_ARM_V7EM:
1078 if (McpuDefault)
1079 *McpuDefault = "cortex-m4";
1080 return Triple("armv7em-apple-darwin");
1081 case MachO::CPU_SUBTYPE_ARM_V7K:
1082 return Triple("armv7k-apple-darwin");
1083 case MachO::CPU_SUBTYPE_ARM_V7M:
1084 if (McpuDefault)
1085 *McpuDefault = "cortex-m3";
1086 return Triple("armv7m-apple-darwin");
1087 case MachO::CPU_SUBTYPE_ARM_V7S:
1088 return Triple("armv7s-apple-darwin");
1089 default:
1090 return Triple();
1091 }
1092 case MachO::CPU_TYPE_ARM64:
1093 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1094 case MachO::CPU_SUBTYPE_ARM64_ALL:
1095 return Triple("arm64-apple-darwin");
1096 default:
1097 return Triple();
1098 }
1099 case MachO::CPU_TYPE_POWERPC:
1100 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1101 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1102 return Triple("ppc-apple-darwin");
1103 default:
1104 return Triple();
1105 }
1106 case MachO::CPU_TYPE_POWERPC64:
1107 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1108 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1109 return Triple("ppc64-apple-darwin");
1110 default:
1111 return Triple();
1112 }
1113 default:
1114 return Triple();
1115 }
1116 }
1117
getThumbArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1118 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1119 const char **McpuDefault) {
1120 if (McpuDefault)
1121 *McpuDefault = nullptr;
1122
1123 switch (CPUType) {
1124 case MachO::CPU_TYPE_ARM:
1125 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1126 case MachO::CPU_SUBTYPE_ARM_V4T:
1127 return Triple("thumbv4t-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1129 return Triple("thumbv5e-apple-darwin");
1130 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1131 return Triple("xscale-apple-darwin");
1132 case MachO::CPU_SUBTYPE_ARM_V6:
1133 return Triple("thumbv6-apple-darwin");
1134 case MachO::CPU_SUBTYPE_ARM_V6M:
1135 if (McpuDefault)
1136 *McpuDefault = "cortex-m0";
1137 return Triple("thumbv6m-apple-darwin");
1138 case MachO::CPU_SUBTYPE_ARM_V7:
1139 return Triple("thumbv7-apple-darwin");
1140 case MachO::CPU_SUBTYPE_ARM_V7EM:
1141 if (McpuDefault)
1142 *McpuDefault = "cortex-m4";
1143 return Triple("thumbv7em-apple-darwin");
1144 case MachO::CPU_SUBTYPE_ARM_V7K:
1145 return Triple("thumbv7k-apple-darwin");
1146 case MachO::CPU_SUBTYPE_ARM_V7M:
1147 if (McpuDefault)
1148 *McpuDefault = "cortex-m3";
1149 return Triple("thumbv7m-apple-darwin");
1150 case MachO::CPU_SUBTYPE_ARM_V7S:
1151 return Triple("thumbv7s-apple-darwin");
1152 default:
1153 return Triple();
1154 }
1155 default:
1156 return Triple();
1157 }
1158 }
1159
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,Triple * ThumbTriple)1160 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1161 const char **McpuDefault, Triple *ThumbTriple) {
1162 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1163 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1164 McpuDefault);
1165 return T;
1166 }
1167
getHostArch()1168 Triple MachOObjectFile::getHostArch() {
1169 return Triple(sys::getDefaultTargetTriple());
1170 }
1171
isValidArch(StringRef ArchFlag)1172 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1173 return StringSwitch<bool>(ArchFlag)
1174 .Case("i386", true)
1175 .Case("x86_64", true)
1176 .Case("x86_64h", true)
1177 .Case("armv4t", true)
1178 .Case("arm", true)
1179 .Case("armv5e", true)
1180 .Case("armv6", true)
1181 .Case("armv6m", true)
1182 .Case("armv7", true)
1183 .Case("armv7em", true)
1184 .Case("armv7k", true)
1185 .Case("armv7m", true)
1186 .Case("armv7s", true)
1187 .Case("arm64", true)
1188 .Case("ppc", true)
1189 .Case("ppc64", true)
1190 .Default(false);
1191 }
1192
getArch() const1193 unsigned MachOObjectFile::getArch() const {
1194 return getArch(getCPUType(this));
1195 }
1196
getArch(const char ** McpuDefault,Triple * ThumbTriple) const1197 Triple MachOObjectFile::getArch(const char **McpuDefault,
1198 Triple *ThumbTriple) const {
1199 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1200 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1201 }
1202
section_rel_begin(unsigned Index) const1203 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1204 DataRefImpl DRI;
1205 DRI.d.a = Index;
1206 return section_rel_begin(DRI);
1207 }
1208
section_rel_end(unsigned Index) const1209 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1210 DataRefImpl DRI;
1211 DRI.d.a = Index;
1212 return section_rel_end(DRI);
1213 }
1214
begin_dices() const1215 dice_iterator MachOObjectFile::begin_dices() const {
1216 DataRefImpl DRI;
1217 if (!DataInCodeLoadCmd)
1218 return dice_iterator(DiceRef(DRI, this));
1219
1220 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1221 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1222 return dice_iterator(DiceRef(DRI, this));
1223 }
1224
end_dices() const1225 dice_iterator MachOObjectFile::end_dices() const {
1226 DataRefImpl DRI;
1227 if (!DataInCodeLoadCmd)
1228 return dice_iterator(DiceRef(DRI, this));
1229
1230 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1231 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1232 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1233 return dice_iterator(DiceRef(DRI, this));
1234 }
1235
ExportEntry(ArrayRef<uint8_t> T)1236 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1237 : Trie(T), Malformed(false), Done(false) {}
1238
moveToFirst()1239 void ExportEntry::moveToFirst() {
1240 pushNode(0);
1241 pushDownUntilBottom();
1242 }
1243
moveToEnd()1244 void ExportEntry::moveToEnd() {
1245 Stack.clear();
1246 Done = true;
1247 }
1248
operator ==(const ExportEntry & Other) const1249 bool ExportEntry::operator==(const ExportEntry &Other) const {
1250 // Common case, one at end, other iterating from begin.
1251 if (Done || Other.Done)
1252 return (Done == Other.Done);
1253 // Not equal if different stack sizes.
1254 if (Stack.size() != Other.Stack.size())
1255 return false;
1256 // Not equal if different cumulative strings.
1257 if (!CumulativeString.equals(Other.CumulativeString))
1258 return false;
1259 // Equal if all nodes in both stacks match.
1260 for (unsigned i=0; i < Stack.size(); ++i) {
1261 if (Stack[i].Start != Other.Stack[i].Start)
1262 return false;
1263 }
1264 return true;
1265 }
1266
readULEB128(const uint8_t * & Ptr)1267 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1268 unsigned Count;
1269 uint64_t Result = decodeULEB128(Ptr, &Count);
1270 Ptr += Count;
1271 if (Ptr > Trie.end()) {
1272 Ptr = Trie.end();
1273 Malformed = true;
1274 }
1275 return Result;
1276 }
1277
name() const1278 StringRef ExportEntry::name() const {
1279 return CumulativeString;
1280 }
1281
flags() const1282 uint64_t ExportEntry::flags() const {
1283 return Stack.back().Flags;
1284 }
1285
address() const1286 uint64_t ExportEntry::address() const {
1287 return Stack.back().Address;
1288 }
1289
other() const1290 uint64_t ExportEntry::other() const {
1291 return Stack.back().Other;
1292 }
1293
otherName() const1294 StringRef ExportEntry::otherName() const {
1295 const char* ImportName = Stack.back().ImportName;
1296 if (ImportName)
1297 return StringRef(ImportName);
1298 return StringRef();
1299 }
1300
nodeOffset() const1301 uint32_t ExportEntry::nodeOffset() const {
1302 return Stack.back().Start - Trie.begin();
1303 }
1304
NodeState(const uint8_t * Ptr)1305 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1306 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1307 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1308 ParentStringLength(0), IsExportNode(false) {}
1309
pushNode(uint64_t offset)1310 void ExportEntry::pushNode(uint64_t offset) {
1311 const uint8_t *Ptr = Trie.begin() + offset;
1312 NodeState State(Ptr);
1313 uint64_t ExportInfoSize = readULEB128(State.Current);
1314 State.IsExportNode = (ExportInfoSize != 0);
1315 const uint8_t* Children = State.Current + ExportInfoSize;
1316 if (State.IsExportNode) {
1317 State.Flags = readULEB128(State.Current);
1318 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1319 State.Address = 0;
1320 State.Other = readULEB128(State.Current); // dylib ordinal
1321 State.ImportName = reinterpret_cast<const char*>(State.Current);
1322 } else {
1323 State.Address = readULEB128(State.Current);
1324 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1325 State.Other = readULEB128(State.Current);
1326 }
1327 }
1328 State.ChildCount = *Children;
1329 State.Current = Children + 1;
1330 State.NextChildIndex = 0;
1331 State.ParentStringLength = CumulativeString.size();
1332 Stack.push_back(State);
1333 }
1334
pushDownUntilBottom()1335 void ExportEntry::pushDownUntilBottom() {
1336 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1337 NodeState &Top = Stack.back();
1338 CumulativeString.resize(Top.ParentStringLength);
1339 for (;*Top.Current != 0; Top.Current++) {
1340 char C = *Top.Current;
1341 CumulativeString.push_back(C);
1342 }
1343 Top.Current += 1;
1344 uint64_t childNodeIndex = readULEB128(Top.Current);
1345 Top.NextChildIndex += 1;
1346 pushNode(childNodeIndex);
1347 }
1348 if (!Stack.back().IsExportNode) {
1349 Malformed = true;
1350 moveToEnd();
1351 }
1352 }
1353
1354 // We have a trie data structure and need a way to walk it that is compatible
1355 // with the C++ iterator model. The solution is a non-recursive depth first
1356 // traversal where the iterator contains a stack of parent nodes along with a
1357 // string that is the accumulation of all edge strings along the parent chain
1358 // to this point.
1359 //
1360 // There is one "export" node for each exported symbol. But because some
1361 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1362 // node may have child nodes too.
1363 //
1364 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1365 // child until hitting a node with no children (which is an export node or
1366 // else the trie is malformed). On the way down, each node is pushed on the
1367 // stack ivar. If there is no more ways down, it pops up one and tries to go
1368 // down a sibling path until a childless node is reached.
moveNext()1369 void ExportEntry::moveNext() {
1370 if (Stack.empty() || !Stack.back().IsExportNode) {
1371 Malformed = true;
1372 moveToEnd();
1373 return;
1374 }
1375
1376 Stack.pop_back();
1377 while (!Stack.empty()) {
1378 NodeState &Top = Stack.back();
1379 if (Top.NextChildIndex < Top.ChildCount) {
1380 pushDownUntilBottom();
1381 // Now at the next export node.
1382 return;
1383 } else {
1384 if (Top.IsExportNode) {
1385 // This node has no children but is itself an export node.
1386 CumulativeString.resize(Top.ParentStringLength);
1387 return;
1388 }
1389 Stack.pop_back();
1390 }
1391 }
1392 Done = true;
1393 }
1394
1395 iterator_range<export_iterator>
exports(ArrayRef<uint8_t> Trie)1396 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1397 ExportEntry Start(Trie);
1398 if (Trie.size() == 0)
1399 Start.moveToEnd();
1400 else
1401 Start.moveToFirst();
1402
1403 ExportEntry Finish(Trie);
1404 Finish.moveToEnd();
1405
1406 return make_range(export_iterator(Start), export_iterator(Finish));
1407 }
1408
exports() const1409 iterator_range<export_iterator> MachOObjectFile::exports() const {
1410 return exports(getDyldInfoExportsTrie());
1411 }
1412
MachORebaseEntry(ArrayRef<uint8_t> Bytes,bool is64Bit)1413 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1414 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1415 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1416 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1417
moveToFirst()1418 void MachORebaseEntry::moveToFirst() {
1419 Ptr = Opcodes.begin();
1420 moveNext();
1421 }
1422
moveToEnd()1423 void MachORebaseEntry::moveToEnd() {
1424 Ptr = Opcodes.end();
1425 RemainingLoopCount = 0;
1426 Done = true;
1427 }
1428
moveNext()1429 void MachORebaseEntry::moveNext() {
1430 // If in the middle of some loop, move to next rebasing in loop.
1431 SegmentOffset += AdvanceAmount;
1432 if (RemainingLoopCount) {
1433 --RemainingLoopCount;
1434 return;
1435 }
1436 if (Ptr == Opcodes.end()) {
1437 Done = true;
1438 return;
1439 }
1440 bool More = true;
1441 while (More && !Malformed) {
1442 // Parse next opcode and set up next loop.
1443 uint8_t Byte = *Ptr++;
1444 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1445 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1446 switch (Opcode) {
1447 case MachO::REBASE_OPCODE_DONE:
1448 More = false;
1449 Done = true;
1450 moveToEnd();
1451 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1452 break;
1453 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1454 RebaseType = ImmValue;
1455 DEBUG_WITH_TYPE(
1456 "mach-o-rebase",
1457 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1458 << "RebaseType=" << (int) RebaseType << "\n");
1459 break;
1460 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1461 SegmentIndex = ImmValue;
1462 SegmentOffset = readULEB128();
1463 DEBUG_WITH_TYPE(
1464 "mach-o-rebase",
1465 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1466 << "SegmentIndex=" << SegmentIndex << ", "
1467 << format("SegmentOffset=0x%06X", SegmentOffset)
1468 << "\n");
1469 break;
1470 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1471 SegmentOffset += readULEB128();
1472 DEBUG_WITH_TYPE("mach-o-rebase",
1473 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1474 << format("SegmentOffset=0x%06X",
1475 SegmentOffset) << "\n");
1476 break;
1477 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1478 SegmentOffset += ImmValue * PointerSize;
1479 DEBUG_WITH_TYPE("mach-o-rebase",
1480 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1481 << format("SegmentOffset=0x%06X",
1482 SegmentOffset) << "\n");
1483 break;
1484 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1485 AdvanceAmount = PointerSize;
1486 RemainingLoopCount = ImmValue - 1;
1487 DEBUG_WITH_TYPE(
1488 "mach-o-rebase",
1489 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1490 << format("SegmentOffset=0x%06X", SegmentOffset)
1491 << ", AdvanceAmount=" << AdvanceAmount
1492 << ", RemainingLoopCount=" << RemainingLoopCount
1493 << "\n");
1494 return;
1495 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1496 AdvanceAmount = PointerSize;
1497 RemainingLoopCount = readULEB128() - 1;
1498 DEBUG_WITH_TYPE(
1499 "mach-o-rebase",
1500 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1501 << format("SegmentOffset=0x%06X", SegmentOffset)
1502 << ", AdvanceAmount=" << AdvanceAmount
1503 << ", RemainingLoopCount=" << RemainingLoopCount
1504 << "\n");
1505 return;
1506 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1507 AdvanceAmount = readULEB128() + PointerSize;
1508 RemainingLoopCount = 0;
1509 DEBUG_WITH_TYPE(
1510 "mach-o-rebase",
1511 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1512 << format("SegmentOffset=0x%06X", SegmentOffset)
1513 << ", AdvanceAmount=" << AdvanceAmount
1514 << ", RemainingLoopCount=" << RemainingLoopCount
1515 << "\n");
1516 return;
1517 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1518 RemainingLoopCount = readULEB128() - 1;
1519 AdvanceAmount = readULEB128() + PointerSize;
1520 DEBUG_WITH_TYPE(
1521 "mach-o-rebase",
1522 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1523 << format("SegmentOffset=0x%06X", SegmentOffset)
1524 << ", AdvanceAmount=" << AdvanceAmount
1525 << ", RemainingLoopCount=" << RemainingLoopCount
1526 << "\n");
1527 return;
1528 default:
1529 Malformed = true;
1530 }
1531 }
1532 }
1533
readULEB128()1534 uint64_t MachORebaseEntry::readULEB128() {
1535 unsigned Count;
1536 uint64_t Result = decodeULEB128(Ptr, &Count);
1537 Ptr += Count;
1538 if (Ptr > Opcodes.end()) {
1539 Ptr = Opcodes.end();
1540 Malformed = true;
1541 }
1542 return Result;
1543 }
1544
segmentIndex() const1545 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1546
segmentOffset() const1547 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1548
typeName() const1549 StringRef MachORebaseEntry::typeName() const {
1550 switch (RebaseType) {
1551 case MachO::REBASE_TYPE_POINTER:
1552 return "pointer";
1553 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1554 return "text abs32";
1555 case MachO::REBASE_TYPE_TEXT_PCREL32:
1556 return "text rel32";
1557 }
1558 return "unknown";
1559 }
1560
operator ==(const MachORebaseEntry & Other) const1561 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1562 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1563 return (Ptr == Other.Ptr) &&
1564 (RemainingLoopCount == Other.RemainingLoopCount) &&
1565 (Done == Other.Done);
1566 }
1567
1568 iterator_range<rebase_iterator>
rebaseTable(ArrayRef<uint8_t> Opcodes,bool is64)1569 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1570 MachORebaseEntry Start(Opcodes, is64);
1571 Start.moveToFirst();
1572
1573 MachORebaseEntry Finish(Opcodes, is64);
1574 Finish.moveToEnd();
1575
1576 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
1577 }
1578
rebaseTable() const1579 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1580 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1581 }
1582
MachOBindEntry(ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)1583 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
1584 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1585 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1586 BindType(0), PointerSize(is64Bit ? 8 : 4),
1587 TableKind(BK), Malformed(false), Done(false) {}
1588
moveToFirst()1589 void MachOBindEntry::moveToFirst() {
1590 Ptr = Opcodes.begin();
1591 moveNext();
1592 }
1593
moveToEnd()1594 void MachOBindEntry::moveToEnd() {
1595 Ptr = Opcodes.end();
1596 RemainingLoopCount = 0;
1597 Done = true;
1598 }
1599
moveNext()1600 void MachOBindEntry::moveNext() {
1601 // If in the middle of some loop, move to next binding in loop.
1602 SegmentOffset += AdvanceAmount;
1603 if (RemainingLoopCount) {
1604 --RemainingLoopCount;
1605 return;
1606 }
1607 if (Ptr == Opcodes.end()) {
1608 Done = true;
1609 return;
1610 }
1611 bool More = true;
1612 while (More && !Malformed) {
1613 // Parse next opcode and set up next loop.
1614 uint8_t Byte = *Ptr++;
1615 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1616 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1617 int8_t SignExtended;
1618 const uint8_t *SymStart;
1619 switch (Opcode) {
1620 case MachO::BIND_OPCODE_DONE:
1621 if (TableKind == Kind::Lazy) {
1622 // Lazying bindings have a DONE opcode between entries. Need to ignore
1623 // it to advance to next entry. But need not if this is last entry.
1624 bool NotLastEntry = false;
1625 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1626 if (*P) {
1627 NotLastEntry = true;
1628 }
1629 }
1630 if (NotLastEntry)
1631 break;
1632 }
1633 More = false;
1634 Done = true;
1635 moveToEnd();
1636 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1637 break;
1638 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1639 Ordinal = ImmValue;
1640 DEBUG_WITH_TYPE(
1641 "mach-o-bind",
1642 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1643 << "Ordinal=" << Ordinal << "\n");
1644 break;
1645 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1646 Ordinal = readULEB128();
1647 DEBUG_WITH_TYPE(
1648 "mach-o-bind",
1649 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1650 << "Ordinal=" << Ordinal << "\n");
1651 break;
1652 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1653 if (ImmValue) {
1654 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1655 Ordinal = SignExtended;
1656 } else
1657 Ordinal = 0;
1658 DEBUG_WITH_TYPE(
1659 "mach-o-bind",
1660 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1661 << "Ordinal=" << Ordinal << "\n");
1662 break;
1663 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1664 Flags = ImmValue;
1665 SymStart = Ptr;
1666 while (*Ptr) {
1667 ++Ptr;
1668 }
1669 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1670 Ptr-SymStart);
1671 ++Ptr;
1672 DEBUG_WITH_TYPE(
1673 "mach-o-bind",
1674 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1675 << "SymbolName=" << SymbolName << "\n");
1676 if (TableKind == Kind::Weak) {
1677 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1678 return;
1679 }
1680 break;
1681 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1682 BindType = ImmValue;
1683 DEBUG_WITH_TYPE(
1684 "mach-o-bind",
1685 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1686 << "BindType=" << (int)BindType << "\n");
1687 break;
1688 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1689 Addend = readSLEB128();
1690 if (TableKind == Kind::Lazy)
1691 Malformed = true;
1692 DEBUG_WITH_TYPE(
1693 "mach-o-bind",
1694 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1695 << "Addend=" << Addend << "\n");
1696 break;
1697 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1698 SegmentIndex = ImmValue;
1699 SegmentOffset = readULEB128();
1700 DEBUG_WITH_TYPE(
1701 "mach-o-bind",
1702 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1703 << "SegmentIndex=" << SegmentIndex << ", "
1704 << format("SegmentOffset=0x%06X", SegmentOffset)
1705 << "\n");
1706 break;
1707 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1708 SegmentOffset += readULEB128();
1709 DEBUG_WITH_TYPE("mach-o-bind",
1710 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1711 << format("SegmentOffset=0x%06X",
1712 SegmentOffset) << "\n");
1713 break;
1714 case MachO::BIND_OPCODE_DO_BIND:
1715 AdvanceAmount = PointerSize;
1716 RemainingLoopCount = 0;
1717 DEBUG_WITH_TYPE("mach-o-bind",
1718 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1719 << format("SegmentOffset=0x%06X",
1720 SegmentOffset) << "\n");
1721 return;
1722 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1723 AdvanceAmount = readULEB128() + PointerSize;
1724 RemainingLoopCount = 0;
1725 if (TableKind == Kind::Lazy)
1726 Malformed = true;
1727 DEBUG_WITH_TYPE(
1728 "mach-o-bind",
1729 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1730 << format("SegmentOffset=0x%06X", SegmentOffset)
1731 << ", AdvanceAmount=" << AdvanceAmount
1732 << ", RemainingLoopCount=" << RemainingLoopCount
1733 << "\n");
1734 return;
1735 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1736 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1737 RemainingLoopCount = 0;
1738 if (TableKind == Kind::Lazy)
1739 Malformed = true;
1740 DEBUG_WITH_TYPE("mach-o-bind",
1741 llvm::dbgs()
1742 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1743 << format("SegmentOffset=0x%06X",
1744 SegmentOffset) << "\n");
1745 return;
1746 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1747 RemainingLoopCount = readULEB128() - 1;
1748 AdvanceAmount = readULEB128() + PointerSize;
1749 if (TableKind == Kind::Lazy)
1750 Malformed = true;
1751 DEBUG_WITH_TYPE(
1752 "mach-o-bind",
1753 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1754 << format("SegmentOffset=0x%06X", SegmentOffset)
1755 << ", AdvanceAmount=" << AdvanceAmount
1756 << ", RemainingLoopCount=" << RemainingLoopCount
1757 << "\n");
1758 return;
1759 default:
1760 Malformed = true;
1761 }
1762 }
1763 }
1764
readULEB128()1765 uint64_t MachOBindEntry::readULEB128() {
1766 unsigned Count;
1767 uint64_t Result = decodeULEB128(Ptr, &Count);
1768 Ptr += Count;
1769 if (Ptr > Opcodes.end()) {
1770 Ptr = Opcodes.end();
1771 Malformed = true;
1772 }
1773 return Result;
1774 }
1775
readSLEB128()1776 int64_t MachOBindEntry::readSLEB128() {
1777 unsigned Count;
1778 int64_t Result = decodeSLEB128(Ptr, &Count);
1779 Ptr += Count;
1780 if (Ptr > Opcodes.end()) {
1781 Ptr = Opcodes.end();
1782 Malformed = true;
1783 }
1784 return Result;
1785 }
1786
segmentIndex() const1787 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1788
segmentOffset() const1789 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1790
typeName() const1791 StringRef MachOBindEntry::typeName() const {
1792 switch (BindType) {
1793 case MachO::BIND_TYPE_POINTER:
1794 return "pointer";
1795 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1796 return "text abs32";
1797 case MachO::BIND_TYPE_TEXT_PCREL32:
1798 return "text rel32";
1799 }
1800 return "unknown";
1801 }
1802
symbolName() const1803 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1804
addend() const1805 int64_t MachOBindEntry::addend() const { return Addend; }
1806
flags() const1807 uint32_t MachOBindEntry::flags() const { return Flags; }
1808
ordinal() const1809 int MachOBindEntry::ordinal() const { return Ordinal; }
1810
operator ==(const MachOBindEntry & Other) const1811 bool MachOBindEntry::operator==(const MachOBindEntry &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<bind_iterator>
bindTable(ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)1819 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1820 MachOBindEntry::Kind BKind) {
1821 MachOBindEntry Start(Opcodes, is64, BKind);
1822 Start.moveToFirst();
1823
1824 MachOBindEntry Finish(Opcodes, is64, BKind);
1825 Finish.moveToEnd();
1826
1827 return make_range(bind_iterator(Start), bind_iterator(Finish));
1828 }
1829
bindTable() const1830 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1831 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1832 MachOBindEntry::Kind::Regular);
1833 }
1834
lazyBindTable() const1835 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1836 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1837 MachOBindEntry::Kind::Lazy);
1838 }
1839
weakBindTable() const1840 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1841 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1842 MachOBindEntry::Kind::Weak);
1843 }
1844
1845 MachOObjectFile::load_command_iterator
begin_load_commands() const1846 MachOObjectFile::begin_load_commands() const {
1847 return LoadCommands.begin();
1848 }
1849
1850 MachOObjectFile::load_command_iterator
end_load_commands() const1851 MachOObjectFile::end_load_commands() const {
1852 return LoadCommands.end();
1853 }
1854
1855 iterator_range<MachOObjectFile::load_command_iterator>
load_commands() const1856 MachOObjectFile::load_commands() const {
1857 return make_range(begin_load_commands(), end_load_commands());
1858 }
1859
1860 StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const1861 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1862 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1863 return parseSegmentOrSectionName(Raw.data());
1864 }
1865
1866 ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const1867 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1868 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1869 const section_base *Base =
1870 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1871 return makeArrayRef(Base->sectname);
1872 }
1873
1874 ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const1875 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1876 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1877 const section_base *Base =
1878 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1879 return makeArrayRef(Base->segname);
1880 }
1881
1882 bool
isRelocationScattered(const MachO::any_relocation_info & RE) const1883 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1884 const {
1885 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1886 return false;
1887 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1888 }
1889
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const1890 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1891 const MachO::any_relocation_info &RE) const {
1892 if (isLittleEndian())
1893 return RE.r_word1 & 0xffffff;
1894 return RE.r_word1 >> 8;
1895 }
1896
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const1897 bool MachOObjectFile::getPlainRelocationExternal(
1898 const MachO::any_relocation_info &RE) const {
1899 if (isLittleEndian())
1900 return (RE.r_word1 >> 27) & 1;
1901 return (RE.r_word1 >> 4) & 1;
1902 }
1903
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const1904 bool MachOObjectFile::getScatteredRelocationScattered(
1905 const MachO::any_relocation_info &RE) const {
1906 return RE.r_word0 >> 31;
1907 }
1908
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const1909 uint32_t MachOObjectFile::getScatteredRelocationValue(
1910 const MachO::any_relocation_info &RE) const {
1911 return RE.r_word1;
1912 }
1913
getScatteredRelocationType(const MachO::any_relocation_info & RE) const1914 uint32_t MachOObjectFile::getScatteredRelocationType(
1915 const MachO::any_relocation_info &RE) const {
1916 return (RE.r_word0 >> 24) & 0xf;
1917 }
1918
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const1919 unsigned MachOObjectFile::getAnyRelocationAddress(
1920 const MachO::any_relocation_info &RE) const {
1921 if (isRelocationScattered(RE))
1922 return getScatteredRelocationAddress(RE);
1923 return getPlainRelocationAddress(RE);
1924 }
1925
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const1926 unsigned MachOObjectFile::getAnyRelocationPCRel(
1927 const MachO::any_relocation_info &RE) const {
1928 if (isRelocationScattered(RE))
1929 return getScatteredRelocationPCRel(this, RE);
1930 return getPlainRelocationPCRel(this, RE);
1931 }
1932
getAnyRelocationLength(const MachO::any_relocation_info & RE) const1933 unsigned MachOObjectFile::getAnyRelocationLength(
1934 const MachO::any_relocation_info &RE) const {
1935 if (isRelocationScattered(RE))
1936 return getScatteredRelocationLength(RE);
1937 return getPlainRelocationLength(this, RE);
1938 }
1939
1940 unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const1941 MachOObjectFile::getAnyRelocationType(
1942 const MachO::any_relocation_info &RE) const {
1943 if (isRelocationScattered(RE))
1944 return getScatteredRelocationType(RE);
1945 return getPlainRelocationType(this, RE);
1946 }
1947
1948 SectionRef
getAnyRelocationSection(const MachO::any_relocation_info & RE) const1949 MachOObjectFile::getAnyRelocationSection(
1950 const MachO::any_relocation_info &RE) const {
1951 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1952 return *section_end();
1953 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1954 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1955 return *section_end();
1956 DataRefImpl DRI;
1957 DRI.d.a = SecNum - 1;
1958 return SectionRef(DRI, this);
1959 }
1960
getSection(DataRefImpl DRI) const1961 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1962 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1963 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1964 }
1965
getSection64(DataRefImpl DRI) const1966 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1967 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1968 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1969 }
1970
getSection(const LoadCommandInfo & L,unsigned Index) const1971 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1972 unsigned Index) const {
1973 const char *Sec = getSectionPtr(this, L, Index);
1974 return getStruct<MachO::section>(this, Sec);
1975 }
1976
getSection64(const LoadCommandInfo & L,unsigned Index) const1977 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1978 unsigned Index) const {
1979 const char *Sec = getSectionPtr(this, L, Index);
1980 return getStruct<MachO::section_64>(this, Sec);
1981 }
1982
1983 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const1984 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1985 const char *P = reinterpret_cast<const char *>(DRI.p);
1986 return getStruct<MachO::nlist>(this, P);
1987 }
1988
1989 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const1990 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1991 const char *P = reinterpret_cast<const char *>(DRI.p);
1992 return getStruct<MachO::nlist_64>(this, P);
1993 }
1994
1995 MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const1996 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1997 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1998 }
1999
2000 MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const2001 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2002 return getStruct<MachO::segment_command>(this, L.Ptr);
2003 }
2004
2005 MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const2006 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2007 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2008 }
2009
2010 MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const2011 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2012 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2013 }
2014
2015 MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const2016 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2017 return getStruct<MachO::version_min_command>(this, L.Ptr);
2018 }
2019
2020 MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const2021 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2022 return getStruct<MachO::dylib_command>(this, L.Ptr);
2023 }
2024
2025 MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const2026 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2027 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2028 }
2029
2030 MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const2031 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2032 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2033 }
2034
2035 MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const2036 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2037 return getStruct<MachO::uuid_command>(this, L.Ptr);
2038 }
2039
2040 MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const2041 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2042 return getStruct<MachO::rpath_command>(this, L.Ptr);
2043 }
2044
2045 MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const2046 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2047 return getStruct<MachO::source_version_command>(this, L.Ptr);
2048 }
2049
2050 MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const2051 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2052 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2053 }
2054
2055 MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const2056 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2057 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2058 }
2059
2060 MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const2061 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2062 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2063 }
2064
2065 MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const2066 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2067 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2068 }
2069
2070 MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const2071 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2072 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2073 }
2074
2075 MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const2076 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2077 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2078 }
2079
2080 MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const2081 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2082 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2083 }
2084
2085 MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const2086 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2087 return getStruct<MachO::routines_command>(this, L.Ptr);
2088 }
2089
2090 MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const2091 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2092 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2093 }
2094
2095 MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const2096 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2097 return getStruct<MachO::thread_command>(this, L.Ptr);
2098 }
2099
2100 MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const2101 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2102 DataRefImpl Sec;
2103 Sec.d.a = Rel.d.a;
2104 uint32_t Offset;
2105 if (is64Bit()) {
2106 MachO::section_64 Sect = getSection64(Sec);
2107 Offset = Sect.reloff;
2108 } else {
2109 MachO::section Sect = getSection(Sec);
2110 Offset = Sect.reloff;
2111 }
2112
2113 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2114 getPtr(this, Offset)) + Rel.d.b;
2115 return getStruct<MachO::any_relocation_info>(
2116 this, reinterpret_cast<const char *>(P));
2117 }
2118
2119 MachO::data_in_code_entry
getDice(DataRefImpl Rel) const2120 MachOObjectFile::getDice(DataRefImpl Rel) const {
2121 const char *P = reinterpret_cast<const char *>(Rel.p);
2122 return getStruct<MachO::data_in_code_entry>(this, P);
2123 }
2124
getHeader() const2125 const MachO::mach_header &MachOObjectFile::getHeader() const {
2126 return Header;
2127 }
2128
getHeader64() const2129 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2130 assert(is64Bit());
2131 return Header64;
2132 }
2133
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const2134 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2135 const MachO::dysymtab_command &DLC,
2136 unsigned Index) const {
2137 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2138 return getStruct<uint32_t>(this, getPtr(this, Offset));
2139 }
2140
2141 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const2142 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2143 unsigned Index) const {
2144 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2145 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2146 }
2147
getSymtabLoadCommand() const2148 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2149 if (SymtabLoadCmd)
2150 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2151
2152 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2153 MachO::symtab_command Cmd;
2154 Cmd.cmd = MachO::LC_SYMTAB;
2155 Cmd.cmdsize = sizeof(MachO::symtab_command);
2156 Cmd.symoff = 0;
2157 Cmd.nsyms = 0;
2158 Cmd.stroff = 0;
2159 Cmd.strsize = 0;
2160 return Cmd;
2161 }
2162
getDysymtabLoadCommand() const2163 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2164 if (DysymtabLoadCmd)
2165 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2166
2167 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2168 MachO::dysymtab_command Cmd;
2169 Cmd.cmd = MachO::LC_DYSYMTAB;
2170 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2171 Cmd.ilocalsym = 0;
2172 Cmd.nlocalsym = 0;
2173 Cmd.iextdefsym = 0;
2174 Cmd.nextdefsym = 0;
2175 Cmd.iundefsym = 0;
2176 Cmd.nundefsym = 0;
2177 Cmd.tocoff = 0;
2178 Cmd.ntoc = 0;
2179 Cmd.modtaboff = 0;
2180 Cmd.nmodtab = 0;
2181 Cmd.extrefsymoff = 0;
2182 Cmd.nextrefsyms = 0;
2183 Cmd.indirectsymoff = 0;
2184 Cmd.nindirectsyms = 0;
2185 Cmd.extreloff = 0;
2186 Cmd.nextrel = 0;
2187 Cmd.locreloff = 0;
2188 Cmd.nlocrel = 0;
2189 return Cmd;
2190 }
2191
2192 MachO::linkedit_data_command
getDataInCodeLoadCommand() const2193 MachOObjectFile::getDataInCodeLoadCommand() const {
2194 if (DataInCodeLoadCmd)
2195 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2196
2197 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2198 MachO::linkedit_data_command Cmd;
2199 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2200 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2201 Cmd.dataoff = 0;
2202 Cmd.datasize = 0;
2203 return Cmd;
2204 }
2205
2206 MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const2207 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2208 if (LinkOptHintsLoadCmd)
2209 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2210
2211 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2212 // fields.
2213 MachO::linkedit_data_command Cmd;
2214 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2215 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2216 Cmd.dataoff = 0;
2217 Cmd.datasize = 0;
2218 return Cmd;
2219 }
2220
getDyldInfoRebaseOpcodes() const2221 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2222 if (!DyldInfoLoadCmd)
2223 return None;
2224
2225 MachO::dyld_info_command DyldInfo =
2226 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2227 const uint8_t *Ptr =
2228 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
2229 return makeArrayRef(Ptr, DyldInfo.rebase_size);
2230 }
2231
getDyldInfoBindOpcodes() const2232 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2233 if (!DyldInfoLoadCmd)
2234 return None;
2235
2236 MachO::dyld_info_command DyldInfo =
2237 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2238 const uint8_t *Ptr =
2239 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
2240 return makeArrayRef(Ptr, DyldInfo.bind_size);
2241 }
2242
getDyldInfoWeakBindOpcodes() const2243 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2244 if (!DyldInfoLoadCmd)
2245 return None;
2246
2247 MachO::dyld_info_command DyldInfo =
2248 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2249 const uint8_t *Ptr =
2250 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
2251 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
2252 }
2253
getDyldInfoLazyBindOpcodes() const2254 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2255 if (!DyldInfoLoadCmd)
2256 return None;
2257
2258 MachO::dyld_info_command DyldInfo =
2259 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2260 const uint8_t *Ptr =
2261 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
2262 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
2263 }
2264
getDyldInfoExportsTrie() const2265 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2266 if (!DyldInfoLoadCmd)
2267 return None;
2268
2269 MachO::dyld_info_command DyldInfo =
2270 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2271 const uint8_t *Ptr =
2272 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
2273 return makeArrayRef(Ptr, DyldInfo.export_size);
2274 }
2275
getUuid() const2276 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2277 if (!UuidLoadCmd)
2278 return None;
2279 // Returning a pointer is fine as uuid doesn't need endian swapping.
2280 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2281 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
2282 }
2283
getStringTableData() const2284 StringRef MachOObjectFile::getStringTableData() const {
2285 MachO::symtab_command S = getSymtabLoadCommand();
2286 return getData().substr(S.stroff, S.strsize);
2287 }
2288
is64Bit() const2289 bool MachOObjectFile::is64Bit() const {
2290 return getType() == getMachOType(false, true) ||
2291 getType() == getMachOType(true, true);
2292 }
2293
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const2294 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2295 SmallVectorImpl<uint64_t> &Out) const {
2296 DataExtractor extractor(ObjectFile::getData(), true, 0);
2297
2298 uint32_t offset = Index;
2299 uint64_t data = 0;
2300 while (uint64_t delta = extractor.getULEB128(&offset)) {
2301 data += delta;
2302 Out.push_back(data);
2303 }
2304 }
2305
isRelocatableObject() const2306 bool MachOObjectFile::isRelocatableObject() const {
2307 return getHeader().filetype == MachO::MH_OBJECT;
2308 }
2309
2310 ErrorOr<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer)2311 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2312 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2313 std::error_code EC;
2314 std::unique_ptr<MachOObjectFile> Ret;
2315 if (Magic == "\xFE\xED\xFA\xCE")
2316 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2317 else if (Magic == "\xCE\xFA\xED\xFE")
2318 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2319 else if (Magic == "\xFE\xED\xFA\xCF")
2320 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2321 else if (Magic == "\xCF\xFA\xED\xFE")
2322 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2323 else
2324 return object_error::parse_failed;
2325
2326 if (EC)
2327 return EC;
2328 return std::move(Ret);
2329 }
2330