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