1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
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"
33 using namespace object;
43 malformedError(Twine Msg) {
44 std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")";
45 return make_error<GenericBinaryError>(std::move(StringMsg),
46 object_error::parse_failed);
49 // FIXME: Replace all uses of this function with getStructOrErr.
51 static T getStruct(const MachOObjectFile &O, const char *P) {
52 // Don't read before the beginning or past the end of the file
53 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
54 report_fatal_error("Malformed MachO file.");
57 memcpy(&Cmd, P, sizeof(T));
58 if (O.isLittleEndian() != sys::IsLittleEndianHost)
59 MachO::swapStruct(Cmd);
64 static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
65 // Don't read before the beginning or past the end of the file
66 if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
67 return malformedError("Structure read out-of-range");
70 memcpy(&Cmd, P, sizeof(T));
71 if (O.isLittleEndian() != sys::IsLittleEndianHost)
72 MachO::swapStruct(Cmd);
77 getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
79 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
81 bool Is64 = O.is64Bit();
82 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
83 sizeof(MachO::segment_command);
84 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
85 sizeof(MachO::section);
87 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
88 return reinterpret_cast<const char*>(SectionAddr);
91 static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
92 return O.getData().substr(Offset, 1).data();
95 static MachO::nlist_base
96 getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
97 const char *P = reinterpret_cast<const char *>(DRI.p);
98 return getStruct<MachO::nlist_base>(O, P);
101 static StringRef parseSegmentOrSectionName(const char *P) {
105 // Not null terminated, so this is a 16 char string.
106 return StringRef(P, 16);
109 // Helper to advance a section or symbol iterator multiple increments at a time.
111 static void advance(T &it, size_t Val) {
116 static unsigned getCPUType(const MachOObjectFile &O) {
117 return O.getHeader().cputype;
121 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
126 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
127 return RE.r_word0 & 0xffffff;
130 static bool getPlainRelocationPCRel(const MachOObjectFile &O,
131 const MachO::any_relocation_info &RE) {
132 if (O.isLittleEndian())
133 return (RE.r_word1 >> 24) & 1;
134 return (RE.r_word1 >> 7) & 1;
138 getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
139 return (RE.r_word0 >> 30) & 1;
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;
150 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
151 return (RE.r_word0 >> 28) & 3;
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;
161 static uint32_t getSectionFlags(const MachOObjectFile &O,
164 MachO::section_64 Sect = O.getSection64(Sec);
167 MachO::section Sect = O.getSection(Sec);
171 static Expected<MachOObjectFile::LoadCommandInfo>
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});
180 return CmdOrErr.takeError();
183 static Expected<MachOObjectFile::LoadCommandInfo>
184 getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
185 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
186 : sizeof(MachO::mach_header);
187 if (sizeof(MachO::load_command) > 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);
193 static Expected<MachOObjectFile::LoadCommandInfo>
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(MachO::load_command) >
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);
205 template <typename T>
206 static void parseHeader(const MachOObjectFile &Obj, T &Header,
208 if (sizeof(T) > Obj.getData().size()) {
209 Err = malformedError("the mach header extends past the end of the "
213 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
214 Header = *HeaderOrErr;
216 Err = HeaderOrErr.takeError();
219 // This is used to check for overlapping of Mach-O elements.
220 struct MachOElement {
226 static Error checkOverlappingElement(std::list<MachOElement> &Elements,
227 uint64_t Offset, uint64_t Size,
230 return Error::success();
232 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
234 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
235 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
236 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
237 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
238 " with a size of " + Twine(Size) + ", overlaps " +
239 E.Name + " at offset " + Twine(E.Offset) + " with "
240 "a size of " + Twine(E.Size));
243 if (nt != Elements.end()) {
245 if (Offset + Size <= N.Offset) {
246 Elements.insert(nt, {Offset, Size, Name});
247 return Error::success();
251 Elements.push_back({Offset, Size, Name});
252 return Error::success();
255 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
256 // sections to \param Sections, and optionally sets
257 // \param IsPageZeroSegment to true.
258 template <typename Segment, typename Section>
259 static Error parseSegmentLoadCommand(
260 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
261 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
262 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
263 std::list<MachOElement> &Elements) {
264 const unsigned SegmentLoadSize = sizeof(Segment);
265 if (Load.C.cmdsize < SegmentLoadSize)
266 return malformedError("load command " + Twine(LoadCommandIndex) +
267 " " + CmdName + " cmdsize too small");
268 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
269 Segment S = SegOrErr.get();
270 const unsigned SectionSize = sizeof(Section);
271 uint64_t FileSize = Obj.getData().size();
272 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
273 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
274 return malformedError("load command " + Twine(LoadCommandIndex) +
275 " inconsistent cmdsize in " + CmdName +
276 " for the number of sections");
277 for (unsigned J = 0; J < S.nsects; ++J) {
278 const char *Sec = getSectionPtr(Obj, Load, J);
279 Sections.push_back(Sec);
280 Section s = getStruct<Section>(Obj, Sec);
281 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
282 Obj.getHeader().filetype != MachO::MH_DSYM &&
283 s.flags != MachO::S_ZEROFILL &&
284 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
286 return malformedError("offset field of section " + Twine(J) + " in " +
287 CmdName + " command " + Twine(LoadCommandIndex) +
288 " extends past the end of the file");
289 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
290 Obj.getHeader().filetype != MachO::MH_DSYM &&
291 s.flags != MachO::S_ZEROFILL &&
292 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
293 s.offset < SizeOfHeaders && s.size != 0)
294 return malformedError("offset field of section " + Twine(J) + " in " +
295 CmdName + " command " + Twine(LoadCommandIndex) +
296 " not past the headers of the file");
297 uint64_t BigSize = s.offset;
299 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
300 Obj.getHeader().filetype != MachO::MH_DSYM &&
301 s.flags != MachO::S_ZEROFILL &&
302 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
304 return malformedError("offset field plus size field of section " +
305 Twine(J) + " in " + CmdName + " command " +
306 Twine(LoadCommandIndex) +
307 " extends past the end of the file");
308 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
309 Obj.getHeader().filetype != MachO::MH_DSYM &&
310 s.flags != MachO::S_ZEROFILL &&
311 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
313 return malformedError("size field of section " +
314 Twine(J) + " in " + CmdName + " command " +
315 Twine(LoadCommandIndex) +
316 " greater than the segment");
317 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
318 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
320 return malformedError("addr field of section " + Twine(J) + " in " +
321 CmdName + " command " + Twine(LoadCommandIndex) +
322 " less than the segment's vmaddr");
325 uint64_t BigEnd = S.vmaddr;
327 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
328 return malformedError("addr field plus size of section " + Twine(J) +
329 " in " + CmdName + " command " +
330 Twine(LoadCommandIndex) +
331 " greater than than "
332 "the segment's vmaddr plus vmsize");
333 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
334 Obj.getHeader().filetype != MachO::MH_DSYM &&
335 s.flags != MachO::S_ZEROFILL &&
336 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
337 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
340 if (s.reloff > FileSize)
341 return malformedError("reloff field of section " + Twine(J) + " in " +
342 CmdName + " command " + Twine(LoadCommandIndex) +
343 " extends past the end of the file");
345 BigSize *= sizeof(struct MachO::relocation_info);
347 if (BigSize > FileSize)
348 return malformedError("reloff field plus nreloc field times sizeof("
349 "struct relocation_info) of section " +
350 Twine(J) + " in " + CmdName + " command " +
351 Twine(LoadCommandIndex) +
352 " extends past the end of the file");
353 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
355 MachO::relocation_info),
356 "section relocation entries"))
359 if (S.fileoff > FileSize)
360 return malformedError("load command " + Twine(LoadCommandIndex) +
361 " fileoff field in " + CmdName +
362 " extends past the end of the file");
363 uint64_t BigSize = S.fileoff;
364 BigSize += S.filesize;
365 if (BigSize > FileSize)
366 return malformedError("load command " + Twine(LoadCommandIndex) +
367 " fileoff field plus filesize field in " +
368 CmdName + " extends past the end of the file");
369 if (S.vmsize != 0 && S.filesize > S.vmsize)
370 return malformedError("load command " + Twine(LoadCommandIndex) +
371 " fileoff field in " + CmdName +
372 " greater than vmsize field");
373 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
375 return SegOrErr.takeError();
377 return Error::success();
380 static Error checkSymtabCommand(const MachOObjectFile &Obj,
381 const MachOObjectFile::LoadCommandInfo &Load,
382 uint32_t LoadCommandIndex,
383 const char **SymtabLoadCmd,
384 std::list<MachOElement> &Elements) {
385 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
386 return malformedError("load command " + Twine(LoadCommandIndex) +
387 " LC_SYMTAB cmdsize too small");
388 if (*SymtabLoadCmd != nullptr)
389 return malformedError("more than one LC_SYMTAB command");
390 MachO::symtab_command Symtab =
391 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
392 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
393 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
394 " has incorrect cmdsize");
395 uint64_t FileSize = Obj.getData().size();
396 if (Symtab.symoff > FileSize)
397 return malformedError("symoff field of LC_SYMTAB command " +
398 Twine(LoadCommandIndex) + " extends past the end "
400 uint64_t SymtabSize = Symtab.nsyms;
401 const char *struct_nlist_name;
403 SymtabSize *= sizeof(MachO::nlist_64);
404 struct_nlist_name = "struct nlist_64";
406 SymtabSize *= sizeof(MachO::nlist);
407 struct_nlist_name = "struct nlist";
409 uint64_t BigSize = SymtabSize;
410 BigSize += Symtab.symoff;
411 if (BigSize > FileSize)
412 return malformedError("symoff field plus nsyms field times sizeof(" +
413 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
414 Twine(LoadCommandIndex) + " extends past the end "
416 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
419 if (Symtab.stroff > FileSize)
420 return malformedError("stroff field of LC_SYMTAB command " +
421 Twine(LoadCommandIndex) + " extends past the end "
423 BigSize = Symtab.stroff;
424 BigSize += Symtab.strsize;
425 if (BigSize > FileSize)
426 return malformedError("stroff field plus strsize field of LC_SYMTAB "
427 "command " + Twine(LoadCommandIndex) + " extends "
428 "past the end of the file");
429 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
430 Symtab.strsize, "string table"))
432 *SymtabLoadCmd = Load.Ptr;
433 return Error::success();
436 static Error checkDysymtabCommand(const MachOObjectFile &Obj,
437 const MachOObjectFile::LoadCommandInfo &Load,
438 uint32_t LoadCommandIndex,
439 const char **DysymtabLoadCmd,
440 std::list<MachOElement> &Elements) {
441 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
442 return malformedError("load command " + Twine(LoadCommandIndex) +
443 " LC_DYSYMTAB cmdsize too small");
444 if (*DysymtabLoadCmd != nullptr)
445 return malformedError("more than one LC_DYSYMTAB command");
446 MachO::dysymtab_command Dysymtab =
447 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
448 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
449 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
450 " has incorrect cmdsize");
451 uint64_t FileSize = Obj.getData().size();
452 if (Dysymtab.tocoff > FileSize)
453 return malformedError("tocoff field of LC_DYSYMTAB command " +
454 Twine(LoadCommandIndex) + " extends past the end of "
456 uint64_t BigSize = Dysymtab.ntoc;
457 BigSize *= sizeof(MachO::dylib_table_of_contents);
458 BigSize += Dysymtab.tocoff;
459 if (BigSize > FileSize)
460 return malformedError("tocoff field plus ntoc field times sizeof(struct "
461 "dylib_table_of_contents) of LC_DYSYMTAB command " +
462 Twine(LoadCommandIndex) + " extends past the end of "
464 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
465 Dysymtab.ntoc * sizeof(struct
466 MachO::dylib_table_of_contents),
467 "table of contents"))
469 if (Dysymtab.modtaboff > FileSize)
470 return malformedError("modtaboff field of LC_DYSYMTAB command " +
471 Twine(LoadCommandIndex) + " extends past the end of "
473 BigSize = Dysymtab.nmodtab;
474 const char *struct_dylib_module_name;
475 uint64_t sizeof_modtab;
477 sizeof_modtab = sizeof(MachO::dylib_module_64);
478 struct_dylib_module_name = "struct dylib_module_64";
480 sizeof_modtab = sizeof(MachO::dylib_module);
481 struct_dylib_module_name = "struct dylib_module";
483 BigSize *= sizeof_modtab;
484 BigSize += Dysymtab.modtaboff;
485 if (BigSize > FileSize)
486 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
487 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
488 "command " + Twine(LoadCommandIndex) + " extends "
489 "past the end of the file");
490 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
491 Dysymtab.nmodtab * sizeof_modtab,
494 if (Dysymtab.extrefsymoff > FileSize)
495 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
496 Twine(LoadCommandIndex) + " extends past the end of "
498 BigSize = Dysymtab.nextrefsyms;
499 BigSize *= sizeof(MachO::dylib_reference);
500 BigSize += Dysymtab.extrefsymoff;
501 if (BigSize > FileSize)
502 return malformedError("extrefsymoff field plus nextrefsyms field times "
503 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
504 "command " + Twine(LoadCommandIndex) + " extends "
505 "past the end of the file");
506 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
507 Dysymtab.nextrefsyms *
508 sizeof(MachO::dylib_reference),
511 if (Dysymtab.indirectsymoff > FileSize)
512 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
513 Twine(LoadCommandIndex) + " extends past the end of "
515 BigSize = Dysymtab.nindirectsyms;
516 BigSize *= sizeof(uint32_t);
517 BigSize += Dysymtab.indirectsymoff;
518 if (BigSize > FileSize)
519 return malformedError("indirectsymoff field plus nindirectsyms field times "
520 "sizeof(uint32_t) of LC_DYSYMTAB command " +
521 Twine(LoadCommandIndex) + " extends past the end of "
523 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
524 Dysymtab.nindirectsyms *
528 if (Dysymtab.extreloff > FileSize)
529 return malformedError("extreloff field of LC_DYSYMTAB command " +
530 Twine(LoadCommandIndex) + " extends past the end of "
532 BigSize = Dysymtab.nextrel;
533 BigSize *= sizeof(MachO::relocation_info);
534 BigSize += Dysymtab.extreloff;
535 if (BigSize > FileSize)
536 return malformedError("extreloff field plus nextrel field times sizeof"
537 "(struct relocation_info) of LC_DYSYMTAB command " +
538 Twine(LoadCommandIndex) + " extends past the end of "
540 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
542 sizeof(MachO::relocation_info),
543 "external relocation table"))
545 if (Dysymtab.locreloff > FileSize)
546 return malformedError("locreloff field of LC_DYSYMTAB command " +
547 Twine(LoadCommandIndex) + " extends past the end of "
549 BigSize = Dysymtab.nlocrel;
550 BigSize *= sizeof(MachO::relocation_info);
551 BigSize += Dysymtab.locreloff;
552 if (BigSize > FileSize)
553 return malformedError("locreloff field plus nlocrel field times sizeof"
554 "(struct relocation_info) of LC_DYSYMTAB command " +
555 Twine(LoadCommandIndex) + " extends past the end of "
557 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
559 sizeof(MachO::relocation_info),
560 "local relocation table"))
562 *DysymtabLoadCmd = Load.Ptr;
563 return Error::success();
566 static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
567 const MachOObjectFile::LoadCommandInfo &Load,
568 uint32_t LoadCommandIndex,
569 const char **LoadCmd, const char *CmdName,
570 std::list<MachOElement> &Elements,
571 const char *ElementName) {
572 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
573 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
574 CmdName + " cmdsize too small");
575 if (*LoadCmd != nullptr)
576 return malformedError("more than one " + Twine(CmdName) + " command");
577 MachO::linkedit_data_command LinkData =
578 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
579 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
580 return malformedError(Twine(CmdName) + " command " +
581 Twine(LoadCommandIndex) + " has incorrect cmdsize");
582 uint64_t FileSize = Obj.getData().size();
583 if (LinkData.dataoff > FileSize)
584 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
585 Twine(LoadCommandIndex) + " extends past the end of "
587 uint64_t BigSize = LinkData.dataoff;
588 BigSize += LinkData.datasize;
589 if (BigSize > FileSize)
590 return malformedError("dataoff field plus datasize field of " +
591 Twine(CmdName) + " command " +
592 Twine(LoadCommandIndex) + " extends past the end of "
594 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
595 LinkData.datasize, ElementName))
598 return Error::success();
601 static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
602 const MachOObjectFile::LoadCommandInfo &Load,
603 uint32_t LoadCommandIndex,
604 const char **LoadCmd, const char *CmdName,
605 std::list<MachOElement> &Elements) {
606 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
607 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
608 CmdName + " cmdsize too small");
609 if (*LoadCmd != nullptr)
610 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
612 MachO::dyld_info_command DyldInfo =
613 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
614 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
615 return malformedError(Twine(CmdName) + " command " +
616 Twine(LoadCommandIndex) + " has incorrect cmdsize");
617 uint64_t FileSize = Obj.getData().size();
618 if (DyldInfo.rebase_off > FileSize)
619 return malformedError("rebase_off field of " + Twine(CmdName) +
620 " command " + Twine(LoadCommandIndex) + " extends "
621 "past the end of the file");
622 uint64_t BigSize = DyldInfo.rebase_off;
623 BigSize += DyldInfo.rebase_size;
624 if (BigSize > FileSize)
625 return malformedError("rebase_off field plus rebase_size field of " +
626 Twine(CmdName) + " command " +
627 Twine(LoadCommandIndex) + " extends past the end of "
629 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
630 DyldInfo.rebase_size,
633 if (DyldInfo.bind_off > FileSize)
634 return malformedError("bind_off field of " + Twine(CmdName) +
635 " command " + Twine(LoadCommandIndex) + " extends "
636 "past the end of the file");
637 BigSize = DyldInfo.bind_off;
638 BigSize += DyldInfo.bind_size;
639 if (BigSize > FileSize)
640 return malformedError("bind_off field plus bind_size field of " +
641 Twine(CmdName) + " command " +
642 Twine(LoadCommandIndex) + " extends past the end of "
644 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
648 if (DyldInfo.weak_bind_off > FileSize)
649 return malformedError("weak_bind_off field of " + Twine(CmdName) +
650 " command " + Twine(LoadCommandIndex) + " extends "
651 "past the end of the file");
652 BigSize = DyldInfo.weak_bind_off;
653 BigSize += DyldInfo.weak_bind_size;
654 if (BigSize > FileSize)
655 return malformedError("weak_bind_off field plus weak_bind_size field of " +
656 Twine(CmdName) + " command " +
657 Twine(LoadCommandIndex) + " extends past the end of "
659 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
660 DyldInfo.weak_bind_size,
661 "dyld weak bind info"))
663 if (DyldInfo.lazy_bind_off > FileSize)
664 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
665 " command " + Twine(LoadCommandIndex) + " extends "
666 "past the end of the file");
667 BigSize = DyldInfo.lazy_bind_off;
668 BigSize += DyldInfo.lazy_bind_size;
669 if (BigSize > FileSize)
670 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
671 Twine(CmdName) + " command " +
672 Twine(LoadCommandIndex) + " extends past the end of "
674 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
675 DyldInfo.lazy_bind_size,
676 "dyld lazy bind info"))
678 if (DyldInfo.export_off > FileSize)
679 return malformedError("export_off field of " + Twine(CmdName) +
680 " command " + Twine(LoadCommandIndex) + " extends "
681 "past the end of the file");
682 BigSize = DyldInfo.export_off;
683 BigSize += DyldInfo.export_size;
684 if (BigSize > FileSize)
685 return malformedError("export_off field plus export_size field of " +
686 Twine(CmdName) + " command " +
687 Twine(LoadCommandIndex) + " extends past the end of "
689 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
690 DyldInfo.export_size,
694 return Error::success();
697 static Error checkDylibCommand(const MachOObjectFile &Obj,
698 const MachOObjectFile::LoadCommandInfo &Load,
699 uint32_t LoadCommandIndex, const char *CmdName) {
700 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
701 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
702 CmdName + " cmdsize too small");
703 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
704 if (D.dylib.name < sizeof(MachO::dylib_command))
705 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
706 CmdName + " name.offset field too small, not past "
707 "the end of the dylib_command struct");
708 if (D.dylib.name >= D.cmdsize)
709 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
710 CmdName + " name.offset field extends past the end "
711 "of the load command");
712 // Make sure there is a null between the starting offset of the name and
713 // the end of the load command.
715 const char *P = (const char *)Load.Ptr;
716 for (i = D.dylib.name; i < D.cmdsize; i++)
720 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
721 CmdName + " library name extends past the end of the "
723 return Error::success();
726 static Error checkDylibIdCommand(const MachOObjectFile &Obj,
727 const MachOObjectFile::LoadCommandInfo &Load,
728 uint32_t LoadCommandIndex,
729 const char **LoadCmd) {
730 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
733 if (*LoadCmd != nullptr)
734 return malformedError("more than one LC_ID_DYLIB command");
735 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
736 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
737 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
740 return Error::success();
743 static Error checkDyldCommand(const MachOObjectFile &Obj,
744 const MachOObjectFile::LoadCommandInfo &Load,
745 uint32_t LoadCommandIndex, const char *CmdName) {
746 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
747 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
748 CmdName + " cmdsize too small");
749 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
750 if (D.name < sizeof(MachO::dylinker_command))
751 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
752 CmdName + " name.offset field too small, not past "
753 "the end of the dylinker_command struct");
754 if (D.name >= D.cmdsize)
755 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
756 CmdName + " name.offset field extends past the end "
757 "of the load command");
758 // Make sure there is a null between the starting offset of the name and
759 // the end of the load command.
761 const char *P = (const char *)Load.Ptr;
762 for (i = D.name; i < D.cmdsize; i++)
766 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
767 CmdName + " dyld name extends past the end of the "
769 return Error::success();
772 static Error checkVersCommand(const MachOObjectFile &Obj,
773 const MachOObjectFile::LoadCommandInfo &Load,
774 uint32_t LoadCommandIndex,
775 const char **LoadCmd, const char *CmdName) {
776 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
777 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
778 CmdName + " has incorrect cmdsize");
779 if (*LoadCmd != nullptr)
780 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
781 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
782 "LC_VERSION_MIN_WATCHOS command");
784 return Error::success();
787 static Error checkRpathCommand(const MachOObjectFile &Obj,
788 const MachOObjectFile::LoadCommandInfo &Load,
789 uint32_t LoadCommandIndex) {
790 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
791 return malformedError("load command " + Twine(LoadCommandIndex) +
792 " LC_RPATH cmdsize too small");
793 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
794 if (R.path < sizeof(MachO::rpath_command))
795 return malformedError("load command " + Twine(LoadCommandIndex) +
796 " LC_RPATH path.offset field too small, not past "
797 "the end of the rpath_command struct");
798 if (R.path >= R.cmdsize)
799 return malformedError("load command " + Twine(LoadCommandIndex) +
800 " LC_RPATH path.offset field extends past the end "
801 "of the load command");
802 // Make sure there is a null between the starting offset of the path and
803 // the end of the load command.
805 const char *P = (const char *)Load.Ptr;
806 for (i = R.path; i < R.cmdsize; i++)
810 return malformedError("load command " + Twine(LoadCommandIndex) +
811 " LC_RPATH library name extends past the end of the "
813 return Error::success();
816 static Error checkEncryptCommand(const MachOObjectFile &Obj,
817 const MachOObjectFile::LoadCommandInfo &Load,
818 uint32_t LoadCommandIndex,
819 uint64_t cryptoff, uint64_t cryptsize,
820 const char **LoadCmd, const char *CmdName) {
821 if (*LoadCmd != nullptr)
822 return malformedError("more than one LC_ENCRYPTION_INFO and or "
823 "LC_ENCRYPTION_INFO_64 command");
824 uint64_t FileSize = Obj.getData().size();
825 if (cryptoff > FileSize)
826 return malformedError("cryptoff field of " + Twine(CmdName) +
827 " command " + Twine(LoadCommandIndex) + " extends "
828 "past the end of the file");
829 uint64_t BigSize = cryptoff;
830 BigSize += cryptsize;
831 if (BigSize > FileSize)
832 return malformedError("cryptoff field plus cryptsize field of " +
833 Twine(CmdName) + " command " +
834 Twine(LoadCommandIndex) + " extends past the end of "
837 return Error::success();
840 static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
841 const MachOObjectFile::LoadCommandInfo &Load,
842 uint32_t LoadCommandIndex) {
843 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
844 return malformedError("load command " + Twine(LoadCommandIndex) +
845 " LC_LINKER_OPTION cmdsize too small");
846 MachO::linker_option_command L =
847 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
848 // Make sure the count of strings is correct.
849 const char *string = (const char *)Load.Ptr +
850 sizeof(struct MachO::linker_option_command);
851 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
854 while (*string == '\0' && left > 0) {
860 uint32_t NullPos = StringRef(string, left).find('\0');
861 uint32_t len = std::min(NullPos, left) + 1;
867 return malformedError("load command " + Twine(LoadCommandIndex) +
868 " LC_LINKER_OPTION string count " + Twine(L.count) +
869 " does not match number of strings");
870 return Error::success();
873 static Error checkSubCommand(const MachOObjectFile &Obj,
874 const MachOObjectFile::LoadCommandInfo &Load,
875 uint32_t LoadCommandIndex, const char *CmdName,
876 size_t SizeOfCmd, const char *CmdStructName,
877 uint32_t PathOffset, const char *PathFieldName) {
878 if (PathOffset < SizeOfCmd)
879 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
880 CmdName + " " + PathFieldName + ".offset field too "
881 "small, not past the end of the " + CmdStructName);
882 if (PathOffset >= Load.C.cmdsize)
883 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
884 CmdName + " " + PathFieldName + ".offset field "
885 "extends past the end of the load command");
886 // Make sure there is a null between the starting offset of the path and
887 // the end of the load command.
889 const char *P = (const char *)Load.Ptr;
890 for (i = PathOffset; i < Load.C.cmdsize; i++)
893 if (i >= Load.C.cmdsize)
894 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
895 CmdName + " " + PathFieldName + " name extends past "
896 "the end of the load command");
897 return Error::success();
900 static Error checkThreadCommand(const MachOObjectFile &Obj,
901 const MachOObjectFile::LoadCommandInfo &Load,
902 uint32_t LoadCommandIndex,
903 const char *CmdName) {
904 if (Load.C.cmdsize < sizeof(MachO::thread_command))
905 return malformedError("load command " + Twine(LoadCommandIndex) +
906 CmdName + " cmdsize too small");
907 MachO::thread_command T =
908 getStruct<MachO::thread_command>(Obj, Load.Ptr);
909 const char *state = Load.Ptr + sizeof(MachO::thread_command);
910 const char *end = Load.Ptr + T.cmdsize;
911 uint32_t nflavor = 0;
912 uint32_t cputype = getCPUType(Obj);
913 while (state < end) {
914 if(state + sizeof(uint32_t) > end)
915 return malformedError("load command " + Twine(LoadCommandIndex) +
916 "flavor in " + CmdName + " extends past end of "
919 memcpy(&flavor, state, sizeof(uint32_t));
920 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
921 sys::swapByteOrder(flavor);
922 state += sizeof(uint32_t);
924 if(state + sizeof(uint32_t) > end)
925 return malformedError("load command " + Twine(LoadCommandIndex) +
926 " count in " + CmdName + " extends past end of "
929 memcpy(&count, state, sizeof(uint32_t));
930 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
931 sys::swapByteOrder(count);
932 state += sizeof(uint32_t);
934 if (cputype == MachO::CPU_TYPE_X86_64) {
935 if (flavor == MachO::x86_THREAD_STATE64) {
936 if (count != MachO::x86_THREAD_STATE64_COUNT)
937 return malformedError("load command " + Twine(LoadCommandIndex) +
938 " count not x86_THREAD_STATE64_COUNT for "
939 "flavor number " + Twine(nflavor) + " which is "
940 "a x86_THREAD_STATE64 flavor in " + CmdName +
942 if (state + sizeof(MachO::x86_thread_state64_t) > end)
943 return malformedError("load command " + Twine(LoadCommandIndex) +
944 " x86_THREAD_STATE64 extends past end of "
945 "command in " + CmdName + " command");
946 state += sizeof(MachO::x86_thread_state64_t);
948 return malformedError("load command " + Twine(LoadCommandIndex) +
949 " unknown flavor (" + Twine(flavor) + ") for "
950 "flavor number " + Twine(nflavor) + " in " +
951 CmdName + " command");
953 } else if (cputype == MachO::CPU_TYPE_ARM) {
954 if (flavor == MachO::ARM_THREAD_STATE) {
955 if (count != MachO::ARM_THREAD_STATE_COUNT)
956 return malformedError("load command " + Twine(LoadCommandIndex) +
957 " count not ARM_THREAD_STATE_COUNT for "
958 "flavor number " + Twine(nflavor) + " which is "
959 "a ARM_THREAD_STATE flavor in " + CmdName +
961 if (state + sizeof(MachO::arm_thread_state32_t) > end)
962 return malformedError("load command " + Twine(LoadCommandIndex) +
963 " ARM_THREAD_STATE extends past end of "
964 "command in " + CmdName + " command");
965 state += sizeof(MachO::arm_thread_state32_t);
967 return malformedError("load command " + Twine(LoadCommandIndex) +
968 " unknown flavor (" + Twine(flavor) + ") for "
969 "flavor number " + Twine(nflavor) + " in " +
970 CmdName + " command");
972 } else if (cputype == MachO::CPU_TYPE_ARM64) {
973 if (flavor == MachO::ARM_THREAD_STATE64) {
974 if (count != MachO::ARM_THREAD_STATE64_COUNT)
975 return malformedError("load command " + Twine(LoadCommandIndex) +
976 " count not ARM_THREAD_STATE64_COUNT for "
977 "flavor number " + Twine(nflavor) + " which is "
978 "a ARM_THREAD_STATE64 flavor in " + CmdName +
980 if (state + sizeof(MachO::arm_thread_state64_t) > end)
981 return malformedError("load command " + Twine(LoadCommandIndex) +
982 " ARM_THREAD_STATE64 extends past end of "
983 "command in " + CmdName + " command");
984 state += sizeof(MachO::arm_thread_state64_t);
986 return malformedError("load command " + Twine(LoadCommandIndex) +
987 " unknown flavor (" + Twine(flavor) + ") for "
988 "flavor number " + Twine(nflavor) + " in " +
989 CmdName + " command");
991 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
992 if (flavor == MachO::PPC_THREAD_STATE) {
993 if (count != MachO::PPC_THREAD_STATE_COUNT)
994 return malformedError("load command " + Twine(LoadCommandIndex) +
995 " count not PPC_THREAD_STATE_COUNT for "
996 "flavor number " + Twine(nflavor) + " which is "
997 "a PPC_THREAD_STATE flavor in " + CmdName +
999 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1000 return malformedError("load command " + Twine(LoadCommandIndex) +
1001 " PPC_THREAD_STATE extends past end of "
1002 "command in " + CmdName + " command");
1003 state += sizeof(MachO::ppc_thread_state32_t);
1005 return malformedError("load command " + Twine(LoadCommandIndex) +
1006 " unknown flavor (" + Twine(flavor) + ") for "
1007 "flavor number " + Twine(nflavor) + " in " +
1008 CmdName + " command");
1011 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1012 "command " + Twine(LoadCommandIndex) + " for " +
1013 CmdName + " command can't be checked");
1017 return Error::success();
1020 static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1021 const MachOObjectFile::LoadCommandInfo
1023 uint32_t LoadCommandIndex,
1024 const char **LoadCmd,
1025 std::list<MachOElement> &Elements) {
1026 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1027 return malformedError("load command " + Twine(LoadCommandIndex) +
1028 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1029 if (*LoadCmd != nullptr)
1030 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1031 MachO::twolevel_hints_command Hints =
1032 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1033 uint64_t FileSize = Obj.getData().size();
1034 if (Hints.offset > FileSize)
1035 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1036 Twine(LoadCommandIndex) + " extends past the end of "
1038 uint64_t BigSize = Hints.nhints;
1039 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
1040 BigSize += Hints.offset;
1041 if (BigSize > FileSize)
1042 return malformedError("offset field plus nhints times sizeof(struct "
1043 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1044 Twine(LoadCommandIndex) + " extends past the end of "
1046 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1047 sizeof(MachO::twolevel_hint),
1050 *LoadCmd = Load.Ptr;
1051 return Error::success();
1054 // Returns true if the libObject code does not support the load command and its
1055 // contents. The cmd value it is treated as an unknown load command but with
1056 // an error message that says the cmd value is obsolete.
1057 static bool isLoadCommandObsolete(uint32_t cmd) {
1058 if (cmd == MachO::LC_SYMSEG ||
1059 cmd == MachO::LC_LOADFVMLIB ||
1060 cmd == MachO::LC_IDFVMLIB ||
1061 cmd == MachO::LC_IDENT ||
1062 cmd == MachO::LC_FVMFILE ||
1063 cmd == MachO::LC_PREPAGE ||
1064 cmd == MachO::LC_PREBOUND_DYLIB ||
1065 cmd == MachO::LC_TWOLEVEL_HINTS ||
1066 cmd == MachO::LC_PREBIND_CKSUM)
1071 Expected<std::unique_ptr<MachOObjectFile>>
1072 MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1073 bool Is64Bits, uint32_t UniversalCputype,
1074 uint32_t UniversalIndex) {
1075 Error Err = Error::success();
1076 std::unique_ptr<MachOObjectFile> Obj(
1077 new MachOObjectFile(std::move(Object), IsLittleEndian,
1078 Is64Bits, Err, UniversalCputype,
1081 return std::move(Err);
1082 return std::move(Obj);
1085 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1086 bool Is64bits, Error &Err,
1087 uint32_t UniversalCputype,
1088 uint32_t UniversalIndex)
1089 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
1090 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
1091 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
1092 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
1093 HasPageZeroSegment(false) {
1094 ErrorAsOutParameter ErrAsOutParam(&Err);
1095 uint64_t SizeOfHeaders;
1098 parseHeader(*this, Header64, Err);
1099 SizeOfHeaders = sizeof(MachO::mach_header_64);
1100 cputype = Header64.cputype;
1102 parseHeader(*this, Header, Err);
1103 SizeOfHeaders = sizeof(MachO::mach_header);
1104 cputype = Header.cputype;
1108 SizeOfHeaders += getHeader().sizeofcmds;
1109 if (getData().data() + SizeOfHeaders > getData().end()) {
1110 Err = malformedError("load commands extend past the end of the file");
1113 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1114 Err = malformedError("universal header architecture: " +
1115 Twine(UniversalIndex) + "'s cputype does not match "
1116 "object file's mach header");
1119 std::list<MachOElement> Elements;
1120 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
1122 uint32_t LoadCommandCount = getHeader().ncmds;
1123 LoadCommandInfo Load;
1124 if (LoadCommandCount != 0) {
1125 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
1128 Err = LoadOrErr.takeError();
1133 const char *DyldIdLoadCmd = nullptr;
1134 const char *FuncStartsLoadCmd = nullptr;
1135 const char *SplitInfoLoadCmd = nullptr;
1136 const char *CodeSignDrsLoadCmd = nullptr;
1137 const char *CodeSignLoadCmd = nullptr;
1138 const char *VersLoadCmd = nullptr;
1139 const char *SourceLoadCmd = nullptr;
1140 const char *EntryPointLoadCmd = nullptr;
1141 const char *EncryptLoadCmd = nullptr;
1142 const char *RoutinesLoadCmd = nullptr;
1143 const char *UnixThreadLoadCmd = nullptr;
1144 const char *TwoLevelHintsLoadCmd = nullptr;
1145 for (unsigned I = 0; I < LoadCommandCount; ++I) {
1147 if (Load.C.cmdsize % 8 != 0) {
1148 // We have a hack here to allow 64-bit Mach-O core files to have
1149 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1150 // allowed since the macOS kernel produces them.
1151 if (getHeader().filetype != MachO::MH_CORE ||
1152 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1153 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1159 if (Load.C.cmdsize % 4 != 0) {
1160 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1165 LoadCommands.push_back(Load);
1166 if (Load.C.cmd == MachO::LC_SYMTAB) {
1167 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
1169 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1170 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1173 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1174 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1175 "LC_DATA_IN_CODE", Elements,
1176 "data in code info")))
1178 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1179 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1180 "LC_LINKER_OPTIMIZATION_HINT",
1181 Elements, "linker optimization "
1184 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1185 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1186 "LC_FUNCTION_STARTS", Elements,
1187 "function starts data")))
1189 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1190 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1191 "LC_SEGMENT_SPLIT_INFO", Elements,
1192 "split info data")))
1194 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1195 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1196 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1197 "code signing RDs data")))
1199 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1200 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1201 "LC_CODE_SIGNATURE", Elements,
1202 "code signature data")))
1204 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1205 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1206 "LC_DYLD_INFO", Elements)))
1208 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1209 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1210 "LC_DYLD_INFO_ONLY", Elements)))
1212 } else if (Load.C.cmd == MachO::LC_UUID) {
1213 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1214 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1219 Err = malformedError("more than one LC_UUID command");
1222 UuidLoadCmd = Load.Ptr;
1223 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1224 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1226 *this, Load, Sections, HasPageZeroSegment, I,
1227 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
1229 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1230 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1232 *this, Load, Sections, HasPageZeroSegment, I,
1233 "LC_SEGMENT", SizeOfHeaders, Elements)))
1235 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1236 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1238 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1239 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1241 Libraries.push_back(Load.Ptr);
1242 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1243 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1245 Libraries.push_back(Load.Ptr);
1246 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1247 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1249 Libraries.push_back(Load.Ptr);
1250 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1251 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1253 Libraries.push_back(Load.Ptr);
1254 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1255 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1257 Libraries.push_back(Load.Ptr);
1258 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1259 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1261 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1262 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1264 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1265 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1267 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1268 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1269 "LC_VERSION_MIN_MACOSX")))
1271 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1272 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1273 "LC_VERSION_MIN_IPHONEOS")))
1275 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1276 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1277 "LC_VERSION_MIN_TVOS")))
1279 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1280 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1281 "LC_VERSION_MIN_WATCHOS")))
1283 } else if (Load.C.cmd == MachO::LC_RPATH) {
1284 if ((Err = checkRpathCommand(*this, Load, I)))
1286 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1287 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1288 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1289 " has incorrect cmdsize");
1292 if (SourceLoadCmd) {
1293 Err = malformedError("more than one LC_SOURCE_VERSION command");
1296 SourceLoadCmd = Load.Ptr;
1297 } else if (Load.C.cmd == MachO::LC_MAIN) {
1298 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1299 Err = malformedError("LC_MAIN command " + Twine(I) +
1300 " has incorrect cmdsize");
1303 if (EntryPointLoadCmd) {
1304 Err = malformedError("more than one LC_MAIN command");
1307 EntryPointLoadCmd = Load.Ptr;
1308 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1309 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1310 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1311 " has incorrect cmdsize");
1314 MachO::encryption_info_command E =
1315 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1316 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1317 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1319 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1320 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1321 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1322 " has incorrect cmdsize");
1325 MachO::encryption_info_command_64 E =
1326 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1327 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1328 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1330 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1331 if ((Err = checkLinkerOptCommand(*this, Load, I)))
1333 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1334 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1335 Err = malformedError("load command " + Twine(I) +
1336 " LC_SUB_FRAMEWORK cmdsize too small");
1339 MachO::sub_framework_command S =
1340 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1341 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1342 sizeof(MachO::sub_framework_command),
1343 "sub_framework_command", S.umbrella,
1346 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1347 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1348 Err = malformedError("load command " + Twine(I) +
1349 " LC_SUB_UMBRELLA cmdsize too small");
1352 MachO::sub_umbrella_command S =
1353 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1354 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1355 sizeof(MachO::sub_umbrella_command),
1356 "sub_umbrella_command", S.sub_umbrella,
1359 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1360 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1361 Err = malformedError("load command " + Twine(I) +
1362 " LC_SUB_LIBRARY cmdsize too small");
1365 MachO::sub_library_command S =
1366 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1367 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1368 sizeof(MachO::sub_library_command),
1369 "sub_library_command", S.sub_library,
1372 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1373 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1374 Err = malformedError("load command " + Twine(I) +
1375 " LC_SUB_CLIENT cmdsize too small");
1378 MachO::sub_client_command S =
1379 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1380 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1381 sizeof(MachO::sub_client_command),
1382 "sub_client_command", S.client, "client")))
1384 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1385 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1386 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1387 " has incorrect cmdsize");
1390 if (RoutinesLoadCmd) {
1391 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1395 RoutinesLoadCmd = Load.Ptr;
1396 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1397 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1398 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1399 " has incorrect cmdsize");
1402 if (RoutinesLoadCmd) {
1403 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1407 RoutinesLoadCmd = Load.Ptr;
1408 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1409 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1411 if (UnixThreadLoadCmd) {
1412 Err = malformedError("more than one LC_UNIXTHREAD command");
1415 UnixThreadLoadCmd = Load.Ptr;
1416 } else if (Load.C.cmd == MachO::LC_THREAD) {
1417 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1419 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1420 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1421 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1422 &TwoLevelHintsLoadCmd, Elements)))
1424 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1425 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1426 Twine(Load.C.cmd) + " is obsolete and not "
1430 // TODO: generate a error for unknown load commands by default. But still
1431 // need work out an approach to allow or not allow unknown values like this
1432 // as an option for some uses like lldb.
1433 if (I < LoadCommandCount - 1) {
1434 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
1437 Err = LoadOrErr.takeError();
1442 if (!SymtabLoadCmd) {
1443 if (DysymtabLoadCmd) {
1444 Err = malformedError("contains LC_DYSYMTAB load command without a "
1445 "LC_SYMTAB load command");
1448 } else if (DysymtabLoadCmd) {
1449 MachO::symtab_command Symtab =
1450 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
1451 MachO::dysymtab_command Dysymtab =
1452 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
1453 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1454 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
1455 "extends past the end of the symbol table");
1458 uint64_t BigSize = Dysymtab.ilocalsym;
1459 BigSize += Dysymtab.nlocalsym;
1460 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
1461 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1462 "command extends past the end of the symbol table");
1465 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1466 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
1467 "extends past the end of the symbol table");
1470 BigSize = Dysymtab.iextdefsym;
1471 BigSize += Dysymtab.nextdefsym;
1472 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
1473 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1474 "load command extends past the end of the symbol "
1478 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
1479 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
1480 "extends past the end of the symbol table");
1483 BigSize = Dysymtab.iundefsym;
1484 BigSize += Dysymtab.nundefsym;
1485 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
1486 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1487 " command extends past the end of the symbol table");
1491 if ((getHeader().filetype == MachO::MH_DYLIB ||
1492 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1493 DyldIdLoadCmd == nullptr) {
1494 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1498 assert(LoadCommands.size() == LoadCommandCount);
1500 Err = Error::success();
1503 Error MachOObjectFile::checkSymbolTable() const {
1506 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1509 MachO::mach_header H = MachOObjectFile::getHeader();
1516 uint64_t NValue = 0;
1517 uint32_t SymbolIndex = 0;
1518 MachO::symtab_command S = getSymtabLoadCommand();
1519 for (const SymbolRef &Symbol : symbols()) {
1520 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1522 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1523 NType = STE_64.n_type;
1524 NSect = STE_64.n_sect;
1525 NDesc = STE_64.n_desc;
1526 NStrx = STE_64.n_strx;
1527 NValue = STE_64.n_value;
1529 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1535 NValue = STE.n_value;
1537 if ((NType & MachO::N_STAB) == 0 &&
1538 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1539 if (NSect == 0 || NSect > Sections.size())
1540 return malformedError("bad section index: " + Twine((int)NSect) +
1541 " for symbol at index " + Twine(SymbolIndex));
1543 if ((NType & MachO::N_STAB) == 0 &&
1544 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1545 if (NValue >= S.strsize)
1546 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1547 "the end of string table, for N_INDR symbol at "
1548 "index " + Twine(SymbolIndex));
1550 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1551 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1552 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1553 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1554 if (LibraryOrdinal != 0 &&
1555 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1556 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1557 LibraryOrdinal - 1 >= Libraries.size() ) {
1558 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1559 " for symbol at index " + Twine(SymbolIndex));
1562 if (NStrx >= S.strsize)
1563 return malformedError("bad string table index: " + Twine((int)NStrx) +
1564 " past the end of string table, for symbol at "
1565 "index " + Twine(SymbolIndex));
1568 return Error::success();
1571 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1572 unsigned SymbolTableEntrySize = is64Bit() ?
1573 sizeof(MachO::nlist_64) :
1574 sizeof(MachO::nlist);
1575 Symb.p += SymbolTableEntrySize;
1578 Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1579 StringRef StringTable = getStringTableData();
1580 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1581 const char *Start = &StringTable.data()[Entry.n_strx];
1582 if (Start < getData().begin() || Start >= getData().end()) {
1583 return malformedError("bad string index: " + Twine(Entry.n_strx) +
1584 " for symbol at index " + Twine(getSymbolIndex(Symb)));
1586 return StringRef(Start);
1589 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1590 DataRefImpl DRI = Sec.getRawDataRefImpl();
1591 uint32_t Flags = getSectionFlags(*this, DRI);
1592 return Flags & MachO::SECTION_TYPE;
1595 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1597 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1598 return Entry.n_value;
1600 MachO::nlist Entry = getSymbolTableEntry(Sym);
1601 return Entry.n_value;
1604 // getIndirectName() returns the name of the alias'ed symbol who's string table
1605 // index is in the n_value field.
1606 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1607 StringRef &Res) const {
1608 StringRef StringTable = getStringTableData();
1609 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1610 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1611 return object_error::parse_failed;
1612 uint64_t NValue = getNValue(Symb);
1613 if (NValue >= StringTable.size())
1614 return object_error::parse_failed;
1615 const char *Start = &StringTable.data()[NValue];
1616 Res = StringRef(Start);
1617 return std::error_code();
1620 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1621 return getNValue(Sym);
1624 Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1625 return getSymbolValue(Sym);
1628 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
1629 uint32_t flags = getSymbolFlags(DRI);
1630 if (flags & SymbolRef::SF_Common) {
1631 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1632 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
1637 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1638 return getNValue(DRI);
1641 Expected<SymbolRef::Type>
1642 MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1643 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1644 uint8_t n_type = Entry.n_type;
1646 // If this is a STAB debugging symbol, we can do nothing more.
1647 if (n_type & MachO::N_STAB)
1648 return SymbolRef::ST_Debug;
1650 switch (n_type & MachO::N_TYPE) {
1651 case MachO::N_UNDF :
1652 return SymbolRef::ST_Unknown;
1653 case MachO::N_SECT :
1654 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
1656 return SecOrError.takeError();
1657 section_iterator Sec = *SecOrError;
1658 if (Sec->isData() || Sec->isBSS())
1659 return SymbolRef::ST_Data;
1660 return SymbolRef::ST_Function;
1662 return SymbolRef::ST_Other;
1665 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1666 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1668 uint8_t MachOType = Entry.n_type;
1669 uint16_t MachOFlags = Entry.n_desc;
1671 uint32_t Result = SymbolRef::SF_None;
1673 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1674 Result |= SymbolRef::SF_Indirect;
1676 if (MachOType & MachO::N_STAB)
1677 Result |= SymbolRef::SF_FormatSpecific;
1679 if (MachOType & MachO::N_EXT) {
1680 Result |= SymbolRef::SF_Global;
1681 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1683 Result |= SymbolRef::SF_Common;
1685 Result |= SymbolRef::SF_Undefined;
1688 if (!(MachOType & MachO::N_PEXT))
1689 Result |= SymbolRef::SF_Exported;
1692 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1693 Result |= SymbolRef::SF_Weak;
1695 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1696 Result |= SymbolRef::SF_Thumb;
1698 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1699 Result |= SymbolRef::SF_Absolute;
1704 Expected<section_iterator>
1705 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1706 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1707 uint8_t index = Entry.n_sect;
1710 return section_end();
1712 DRI.d.a = index - 1;
1713 if (DRI.d.a >= Sections.size()){
1714 return malformedError("bad section index: " + Twine((int)index) +
1715 " for symbol at index " + Twine(getSymbolIndex(Symb)));
1717 return section_iterator(SectionRef(DRI, this));
1720 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1721 MachO::nlist_base Entry =
1722 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
1723 return Entry.n_sect - 1;
1726 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1730 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1731 StringRef &Result) const {
1732 ArrayRef<char> Raw = getSectionRawName(Sec);
1733 Result = parseSegmentOrSectionName(Raw.data());
1734 return std::error_code();
1737 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1739 return getSection64(Sec).addr;
1740 return getSection(Sec).addr;
1743 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
1744 // In the case if a malformed Mach-O file where the section offset is past
1745 // the end of the file or some part of the section size is past the end of
1746 // the file return a size of zero or a size that covers the rest of the file
1747 // but does not extend past the end of the file.
1748 uint32_t SectOffset, SectType;
1752 MachO::section_64 Sect = getSection64(Sec);
1753 SectOffset = Sect.offset;
1754 SectSize = Sect.size;
1755 SectType = Sect.flags & MachO::SECTION_TYPE;
1757 MachO::section Sect = getSection(Sec);
1758 SectOffset = Sect.offset;
1759 SectSize = Sect.size;
1760 SectType = Sect.flags & MachO::SECTION_TYPE;
1762 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1764 uint64_t FileSize = getData().size();
1765 if (SectOffset > FileSize)
1767 if (FileSize - SectOffset < SectSize)
1768 return FileSize - SectOffset;
1772 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1773 StringRef &Res) const {
1778 MachO::section_64 Sect = getSection64(Sec);
1779 Offset = Sect.offset;
1782 MachO::section Sect = getSection(Sec);
1783 Offset = Sect.offset;
1787 Res = this->getData().substr(Offset, Size);
1788 return std::error_code();
1791 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1794 MachO::section_64 Sect = getSection64(Sec);
1797 MachO::section Sect = getSection(Sec);
1801 return uint64_t(1) << Align;
1804 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1808 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
1809 uint32_t Flags = getSectionFlags(*this, Sec);
1810 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
1813 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
1814 uint32_t Flags = getSectionFlags(*this, Sec);
1815 unsigned SectionType = Flags & MachO::SECTION_TYPE;
1816 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1817 !(SectionType == MachO::S_ZEROFILL ||
1818 SectionType == MachO::S_GB_ZEROFILL);
1821 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
1822 uint32_t Flags = getSectionFlags(*this, Sec);
1823 unsigned SectionType = Flags & MachO::SECTION_TYPE;
1824 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1825 (SectionType == MachO::S_ZEROFILL ||
1826 SectionType == MachO::S_GB_ZEROFILL);
1829 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1830 return Sec.getRawDataRefImpl().d.a;
1833 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
1834 // FIXME: Unimplemented.
1838 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1839 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1841 if (!getSectionName(Sec, SectName))
1842 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1846 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
1850 return relocation_iterator(RelocationRef(Ret, this));
1854 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
1857 MachO::section_64 Sect = getSection64(Sec);
1860 MachO::section Sect = getSection(Sec);
1867 return relocation_iterator(RelocationRef(Ret, this));
1870 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1874 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
1875 assert(getHeader().filetype == MachO::MH_OBJECT &&
1876 "Only implemented for MH_OBJECT");
1877 MachO::any_relocation_info RE = getRelocation(Rel);
1878 return getAnyRelocationAddress(RE);
1882 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1883 MachO::any_relocation_info RE = getRelocation(Rel);
1884 if (isRelocationScattered(RE))
1885 return symbol_end();
1887 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1888 bool isExtern = getPlainRelocationExternal(RE);
1890 return symbol_end();
1892 MachO::symtab_command S = getSymtabLoadCommand();
1893 unsigned SymbolTableEntrySize = is64Bit() ?
1894 sizeof(MachO::nlist_64) :
1895 sizeof(MachO::nlist);
1896 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
1898 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
1899 return symbol_iterator(SymbolRef(Sym, this));
1903 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
1904 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
1907 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
1908 MachO::any_relocation_info RE = getRelocation(Rel);
1909 return getAnyRelocationType(RE);
1912 void MachOObjectFile::getRelocationTypeName(
1913 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1915 uint64_t RType = getRelocationType(Rel);
1917 unsigned Arch = this->getArch();
1921 static const char *const Table[] = {
1922 "GENERIC_RELOC_VANILLA",
1923 "GENERIC_RELOC_PAIR",
1924 "GENERIC_RELOC_SECTDIFF",
1925 "GENERIC_RELOC_PB_LA_PTR",
1926 "GENERIC_RELOC_LOCAL_SECTDIFF",
1927 "GENERIC_RELOC_TLV" };
1935 case Triple::x86_64: {
1936 static const char *const Table[] = {
1937 "X86_64_RELOC_UNSIGNED",
1938 "X86_64_RELOC_SIGNED",
1939 "X86_64_RELOC_BRANCH",
1940 "X86_64_RELOC_GOT_LOAD",
1942 "X86_64_RELOC_SUBTRACTOR",
1943 "X86_64_RELOC_SIGNED_1",
1944 "X86_64_RELOC_SIGNED_2",
1945 "X86_64_RELOC_SIGNED_4",
1946 "X86_64_RELOC_TLV" };
1955 static const char *const Table[] = {
1956 "ARM_RELOC_VANILLA",
1958 "ARM_RELOC_SECTDIFF",
1959 "ARM_RELOC_LOCAL_SECTDIFF",
1960 "ARM_RELOC_PB_LA_PTR",
1962 "ARM_THUMB_RELOC_BR22",
1963 "ARM_THUMB_32BIT_BRANCH",
1965 "ARM_RELOC_HALF_SECTDIFF" };
1973 case Triple::aarch64: {
1974 static const char *const Table[] = {
1975 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
1976 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
1977 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
1978 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
1979 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
1980 "ARM64_RELOC_ADDEND"
1983 if (RType >= array_lengthof(Table))
1990 static const char *const Table[] = {
1991 "PPC_RELOC_VANILLA",
1999 "PPC_RELOC_SECTDIFF",
2000 "PPC_RELOC_PB_LA_PTR",
2001 "PPC_RELOC_HI16_SECTDIFF",
2002 "PPC_RELOC_LO16_SECTDIFF",
2003 "PPC_RELOC_HA16_SECTDIFF",
2005 "PPC_RELOC_LO14_SECTDIFF",
2006 "PPC_RELOC_LOCAL_SECTDIFF" };
2014 case Triple::UnknownArch:
2018 Result.append(res.begin(), res.end());
2021 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2022 MachO::any_relocation_info RE = getRelocation(Rel);
2023 return getAnyRelocationLength(RE);
2027 // guessLibraryShortName() is passed a name of a dynamic library and returns a
2028 // guess on what the short name is. Then name is returned as a substring of the
2029 // StringRef Name passed in. The name of the dynamic library is recognized as
2030 // a framework if it has one of the two following forms:
2031 // Foo.framework/Versions/A/Foo
2032 // Foo.framework/Foo
2033 // Where A and Foo can be any string. And may contain a trailing suffix
2034 // starting with an underbar. If the Name is recognized as a framework then
2035 // isFramework is set to true else it is set to false. If the Name has a
2036 // suffix then Suffix is set to the substring in Name that contains the suffix
2037 // else it is set to a NULL StringRef.
2039 // The Name of the dynamic library is recognized as a library name if it has
2040 // one of the two following forms:
2043 // The library may have a suffix trailing the name Foo of the form:
2044 // libFoo_profile.A.dylib
2045 // libFoo_profile.dylib
2047 // The Name of the dynamic library is also recognized as a library name if it
2048 // has the following form:
2051 // If the Name of the dynamic library is none of the forms above then a NULL
2052 // StringRef is returned.
2054 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2056 StringRef &Suffix) {
2057 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2058 size_t a, b, c, d, Idx;
2060 isFramework = false;
2061 Suffix = StringRef();
2063 // Pull off the last component and make Foo point to it
2064 a = Name.rfind('/');
2065 if (a == Name.npos || a == 0)
2067 Foo = Name.slice(a+1, Name.npos);
2069 // Look for a suffix starting with a '_'
2070 Idx = Foo.rfind('_');
2071 if (Idx != Foo.npos && Foo.size() >= 2) {
2072 Suffix = Foo.slice(Idx, Foo.npos);
2073 Foo = Foo.slice(0, Idx);
2076 // First look for the form Foo.framework/Foo
2077 b = Name.rfind('/', a);
2082 F = Name.slice(Idx, Idx + Foo.size());
2083 DotFramework = Name.slice(Idx + Foo.size(),
2084 Idx + Foo.size() + sizeof(".framework/")-1);
2085 if (F == Foo && DotFramework == ".framework/") {
2090 // Next look for the form Foo.framework/Versions/A/Foo
2093 c = Name.rfind('/', b);
2094 if (c == Name.npos || c == 0)
2096 V = Name.slice(c+1, Name.npos);
2097 if (!V.startswith("Versions/"))
2099 d = Name.rfind('/', c);
2104 F = Name.slice(Idx, Idx + Foo.size());
2105 DotFramework = Name.slice(Idx + Foo.size(),
2106 Idx + Foo.size() + sizeof(".framework/")-1);
2107 if (F == Foo && DotFramework == ".framework/") {
2113 // pull off the suffix after the "." and make a point to it
2114 a = Name.rfind('.');
2115 if (a == Name.npos || a == 0)
2117 Dylib = Name.slice(a, Name.npos);
2118 if (Dylib != ".dylib")
2121 // First pull off the version letter for the form Foo.A.dylib if any.
2123 Dot = Name.slice(a-2, a-1);
2128 b = Name.rfind('/', a);
2133 // ignore any suffix after an underbar like Foo_profile.A.dylib
2134 Idx = Name.find('_', b);
2135 if (Idx != Name.npos && Idx != b) {
2136 Lib = Name.slice(b, Idx);
2137 Suffix = Name.slice(Idx, a);
2140 Lib = Name.slice(b, a);
2141 // There are incorrect library names of the form:
2142 // libATS.A_profile.dylib so check for these.
2143 if (Lib.size() >= 3) {
2144 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2146 Lib = Lib.slice(0, Lib.size()-2);
2151 Qtx = Name.slice(a, Name.npos);
2154 b = Name.rfind('/', a);
2156 Lib = Name.slice(0, a);
2158 Lib = Name.slice(b+1, a);
2159 // There are library names of the form: QT.A.qtx so check for these.
2160 if (Lib.size() >= 3) {
2161 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2163 Lib = Lib.slice(0, Lib.size()-2);
2168 // getLibraryShortNameByIndex() is used to get the short name of the library
2169 // for an undefined symbol in a linked Mach-O binary that was linked with the
2170 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2171 // It is passed the index (0 - based) of the library as translated from
2172 // GET_LIBRARY_ORDINAL (1 - based).
2173 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
2174 StringRef &Res) const {
2175 if (Index >= Libraries.size())
2176 return object_error::parse_failed;
2178 // If the cache of LibrariesShortNames is not built up do that first for
2179 // all the Libraries.
2180 if (LibrariesShortNames.size() == 0) {
2181 for (unsigned i = 0; i < Libraries.size(); i++) {
2182 MachO::dylib_command D =
2183 getStruct<MachO::dylib_command>(*this, Libraries[i]);
2184 if (D.dylib.name >= D.cmdsize)
2185 return object_error::parse_failed;
2186 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
2187 StringRef Name = StringRef(P);
2188 if (D.dylib.name+Name.size() >= D.cmdsize)
2189 return object_error::parse_failed;
2192 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
2193 if (shortName.empty())
2194 LibrariesShortNames.push_back(Name);
2196 LibrariesShortNames.push_back(shortName);
2200 Res = LibrariesShortNames[Index];
2201 return std::error_code();
2205 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2207 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2208 return section_iterator(SectionRef(Sec, this));
2211 basic_symbol_iterator MachOObjectFile::symbol_begin() const {
2213 MachO::symtab_command Symtab = getSymtabLoadCommand();
2214 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2215 return basic_symbol_iterator(SymbolRef(DRI, this));
2217 return getSymbolByIndex(0);
2220 basic_symbol_iterator MachOObjectFile::symbol_end() const {
2222 MachO::symtab_command Symtab = getSymtabLoadCommand();
2223 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2224 return basic_symbol_iterator(SymbolRef(DRI, this));
2226 unsigned SymbolTableEntrySize = is64Bit() ?
2227 sizeof(MachO::nlist_64) :
2228 sizeof(MachO::nlist);
2229 unsigned Offset = Symtab.symoff +
2230 Symtab.nsyms * SymbolTableEntrySize;
2231 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2232 return basic_symbol_iterator(SymbolRef(DRI, this));
2235 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
2236 MachO::symtab_command Symtab = getSymtabLoadCommand();
2237 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2238 report_fatal_error("Requested symbol index is out of range.");
2239 unsigned SymbolTableEntrySize =
2240 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2242 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2243 DRI.p += Index * SymbolTableEntrySize;
2244 return basic_symbol_iterator(SymbolRef(DRI, this));
2247 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2248 MachO::symtab_command Symtab = getSymtabLoadCommand();
2250 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2251 unsigned SymbolTableEntrySize =
2252 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2253 DataRefImpl DRIstart;
2254 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2255 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2259 section_iterator MachOObjectFile::section_begin() const {
2261 return section_iterator(SectionRef(DRI, this));
2264 section_iterator MachOObjectFile::section_end() const {
2266 DRI.d.a = Sections.size();
2267 return section_iterator(SectionRef(DRI, this));
2270 uint8_t MachOObjectFile::getBytesInAddress() const {
2271 return is64Bit() ? 8 : 4;
2274 StringRef MachOObjectFile::getFileFormatName() const {
2275 unsigned CPUType = getCPUType(*this);
2278 case llvm::MachO::CPU_TYPE_I386:
2279 return "Mach-O 32-bit i386";
2280 case llvm::MachO::CPU_TYPE_ARM:
2281 return "Mach-O arm";
2282 case llvm::MachO::CPU_TYPE_POWERPC:
2283 return "Mach-O 32-bit ppc";
2285 return "Mach-O 32-bit unknown";
2290 case llvm::MachO::CPU_TYPE_X86_64:
2291 return "Mach-O 64-bit x86-64";
2292 case llvm::MachO::CPU_TYPE_ARM64:
2293 return "Mach-O arm64";
2294 case llvm::MachO::CPU_TYPE_POWERPC64:
2295 return "Mach-O 64-bit ppc64";
2297 return "Mach-O 64-bit unknown";
2301 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2303 case llvm::MachO::CPU_TYPE_I386:
2305 case llvm::MachO::CPU_TYPE_X86_64:
2306 return Triple::x86_64;
2307 case llvm::MachO::CPU_TYPE_ARM:
2309 case llvm::MachO::CPU_TYPE_ARM64:
2310 return Triple::aarch64;
2311 case llvm::MachO::CPU_TYPE_POWERPC:
2313 case llvm::MachO::CPU_TYPE_POWERPC64:
2314 return Triple::ppc64;
2316 return Triple::UnknownArch;
2320 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2321 const char **McpuDefault,
2322 const char **ArchFlag) {
2324 *McpuDefault = nullptr;
2326 *ArchFlag = nullptr;
2329 case MachO::CPU_TYPE_I386:
2330 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2331 case MachO::CPU_SUBTYPE_I386_ALL:
2334 return Triple("i386-apple-darwin");
2338 case MachO::CPU_TYPE_X86_64:
2339 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2340 case MachO::CPU_SUBTYPE_X86_64_ALL:
2342 *ArchFlag = "x86_64";
2343 return Triple("x86_64-apple-darwin");
2344 case MachO::CPU_SUBTYPE_X86_64_H:
2346 *ArchFlag = "x86_64h";
2347 return Triple("x86_64h-apple-darwin");
2351 case MachO::CPU_TYPE_ARM:
2352 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2353 case MachO::CPU_SUBTYPE_ARM_V4T:
2355 *ArchFlag = "armv4t";
2356 return Triple("armv4t-apple-darwin");
2357 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2359 *ArchFlag = "armv5e";
2360 return Triple("armv5e-apple-darwin");
2361 case MachO::CPU_SUBTYPE_ARM_XSCALE:
2363 *ArchFlag = "xscale";
2364 return Triple("xscale-apple-darwin");
2365 case MachO::CPU_SUBTYPE_ARM_V6:
2367 *ArchFlag = "armv6";
2368 return Triple("armv6-apple-darwin");
2369 case MachO::CPU_SUBTYPE_ARM_V6M:
2371 *McpuDefault = "cortex-m0";
2373 *ArchFlag = "armv6m";
2374 return Triple("armv6m-apple-darwin");
2375 case MachO::CPU_SUBTYPE_ARM_V7:
2377 *ArchFlag = "armv7";
2378 return Triple("armv7-apple-darwin");
2379 case MachO::CPU_SUBTYPE_ARM_V7EM:
2381 *McpuDefault = "cortex-m4";
2383 *ArchFlag = "armv7em";
2384 return Triple("thumbv7em-apple-darwin");
2385 case MachO::CPU_SUBTYPE_ARM_V7K:
2387 *ArchFlag = "armv7k";
2388 return Triple("armv7k-apple-darwin");
2389 case MachO::CPU_SUBTYPE_ARM_V7M:
2391 *McpuDefault = "cortex-m3";
2393 *ArchFlag = "armv7m";
2394 return Triple("thumbv7m-apple-darwin");
2395 case MachO::CPU_SUBTYPE_ARM_V7S:
2397 *ArchFlag = "armv7s";
2398 return Triple("armv7s-apple-darwin");
2402 case MachO::CPU_TYPE_ARM64:
2403 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2404 case MachO::CPU_SUBTYPE_ARM64_ALL:
2406 *ArchFlag = "arm64";
2407 return Triple("arm64-apple-darwin");
2411 case MachO::CPU_TYPE_POWERPC:
2412 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2413 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2416 return Triple("ppc-apple-darwin");
2420 case MachO::CPU_TYPE_POWERPC64:
2421 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2422 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2424 *ArchFlag = "ppc64";
2425 return Triple("ppc64-apple-darwin");
2434 Triple MachOObjectFile::getHostArch() {
2435 return Triple(sys::getDefaultTargetTriple());
2438 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2439 return StringSwitch<bool>(ArchFlag)
2441 .Case("x86_64", true)
2442 .Case("x86_64h", true)
2443 .Case("armv4t", true)
2445 .Case("armv5e", true)
2446 .Case("armv6", true)
2447 .Case("armv6m", true)
2448 .Case("armv7", true)
2449 .Case("armv7em", true)
2450 .Case("armv7k", true)
2451 .Case("armv7m", true)
2452 .Case("armv7s", true)
2453 .Case("arm64", true)
2455 .Case("ppc64", true)
2459 unsigned MachOObjectFile::getArch() const {
2460 return getArch(getCPUType(*this));
2463 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2464 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2467 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2470 return section_rel_begin(DRI);
2473 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2476 return section_rel_end(DRI);
2479 dice_iterator MachOObjectFile::begin_dices() const {
2481 if (!DataInCodeLoadCmd)
2482 return dice_iterator(DiceRef(DRI, this));
2484 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2485 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2486 return dice_iterator(DiceRef(DRI, this));
2489 dice_iterator MachOObjectFile::end_dices() const {
2491 if (!DataInCodeLoadCmd)
2492 return dice_iterator(DiceRef(DRI, this));
2494 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2495 unsigned Offset = DicLC.dataoff + DicLC.datasize;
2496 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2497 return dice_iterator(DiceRef(DRI, this));
2500 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
2501 : Trie(T), Malformed(false), Done(false) {}
2503 void ExportEntry::moveToFirst() {
2505 pushDownUntilBottom();
2508 void ExportEntry::moveToEnd() {
2513 bool ExportEntry::operator==(const ExportEntry &Other) const {
2514 // Common case, one at end, other iterating from begin.
2515 if (Done || Other.Done)
2516 return (Done == Other.Done);
2517 // Not equal if different stack sizes.
2518 if (Stack.size() != Other.Stack.size())
2520 // Not equal if different cumulative strings.
2521 if (!CumulativeString.equals(Other.CumulativeString))
2523 // Equal if all nodes in both stacks match.
2524 for (unsigned i=0; i < Stack.size(); ++i) {
2525 if (Stack[i].Start != Other.Stack[i].Start)
2531 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
2533 uint64_t Result = decodeULEB128(Ptr, &Count);
2535 if (Ptr > Trie.end()) {
2542 StringRef ExportEntry::name() const {
2543 return CumulativeString;
2546 uint64_t ExportEntry::flags() const {
2547 return Stack.back().Flags;
2550 uint64_t ExportEntry::address() const {
2551 return Stack.back().Address;
2554 uint64_t ExportEntry::other() const {
2555 return Stack.back().Other;
2558 StringRef ExportEntry::otherName() const {
2559 const char* ImportName = Stack.back().ImportName;
2561 return StringRef(ImportName);
2565 uint32_t ExportEntry::nodeOffset() const {
2566 return Stack.back().Start - Trie.begin();
2569 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2570 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
2571 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
2572 ParentStringLength(0), IsExportNode(false) {}
2574 void ExportEntry::pushNode(uint64_t offset) {
2575 const uint8_t *Ptr = Trie.begin() + offset;
2576 NodeState State(Ptr);
2577 uint64_t ExportInfoSize = readULEB128(State.Current);
2578 State.IsExportNode = (ExportInfoSize != 0);
2579 const uint8_t* Children = State.Current + ExportInfoSize;
2580 if (State.IsExportNode) {
2581 State.Flags = readULEB128(State.Current);
2582 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2584 State.Other = readULEB128(State.Current); // dylib ordinal
2585 State.ImportName = reinterpret_cast<const char*>(State.Current);
2587 State.Address = readULEB128(State.Current);
2588 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
2589 State.Other = readULEB128(State.Current);
2592 State.ChildCount = *Children;
2593 State.Current = Children + 1;
2594 State.NextChildIndex = 0;
2595 State.ParentStringLength = CumulativeString.size();
2596 Stack.push_back(State);
2599 void ExportEntry::pushDownUntilBottom() {
2600 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2601 NodeState &Top = Stack.back();
2602 CumulativeString.resize(Top.ParentStringLength);
2603 for (;*Top.Current != 0; Top.Current++) {
2604 char C = *Top.Current;
2605 CumulativeString.push_back(C);
2608 uint64_t childNodeIndex = readULEB128(Top.Current);
2609 Top.NextChildIndex += 1;
2610 pushNode(childNodeIndex);
2612 if (!Stack.back().IsExportNode) {
2618 // We have a trie data structure and need a way to walk it that is compatible
2619 // with the C++ iterator model. The solution is a non-recursive depth first
2620 // traversal where the iterator contains a stack of parent nodes along with a
2621 // string that is the accumulation of all edge strings along the parent chain
2624 // There is one "export" node for each exported symbol. But because some
2625 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
2626 // node may have child nodes too.
2628 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
2629 // child until hitting a node with no children (which is an export node or
2630 // else the trie is malformed). On the way down, each node is pushed on the
2631 // stack ivar. If there is no more ways down, it pops up one and tries to go
2632 // down a sibling path until a childless node is reached.
2633 void ExportEntry::moveNext() {
2634 if (Stack.empty() || !Stack.back().IsExportNode) {
2641 while (!Stack.empty()) {
2642 NodeState &Top = Stack.back();
2643 if (Top.NextChildIndex < Top.ChildCount) {
2644 pushDownUntilBottom();
2645 // Now at the next export node.
2648 if (Top.IsExportNode) {
2649 // This node has no children but is itself an export node.
2650 CumulativeString.resize(Top.ParentStringLength);
2659 iterator_range<export_iterator>
2660 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
2661 ExportEntry Start(Trie);
2662 if (Trie.size() == 0)
2665 Start.moveToFirst();
2667 ExportEntry Finish(Trie);
2670 return make_range(export_iterator(Start), export_iterator(Finish));
2673 iterator_range<export_iterator> MachOObjectFile::exports() const {
2674 return exports(getDyldInfoExportsTrie());
2677 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
2678 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2679 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2680 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
2682 void MachORebaseEntry::moveToFirst() {
2683 Ptr = Opcodes.begin();
2687 void MachORebaseEntry::moveToEnd() {
2688 Ptr = Opcodes.end();
2689 RemainingLoopCount = 0;
2693 void MachORebaseEntry::moveNext() {
2694 // If in the middle of some loop, move to next rebasing in loop.
2695 SegmentOffset += AdvanceAmount;
2696 if (RemainingLoopCount) {
2697 --RemainingLoopCount;
2700 if (Ptr == Opcodes.end()) {
2705 while (More && !Malformed) {
2706 // Parse next opcode and set up next loop.
2707 uint8_t Byte = *Ptr++;
2708 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2709 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
2711 case MachO::REBASE_OPCODE_DONE:
2715 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
2717 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2718 RebaseType = ImmValue;
2721 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2722 << "RebaseType=" << (int) RebaseType << "\n");
2724 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2725 SegmentIndex = ImmValue;
2726 SegmentOffset = readULEB128();
2729 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2730 << "SegmentIndex=" << SegmentIndex << ", "
2731 << format("SegmentOffset=0x%06X", SegmentOffset)
2734 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
2735 SegmentOffset += readULEB128();
2736 DEBUG_WITH_TYPE("mach-o-rebase",
2737 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
2738 << format("SegmentOffset=0x%06X",
2739 SegmentOffset) << "\n");
2741 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
2742 SegmentOffset += ImmValue * PointerSize;
2743 DEBUG_WITH_TYPE("mach-o-rebase",
2744 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
2745 << format("SegmentOffset=0x%06X",
2746 SegmentOffset) << "\n");
2748 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
2749 AdvanceAmount = PointerSize;
2750 RemainingLoopCount = ImmValue - 1;
2753 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
2754 << format("SegmentOffset=0x%06X", SegmentOffset)
2755 << ", AdvanceAmount=" << AdvanceAmount
2756 << ", RemainingLoopCount=" << RemainingLoopCount
2759 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
2760 AdvanceAmount = PointerSize;
2761 RemainingLoopCount = readULEB128() - 1;
2764 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
2765 << format("SegmentOffset=0x%06X", SegmentOffset)
2766 << ", AdvanceAmount=" << AdvanceAmount
2767 << ", RemainingLoopCount=" << RemainingLoopCount
2770 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
2771 AdvanceAmount = readULEB128() + PointerSize;
2772 RemainingLoopCount = 0;
2775 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
2776 << format("SegmentOffset=0x%06X", SegmentOffset)
2777 << ", AdvanceAmount=" << AdvanceAmount
2778 << ", RemainingLoopCount=" << RemainingLoopCount
2781 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
2782 RemainingLoopCount = readULEB128() - 1;
2783 AdvanceAmount = readULEB128() + PointerSize;
2786 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
2787 << format("SegmentOffset=0x%06X", SegmentOffset)
2788 << ", AdvanceAmount=" << AdvanceAmount
2789 << ", RemainingLoopCount=" << RemainingLoopCount
2798 uint64_t MachORebaseEntry::readULEB128() {
2800 uint64_t Result = decodeULEB128(Ptr, &Count);
2802 if (Ptr > Opcodes.end()) {
2803 Ptr = Opcodes.end();
2809 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
2811 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
2813 StringRef MachORebaseEntry::typeName() const {
2814 switch (RebaseType) {
2815 case MachO::REBASE_TYPE_POINTER:
2817 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
2818 return "text abs32";
2819 case MachO::REBASE_TYPE_TEXT_PCREL32:
2820 return "text rel32";
2825 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
2826 #ifdef EXPENSIVE_CHECKS
2827 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2829 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
2831 return (Ptr == Other.Ptr) &&
2832 (RemainingLoopCount == Other.RemainingLoopCount) &&
2833 (Done == Other.Done);
2836 iterator_range<rebase_iterator>
2837 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
2838 MachORebaseEntry Start(Opcodes, is64);
2839 Start.moveToFirst();
2841 MachORebaseEntry Finish(Opcodes, is64);
2844 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
2847 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
2848 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
2851 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
2852 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2853 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
2854 BindType(0), PointerSize(is64Bit ? 8 : 4),
2855 TableKind(BK), Malformed(false), Done(false) {}
2857 void MachOBindEntry::moveToFirst() {
2858 Ptr = Opcodes.begin();
2862 void MachOBindEntry::moveToEnd() {
2863 Ptr = Opcodes.end();
2864 RemainingLoopCount = 0;
2868 void MachOBindEntry::moveNext() {
2869 // If in the middle of some loop, move to next binding in loop.
2870 SegmentOffset += AdvanceAmount;
2871 if (RemainingLoopCount) {
2872 --RemainingLoopCount;
2875 if (Ptr == Opcodes.end()) {
2880 while (More && !Malformed) {
2881 // Parse next opcode and set up next loop.
2882 uint8_t Byte = *Ptr++;
2883 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
2884 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
2885 int8_t SignExtended;
2886 const uint8_t *SymStart;
2888 case MachO::BIND_OPCODE_DONE:
2889 if (TableKind == Kind::Lazy) {
2890 // Lazying bindings have a DONE opcode between entries. Need to ignore
2891 // it to advance to next entry. But need not if this is last entry.
2892 bool NotLastEntry = false;
2893 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
2895 NotLastEntry = true;
2904 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
2906 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
2910 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
2911 << "Ordinal=" << Ordinal << "\n");
2913 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
2914 Ordinal = readULEB128();
2917 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
2918 << "Ordinal=" << Ordinal << "\n");
2920 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
2922 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
2923 Ordinal = SignExtended;
2928 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
2929 << "Ordinal=" << Ordinal << "\n");
2931 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
2937 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
2942 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
2943 << "SymbolName=" << SymbolName << "\n");
2944 if (TableKind == Kind::Weak) {
2945 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
2949 case MachO::BIND_OPCODE_SET_TYPE_IMM:
2950 BindType = ImmValue;
2953 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
2954 << "BindType=" << (int)BindType << "\n");
2956 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
2957 Addend = readSLEB128();
2958 if (TableKind == Kind::Lazy)
2962 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
2963 << "Addend=" << Addend << "\n");
2965 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2966 SegmentIndex = ImmValue;
2967 SegmentOffset = readULEB128();
2970 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2971 << "SegmentIndex=" << SegmentIndex << ", "
2972 << format("SegmentOffset=0x%06X", SegmentOffset)
2975 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2976 SegmentOffset += readULEB128();
2977 DEBUG_WITH_TYPE("mach-o-bind",
2978 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2979 << format("SegmentOffset=0x%06X",
2980 SegmentOffset) << "\n");
2982 case MachO::BIND_OPCODE_DO_BIND:
2983 AdvanceAmount = PointerSize;
2984 RemainingLoopCount = 0;
2985 DEBUG_WITH_TYPE("mach-o-bind",
2986 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2987 << format("SegmentOffset=0x%06X",
2988 SegmentOffset) << "\n");
2990 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2991 AdvanceAmount = readULEB128() + PointerSize;
2992 RemainingLoopCount = 0;
2993 if (TableKind == Kind::Lazy)
2997 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
2998 << format("SegmentOffset=0x%06X", SegmentOffset)
2999 << ", AdvanceAmount=" << AdvanceAmount
3000 << ", RemainingLoopCount=" << RemainingLoopCount
3003 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
3004 AdvanceAmount = ImmValue * PointerSize + PointerSize;
3005 RemainingLoopCount = 0;
3006 if (TableKind == Kind::Lazy)
3008 DEBUG_WITH_TYPE("mach-o-bind",
3010 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3011 << format("SegmentOffset=0x%06X",
3012 SegmentOffset) << "\n");
3014 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3015 RemainingLoopCount = readULEB128() - 1;
3016 AdvanceAmount = readULEB128() + PointerSize;
3017 if (TableKind == Kind::Lazy)
3021 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3022 << format("SegmentOffset=0x%06X", SegmentOffset)
3023 << ", AdvanceAmount=" << AdvanceAmount
3024 << ", RemainingLoopCount=" << RemainingLoopCount
3033 uint64_t MachOBindEntry::readULEB128() {
3035 uint64_t Result = decodeULEB128(Ptr, &Count);
3037 if (Ptr > Opcodes.end()) {
3038 Ptr = Opcodes.end();
3044 int64_t MachOBindEntry::readSLEB128() {
3046 int64_t Result = decodeSLEB128(Ptr, &Count);
3048 if (Ptr > Opcodes.end()) {
3049 Ptr = Opcodes.end();
3055 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3057 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3059 StringRef MachOBindEntry::typeName() const {
3061 case MachO::BIND_TYPE_POINTER:
3063 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3064 return "text abs32";
3065 case MachO::BIND_TYPE_TEXT_PCREL32:
3066 return "text rel32";
3071 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3073 int64_t MachOBindEntry::addend() const { return Addend; }
3075 uint32_t MachOBindEntry::flags() const { return Flags; }
3077 int MachOBindEntry::ordinal() const { return Ordinal; }
3079 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3080 #ifdef EXPENSIVE_CHECKS
3081 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3083 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3085 return (Ptr == Other.Ptr) &&
3086 (RemainingLoopCount == Other.RemainingLoopCount) &&
3087 (Done == Other.Done);
3090 iterator_range<bind_iterator>
3091 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
3092 MachOBindEntry::Kind BKind) {
3093 MachOBindEntry Start(Opcodes, is64, BKind);
3094 Start.moveToFirst();
3096 MachOBindEntry Finish(Opcodes, is64, BKind);
3099 return make_range(bind_iterator(Start), bind_iterator(Finish));
3102 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
3103 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
3104 MachOBindEntry::Kind::Regular);
3107 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
3108 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
3109 MachOBindEntry::Kind::Lazy);
3112 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
3113 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
3114 MachOBindEntry::Kind::Weak);
3117 MachOObjectFile::load_command_iterator
3118 MachOObjectFile::begin_load_commands() const {
3119 return LoadCommands.begin();
3122 MachOObjectFile::load_command_iterator
3123 MachOObjectFile::end_load_commands() const {
3124 return LoadCommands.end();
3127 iterator_range<MachOObjectFile::load_command_iterator>
3128 MachOObjectFile::load_commands() const {
3129 return make_range(begin_load_commands(), end_load_commands());
3133 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
3134 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
3135 return parseSegmentOrSectionName(Raw.data());
3139 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
3140 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
3141 const section_base *Base =
3142 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
3143 return makeArrayRef(Base->sectname);
3147 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
3148 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
3149 const section_base *Base =
3150 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
3151 return makeArrayRef(Base->segname);
3155 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
3157 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
3159 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
3162 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
3163 const MachO::any_relocation_info &RE) const {
3164 if (isLittleEndian())
3165 return RE.r_word1 & 0xffffff;
3166 return RE.r_word1 >> 8;
3169 bool MachOObjectFile::getPlainRelocationExternal(
3170 const MachO::any_relocation_info &RE) const {
3171 if (isLittleEndian())
3172 return (RE.r_word1 >> 27) & 1;
3173 return (RE.r_word1 >> 4) & 1;
3176 bool MachOObjectFile::getScatteredRelocationScattered(
3177 const MachO::any_relocation_info &RE) const {
3178 return RE.r_word0 >> 31;
3181 uint32_t MachOObjectFile::getScatteredRelocationValue(
3182 const MachO::any_relocation_info &RE) const {
3186 uint32_t MachOObjectFile::getScatteredRelocationType(
3187 const MachO::any_relocation_info &RE) const {
3188 return (RE.r_word0 >> 24) & 0xf;
3191 unsigned MachOObjectFile::getAnyRelocationAddress(
3192 const MachO::any_relocation_info &RE) const {
3193 if (isRelocationScattered(RE))
3194 return getScatteredRelocationAddress(RE);
3195 return getPlainRelocationAddress(RE);
3198 unsigned MachOObjectFile::getAnyRelocationPCRel(
3199 const MachO::any_relocation_info &RE) const {
3200 if (isRelocationScattered(RE))
3201 return getScatteredRelocationPCRel(RE);
3202 return getPlainRelocationPCRel(*this, RE);
3205 unsigned MachOObjectFile::getAnyRelocationLength(
3206 const MachO::any_relocation_info &RE) const {
3207 if (isRelocationScattered(RE))
3208 return getScatteredRelocationLength(RE);
3209 return getPlainRelocationLength(*this, RE);
3213 MachOObjectFile::getAnyRelocationType(
3214 const MachO::any_relocation_info &RE) const {
3215 if (isRelocationScattered(RE))
3216 return getScatteredRelocationType(RE);
3217 return getPlainRelocationType(*this, RE);
3221 MachOObjectFile::getAnyRelocationSection(
3222 const MachO::any_relocation_info &RE) const {
3223 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
3224 return *section_end();
3225 unsigned SecNum = getPlainRelocationSymbolNum(RE);
3226 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
3227 return *section_end();
3229 DRI.d.a = SecNum - 1;
3230 return SectionRef(DRI, this);
3233 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
3234 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
3235 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
3238 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
3239 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
3240 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
3243 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
3244 unsigned Index) const {
3245 const char *Sec = getSectionPtr(*this, L, Index);
3246 return getStruct<MachO::section>(*this, Sec);
3249 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
3250 unsigned Index) const {
3251 const char *Sec = getSectionPtr(*this, L, Index);
3252 return getStruct<MachO::section_64>(*this, Sec);
3256 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
3257 const char *P = reinterpret_cast<const char *>(DRI.p);
3258 return getStruct<MachO::nlist>(*this, P);
3262 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
3263 const char *P = reinterpret_cast<const char *>(DRI.p);
3264 return getStruct<MachO::nlist_64>(*this, P);
3267 MachO::linkedit_data_command
3268 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
3269 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
3272 MachO::segment_command
3273 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
3274 return getStruct<MachO::segment_command>(*this, L.Ptr);
3277 MachO::segment_command_64
3278 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
3279 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
3282 MachO::linker_option_command
3283 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
3284 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
3287 MachO::version_min_command
3288 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
3289 return getStruct<MachO::version_min_command>(*this, L.Ptr);
3292 MachO::dylib_command
3293 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
3294 return getStruct<MachO::dylib_command>(*this, L.Ptr);
3297 MachO::dyld_info_command
3298 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
3299 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
3302 MachO::dylinker_command
3303 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
3304 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
3308 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
3309 return getStruct<MachO::uuid_command>(*this, L.Ptr);
3312 MachO::rpath_command
3313 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
3314 return getStruct<MachO::rpath_command>(*this, L.Ptr);
3317 MachO::source_version_command
3318 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
3319 return getStruct<MachO::source_version_command>(*this, L.Ptr);
3322 MachO::entry_point_command
3323 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
3324 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
3327 MachO::encryption_info_command
3328 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
3329 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
3332 MachO::encryption_info_command_64
3333 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
3334 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
3337 MachO::sub_framework_command
3338 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
3339 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
3342 MachO::sub_umbrella_command
3343 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
3344 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
3347 MachO::sub_library_command
3348 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
3349 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
3352 MachO::sub_client_command
3353 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
3354 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
3357 MachO::routines_command
3358 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
3359 return getStruct<MachO::routines_command>(*this, L.Ptr);
3362 MachO::routines_command_64
3363 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
3364 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
3367 MachO::thread_command
3368 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
3369 return getStruct<MachO::thread_command>(*this, L.Ptr);
3372 MachO::any_relocation_info
3373 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
3378 MachO::section_64 Sect = getSection64(Sec);
3379 Offset = Sect.reloff;
3381 MachO::section Sect = getSection(Sec);
3382 Offset = Sect.reloff;
3385 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
3386 getPtr(*this, Offset)) + Rel.d.b;
3387 return getStruct<MachO::any_relocation_info>(
3388 *this, reinterpret_cast<const char *>(P));
3391 MachO::data_in_code_entry
3392 MachOObjectFile::getDice(DataRefImpl Rel) const {
3393 const char *P = reinterpret_cast<const char *>(Rel.p);
3394 return getStruct<MachO::data_in_code_entry>(*this, P);
3397 const MachO::mach_header &MachOObjectFile::getHeader() const {
3401 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
3406 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
3407 const MachO::dysymtab_command &DLC,
3408 unsigned Index) const {
3409 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
3410 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
3413 MachO::data_in_code_entry
3414 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
3415 unsigned Index) const {
3416 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
3417 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
3420 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
3422 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
3424 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
3425 MachO::symtab_command Cmd;
3426 Cmd.cmd = MachO::LC_SYMTAB;
3427 Cmd.cmdsize = sizeof(MachO::symtab_command);
3435 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
3436 if (DysymtabLoadCmd)
3437 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
3439 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
3440 MachO::dysymtab_command Cmd;
3441 Cmd.cmd = MachO::LC_DYSYMTAB;
3442 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
3453 Cmd.extrefsymoff = 0;
3454 Cmd.nextrefsyms = 0;
3455 Cmd.indirectsymoff = 0;
3456 Cmd.nindirectsyms = 0;
3464 MachO::linkedit_data_command
3465 MachOObjectFile::getDataInCodeLoadCommand() const {
3466 if (DataInCodeLoadCmd)
3467 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
3469 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
3470 MachO::linkedit_data_command Cmd;
3471 Cmd.cmd = MachO::LC_DATA_IN_CODE;
3472 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3478 MachO::linkedit_data_command
3479 MachOObjectFile::getLinkOptHintsLoadCommand() const {
3480 if (LinkOptHintsLoadCmd)
3481 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
3483 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
3485 MachO::linkedit_data_command Cmd;
3486 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
3487 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3493 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
3494 if (!DyldInfoLoadCmd)
3497 MachO::dyld_info_command DyldInfo =
3498 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3499 const uint8_t *Ptr =
3500 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
3501 return makeArrayRef(Ptr, DyldInfo.rebase_size);
3504 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
3505 if (!DyldInfoLoadCmd)
3508 MachO::dyld_info_command DyldInfo =
3509 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3510 const uint8_t *Ptr =
3511 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
3512 return makeArrayRef(Ptr, DyldInfo.bind_size);
3515 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
3516 if (!DyldInfoLoadCmd)
3519 MachO::dyld_info_command DyldInfo =
3520 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3521 const uint8_t *Ptr =
3522 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
3523 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
3526 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
3527 if (!DyldInfoLoadCmd)
3530 MachO::dyld_info_command DyldInfo =
3531 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3532 const uint8_t *Ptr =
3533 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
3534 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
3537 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
3538 if (!DyldInfoLoadCmd)
3541 MachO::dyld_info_command DyldInfo =
3542 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3543 const uint8_t *Ptr =
3544 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
3545 return makeArrayRef(Ptr, DyldInfo.export_size);
3548 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
3551 // Returning a pointer is fine as uuid doesn't need endian swapping.
3552 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
3553 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
3556 StringRef MachOObjectFile::getStringTableData() const {
3557 MachO::symtab_command S = getSymtabLoadCommand();
3558 return getData().substr(S.stroff, S.strsize);
3561 bool MachOObjectFile::is64Bit() const {
3562 return getType() == getMachOType(false, true) ||
3563 getType() == getMachOType(true, true);
3566 void MachOObjectFile::ReadULEB128s(uint64_t Index,
3567 SmallVectorImpl<uint64_t> &Out) const {
3568 DataExtractor extractor(ObjectFile::getData(), true, 0);
3570 uint32_t offset = Index;
3572 while (uint64_t delta = extractor.getULEB128(&offset)) {
3574 Out.push_back(data);
3578 bool MachOObjectFile::isRelocatableObject() const {
3579 return getHeader().filetype == MachO::MH_OBJECT;
3582 Expected<std::unique_ptr<MachOObjectFile>>
3583 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
3584 uint32_t UniversalCputype,
3585 uint32_t UniversalIndex) {
3586 StringRef Magic = Buffer.getBuffer().slice(0, 4);
3587 if (Magic == "\xFE\xED\xFA\xCE")
3588 return MachOObjectFile::create(Buffer, false, false,
3589 UniversalCputype, UniversalIndex);
3590 if (Magic == "\xCE\xFA\xED\xFE")
3591 return MachOObjectFile::create(Buffer, true, false,
3592 UniversalCputype, UniversalIndex);
3593 if (Magic == "\xFE\xED\xFA\xCF")
3594 return MachOObjectFile::create(Buffer, false, true,
3595 UniversalCputype, UniversalIndex);
3596 if (Magic == "\xCF\xFA\xED\xFE")
3597 return MachOObjectFile::create(Buffer, true, true,
3598 UniversalCputype, UniversalIndex);
3599 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
3600 object_error::invalid_file_type);