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 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2827 return (Ptr == Other.Ptr) &&
2828 (RemainingLoopCount == Other.RemainingLoopCount) &&
2829 (Done == Other.Done);
2832 iterator_range<rebase_iterator>
2833 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
2834 MachORebaseEntry Start(Opcodes, is64);
2835 Start.moveToFirst();
2837 MachORebaseEntry Finish(Opcodes, is64);
2840 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
2843 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
2844 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
2847 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
2848 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
2849 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
2850 BindType(0), PointerSize(is64Bit ? 8 : 4),
2851 TableKind(BK), Malformed(false), Done(false) {}
2853 void MachOBindEntry::moveToFirst() {
2854 Ptr = Opcodes.begin();
2858 void MachOBindEntry::moveToEnd() {
2859 Ptr = Opcodes.end();
2860 RemainingLoopCount = 0;
2864 void MachOBindEntry::moveNext() {
2865 // If in the middle of some loop, move to next binding in loop.
2866 SegmentOffset += AdvanceAmount;
2867 if (RemainingLoopCount) {
2868 --RemainingLoopCount;
2871 if (Ptr == Opcodes.end()) {
2876 while (More && !Malformed) {
2877 // Parse next opcode and set up next loop.
2878 uint8_t Byte = *Ptr++;
2879 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
2880 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
2881 int8_t SignExtended;
2882 const uint8_t *SymStart;
2884 case MachO::BIND_OPCODE_DONE:
2885 if (TableKind == Kind::Lazy) {
2886 // Lazying bindings have a DONE opcode between entries. Need to ignore
2887 // it to advance to next entry. But need not if this is last entry.
2888 bool NotLastEntry = false;
2889 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
2891 NotLastEntry = true;
2900 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
2902 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
2906 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
2907 << "Ordinal=" << Ordinal << "\n");
2909 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
2910 Ordinal = readULEB128();
2913 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
2914 << "Ordinal=" << Ordinal << "\n");
2916 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
2918 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
2919 Ordinal = SignExtended;
2924 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
2925 << "Ordinal=" << Ordinal << "\n");
2927 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
2933 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
2938 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
2939 << "SymbolName=" << SymbolName << "\n");
2940 if (TableKind == Kind::Weak) {
2941 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
2945 case MachO::BIND_OPCODE_SET_TYPE_IMM:
2946 BindType = ImmValue;
2949 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
2950 << "BindType=" << (int)BindType << "\n");
2952 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
2953 Addend = readSLEB128();
2954 if (TableKind == Kind::Lazy)
2958 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
2959 << "Addend=" << Addend << "\n");
2961 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2962 SegmentIndex = ImmValue;
2963 SegmentOffset = readULEB128();
2966 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2967 << "SegmentIndex=" << SegmentIndex << ", "
2968 << format("SegmentOffset=0x%06X", SegmentOffset)
2971 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2972 SegmentOffset += readULEB128();
2973 DEBUG_WITH_TYPE("mach-o-bind",
2974 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2975 << format("SegmentOffset=0x%06X",
2976 SegmentOffset) << "\n");
2978 case MachO::BIND_OPCODE_DO_BIND:
2979 AdvanceAmount = PointerSize;
2980 RemainingLoopCount = 0;
2981 DEBUG_WITH_TYPE("mach-o-bind",
2982 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2983 << format("SegmentOffset=0x%06X",
2984 SegmentOffset) << "\n");
2986 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2987 AdvanceAmount = readULEB128() + PointerSize;
2988 RemainingLoopCount = 0;
2989 if (TableKind == Kind::Lazy)
2993 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
2994 << format("SegmentOffset=0x%06X", SegmentOffset)
2995 << ", AdvanceAmount=" << AdvanceAmount
2996 << ", RemainingLoopCount=" << RemainingLoopCount
2999 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
3000 AdvanceAmount = ImmValue * PointerSize + PointerSize;
3001 RemainingLoopCount = 0;
3002 if (TableKind == Kind::Lazy)
3004 DEBUG_WITH_TYPE("mach-o-bind",
3006 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3007 << format("SegmentOffset=0x%06X",
3008 SegmentOffset) << "\n");
3010 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3011 RemainingLoopCount = readULEB128() - 1;
3012 AdvanceAmount = readULEB128() + PointerSize;
3013 if (TableKind == Kind::Lazy)
3017 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3018 << format("SegmentOffset=0x%06X", SegmentOffset)
3019 << ", AdvanceAmount=" << AdvanceAmount
3020 << ", RemainingLoopCount=" << RemainingLoopCount
3029 uint64_t MachOBindEntry::readULEB128() {
3031 uint64_t Result = decodeULEB128(Ptr, &Count);
3033 if (Ptr > Opcodes.end()) {
3034 Ptr = Opcodes.end();
3040 int64_t MachOBindEntry::readSLEB128() {
3042 int64_t Result = decodeSLEB128(Ptr, &Count);
3044 if (Ptr > Opcodes.end()) {
3045 Ptr = Opcodes.end();
3051 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3053 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3055 StringRef MachOBindEntry::typeName() const {
3057 case MachO::BIND_TYPE_POINTER:
3059 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3060 return "text abs32";
3061 case MachO::BIND_TYPE_TEXT_PCREL32:
3062 return "text rel32";
3067 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3069 int64_t MachOBindEntry::addend() const { return Addend; }
3071 uint32_t MachOBindEntry::flags() const { return Flags; }
3073 int MachOBindEntry::ordinal() const { return Ordinal; }
3075 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3076 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3077 return (Ptr == Other.Ptr) &&
3078 (RemainingLoopCount == Other.RemainingLoopCount) &&
3079 (Done == Other.Done);
3082 iterator_range<bind_iterator>
3083 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
3084 MachOBindEntry::Kind BKind) {
3085 MachOBindEntry Start(Opcodes, is64, BKind);
3086 Start.moveToFirst();
3088 MachOBindEntry Finish(Opcodes, is64, BKind);
3091 return make_range(bind_iterator(Start), bind_iterator(Finish));
3094 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
3095 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
3096 MachOBindEntry::Kind::Regular);
3099 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
3100 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
3101 MachOBindEntry::Kind::Lazy);
3104 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
3105 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
3106 MachOBindEntry::Kind::Weak);
3109 MachOObjectFile::load_command_iterator
3110 MachOObjectFile::begin_load_commands() const {
3111 return LoadCommands.begin();
3114 MachOObjectFile::load_command_iterator
3115 MachOObjectFile::end_load_commands() const {
3116 return LoadCommands.end();
3119 iterator_range<MachOObjectFile::load_command_iterator>
3120 MachOObjectFile::load_commands() const {
3121 return make_range(begin_load_commands(), end_load_commands());
3125 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
3126 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
3127 return parseSegmentOrSectionName(Raw.data());
3131 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
3132 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
3133 const section_base *Base =
3134 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
3135 return makeArrayRef(Base->sectname);
3139 MachOObjectFile::getSectionRawFinalSegmentName(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->segname);
3147 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
3149 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
3151 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
3154 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
3155 const MachO::any_relocation_info &RE) const {
3156 if (isLittleEndian())
3157 return RE.r_word1 & 0xffffff;
3158 return RE.r_word1 >> 8;
3161 bool MachOObjectFile::getPlainRelocationExternal(
3162 const MachO::any_relocation_info &RE) const {
3163 if (isLittleEndian())
3164 return (RE.r_word1 >> 27) & 1;
3165 return (RE.r_word1 >> 4) & 1;
3168 bool MachOObjectFile::getScatteredRelocationScattered(
3169 const MachO::any_relocation_info &RE) const {
3170 return RE.r_word0 >> 31;
3173 uint32_t MachOObjectFile::getScatteredRelocationValue(
3174 const MachO::any_relocation_info &RE) const {
3178 uint32_t MachOObjectFile::getScatteredRelocationType(
3179 const MachO::any_relocation_info &RE) const {
3180 return (RE.r_word0 >> 24) & 0xf;
3183 unsigned MachOObjectFile::getAnyRelocationAddress(
3184 const MachO::any_relocation_info &RE) const {
3185 if (isRelocationScattered(RE))
3186 return getScatteredRelocationAddress(RE);
3187 return getPlainRelocationAddress(RE);
3190 unsigned MachOObjectFile::getAnyRelocationPCRel(
3191 const MachO::any_relocation_info &RE) const {
3192 if (isRelocationScattered(RE))
3193 return getScatteredRelocationPCRel(RE);
3194 return getPlainRelocationPCRel(*this, RE);
3197 unsigned MachOObjectFile::getAnyRelocationLength(
3198 const MachO::any_relocation_info &RE) const {
3199 if (isRelocationScattered(RE))
3200 return getScatteredRelocationLength(RE);
3201 return getPlainRelocationLength(*this, RE);
3205 MachOObjectFile::getAnyRelocationType(
3206 const MachO::any_relocation_info &RE) const {
3207 if (isRelocationScattered(RE))
3208 return getScatteredRelocationType(RE);
3209 return getPlainRelocationType(*this, RE);
3213 MachOObjectFile::getAnyRelocationSection(
3214 const MachO::any_relocation_info &RE) const {
3215 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
3216 return *section_end();
3217 unsigned SecNum = getPlainRelocationSymbolNum(RE);
3218 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
3219 return *section_end();
3221 DRI.d.a = SecNum - 1;
3222 return SectionRef(DRI, this);
3225 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
3226 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
3227 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
3230 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
3231 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
3232 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
3235 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
3236 unsigned Index) const {
3237 const char *Sec = getSectionPtr(*this, L, Index);
3238 return getStruct<MachO::section>(*this, Sec);
3241 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
3242 unsigned Index) const {
3243 const char *Sec = getSectionPtr(*this, L, Index);
3244 return getStruct<MachO::section_64>(*this, Sec);
3248 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
3249 const char *P = reinterpret_cast<const char *>(DRI.p);
3250 return getStruct<MachO::nlist>(*this, P);
3254 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
3255 const char *P = reinterpret_cast<const char *>(DRI.p);
3256 return getStruct<MachO::nlist_64>(*this, P);
3259 MachO::linkedit_data_command
3260 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
3261 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
3264 MachO::segment_command
3265 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
3266 return getStruct<MachO::segment_command>(*this, L.Ptr);
3269 MachO::segment_command_64
3270 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
3271 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
3274 MachO::linker_option_command
3275 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
3276 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
3279 MachO::version_min_command
3280 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
3281 return getStruct<MachO::version_min_command>(*this, L.Ptr);
3284 MachO::dylib_command
3285 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
3286 return getStruct<MachO::dylib_command>(*this, L.Ptr);
3289 MachO::dyld_info_command
3290 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
3291 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
3294 MachO::dylinker_command
3295 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
3296 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
3300 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
3301 return getStruct<MachO::uuid_command>(*this, L.Ptr);
3304 MachO::rpath_command
3305 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
3306 return getStruct<MachO::rpath_command>(*this, L.Ptr);
3309 MachO::source_version_command
3310 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
3311 return getStruct<MachO::source_version_command>(*this, L.Ptr);
3314 MachO::entry_point_command
3315 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
3316 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
3319 MachO::encryption_info_command
3320 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
3321 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
3324 MachO::encryption_info_command_64
3325 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
3326 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
3329 MachO::sub_framework_command
3330 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
3331 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
3334 MachO::sub_umbrella_command
3335 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
3336 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
3339 MachO::sub_library_command
3340 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
3341 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
3344 MachO::sub_client_command
3345 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
3346 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
3349 MachO::routines_command
3350 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
3351 return getStruct<MachO::routines_command>(*this, L.Ptr);
3354 MachO::routines_command_64
3355 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
3356 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
3359 MachO::thread_command
3360 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
3361 return getStruct<MachO::thread_command>(*this, L.Ptr);
3364 MachO::any_relocation_info
3365 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
3370 MachO::section_64 Sect = getSection64(Sec);
3371 Offset = Sect.reloff;
3373 MachO::section Sect = getSection(Sec);
3374 Offset = Sect.reloff;
3377 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
3378 getPtr(*this, Offset)) + Rel.d.b;
3379 return getStruct<MachO::any_relocation_info>(
3380 *this, reinterpret_cast<const char *>(P));
3383 MachO::data_in_code_entry
3384 MachOObjectFile::getDice(DataRefImpl Rel) const {
3385 const char *P = reinterpret_cast<const char *>(Rel.p);
3386 return getStruct<MachO::data_in_code_entry>(*this, P);
3389 const MachO::mach_header &MachOObjectFile::getHeader() const {
3393 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
3398 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
3399 const MachO::dysymtab_command &DLC,
3400 unsigned Index) const {
3401 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
3402 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
3405 MachO::data_in_code_entry
3406 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
3407 unsigned Index) const {
3408 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
3409 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
3412 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
3414 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
3416 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
3417 MachO::symtab_command Cmd;
3418 Cmd.cmd = MachO::LC_SYMTAB;
3419 Cmd.cmdsize = sizeof(MachO::symtab_command);
3427 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
3428 if (DysymtabLoadCmd)
3429 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
3431 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
3432 MachO::dysymtab_command Cmd;
3433 Cmd.cmd = MachO::LC_DYSYMTAB;
3434 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
3445 Cmd.extrefsymoff = 0;
3446 Cmd.nextrefsyms = 0;
3447 Cmd.indirectsymoff = 0;
3448 Cmd.nindirectsyms = 0;
3456 MachO::linkedit_data_command
3457 MachOObjectFile::getDataInCodeLoadCommand() const {
3458 if (DataInCodeLoadCmd)
3459 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
3461 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
3462 MachO::linkedit_data_command Cmd;
3463 Cmd.cmd = MachO::LC_DATA_IN_CODE;
3464 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3470 MachO::linkedit_data_command
3471 MachOObjectFile::getLinkOptHintsLoadCommand() const {
3472 if (LinkOptHintsLoadCmd)
3473 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
3475 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
3477 MachO::linkedit_data_command Cmd;
3478 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
3479 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
3485 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
3486 if (!DyldInfoLoadCmd)
3489 MachO::dyld_info_command DyldInfo =
3490 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3491 const uint8_t *Ptr =
3492 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
3493 return makeArrayRef(Ptr, DyldInfo.rebase_size);
3496 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
3497 if (!DyldInfoLoadCmd)
3500 MachO::dyld_info_command DyldInfo =
3501 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3502 const uint8_t *Ptr =
3503 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
3504 return makeArrayRef(Ptr, DyldInfo.bind_size);
3507 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
3508 if (!DyldInfoLoadCmd)
3511 MachO::dyld_info_command DyldInfo =
3512 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3513 const uint8_t *Ptr =
3514 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
3515 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
3518 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
3519 if (!DyldInfoLoadCmd)
3522 MachO::dyld_info_command DyldInfo =
3523 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3524 const uint8_t *Ptr =
3525 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
3526 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
3529 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
3530 if (!DyldInfoLoadCmd)
3533 MachO::dyld_info_command DyldInfo =
3534 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
3535 const uint8_t *Ptr =
3536 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
3537 return makeArrayRef(Ptr, DyldInfo.export_size);
3540 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
3543 // Returning a pointer is fine as uuid doesn't need endian swapping.
3544 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
3545 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
3548 StringRef MachOObjectFile::getStringTableData() const {
3549 MachO::symtab_command S = getSymtabLoadCommand();
3550 return getData().substr(S.stroff, S.strsize);
3553 bool MachOObjectFile::is64Bit() const {
3554 return getType() == getMachOType(false, true) ||
3555 getType() == getMachOType(true, true);
3558 void MachOObjectFile::ReadULEB128s(uint64_t Index,
3559 SmallVectorImpl<uint64_t> &Out) const {
3560 DataExtractor extractor(ObjectFile::getData(), true, 0);
3562 uint32_t offset = Index;
3564 while (uint64_t delta = extractor.getULEB128(&offset)) {
3566 Out.push_back(data);
3570 bool MachOObjectFile::isRelocatableObject() const {
3571 return getHeader().filetype == MachO::MH_OBJECT;
3574 Expected<std::unique_ptr<MachOObjectFile>>
3575 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
3576 uint32_t UniversalCputype,
3577 uint32_t UniversalIndex) {
3578 StringRef Magic = Buffer.getBuffer().slice(0, 4);
3579 if (Magic == "\xFE\xED\xFA\xCE")
3580 return MachOObjectFile::create(Buffer, false, false,
3581 UniversalCputype, UniversalIndex);
3582 if (Magic == "\xCE\xFA\xED\xFE")
3583 return MachOObjectFile::create(Buffer, true, false,
3584 UniversalCputype, UniversalIndex);
3585 if (Magic == "\xFE\xED\xFA\xCF")
3586 return MachOObjectFile::create(Buffer, false, true,
3587 UniversalCputype, UniversalIndex);
3588 if (Magic == "\xCF\xFA\xED\xFE")
3589 return MachOObjectFile::create(Buffer, true, true,
3590 UniversalCputype, UniversalIndex);
3591 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
3592 object_error::invalid_file_type);