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 static unsigned getCPUType(const MachOObjectFile &O) {
110 return O.getHeader().cputype;
114 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
119 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
120 return RE.r_word0 & 0xffffff;
123 static bool getPlainRelocationPCRel(const MachOObjectFile &O,
124 const MachO::any_relocation_info &RE) {
125 if (O.isLittleEndian())
126 return (RE.r_word1 >> 24) & 1;
127 return (RE.r_word1 >> 7) & 1;
131 getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
135 static unsigned getPlainRelocationLength(const MachOObjectFile &O,
136 const MachO::any_relocation_info &RE) {
137 if (O.isLittleEndian())
138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
147 static unsigned getPlainRelocationType(const MachOObjectFile &O,
148 const MachO::any_relocation_info &RE) {
149 if (O.isLittleEndian())
150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
154 static uint32_t getSectionFlags(const MachOObjectFile &O,
157 MachO::section_64 Sect = O.getSection64(Sec);
160 MachO::section Sect = O.getSection(Sec);
164 static Expected<MachOObjectFile::LoadCommandInfo>
165 getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
166 uint32_t LoadCommandIndex) {
167 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
168 if (CmdOrErr->cmdsize < 8)
169 return malformedError("load command " + Twine(LoadCommandIndex) +
170 " with size less than 8 bytes");
171 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
173 return CmdOrErr.takeError();
176 static Expected<MachOObjectFile::LoadCommandInfo>
177 getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
178 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
179 : sizeof(MachO::mach_header);
180 if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
181 return malformedError("load command 0 extends past the end all load "
182 "commands in the file");
183 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
186 static Expected<MachOObjectFile::LoadCommandInfo>
187 getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
188 const MachOObjectFile::LoadCommandInfo &L) {
189 unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
190 : sizeof(MachO::mach_header);
191 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
192 Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
193 return malformedError("load command " + Twine(LoadCommandIndex + 1) +
194 " extends past the end all load commands in the file");
195 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
198 template <typename T>
199 static void parseHeader(const MachOObjectFile &Obj, T &Header,
201 if (sizeof(T) > Obj.getData().size()) {
202 Err = malformedError("the mach header extends past the end of the "
206 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
207 Header = *HeaderOrErr;
209 Err = HeaderOrErr.takeError();
212 // This is used to check for overlapping of Mach-O elements.
213 struct MachOElement {
219 static Error checkOverlappingElement(std::list<MachOElement> &Elements,
220 uint64_t Offset, uint64_t Size,
223 return Error::success();
225 for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
227 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
228 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
229 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
230 return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
231 " with a size of " + Twine(Size) + ", overlaps " +
232 E.Name + " at offset " + Twine(E.Offset) + " with "
233 "a size of " + Twine(E.Size));
236 if (nt != Elements.end()) {
238 if (Offset + Size <= N.Offset) {
239 Elements.insert(nt, {Offset, Size, Name});
240 return Error::success();
244 Elements.push_back({Offset, Size, Name});
245 return Error::success();
248 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
249 // sections to \param Sections, and optionally sets
250 // \param IsPageZeroSegment to true.
251 template <typename Segment, typename Section>
252 static Error parseSegmentLoadCommand(
253 const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
254 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
255 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
256 std::list<MachOElement> &Elements) {
257 const unsigned SegmentLoadSize = sizeof(Segment);
258 if (Load.C.cmdsize < SegmentLoadSize)
259 return malformedError("load command " + Twine(LoadCommandIndex) +
260 " " + CmdName + " cmdsize too small");
261 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
262 Segment S = SegOrErr.get();
263 const unsigned SectionSize = sizeof(Section);
264 uint64_t FileSize = Obj.getData().size();
265 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
266 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
267 return malformedError("load command " + Twine(LoadCommandIndex) +
268 " inconsistent cmdsize in " + CmdName +
269 " for the number of sections");
270 for (unsigned J = 0; J < S.nsects; ++J) {
271 const char *Sec = getSectionPtr(Obj, Load, J);
272 Sections.push_back(Sec);
273 Section s = getStruct<Section>(Obj, Sec);
274 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
275 Obj.getHeader().filetype != MachO::MH_DSYM &&
276 s.flags != MachO::S_ZEROFILL &&
277 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
279 return malformedError("offset field of section " + Twine(J) + " in " +
280 CmdName + " command " + Twine(LoadCommandIndex) +
281 " extends past the end of the file");
282 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
283 Obj.getHeader().filetype != MachO::MH_DSYM &&
284 s.flags != MachO::S_ZEROFILL &&
285 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
286 s.offset < SizeOfHeaders && s.size != 0)
287 return malformedError("offset field of section " + Twine(J) + " in " +
288 CmdName + " command " + Twine(LoadCommandIndex) +
289 " not past the headers of the file");
290 uint64_t BigSize = s.offset;
292 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
293 Obj.getHeader().filetype != MachO::MH_DSYM &&
294 s.flags != MachO::S_ZEROFILL &&
295 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
297 return malformedError("offset field plus size field of section " +
298 Twine(J) + " in " + CmdName + " command " +
299 Twine(LoadCommandIndex) +
300 " extends past the end of the file");
301 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
302 Obj.getHeader().filetype != MachO::MH_DSYM &&
303 s.flags != MachO::S_ZEROFILL &&
304 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
306 return malformedError("size field of section " +
307 Twine(J) + " in " + CmdName + " command " +
308 Twine(LoadCommandIndex) +
309 " greater than the segment");
310 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
311 Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
313 return malformedError("addr field of section " + Twine(J) + " in " +
314 CmdName + " command " + Twine(LoadCommandIndex) +
315 " less than the segment's vmaddr");
318 uint64_t BigEnd = S.vmaddr;
320 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
321 return malformedError("addr field plus size of section " + Twine(J) +
322 " in " + CmdName + " command " +
323 Twine(LoadCommandIndex) +
324 " greater than than "
325 "the segment's vmaddr plus vmsize");
326 if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
327 Obj.getHeader().filetype != MachO::MH_DSYM &&
328 s.flags != MachO::S_ZEROFILL &&
329 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
330 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
333 if (s.reloff > FileSize)
334 return malformedError("reloff field of section " + Twine(J) + " in " +
335 CmdName + " command " + Twine(LoadCommandIndex) +
336 " extends past the end of the file");
338 BigSize *= sizeof(struct MachO::relocation_info);
340 if (BigSize > FileSize)
341 return malformedError("reloff field plus nreloc field times sizeof("
342 "struct relocation_info) of section " +
343 Twine(J) + " in " + CmdName + " command " +
344 Twine(LoadCommandIndex) +
345 " extends past the end of the file");
346 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
348 MachO::relocation_info),
349 "section relocation entries"))
352 if (S.fileoff > FileSize)
353 return malformedError("load command " + Twine(LoadCommandIndex) +
354 " fileoff field in " + CmdName +
355 " extends past the end of the file");
356 uint64_t BigSize = S.fileoff;
357 BigSize += S.filesize;
358 if (BigSize > FileSize)
359 return malformedError("load command " + Twine(LoadCommandIndex) +
360 " fileoff field plus filesize field in " +
361 CmdName + " extends past the end of the file");
362 if (S.vmsize != 0 && S.filesize > S.vmsize)
363 return malformedError("load command " + Twine(LoadCommandIndex) +
364 " filesize field in " + CmdName +
365 " greater than vmsize field");
366 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
368 return SegOrErr.takeError();
370 return Error::success();
373 static Error checkSymtabCommand(const MachOObjectFile &Obj,
374 const MachOObjectFile::LoadCommandInfo &Load,
375 uint32_t LoadCommandIndex,
376 const char **SymtabLoadCmd,
377 std::list<MachOElement> &Elements) {
378 if (Load.C.cmdsize < sizeof(MachO::symtab_command))
379 return malformedError("load command " + Twine(LoadCommandIndex) +
380 " LC_SYMTAB cmdsize too small");
381 if (*SymtabLoadCmd != nullptr)
382 return malformedError("more than one LC_SYMTAB command");
383 MachO::symtab_command Symtab =
384 getStruct<MachO::symtab_command>(Obj, Load.Ptr);
385 if (Symtab.cmdsize != sizeof(MachO::symtab_command))
386 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
387 " has incorrect cmdsize");
388 uint64_t FileSize = Obj.getData().size();
389 if (Symtab.symoff > FileSize)
390 return malformedError("symoff field of LC_SYMTAB command " +
391 Twine(LoadCommandIndex) + " extends past the end "
393 uint64_t SymtabSize = Symtab.nsyms;
394 const char *struct_nlist_name;
396 SymtabSize *= sizeof(MachO::nlist_64);
397 struct_nlist_name = "struct nlist_64";
399 SymtabSize *= sizeof(MachO::nlist);
400 struct_nlist_name = "struct nlist";
402 uint64_t BigSize = SymtabSize;
403 BigSize += Symtab.symoff;
404 if (BigSize > FileSize)
405 return malformedError("symoff field plus nsyms field times sizeof(" +
406 Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
407 Twine(LoadCommandIndex) + " extends past the end "
409 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
412 if (Symtab.stroff > FileSize)
413 return malformedError("stroff field of LC_SYMTAB command " +
414 Twine(LoadCommandIndex) + " extends past the end "
416 BigSize = Symtab.stroff;
417 BigSize += Symtab.strsize;
418 if (BigSize > FileSize)
419 return malformedError("stroff field plus strsize field of LC_SYMTAB "
420 "command " + Twine(LoadCommandIndex) + " extends "
421 "past the end of the file");
422 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
423 Symtab.strsize, "string table"))
425 *SymtabLoadCmd = Load.Ptr;
426 return Error::success();
429 static Error checkDysymtabCommand(const MachOObjectFile &Obj,
430 const MachOObjectFile::LoadCommandInfo &Load,
431 uint32_t LoadCommandIndex,
432 const char **DysymtabLoadCmd,
433 std::list<MachOElement> &Elements) {
434 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
435 return malformedError("load command " + Twine(LoadCommandIndex) +
436 " LC_DYSYMTAB cmdsize too small");
437 if (*DysymtabLoadCmd != nullptr)
438 return malformedError("more than one LC_DYSYMTAB command");
439 MachO::dysymtab_command Dysymtab =
440 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
441 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
442 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
443 " has incorrect cmdsize");
444 uint64_t FileSize = Obj.getData().size();
445 if (Dysymtab.tocoff > FileSize)
446 return malformedError("tocoff field of LC_DYSYMTAB command " +
447 Twine(LoadCommandIndex) + " extends past the end of "
449 uint64_t BigSize = Dysymtab.ntoc;
450 BigSize *= sizeof(MachO::dylib_table_of_contents);
451 BigSize += Dysymtab.tocoff;
452 if (BigSize > FileSize)
453 return malformedError("tocoff field plus ntoc field times sizeof(struct "
454 "dylib_table_of_contents) of LC_DYSYMTAB command " +
455 Twine(LoadCommandIndex) + " extends past the end of "
457 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
458 Dysymtab.ntoc * sizeof(struct
459 MachO::dylib_table_of_contents),
460 "table of contents"))
462 if (Dysymtab.modtaboff > FileSize)
463 return malformedError("modtaboff field of LC_DYSYMTAB command " +
464 Twine(LoadCommandIndex) + " extends past the end of "
466 BigSize = Dysymtab.nmodtab;
467 const char *struct_dylib_module_name;
468 uint64_t sizeof_modtab;
470 sizeof_modtab = sizeof(MachO::dylib_module_64);
471 struct_dylib_module_name = "struct dylib_module_64";
473 sizeof_modtab = sizeof(MachO::dylib_module);
474 struct_dylib_module_name = "struct dylib_module";
476 BigSize *= sizeof_modtab;
477 BigSize += Dysymtab.modtaboff;
478 if (BigSize > FileSize)
479 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
480 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
481 "command " + Twine(LoadCommandIndex) + " extends "
482 "past the end of the file");
483 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
484 Dysymtab.nmodtab * sizeof_modtab,
487 if (Dysymtab.extrefsymoff > FileSize)
488 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
489 Twine(LoadCommandIndex) + " extends past the end of "
491 BigSize = Dysymtab.nextrefsyms;
492 BigSize *= sizeof(MachO::dylib_reference);
493 BigSize += Dysymtab.extrefsymoff;
494 if (BigSize > FileSize)
495 return malformedError("extrefsymoff field plus nextrefsyms field times "
496 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
497 "command " + Twine(LoadCommandIndex) + " extends "
498 "past the end of the file");
499 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
500 Dysymtab.nextrefsyms *
501 sizeof(MachO::dylib_reference),
504 if (Dysymtab.indirectsymoff > FileSize)
505 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
506 Twine(LoadCommandIndex) + " extends past the end of "
508 BigSize = Dysymtab.nindirectsyms;
509 BigSize *= sizeof(uint32_t);
510 BigSize += Dysymtab.indirectsymoff;
511 if (BigSize > FileSize)
512 return malformedError("indirectsymoff field plus nindirectsyms field times "
513 "sizeof(uint32_t) of LC_DYSYMTAB command " +
514 Twine(LoadCommandIndex) + " extends past the end of "
516 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
517 Dysymtab.nindirectsyms *
521 if (Dysymtab.extreloff > FileSize)
522 return malformedError("extreloff field of LC_DYSYMTAB command " +
523 Twine(LoadCommandIndex) + " extends past the end of "
525 BigSize = Dysymtab.nextrel;
526 BigSize *= sizeof(MachO::relocation_info);
527 BigSize += Dysymtab.extreloff;
528 if (BigSize > FileSize)
529 return malformedError("extreloff field plus nextrel field times sizeof"
530 "(struct relocation_info) of LC_DYSYMTAB command " +
531 Twine(LoadCommandIndex) + " extends past the end of "
533 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
535 sizeof(MachO::relocation_info),
536 "external relocation table"))
538 if (Dysymtab.locreloff > FileSize)
539 return malformedError("locreloff field of LC_DYSYMTAB command " +
540 Twine(LoadCommandIndex) + " extends past the end of "
542 BigSize = Dysymtab.nlocrel;
543 BigSize *= sizeof(MachO::relocation_info);
544 BigSize += Dysymtab.locreloff;
545 if (BigSize > FileSize)
546 return malformedError("locreloff field plus nlocrel field times sizeof"
547 "(struct relocation_info) of LC_DYSYMTAB command " +
548 Twine(LoadCommandIndex) + " extends past the end of "
550 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
552 sizeof(MachO::relocation_info),
553 "local relocation table"))
555 *DysymtabLoadCmd = Load.Ptr;
556 return Error::success();
559 static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
560 const MachOObjectFile::LoadCommandInfo &Load,
561 uint32_t LoadCommandIndex,
562 const char **LoadCmd, const char *CmdName,
563 std::list<MachOElement> &Elements,
564 const char *ElementName) {
565 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
566 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
567 CmdName + " cmdsize too small");
568 if (*LoadCmd != nullptr)
569 return malformedError("more than one " + Twine(CmdName) + " command");
570 MachO::linkedit_data_command LinkData =
571 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
572 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
573 return malformedError(Twine(CmdName) + " command " +
574 Twine(LoadCommandIndex) + " has incorrect cmdsize");
575 uint64_t FileSize = Obj.getData().size();
576 if (LinkData.dataoff > FileSize)
577 return malformedError("dataoff field of " + Twine(CmdName) + " command " +
578 Twine(LoadCommandIndex) + " extends past the end of "
580 uint64_t BigSize = LinkData.dataoff;
581 BigSize += LinkData.datasize;
582 if (BigSize > FileSize)
583 return malformedError("dataoff field plus datasize field of " +
584 Twine(CmdName) + " command " +
585 Twine(LoadCommandIndex) + " extends past the end of "
587 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
588 LinkData.datasize, ElementName))
591 return Error::success();
594 static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
595 const MachOObjectFile::LoadCommandInfo &Load,
596 uint32_t LoadCommandIndex,
597 const char **LoadCmd, const char *CmdName,
598 std::list<MachOElement> &Elements) {
599 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
600 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
601 CmdName + " cmdsize too small");
602 if (*LoadCmd != nullptr)
603 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
605 MachO::dyld_info_command DyldInfo =
606 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
607 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
608 return malformedError(Twine(CmdName) + " command " +
609 Twine(LoadCommandIndex) + " has incorrect cmdsize");
610 uint64_t FileSize = Obj.getData().size();
611 if (DyldInfo.rebase_off > FileSize)
612 return malformedError("rebase_off field of " + Twine(CmdName) +
613 " command " + Twine(LoadCommandIndex) + " extends "
614 "past the end of the file");
615 uint64_t BigSize = DyldInfo.rebase_off;
616 BigSize += DyldInfo.rebase_size;
617 if (BigSize > FileSize)
618 return malformedError("rebase_off field plus rebase_size field of " +
619 Twine(CmdName) + " command " +
620 Twine(LoadCommandIndex) + " extends past the end of "
622 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
623 DyldInfo.rebase_size,
626 if (DyldInfo.bind_off > FileSize)
627 return malformedError("bind_off field of " + Twine(CmdName) +
628 " command " + Twine(LoadCommandIndex) + " extends "
629 "past the end of the file");
630 BigSize = DyldInfo.bind_off;
631 BigSize += DyldInfo.bind_size;
632 if (BigSize > FileSize)
633 return malformedError("bind_off field plus bind_size field of " +
634 Twine(CmdName) + " command " +
635 Twine(LoadCommandIndex) + " extends past the end of "
637 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
641 if (DyldInfo.weak_bind_off > FileSize)
642 return malformedError("weak_bind_off field of " + Twine(CmdName) +
643 " command " + Twine(LoadCommandIndex) + " extends "
644 "past the end of the file");
645 BigSize = DyldInfo.weak_bind_off;
646 BigSize += DyldInfo.weak_bind_size;
647 if (BigSize > FileSize)
648 return malformedError("weak_bind_off field plus weak_bind_size field of " +
649 Twine(CmdName) + " command " +
650 Twine(LoadCommandIndex) + " extends past the end of "
652 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
653 DyldInfo.weak_bind_size,
654 "dyld weak bind info"))
656 if (DyldInfo.lazy_bind_off > FileSize)
657 return malformedError("lazy_bind_off field of " + Twine(CmdName) +
658 " command " + Twine(LoadCommandIndex) + " extends "
659 "past the end of the file");
660 BigSize = DyldInfo.lazy_bind_off;
661 BigSize += DyldInfo.lazy_bind_size;
662 if (BigSize > FileSize)
663 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
664 Twine(CmdName) + " command " +
665 Twine(LoadCommandIndex) + " extends past the end of "
667 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
668 DyldInfo.lazy_bind_size,
669 "dyld lazy bind info"))
671 if (DyldInfo.export_off > FileSize)
672 return malformedError("export_off field of " + Twine(CmdName) +
673 " command " + Twine(LoadCommandIndex) + " extends "
674 "past the end of the file");
675 BigSize = DyldInfo.export_off;
676 BigSize += DyldInfo.export_size;
677 if (BigSize > FileSize)
678 return malformedError("export_off field plus export_size field of " +
679 Twine(CmdName) + " command " +
680 Twine(LoadCommandIndex) + " extends past the end of "
682 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
683 DyldInfo.export_size,
687 return Error::success();
690 static Error checkDylibCommand(const MachOObjectFile &Obj,
691 const MachOObjectFile::LoadCommandInfo &Load,
692 uint32_t LoadCommandIndex, const char *CmdName) {
693 if (Load.C.cmdsize < sizeof(MachO::dylib_command))
694 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
695 CmdName + " cmdsize too small");
696 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
697 if (D.dylib.name < sizeof(MachO::dylib_command))
698 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
699 CmdName + " name.offset field too small, not past "
700 "the end of the dylib_command struct");
701 if (D.dylib.name >= D.cmdsize)
702 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
703 CmdName + " name.offset field extends past the end "
704 "of the load command");
705 // Make sure there is a null between the starting offset of the name and
706 // the end of the load command.
708 const char *P = (const char *)Load.Ptr;
709 for (i = D.dylib.name; i < D.cmdsize; i++)
713 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
714 CmdName + " library name extends past the end of the "
716 return Error::success();
719 static Error checkDylibIdCommand(const MachOObjectFile &Obj,
720 const MachOObjectFile::LoadCommandInfo &Load,
721 uint32_t LoadCommandIndex,
722 const char **LoadCmd) {
723 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
726 if (*LoadCmd != nullptr)
727 return malformedError("more than one LC_ID_DYLIB command");
728 if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
729 Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
730 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
733 return Error::success();
736 static Error checkDyldCommand(const MachOObjectFile &Obj,
737 const MachOObjectFile::LoadCommandInfo &Load,
738 uint32_t LoadCommandIndex, const char *CmdName) {
739 if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
740 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
741 CmdName + " cmdsize too small");
742 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
743 if (D.name < sizeof(MachO::dylinker_command))
744 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
745 CmdName + " name.offset field too small, not past "
746 "the end of the dylinker_command struct");
747 if (D.name >= D.cmdsize)
748 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
749 CmdName + " name.offset field extends past the end "
750 "of the load command");
751 // Make sure there is a null between the starting offset of the name and
752 // the end of the load command.
754 const char *P = (const char *)Load.Ptr;
755 for (i = D.name; i < D.cmdsize; i++)
759 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
760 CmdName + " dyld name extends past the end of the "
762 return Error::success();
765 static Error checkVersCommand(const MachOObjectFile &Obj,
766 const MachOObjectFile::LoadCommandInfo &Load,
767 uint32_t LoadCommandIndex,
768 const char **LoadCmd, const char *CmdName) {
769 if (Load.C.cmdsize != sizeof(MachO::version_min_command))
770 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
771 CmdName + " has incorrect cmdsize");
772 if (*LoadCmd != nullptr)
773 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
774 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
775 "LC_VERSION_MIN_WATCHOS command");
777 return Error::success();
780 static Error checkNoteCommand(const MachOObjectFile &Obj,
781 const MachOObjectFile::LoadCommandInfo &Load,
782 uint32_t LoadCommandIndex,
783 std::list<MachOElement> &Elements) {
784 if (Load.C.cmdsize != sizeof(MachO::note_command))
785 return malformedError("load command " + Twine(LoadCommandIndex) +
786 " LC_NOTE has incorrect cmdsize");
787 MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
788 uint64_t FileSize = Obj.getData().size();
789 if (Nt.offset > FileSize)
790 return malformedError("offset field of LC_NOTE command " +
791 Twine(LoadCommandIndex) + " extends "
792 "past the end of the file");
793 uint64_t BigSize = Nt.offset;
795 if (BigSize > FileSize)
796 return malformedError("size field plus offset field of LC_NOTE command " +
797 Twine(LoadCommandIndex) + " extends past the end of "
799 if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
802 return Error::success();
806 parseBuildVersionCommand(const MachOObjectFile &Obj,
807 const MachOObjectFile::LoadCommandInfo &Load,
808 SmallVectorImpl<const char*> &BuildTools,
809 uint32_t LoadCommandIndex) {
810 MachO::build_version_command BVC =
811 getStruct<MachO::build_version_command>(Obj, Load.Ptr);
812 if (Load.C.cmdsize !=
813 sizeof(MachO::build_version_command) +
814 BVC.ntools * sizeof(MachO::build_tool_version))
815 return malformedError("load command " + Twine(LoadCommandIndex) +
816 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
818 auto Start = Load.Ptr + sizeof(MachO::build_version_command);
819 BuildTools.resize(BVC.ntools);
820 for (unsigned i = 0; i < BVC.ntools; ++i)
821 BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
823 return Error::success();
826 static Error checkRpathCommand(const MachOObjectFile &Obj,
827 const MachOObjectFile::LoadCommandInfo &Load,
828 uint32_t LoadCommandIndex) {
829 if (Load.C.cmdsize < sizeof(MachO::rpath_command))
830 return malformedError("load command " + Twine(LoadCommandIndex) +
831 " LC_RPATH cmdsize too small");
832 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
833 if (R.path < sizeof(MachO::rpath_command))
834 return malformedError("load command " + Twine(LoadCommandIndex) +
835 " LC_RPATH path.offset field too small, not past "
836 "the end of the rpath_command struct");
837 if (R.path >= R.cmdsize)
838 return malformedError("load command " + Twine(LoadCommandIndex) +
839 " LC_RPATH path.offset field extends past the end "
840 "of the load command");
841 // Make sure there is a null between the starting offset of the path and
842 // the end of the load command.
844 const char *P = (const char *)Load.Ptr;
845 for (i = R.path; i < R.cmdsize; i++)
849 return malformedError("load command " + Twine(LoadCommandIndex) +
850 " LC_RPATH library name extends past the end of the "
852 return Error::success();
855 static Error checkEncryptCommand(const MachOObjectFile &Obj,
856 const MachOObjectFile::LoadCommandInfo &Load,
857 uint32_t LoadCommandIndex,
858 uint64_t cryptoff, uint64_t cryptsize,
859 const char **LoadCmd, const char *CmdName) {
860 if (*LoadCmd != nullptr)
861 return malformedError("more than one LC_ENCRYPTION_INFO and or "
862 "LC_ENCRYPTION_INFO_64 command");
863 uint64_t FileSize = Obj.getData().size();
864 if (cryptoff > FileSize)
865 return malformedError("cryptoff field of " + Twine(CmdName) +
866 " command " + Twine(LoadCommandIndex) + " extends "
867 "past the end of the file");
868 uint64_t BigSize = cryptoff;
869 BigSize += cryptsize;
870 if (BigSize > FileSize)
871 return malformedError("cryptoff field plus cryptsize field of " +
872 Twine(CmdName) + " command " +
873 Twine(LoadCommandIndex) + " extends past the end of "
876 return Error::success();
879 static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
880 const MachOObjectFile::LoadCommandInfo &Load,
881 uint32_t LoadCommandIndex) {
882 if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
883 return malformedError("load command " + Twine(LoadCommandIndex) +
884 " LC_LINKER_OPTION cmdsize too small");
885 MachO::linker_option_command L =
886 getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
887 // Make sure the count of strings is correct.
888 const char *string = (const char *)Load.Ptr +
889 sizeof(struct MachO::linker_option_command);
890 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
893 while (*string == '\0' && left > 0) {
899 uint32_t NullPos = StringRef(string, left).find('\0');
900 uint32_t len = std::min(NullPos, left) + 1;
906 return malformedError("load command " + Twine(LoadCommandIndex) +
907 " LC_LINKER_OPTION string count " + Twine(L.count) +
908 " does not match number of strings");
909 return Error::success();
912 static Error checkSubCommand(const MachOObjectFile &Obj,
913 const MachOObjectFile::LoadCommandInfo &Load,
914 uint32_t LoadCommandIndex, const char *CmdName,
915 size_t SizeOfCmd, const char *CmdStructName,
916 uint32_t PathOffset, const char *PathFieldName) {
917 if (PathOffset < SizeOfCmd)
918 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
919 CmdName + " " + PathFieldName + ".offset field too "
920 "small, not past the end of the " + CmdStructName);
921 if (PathOffset >= Load.C.cmdsize)
922 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
923 CmdName + " " + PathFieldName + ".offset field "
924 "extends past the end of the load command");
925 // Make sure there is a null between the starting offset of the path and
926 // the end of the load command.
928 const char *P = (const char *)Load.Ptr;
929 for (i = PathOffset; i < Load.C.cmdsize; i++)
932 if (i >= Load.C.cmdsize)
933 return malformedError("load command " + Twine(LoadCommandIndex) + " " +
934 CmdName + " " + PathFieldName + " name extends past "
935 "the end of the load command");
936 return Error::success();
939 static Error checkThreadCommand(const MachOObjectFile &Obj,
940 const MachOObjectFile::LoadCommandInfo &Load,
941 uint32_t LoadCommandIndex,
942 const char *CmdName) {
943 if (Load.C.cmdsize < sizeof(MachO::thread_command))
944 return malformedError("load command " + Twine(LoadCommandIndex) +
945 CmdName + " cmdsize too small");
946 MachO::thread_command T =
947 getStruct<MachO::thread_command>(Obj, Load.Ptr);
948 const char *state = Load.Ptr + sizeof(MachO::thread_command);
949 const char *end = Load.Ptr + T.cmdsize;
950 uint32_t nflavor = 0;
951 uint32_t cputype = getCPUType(Obj);
952 while (state < end) {
953 if(state + sizeof(uint32_t) > end)
954 return malformedError("load command " + Twine(LoadCommandIndex) +
955 "flavor in " + CmdName + " extends past end of "
958 memcpy(&flavor, state, sizeof(uint32_t));
959 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
960 sys::swapByteOrder(flavor);
961 state += sizeof(uint32_t);
963 if(state + sizeof(uint32_t) > end)
964 return malformedError("load command " + Twine(LoadCommandIndex) +
965 " count in " + CmdName + " extends past end of "
968 memcpy(&count, state, sizeof(uint32_t));
969 if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
970 sys::swapByteOrder(count);
971 state += sizeof(uint32_t);
973 if (cputype == MachO::CPU_TYPE_I386) {
974 if (flavor == MachO::x86_THREAD_STATE32) {
975 if (count != MachO::x86_THREAD_STATE32_COUNT)
976 return malformedError("load command " + Twine(LoadCommandIndex) +
977 " count not x86_THREAD_STATE32_COUNT for "
978 "flavor number " + Twine(nflavor) + " which is "
979 "a x86_THREAD_STATE32 flavor in " + CmdName +
981 if (state + sizeof(MachO::x86_thread_state32_t) > end)
982 return malformedError("load command " + Twine(LoadCommandIndex) +
983 " x86_THREAD_STATE32 extends past end of "
984 "command in " + CmdName + " command");
985 state += sizeof(MachO::x86_thread_state32_t);
987 return malformedError("load command " + Twine(LoadCommandIndex) +
988 " unknown flavor (" + Twine(flavor) + ") for "
989 "flavor number " + Twine(nflavor) + " in " +
990 CmdName + " command");
992 } else if (cputype == MachO::CPU_TYPE_X86_64) {
993 if (flavor == MachO::x86_THREAD_STATE64) {
994 if (count != MachO::x86_THREAD_STATE64_COUNT)
995 return malformedError("load command " + Twine(LoadCommandIndex) +
996 " count not x86_THREAD_STATE64_COUNT for "
997 "flavor number " + Twine(nflavor) + " which is "
998 "a x86_THREAD_STATE64 flavor in " + CmdName +
1000 if (state + sizeof(MachO::x86_thread_state64_t) > end)
1001 return malformedError("load command " + Twine(LoadCommandIndex) +
1002 " x86_THREAD_STATE64 extends past end of "
1003 "command in " + CmdName + " command");
1004 state += sizeof(MachO::x86_thread_state64_t);
1006 return malformedError("load command " + Twine(LoadCommandIndex) +
1007 " unknown flavor (" + Twine(flavor) + ") for "
1008 "flavor number " + Twine(nflavor) + " in " +
1009 CmdName + " command");
1011 } else if (cputype == MachO::CPU_TYPE_ARM) {
1012 if (flavor == MachO::ARM_THREAD_STATE) {
1013 if (count != MachO::ARM_THREAD_STATE_COUNT)
1014 return malformedError("load command " + Twine(LoadCommandIndex) +
1015 " count not ARM_THREAD_STATE_COUNT for "
1016 "flavor number " + Twine(nflavor) + " which is "
1017 "a ARM_THREAD_STATE flavor in " + CmdName +
1019 if (state + sizeof(MachO::arm_thread_state32_t) > end)
1020 return malformedError("load command " + Twine(LoadCommandIndex) +
1021 " ARM_THREAD_STATE extends past end of "
1022 "command in " + CmdName + " command");
1023 state += sizeof(MachO::arm_thread_state32_t);
1025 return malformedError("load command " + Twine(LoadCommandIndex) +
1026 " unknown flavor (" + Twine(flavor) + ") for "
1027 "flavor number " + Twine(nflavor) + " in " +
1028 CmdName + " command");
1030 } else if (cputype == MachO::CPU_TYPE_ARM64) {
1031 if (flavor == MachO::ARM_THREAD_STATE64) {
1032 if (count != MachO::ARM_THREAD_STATE64_COUNT)
1033 return malformedError("load command " + Twine(LoadCommandIndex) +
1034 " count not ARM_THREAD_STATE64_COUNT for "
1035 "flavor number " + Twine(nflavor) + " which is "
1036 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1038 if (state + sizeof(MachO::arm_thread_state64_t) > end)
1039 return malformedError("load command " + Twine(LoadCommandIndex) +
1040 " ARM_THREAD_STATE64 extends past end of "
1041 "command in " + CmdName + " command");
1042 state += sizeof(MachO::arm_thread_state64_t);
1044 return malformedError("load command " + Twine(LoadCommandIndex) +
1045 " unknown flavor (" + Twine(flavor) + ") for "
1046 "flavor number " + Twine(nflavor) + " in " +
1047 CmdName + " command");
1049 } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1050 if (flavor == MachO::PPC_THREAD_STATE) {
1051 if (count != MachO::PPC_THREAD_STATE_COUNT)
1052 return malformedError("load command " + Twine(LoadCommandIndex) +
1053 " count not PPC_THREAD_STATE_COUNT for "
1054 "flavor number " + Twine(nflavor) + " which is "
1055 "a PPC_THREAD_STATE flavor in " + CmdName +
1057 if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1058 return malformedError("load command " + Twine(LoadCommandIndex) +
1059 " PPC_THREAD_STATE extends past end of "
1060 "command in " + CmdName + " command");
1061 state += sizeof(MachO::ppc_thread_state32_t);
1063 return malformedError("load command " + Twine(LoadCommandIndex) +
1064 " unknown flavor (" + Twine(flavor) + ") for "
1065 "flavor number " + Twine(nflavor) + " in " +
1066 CmdName + " command");
1069 return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1070 "command " + Twine(LoadCommandIndex) + " for " +
1071 CmdName + " command can't be checked");
1075 return Error::success();
1078 static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1079 const MachOObjectFile::LoadCommandInfo
1081 uint32_t LoadCommandIndex,
1082 const char **LoadCmd,
1083 std::list<MachOElement> &Elements) {
1084 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1085 return malformedError("load command " + Twine(LoadCommandIndex) +
1086 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1087 if (*LoadCmd != nullptr)
1088 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1089 MachO::twolevel_hints_command Hints =
1090 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1091 uint64_t FileSize = Obj.getData().size();
1092 if (Hints.offset > FileSize)
1093 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1094 Twine(LoadCommandIndex) + " extends past the end of "
1096 uint64_t BigSize = Hints.nhints;
1097 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
1098 BigSize += Hints.offset;
1099 if (BigSize > FileSize)
1100 return malformedError("offset field plus nhints times sizeof(struct "
1101 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1102 Twine(LoadCommandIndex) + " extends past the end of "
1104 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1105 sizeof(MachO::twolevel_hint),
1108 *LoadCmd = Load.Ptr;
1109 return Error::success();
1112 // Returns true if the libObject code does not support the load command and its
1113 // contents. The cmd value it is treated as an unknown load command but with
1114 // an error message that says the cmd value is obsolete.
1115 static bool isLoadCommandObsolete(uint32_t cmd) {
1116 if (cmd == MachO::LC_SYMSEG ||
1117 cmd == MachO::LC_LOADFVMLIB ||
1118 cmd == MachO::LC_IDFVMLIB ||
1119 cmd == MachO::LC_IDENT ||
1120 cmd == MachO::LC_FVMFILE ||
1121 cmd == MachO::LC_PREPAGE ||
1122 cmd == MachO::LC_PREBOUND_DYLIB ||
1123 cmd == MachO::LC_TWOLEVEL_HINTS ||
1124 cmd == MachO::LC_PREBIND_CKSUM)
1129 Expected<std::unique_ptr<MachOObjectFile>>
1130 MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1131 bool Is64Bits, uint32_t UniversalCputype,
1132 uint32_t UniversalIndex) {
1133 Error Err = Error::success();
1134 std::unique_ptr<MachOObjectFile> Obj(
1135 new MachOObjectFile(std::move(Object), IsLittleEndian,
1136 Is64Bits, Err, UniversalCputype,
1139 return std::move(Err);
1140 return std::move(Obj);
1143 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1144 bool Is64bits, Error &Err,
1145 uint32_t UniversalCputype,
1146 uint32_t UniversalIndex)
1147 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
1148 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
1149 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
1150 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
1151 HasPageZeroSegment(false) {
1152 ErrorAsOutParameter ErrAsOutParam(&Err);
1153 uint64_t SizeOfHeaders;
1156 parseHeader(*this, Header64, Err);
1157 SizeOfHeaders = sizeof(MachO::mach_header_64);
1158 cputype = Header64.cputype;
1160 parseHeader(*this, Header, Err);
1161 SizeOfHeaders = sizeof(MachO::mach_header);
1162 cputype = Header.cputype;
1166 SizeOfHeaders += getHeader().sizeofcmds;
1167 if (getData().data() + SizeOfHeaders > getData().end()) {
1168 Err = malformedError("load commands extend past the end of the file");
1171 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1172 Err = malformedError("universal header architecture: " +
1173 Twine(UniversalIndex) + "'s cputype does not match "
1174 "object file's mach header");
1177 std::list<MachOElement> Elements;
1178 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
1180 uint32_t LoadCommandCount = getHeader().ncmds;
1181 LoadCommandInfo Load;
1182 if (LoadCommandCount != 0) {
1183 if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
1186 Err = LoadOrErr.takeError();
1191 const char *DyldIdLoadCmd = nullptr;
1192 const char *FuncStartsLoadCmd = nullptr;
1193 const char *SplitInfoLoadCmd = nullptr;
1194 const char *CodeSignDrsLoadCmd = nullptr;
1195 const char *CodeSignLoadCmd = nullptr;
1196 const char *VersLoadCmd = nullptr;
1197 const char *SourceLoadCmd = nullptr;
1198 const char *EntryPointLoadCmd = nullptr;
1199 const char *EncryptLoadCmd = nullptr;
1200 const char *RoutinesLoadCmd = nullptr;
1201 const char *UnixThreadLoadCmd = nullptr;
1202 const char *TwoLevelHintsLoadCmd = nullptr;
1203 for (unsigned I = 0; I < LoadCommandCount; ++I) {
1205 if (Load.C.cmdsize % 8 != 0) {
1206 // We have a hack here to allow 64-bit Mach-O core files to have
1207 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1208 // allowed since the macOS kernel produces them.
1209 if (getHeader().filetype != MachO::MH_CORE ||
1210 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1211 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1217 if (Load.C.cmdsize % 4 != 0) {
1218 Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1223 LoadCommands.push_back(Load);
1224 if (Load.C.cmd == MachO::LC_SYMTAB) {
1225 if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
1227 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1228 if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1231 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1232 if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1233 "LC_DATA_IN_CODE", Elements,
1234 "data in code info")))
1236 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1237 if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1238 "LC_LINKER_OPTIMIZATION_HINT",
1239 Elements, "linker optimization "
1242 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1243 if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1244 "LC_FUNCTION_STARTS", Elements,
1245 "function starts data")))
1247 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1248 if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1249 "LC_SEGMENT_SPLIT_INFO", Elements,
1250 "split info data")))
1252 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1253 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1254 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1255 "code signing RDs data")))
1257 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1258 if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1259 "LC_CODE_SIGNATURE", Elements,
1260 "code signature data")))
1262 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1263 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1264 "LC_DYLD_INFO", Elements)))
1266 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1267 if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1268 "LC_DYLD_INFO_ONLY", Elements)))
1270 } else if (Load.C.cmd == MachO::LC_UUID) {
1271 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1272 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1277 Err = malformedError("more than one LC_UUID command");
1280 UuidLoadCmd = Load.Ptr;
1281 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1282 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1284 *this, Load, Sections, HasPageZeroSegment, I,
1285 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
1287 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1288 if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1290 *this, Load, Sections, HasPageZeroSegment, I,
1291 "LC_SEGMENT", SizeOfHeaders, Elements)))
1293 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1294 if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1296 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1297 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1299 Libraries.push_back(Load.Ptr);
1300 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1301 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1303 Libraries.push_back(Load.Ptr);
1304 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1305 if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1307 Libraries.push_back(Load.Ptr);
1308 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1309 if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1311 Libraries.push_back(Load.Ptr);
1312 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1313 if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1315 Libraries.push_back(Load.Ptr);
1316 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1317 if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1319 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1320 if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1322 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1323 if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1325 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1326 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1327 "LC_VERSION_MIN_MACOSX")))
1329 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1330 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1331 "LC_VERSION_MIN_IPHONEOS")))
1333 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1334 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1335 "LC_VERSION_MIN_TVOS")))
1337 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1338 if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1339 "LC_VERSION_MIN_WATCHOS")))
1341 } else if (Load.C.cmd == MachO::LC_NOTE) {
1342 if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1344 } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1345 if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1347 } else if (Load.C.cmd == MachO::LC_RPATH) {
1348 if ((Err = checkRpathCommand(*this, Load, I)))
1350 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1351 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1352 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1353 " has incorrect cmdsize");
1356 if (SourceLoadCmd) {
1357 Err = malformedError("more than one LC_SOURCE_VERSION command");
1360 SourceLoadCmd = Load.Ptr;
1361 } else if (Load.C.cmd == MachO::LC_MAIN) {
1362 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1363 Err = malformedError("LC_MAIN command " + Twine(I) +
1364 " has incorrect cmdsize");
1367 if (EntryPointLoadCmd) {
1368 Err = malformedError("more than one LC_MAIN command");
1371 EntryPointLoadCmd = Load.Ptr;
1372 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1373 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1374 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1375 " has incorrect cmdsize");
1378 MachO::encryption_info_command E =
1379 getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1380 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1381 &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1383 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1384 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1385 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1386 " has incorrect cmdsize");
1389 MachO::encryption_info_command_64 E =
1390 getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1391 if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1392 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1394 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1395 if ((Err = checkLinkerOptCommand(*this, Load, I)))
1397 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1398 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1399 Err = malformedError("load command " + Twine(I) +
1400 " LC_SUB_FRAMEWORK cmdsize too small");
1403 MachO::sub_framework_command S =
1404 getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1405 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1406 sizeof(MachO::sub_framework_command),
1407 "sub_framework_command", S.umbrella,
1410 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1411 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1412 Err = malformedError("load command " + Twine(I) +
1413 " LC_SUB_UMBRELLA cmdsize too small");
1416 MachO::sub_umbrella_command S =
1417 getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1418 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1419 sizeof(MachO::sub_umbrella_command),
1420 "sub_umbrella_command", S.sub_umbrella,
1423 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1424 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1425 Err = malformedError("load command " + Twine(I) +
1426 " LC_SUB_LIBRARY cmdsize too small");
1429 MachO::sub_library_command S =
1430 getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1431 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1432 sizeof(MachO::sub_library_command),
1433 "sub_library_command", S.sub_library,
1436 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1437 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1438 Err = malformedError("load command " + Twine(I) +
1439 " LC_SUB_CLIENT cmdsize too small");
1442 MachO::sub_client_command S =
1443 getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1444 if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1445 sizeof(MachO::sub_client_command),
1446 "sub_client_command", S.client, "client")))
1448 } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1449 if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1450 Err = malformedError("LC_ROUTINES command " + Twine(I) +
1451 " has incorrect cmdsize");
1454 if (RoutinesLoadCmd) {
1455 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1459 RoutinesLoadCmd = Load.Ptr;
1460 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1461 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1462 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1463 " has incorrect cmdsize");
1466 if (RoutinesLoadCmd) {
1467 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1471 RoutinesLoadCmd = Load.Ptr;
1472 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1473 if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1475 if (UnixThreadLoadCmd) {
1476 Err = malformedError("more than one LC_UNIXTHREAD command");
1479 UnixThreadLoadCmd = Load.Ptr;
1480 } else if (Load.C.cmd == MachO::LC_THREAD) {
1481 if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1483 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1484 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1485 if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1486 &TwoLevelHintsLoadCmd, Elements)))
1488 } else if (isLoadCommandObsolete(Load.C.cmd)) {
1489 Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1490 Twine(Load.C.cmd) + " is obsolete and not "
1494 // TODO: generate a error for unknown load commands by default. But still
1495 // need work out an approach to allow or not allow unknown values like this
1496 // as an option for some uses like lldb.
1497 if (I < LoadCommandCount - 1) {
1498 if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
1501 Err = LoadOrErr.takeError();
1506 if (!SymtabLoadCmd) {
1507 if (DysymtabLoadCmd) {
1508 Err = malformedError("contains LC_DYSYMTAB load command without a "
1509 "LC_SYMTAB load command");
1512 } else if (DysymtabLoadCmd) {
1513 MachO::symtab_command Symtab =
1514 getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
1515 MachO::dysymtab_command Dysymtab =
1516 getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
1517 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1518 Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
1519 "extends past the end of the symbol table");
1522 uint64_t BigSize = Dysymtab.ilocalsym;
1523 BigSize += Dysymtab.nlocalsym;
1524 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
1525 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1526 "command extends past the end of the symbol table");
1529 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1530 Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
1531 "extends past the end of the symbol table");
1534 BigSize = Dysymtab.iextdefsym;
1535 BigSize += Dysymtab.nextdefsym;
1536 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
1537 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1538 "load command extends past the end of the symbol "
1542 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
1543 Err = malformedError("nundefsym in LC_DYSYMTAB load command "
1544 "extends past the end of the symbol table");
1547 BigSize = Dysymtab.iundefsym;
1548 BigSize += Dysymtab.nundefsym;
1549 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
1550 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1551 " command extends past the end of the symbol table");
1555 if ((getHeader().filetype == MachO::MH_DYLIB ||
1556 getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1557 DyldIdLoadCmd == nullptr) {
1558 Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1562 assert(LoadCommands.size() == LoadCommandCount);
1564 Err = Error::success();
1567 Error MachOObjectFile::checkSymbolTable() const {
1570 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1573 MachO::mach_header H = MachOObjectFile::getHeader();
1580 uint64_t NValue = 0;
1581 uint32_t SymbolIndex = 0;
1582 MachO::symtab_command S = getSymtabLoadCommand();
1583 for (const SymbolRef &Symbol : symbols()) {
1584 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1586 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1587 NType = STE_64.n_type;
1588 NSect = STE_64.n_sect;
1589 NDesc = STE_64.n_desc;
1590 NStrx = STE_64.n_strx;
1591 NValue = STE_64.n_value;
1593 MachO::nlist STE = getSymbolTableEntry(SymDRI);
1599 NValue = STE.n_value;
1601 if ((NType & MachO::N_STAB) == 0 &&
1602 (NType & MachO::N_TYPE) == MachO::N_SECT) {
1603 if (NSect == 0 || NSect > Sections.size())
1604 return malformedError("bad section index: " + Twine((int)NSect) +
1605 " for symbol at index " + Twine(SymbolIndex));
1607 if ((NType & MachO::N_STAB) == 0 &&
1608 (NType & MachO::N_TYPE) == MachO::N_INDR) {
1609 if (NValue >= S.strsize)
1610 return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1611 "the end of string table, for N_INDR symbol at "
1612 "index " + Twine(SymbolIndex));
1614 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1615 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1616 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1617 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1618 if (LibraryOrdinal != 0 &&
1619 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1620 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1621 LibraryOrdinal - 1 >= Libraries.size() ) {
1622 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1623 " for symbol at index " + Twine(SymbolIndex));
1626 if (NStrx >= S.strsize)
1627 return malformedError("bad string table index: " + Twine((int)NStrx) +
1628 " past the end of string table, for symbol at "
1629 "index " + Twine(SymbolIndex));
1632 return Error::success();
1635 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1636 unsigned SymbolTableEntrySize = is64Bit() ?
1637 sizeof(MachO::nlist_64) :
1638 sizeof(MachO::nlist);
1639 Symb.p += SymbolTableEntrySize;
1642 Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1643 StringRef StringTable = getStringTableData();
1644 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1645 const char *Start = &StringTable.data()[Entry.n_strx];
1646 if (Start < getData().begin() || Start >= getData().end()) {
1647 return malformedError("bad string index: " + Twine(Entry.n_strx) +
1648 " for symbol at index " + Twine(getSymbolIndex(Symb)));
1650 return StringRef(Start);
1653 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1654 DataRefImpl DRI = Sec.getRawDataRefImpl();
1655 uint32_t Flags = getSectionFlags(*this, DRI);
1656 return Flags & MachO::SECTION_TYPE;
1659 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1661 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1662 return Entry.n_value;
1664 MachO::nlist Entry = getSymbolTableEntry(Sym);
1665 return Entry.n_value;
1668 // getIndirectName() returns the name of the alias'ed symbol who's string table
1669 // index is in the n_value field.
1670 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1671 StringRef &Res) const {
1672 StringRef StringTable = getStringTableData();
1673 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1674 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1675 return object_error::parse_failed;
1676 uint64_t NValue = getNValue(Symb);
1677 if (NValue >= StringTable.size())
1678 return object_error::parse_failed;
1679 const char *Start = &StringTable.data()[NValue];
1680 Res = StringRef(Start);
1681 return std::error_code();
1684 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1685 return getNValue(Sym);
1688 Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1689 return getSymbolValue(Sym);
1692 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
1693 uint32_t flags = getSymbolFlags(DRI);
1694 if (flags & SymbolRef::SF_Common) {
1695 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1696 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
1701 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1702 return getNValue(DRI);
1705 Expected<SymbolRef::Type>
1706 MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1707 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1708 uint8_t n_type = Entry.n_type;
1710 // If this is a STAB debugging symbol, we can do nothing more.
1711 if (n_type & MachO::N_STAB)
1712 return SymbolRef::ST_Debug;
1714 switch (n_type & MachO::N_TYPE) {
1715 case MachO::N_UNDF :
1716 return SymbolRef::ST_Unknown;
1717 case MachO::N_SECT :
1718 Expected<section_iterator> SecOrError = getSymbolSection(Symb);
1720 return SecOrError.takeError();
1721 section_iterator Sec = *SecOrError;
1722 if (Sec->isData() || Sec->isBSS())
1723 return SymbolRef::ST_Data;
1724 return SymbolRef::ST_Function;
1726 return SymbolRef::ST_Other;
1729 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1730 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1732 uint8_t MachOType = Entry.n_type;
1733 uint16_t MachOFlags = Entry.n_desc;
1735 uint32_t Result = SymbolRef::SF_None;
1737 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1738 Result |= SymbolRef::SF_Indirect;
1740 if (MachOType & MachO::N_STAB)
1741 Result |= SymbolRef::SF_FormatSpecific;
1743 if (MachOType & MachO::N_EXT) {
1744 Result |= SymbolRef::SF_Global;
1745 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1747 Result |= SymbolRef::SF_Common;
1749 Result |= SymbolRef::SF_Undefined;
1752 if (!(MachOType & MachO::N_PEXT))
1753 Result |= SymbolRef::SF_Exported;
1756 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1757 Result |= SymbolRef::SF_Weak;
1759 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1760 Result |= SymbolRef::SF_Thumb;
1762 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1763 Result |= SymbolRef::SF_Absolute;
1768 Expected<section_iterator>
1769 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1770 MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1771 uint8_t index = Entry.n_sect;
1774 return section_end();
1776 DRI.d.a = index - 1;
1777 if (DRI.d.a >= Sections.size()){
1778 return malformedError("bad section index: " + Twine((int)index) +
1779 " for symbol at index " + Twine(getSymbolIndex(Symb)));
1781 return section_iterator(SectionRef(DRI, this));
1784 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1785 MachO::nlist_base Entry =
1786 getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
1787 return Entry.n_sect - 1;
1790 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1794 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1795 StringRef &Result) const {
1796 ArrayRef<char> Raw = getSectionRawName(Sec);
1797 Result = parseSegmentOrSectionName(Raw.data());
1798 return std::error_code();
1801 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1803 return getSection64(Sec).addr;
1804 return getSection(Sec).addr;
1807 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
1808 // In the case if a malformed Mach-O file where the section offset is past
1809 // the end of the file or some part of the section size is past the end of
1810 // the file return a size of zero or a size that covers the rest of the file
1811 // but does not extend past the end of the file.
1812 uint32_t SectOffset, SectType;
1816 MachO::section_64 Sect = getSection64(Sec);
1817 SectOffset = Sect.offset;
1818 SectSize = Sect.size;
1819 SectType = Sect.flags & MachO::SECTION_TYPE;
1821 MachO::section Sect = getSection(Sec);
1822 SectOffset = Sect.offset;
1823 SectSize = Sect.size;
1824 SectType = Sect.flags & MachO::SECTION_TYPE;
1826 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1828 uint64_t FileSize = getData().size();
1829 if (SectOffset > FileSize)
1831 if (FileSize - SectOffset < SectSize)
1832 return FileSize - SectOffset;
1836 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1837 StringRef &Res) const {
1842 MachO::section_64 Sect = getSection64(Sec);
1843 Offset = Sect.offset;
1846 MachO::section Sect = getSection(Sec);
1847 Offset = Sect.offset;
1851 Res = this->getData().substr(Offset, Size);
1852 return std::error_code();
1855 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1858 MachO::section_64 Sect = getSection64(Sec);
1861 MachO::section Sect = getSection(Sec);
1865 return uint64_t(1) << Align;
1868 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1872 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
1873 uint32_t Flags = getSectionFlags(*this, Sec);
1874 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
1877 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
1878 uint32_t Flags = getSectionFlags(*this, Sec);
1879 unsigned SectionType = Flags & MachO::SECTION_TYPE;
1880 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1881 !(SectionType == MachO::S_ZEROFILL ||
1882 SectionType == MachO::S_GB_ZEROFILL);
1885 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
1886 uint32_t Flags = getSectionFlags(*this, Sec);
1887 unsigned SectionType = Flags & MachO::SECTION_TYPE;
1888 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1889 (SectionType == MachO::S_ZEROFILL ||
1890 SectionType == MachO::S_GB_ZEROFILL);
1893 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1894 return Sec.getRawDataRefImpl().d.a;
1897 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
1898 // FIXME: Unimplemented.
1902 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
1903 StringRef SegmentName = getSectionFinalSegmentName(Sec);
1905 if (!getSectionName(Sec, SectName))
1906 return (SegmentName == "__LLVM" && SectName == "__bitcode");
1910 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
1914 return relocation_iterator(RelocationRef(Ret, this));
1918 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
1921 MachO::section_64 Sect = getSection64(Sec);
1924 MachO::section Sect = getSection(Sec);
1931 return relocation_iterator(RelocationRef(Ret, this));
1934 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1938 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
1939 assert(getHeader().filetype == MachO::MH_OBJECT &&
1940 "Only implemented for MH_OBJECT");
1941 MachO::any_relocation_info RE = getRelocation(Rel);
1942 return getAnyRelocationAddress(RE);
1946 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1947 MachO::any_relocation_info RE = getRelocation(Rel);
1948 if (isRelocationScattered(RE))
1949 return symbol_end();
1951 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
1952 bool isExtern = getPlainRelocationExternal(RE);
1954 return symbol_end();
1956 MachO::symtab_command S = getSymtabLoadCommand();
1957 unsigned SymbolTableEntrySize = is64Bit() ?
1958 sizeof(MachO::nlist_64) :
1959 sizeof(MachO::nlist);
1960 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
1962 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
1963 return symbol_iterator(SymbolRef(Sym, this));
1967 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
1968 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
1971 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
1972 MachO::any_relocation_info RE = getRelocation(Rel);
1973 return getAnyRelocationType(RE);
1976 void MachOObjectFile::getRelocationTypeName(
1977 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1979 uint64_t RType = getRelocationType(Rel);
1981 unsigned Arch = this->getArch();
1985 static const char *const Table[] = {
1986 "GENERIC_RELOC_VANILLA",
1987 "GENERIC_RELOC_PAIR",
1988 "GENERIC_RELOC_SECTDIFF",
1989 "GENERIC_RELOC_PB_LA_PTR",
1990 "GENERIC_RELOC_LOCAL_SECTDIFF",
1991 "GENERIC_RELOC_TLV" };
1999 case Triple::x86_64: {
2000 static const char *const Table[] = {
2001 "X86_64_RELOC_UNSIGNED",
2002 "X86_64_RELOC_SIGNED",
2003 "X86_64_RELOC_BRANCH",
2004 "X86_64_RELOC_GOT_LOAD",
2006 "X86_64_RELOC_SUBTRACTOR",
2007 "X86_64_RELOC_SIGNED_1",
2008 "X86_64_RELOC_SIGNED_2",
2009 "X86_64_RELOC_SIGNED_4",
2010 "X86_64_RELOC_TLV" };
2019 static const char *const Table[] = {
2020 "ARM_RELOC_VANILLA",
2022 "ARM_RELOC_SECTDIFF",
2023 "ARM_RELOC_LOCAL_SECTDIFF",
2024 "ARM_RELOC_PB_LA_PTR",
2026 "ARM_THUMB_RELOC_BR22",
2027 "ARM_THUMB_32BIT_BRANCH",
2029 "ARM_RELOC_HALF_SECTDIFF" };
2037 case Triple::aarch64: {
2038 static const char *const Table[] = {
2039 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2040 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2041 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2042 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2043 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2044 "ARM64_RELOC_ADDEND"
2047 if (RType >= array_lengthof(Table))
2054 static const char *const Table[] = {
2055 "PPC_RELOC_VANILLA",
2063 "PPC_RELOC_SECTDIFF",
2064 "PPC_RELOC_PB_LA_PTR",
2065 "PPC_RELOC_HI16_SECTDIFF",
2066 "PPC_RELOC_LO16_SECTDIFF",
2067 "PPC_RELOC_HA16_SECTDIFF",
2069 "PPC_RELOC_LO14_SECTDIFF",
2070 "PPC_RELOC_LOCAL_SECTDIFF" };
2078 case Triple::UnknownArch:
2082 Result.append(res.begin(), res.end());
2085 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2086 MachO::any_relocation_info RE = getRelocation(Rel);
2087 return getAnyRelocationLength(RE);
2091 // guessLibraryShortName() is passed a name of a dynamic library and returns a
2092 // guess on what the short name is. Then name is returned as a substring of the
2093 // StringRef Name passed in. The name of the dynamic library is recognized as
2094 // a framework if it has one of the two following forms:
2095 // Foo.framework/Versions/A/Foo
2096 // Foo.framework/Foo
2097 // Where A and Foo can be any string. And may contain a trailing suffix
2098 // starting with an underbar. If the Name is recognized as a framework then
2099 // isFramework is set to true else it is set to false. If the Name has a
2100 // suffix then Suffix is set to the substring in Name that contains the suffix
2101 // else it is set to a NULL StringRef.
2103 // The Name of the dynamic library is recognized as a library name if it has
2104 // one of the two following forms:
2107 // The library may have a suffix trailing the name Foo of the form:
2108 // libFoo_profile.A.dylib
2109 // libFoo_profile.dylib
2111 // The Name of the dynamic library is also recognized as a library name if it
2112 // has the following form:
2115 // If the Name of the dynamic library is none of the forms above then a NULL
2116 // StringRef is returned.
2118 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2120 StringRef &Suffix) {
2121 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2122 size_t a, b, c, d, Idx;
2124 isFramework = false;
2125 Suffix = StringRef();
2127 // Pull off the last component and make Foo point to it
2128 a = Name.rfind('/');
2129 if (a == Name.npos || a == 0)
2131 Foo = Name.slice(a+1, Name.npos);
2133 // Look for a suffix starting with a '_'
2134 Idx = Foo.rfind('_');
2135 if (Idx != Foo.npos && Foo.size() >= 2) {
2136 Suffix = Foo.slice(Idx, Foo.npos);
2137 Foo = Foo.slice(0, Idx);
2140 // First look for the form Foo.framework/Foo
2141 b = Name.rfind('/', a);
2146 F = Name.slice(Idx, Idx + Foo.size());
2147 DotFramework = Name.slice(Idx + Foo.size(),
2148 Idx + Foo.size() + sizeof(".framework/")-1);
2149 if (F == Foo && DotFramework == ".framework/") {
2154 // Next look for the form Foo.framework/Versions/A/Foo
2157 c = Name.rfind('/', b);
2158 if (c == Name.npos || c == 0)
2160 V = Name.slice(c+1, Name.npos);
2161 if (!V.startswith("Versions/"))
2163 d = Name.rfind('/', c);
2168 F = Name.slice(Idx, Idx + Foo.size());
2169 DotFramework = Name.slice(Idx + Foo.size(),
2170 Idx + Foo.size() + sizeof(".framework/")-1);
2171 if (F == Foo && DotFramework == ".framework/") {
2177 // pull off the suffix after the "." and make a point to it
2178 a = Name.rfind('.');
2179 if (a == Name.npos || a == 0)
2181 Dylib = Name.slice(a, Name.npos);
2182 if (Dylib != ".dylib")
2185 // First pull off the version letter for the form Foo.A.dylib if any.
2187 Dot = Name.slice(a-2, a-1);
2192 b = Name.rfind('/', a);
2197 // ignore any suffix after an underbar like Foo_profile.A.dylib
2198 Idx = Name.find('_', b);
2199 if (Idx != Name.npos && Idx != b) {
2200 Lib = Name.slice(b, Idx);
2201 Suffix = Name.slice(Idx, a);
2204 Lib = Name.slice(b, a);
2205 // There are incorrect library names of the form:
2206 // libATS.A_profile.dylib so check for these.
2207 if (Lib.size() >= 3) {
2208 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2210 Lib = Lib.slice(0, Lib.size()-2);
2215 Qtx = Name.slice(a, Name.npos);
2218 b = Name.rfind('/', a);
2220 Lib = Name.slice(0, a);
2222 Lib = Name.slice(b+1, a);
2223 // There are library names of the form: QT.A.qtx so check for these.
2224 if (Lib.size() >= 3) {
2225 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2227 Lib = Lib.slice(0, Lib.size()-2);
2232 // getLibraryShortNameByIndex() is used to get the short name of the library
2233 // for an undefined symbol in a linked Mach-O binary that was linked with the
2234 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2235 // It is passed the index (0 - based) of the library as translated from
2236 // GET_LIBRARY_ORDINAL (1 - based).
2237 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
2238 StringRef &Res) const {
2239 if (Index >= Libraries.size())
2240 return object_error::parse_failed;
2242 // If the cache of LibrariesShortNames is not built up do that first for
2243 // all the Libraries.
2244 if (LibrariesShortNames.size() == 0) {
2245 for (unsigned i = 0; i < Libraries.size(); i++) {
2246 MachO::dylib_command D =
2247 getStruct<MachO::dylib_command>(*this, Libraries[i]);
2248 if (D.dylib.name >= D.cmdsize)
2249 return object_error::parse_failed;
2250 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
2251 StringRef Name = StringRef(P);
2252 if (D.dylib.name+Name.size() >= D.cmdsize)
2253 return object_error::parse_failed;
2256 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
2257 if (shortName.empty())
2258 LibrariesShortNames.push_back(Name);
2260 LibrariesShortNames.push_back(shortName);
2264 Res = LibrariesShortNames[Index];
2265 return std::error_code();
2268 uint32_t MachOObjectFile::getLibraryCount() const {
2269 return Libraries.size();
2273 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2275 Sec.d.a = Rel->getRawDataRefImpl().d.a;
2276 return section_iterator(SectionRef(Sec, this));
2279 basic_symbol_iterator MachOObjectFile::symbol_begin() const {
2281 MachO::symtab_command Symtab = getSymtabLoadCommand();
2282 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2283 return basic_symbol_iterator(SymbolRef(DRI, this));
2285 return getSymbolByIndex(0);
2288 basic_symbol_iterator MachOObjectFile::symbol_end() const {
2290 MachO::symtab_command Symtab = getSymtabLoadCommand();
2291 if (!SymtabLoadCmd || Symtab.nsyms == 0)
2292 return basic_symbol_iterator(SymbolRef(DRI, this));
2294 unsigned SymbolTableEntrySize = is64Bit() ?
2295 sizeof(MachO::nlist_64) :
2296 sizeof(MachO::nlist);
2297 unsigned Offset = Symtab.symoff +
2298 Symtab.nsyms * SymbolTableEntrySize;
2299 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2300 return basic_symbol_iterator(SymbolRef(DRI, this));
2303 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
2304 MachO::symtab_command Symtab = getSymtabLoadCommand();
2305 if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2306 report_fatal_error("Requested symbol index is out of range.");
2307 unsigned SymbolTableEntrySize =
2308 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2310 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2311 DRI.p += Index * SymbolTableEntrySize;
2312 return basic_symbol_iterator(SymbolRef(DRI, this));
2315 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2316 MachO::symtab_command Symtab = getSymtabLoadCommand();
2318 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2319 unsigned SymbolTableEntrySize =
2320 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2321 DataRefImpl DRIstart;
2322 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2323 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2327 section_iterator MachOObjectFile::section_begin() const {
2329 return section_iterator(SectionRef(DRI, this));
2332 section_iterator MachOObjectFile::section_end() const {
2334 DRI.d.a = Sections.size();
2335 return section_iterator(SectionRef(DRI, this));
2338 uint8_t MachOObjectFile::getBytesInAddress() const {
2339 return is64Bit() ? 8 : 4;
2342 StringRef MachOObjectFile::getFileFormatName() const {
2343 unsigned CPUType = getCPUType(*this);
2346 case llvm::MachO::CPU_TYPE_I386:
2347 return "Mach-O 32-bit i386";
2348 case llvm::MachO::CPU_TYPE_ARM:
2349 return "Mach-O arm";
2350 case llvm::MachO::CPU_TYPE_POWERPC:
2351 return "Mach-O 32-bit ppc";
2353 return "Mach-O 32-bit unknown";
2358 case llvm::MachO::CPU_TYPE_X86_64:
2359 return "Mach-O 64-bit x86-64";
2360 case llvm::MachO::CPU_TYPE_ARM64:
2361 return "Mach-O arm64";
2362 case llvm::MachO::CPU_TYPE_POWERPC64:
2363 return "Mach-O 64-bit ppc64";
2365 return "Mach-O 64-bit unknown";
2369 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2371 case llvm::MachO::CPU_TYPE_I386:
2373 case llvm::MachO::CPU_TYPE_X86_64:
2374 return Triple::x86_64;
2375 case llvm::MachO::CPU_TYPE_ARM:
2377 case llvm::MachO::CPU_TYPE_ARM64:
2378 return Triple::aarch64;
2379 case llvm::MachO::CPU_TYPE_POWERPC:
2381 case llvm::MachO::CPU_TYPE_POWERPC64:
2382 return Triple::ppc64;
2384 return Triple::UnknownArch;
2388 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2389 const char **McpuDefault,
2390 const char **ArchFlag) {
2392 *McpuDefault = nullptr;
2394 *ArchFlag = nullptr;
2397 case MachO::CPU_TYPE_I386:
2398 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2399 case MachO::CPU_SUBTYPE_I386_ALL:
2402 return Triple("i386-apple-darwin");
2406 case MachO::CPU_TYPE_X86_64:
2407 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2408 case MachO::CPU_SUBTYPE_X86_64_ALL:
2410 *ArchFlag = "x86_64";
2411 return Triple("x86_64-apple-darwin");
2412 case MachO::CPU_SUBTYPE_X86_64_H:
2414 *ArchFlag = "x86_64h";
2415 return Triple("x86_64h-apple-darwin");
2419 case MachO::CPU_TYPE_ARM:
2420 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2421 case MachO::CPU_SUBTYPE_ARM_V4T:
2423 *ArchFlag = "armv4t";
2424 return Triple("armv4t-apple-darwin");
2425 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2427 *ArchFlag = "armv5e";
2428 return Triple("armv5e-apple-darwin");
2429 case MachO::CPU_SUBTYPE_ARM_XSCALE:
2431 *ArchFlag = "xscale";
2432 return Triple("xscale-apple-darwin");
2433 case MachO::CPU_SUBTYPE_ARM_V6:
2435 *ArchFlag = "armv6";
2436 return Triple("armv6-apple-darwin");
2437 case MachO::CPU_SUBTYPE_ARM_V6M:
2439 *McpuDefault = "cortex-m0";
2441 *ArchFlag = "armv6m";
2442 return Triple("armv6m-apple-darwin");
2443 case MachO::CPU_SUBTYPE_ARM_V7:
2445 *ArchFlag = "armv7";
2446 return Triple("armv7-apple-darwin");
2447 case MachO::CPU_SUBTYPE_ARM_V7EM:
2449 *McpuDefault = "cortex-m4";
2451 *ArchFlag = "armv7em";
2452 return Triple("thumbv7em-apple-darwin");
2453 case MachO::CPU_SUBTYPE_ARM_V7K:
2455 *McpuDefault = "cortex-a7";
2457 *ArchFlag = "armv7k";
2458 return Triple("armv7k-apple-darwin");
2459 case MachO::CPU_SUBTYPE_ARM_V7M:
2461 *McpuDefault = "cortex-m3";
2463 *ArchFlag = "armv7m";
2464 return Triple("thumbv7m-apple-darwin");
2465 case MachO::CPU_SUBTYPE_ARM_V7S:
2467 *McpuDefault = "cortex-a7";
2469 *ArchFlag = "armv7s";
2470 return Triple("armv7s-apple-darwin");
2474 case MachO::CPU_TYPE_ARM64:
2475 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2476 case MachO::CPU_SUBTYPE_ARM64_ALL:
2478 *McpuDefault = "cyclone";
2480 *ArchFlag = "arm64";
2481 return Triple("arm64-apple-darwin");
2485 case MachO::CPU_TYPE_POWERPC:
2486 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2487 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2490 return Triple("ppc-apple-darwin");
2494 case MachO::CPU_TYPE_POWERPC64:
2495 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2496 case MachO::CPU_SUBTYPE_POWERPC_ALL:
2498 *ArchFlag = "ppc64";
2499 return Triple("ppc64-apple-darwin");
2508 Triple MachOObjectFile::getHostArch() {
2509 return Triple(sys::getDefaultTargetTriple());
2512 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2513 return StringSwitch<bool>(ArchFlag)
2515 .Case("x86_64", true)
2516 .Case("x86_64h", true)
2517 .Case("armv4t", true)
2519 .Case("armv5e", true)
2520 .Case("armv6", true)
2521 .Case("armv6m", true)
2522 .Case("armv7", true)
2523 .Case("armv7em", true)
2524 .Case("armv7k", true)
2525 .Case("armv7m", true)
2526 .Case("armv7s", true)
2527 .Case("arm64", true)
2529 .Case("ppc64", true)
2533 unsigned MachOObjectFile::getArch() const {
2534 return getArch(getCPUType(*this));
2537 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2538 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2541 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2544 return section_rel_begin(DRI);
2547 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2550 return section_rel_end(DRI);
2553 dice_iterator MachOObjectFile::begin_dices() const {
2555 if (!DataInCodeLoadCmd)
2556 return dice_iterator(DiceRef(DRI, this));
2558 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2559 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2560 return dice_iterator(DiceRef(DRI, this));
2563 dice_iterator MachOObjectFile::end_dices() const {
2565 if (!DataInCodeLoadCmd)
2566 return dice_iterator(DiceRef(DRI, this));
2568 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2569 unsigned Offset = DicLC.dataoff + DicLC.datasize;
2570 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2571 return dice_iterator(DiceRef(DRI, this));
2574 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
2575 : Trie(T), Malformed(false), Done(false) {}
2577 void ExportEntry::moveToFirst() {
2579 pushDownUntilBottom();
2582 void ExportEntry::moveToEnd() {
2587 bool ExportEntry::operator==(const ExportEntry &Other) const {
2588 // Common case, one at end, other iterating from begin.
2589 if (Done || Other.Done)
2590 return (Done == Other.Done);
2591 // Not equal if different stack sizes.
2592 if (Stack.size() != Other.Stack.size())
2594 // Not equal if different cumulative strings.
2595 if (!CumulativeString.equals(Other.CumulativeString))
2597 // Equal if all nodes in both stacks match.
2598 for (unsigned i=0; i < Stack.size(); ++i) {
2599 if (Stack[i].Start != Other.Stack[i].Start)
2605 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
2607 uint64_t Result = decodeULEB128(Ptr, &Count);
2609 if (Ptr > Trie.end()) {
2616 StringRef ExportEntry::name() const {
2617 return CumulativeString;
2620 uint64_t ExportEntry::flags() const {
2621 return Stack.back().Flags;
2624 uint64_t ExportEntry::address() const {
2625 return Stack.back().Address;
2628 uint64_t ExportEntry::other() const {
2629 return Stack.back().Other;
2632 StringRef ExportEntry::otherName() const {
2633 const char* ImportName = Stack.back().ImportName;
2635 return StringRef(ImportName);
2639 uint32_t ExportEntry::nodeOffset() const {
2640 return Stack.back().Start - Trie.begin();
2643 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2644 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
2645 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
2646 ParentStringLength(0), IsExportNode(false) {}
2648 void ExportEntry::pushNode(uint64_t offset) {
2649 const uint8_t *Ptr = Trie.begin() + offset;
2650 NodeState State(Ptr);
2651 uint64_t ExportInfoSize = readULEB128(State.Current);
2652 State.IsExportNode = (ExportInfoSize != 0);
2653 const uint8_t* Children = State.Current + ExportInfoSize;
2654 if (State.IsExportNode) {
2655 State.Flags = readULEB128(State.Current);
2656 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2658 State.Other = readULEB128(State.Current); // dylib ordinal
2659 State.ImportName = reinterpret_cast<const char*>(State.Current);
2661 State.Address = readULEB128(State.Current);
2662 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
2663 State.Other = readULEB128(State.Current);
2666 State.ChildCount = *Children;
2667 State.Current = Children + 1;
2668 State.NextChildIndex = 0;
2669 State.ParentStringLength = CumulativeString.size();
2670 Stack.push_back(State);
2673 void ExportEntry::pushDownUntilBottom() {
2674 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2675 NodeState &Top = Stack.back();
2676 CumulativeString.resize(Top.ParentStringLength);
2677 for (;*Top.Current != 0; Top.Current++) {
2678 char C = *Top.Current;
2679 CumulativeString.push_back(C);
2682 uint64_t childNodeIndex = readULEB128(Top.Current);
2683 Top.NextChildIndex += 1;
2684 pushNode(childNodeIndex);
2686 if (!Stack.back().IsExportNode) {
2692 // We have a trie data structure and need a way to walk it that is compatible
2693 // with the C++ iterator model. The solution is a non-recursive depth first
2694 // traversal where the iterator contains a stack of parent nodes along with a
2695 // string that is the accumulation of all edge strings along the parent chain
2698 // There is one "export" node for each exported symbol. But because some
2699 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
2700 // node may have child nodes too.
2702 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
2703 // child until hitting a node with no children (which is an export node or
2704 // else the trie is malformed). On the way down, each node is pushed on the
2705 // stack ivar. If there is no more ways down, it pops up one and tries to go
2706 // down a sibling path until a childless node is reached.
2707 void ExportEntry::moveNext() {
2708 if (Stack.empty() || !Stack.back().IsExportNode) {
2715 while (!Stack.empty()) {
2716 NodeState &Top = Stack.back();
2717 if (Top.NextChildIndex < Top.ChildCount) {
2718 pushDownUntilBottom();
2719 // Now at the next export node.
2722 if (Top.IsExportNode) {
2723 // This node has no children but is itself an export node.
2724 CumulativeString.resize(Top.ParentStringLength);
2733 iterator_range<export_iterator>
2734 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
2735 ExportEntry Start(Trie);
2736 if (Trie.size() == 0)
2739 Start.moveToFirst();
2741 ExportEntry Finish(Trie);
2744 return make_range(export_iterator(Start), export_iterator(Finish));
2747 iterator_range<export_iterator> MachOObjectFile::exports() const {
2748 return exports(getDyldInfoExportsTrie());
2751 MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
2752 ArrayRef<uint8_t> Bytes, bool is64Bit)
2753 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0),
2754 SegmentIndex(-1), RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2755 PointerSize(is64Bit ? 8 : 4), Done(false) {}
2757 void MachORebaseEntry::moveToFirst() {
2758 Ptr = Opcodes.begin();
2762 void MachORebaseEntry::moveToEnd() {
2763 Ptr = Opcodes.end();
2764 RemainingLoopCount = 0;
2768 void MachORebaseEntry::moveNext() {
2769 ErrorAsOutParameter ErrAsOutParam(E);
2770 // If in the middle of some loop, move to next rebasing in loop.
2771 SegmentOffset += AdvanceAmount;
2772 if (RemainingLoopCount) {
2773 --RemainingLoopCount;
2776 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
2777 // pointer size. Therefore it is possible to reach the end without ever having
2778 // seen REBASE_OPCODE_DONE.
2779 if (Ptr == Opcodes.end()) {
2785 // Parse next opcode and set up next loop.
2786 const uint8_t *OpcodeStart = Ptr;
2787 uint8_t Byte = *Ptr++;
2788 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
2789 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
2790 uint32_t Count, Skip;
2791 const char *error = nullptr;
2793 case MachO::REBASE_OPCODE_DONE:
2797 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
2799 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
2800 RebaseType = ImmValue;
2801 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
2802 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
2803 Twine((int)RebaseType) + " for opcode at: 0x" +
2804 utohexstr(OpcodeStart - Opcodes.begin()));
2810 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
2811 << "RebaseType=" << (int) RebaseType << "\n");
2813 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
2814 SegmentIndex = ImmValue;
2815 SegmentOffset = readULEB128(&error);
2817 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
2818 Twine(error) + " for opcode at: 0x" +
2819 utohexstr(OpcodeStart - Opcodes.begin()));
2823 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2826 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
2827 Twine(error) + " for opcode at: 0x" +
2828 utohexstr(OpcodeStart - Opcodes.begin()));
2834 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
2835 << "SegmentIndex=" << SegmentIndex << ", "
2836 << format("SegmentOffset=0x%06X", SegmentOffset)
2839 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
2840 SegmentOffset += readULEB128(&error);
2842 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
2843 Twine(error) + " for opcode at: 0x" +
2844 utohexstr(OpcodeStart - Opcodes.begin()));
2848 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2851 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
2852 Twine(error) + " for opcode at: 0x" +
2853 utohexstr(OpcodeStart - Opcodes.begin()));
2857 DEBUG_WITH_TYPE("mach-o-rebase",
2858 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
2859 << format("SegmentOffset=0x%06X",
2860 SegmentOffset) << "\n");
2862 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
2863 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2866 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
2867 Twine(error) + " for opcode at: 0x" +
2868 utohexstr(OpcodeStart - Opcodes.begin()));
2872 SegmentOffset += ImmValue * PointerSize;
2873 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2876 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
2877 " (after adding immediate times the pointer size) " +
2878 Twine(error) + " for opcode at: 0x" +
2879 utohexstr(OpcodeStart - Opcodes.begin()));
2883 DEBUG_WITH_TYPE("mach-o-rebase",
2884 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
2885 << format("SegmentOffset=0x%06X",
2886 SegmentOffset) << "\n");
2888 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
2889 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2892 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
2893 Twine(error) + " for opcode at: 0x" +
2894 utohexstr(OpcodeStart - Opcodes.begin()));
2898 AdvanceAmount = PointerSize;
2902 RemainingLoopCount = ImmValue - 1;
2904 RemainingLoopCount = 0;
2905 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2906 SegmentIndex, SegmentOffset);
2908 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES "
2909 + Twine(error) + " for opcode at: 0x" +
2910 utohexstr(OpcodeStart - Opcodes.begin()));
2916 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
2917 << format("SegmentOffset=0x%06X", SegmentOffset)
2918 << ", AdvanceAmount=" << AdvanceAmount
2919 << ", RemainingLoopCount=" << RemainingLoopCount
2922 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
2923 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2926 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
2927 Twine(error) + " for opcode at: 0x" +
2928 utohexstr(OpcodeStart - Opcodes.begin()));
2932 AdvanceAmount = PointerSize;
2934 Count = readULEB128(&error);
2936 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
2937 Twine(error) + " for opcode at: 0x" +
2938 utohexstr(OpcodeStart - Opcodes.begin()));
2943 RemainingLoopCount = Count - 1;
2945 RemainingLoopCount = 0;
2946 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2947 SegmentIndex, SegmentOffset);
2949 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES "
2950 + Twine(error) + " for opcode at: 0x" +
2951 utohexstr(OpcodeStart - Opcodes.begin()));
2957 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
2958 << format("SegmentOffset=0x%06X", SegmentOffset)
2959 << ", AdvanceAmount=" << AdvanceAmount
2960 << ", RemainingLoopCount=" << RemainingLoopCount
2963 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
2964 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2967 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
2968 Twine(error) + " for opcode at: 0x" +
2969 utohexstr(OpcodeStart - Opcodes.begin()));
2973 Skip = readULEB128(&error);
2975 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
2976 Twine(error) + " for opcode at: 0x" +
2977 utohexstr(OpcodeStart - Opcodes.begin()));
2981 AdvanceAmount = Skip + PointerSize;
2983 RemainingLoopCount = 0;
2984 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2985 SegmentIndex, SegmentOffset);
2987 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB "
2988 + Twine(error) + " for opcode at: 0x" +
2989 utohexstr(OpcodeStart - Opcodes.begin()));
2995 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
2996 << format("SegmentOffset=0x%06X", SegmentOffset)
2997 << ", AdvanceAmount=" << AdvanceAmount
2998 << ", RemainingLoopCount=" << RemainingLoopCount
3001 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
3002 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3005 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3006 "ULEB " + Twine(error) + " for opcode at: 0x" +
3007 utohexstr(OpcodeStart - Opcodes.begin()));
3011 Count = readULEB128(&error);
3013 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3014 "ULEB " + Twine(error) + " for opcode at: 0x" +
3015 utohexstr(OpcodeStart - Opcodes.begin()));
3020 RemainingLoopCount = Count - 1;
3022 RemainingLoopCount = 0;
3023 Skip = readULEB128(&error);
3025 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3026 "ULEB " + Twine(error) + " for opcode at: 0x" +
3027 utohexstr(OpcodeStart - Opcodes.begin()));
3031 AdvanceAmount = Skip + PointerSize;
3033 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3034 SegmentIndex, SegmentOffset);
3036 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3037 "ULEB " + Twine(error) + " for opcode at: 0x" +
3038 utohexstr(OpcodeStart - Opcodes.begin()));
3044 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3045 << format("SegmentOffset=0x%06X", SegmentOffset)
3046 << ", AdvanceAmount=" << AdvanceAmount
3047 << ", RemainingLoopCount=" << RemainingLoopCount
3051 *E = malformedError("bad rebase info (bad opcode value 0x" +
3052 utohexstr(Opcode) + " for opcode at: 0x" +
3053 utohexstr(OpcodeStart - Opcodes.begin()));
3060 uint64_t MachORebaseEntry::readULEB128(const char **error) {
3062 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3064 if (Ptr > Opcodes.end())
3065 Ptr = Opcodes.end();
3069 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
3071 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3073 StringRef MachORebaseEntry::typeName() const {
3074 switch (RebaseType) {
3075 case MachO::REBASE_TYPE_POINTER:
3077 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3078 return "text abs32";
3079 case MachO::REBASE_TYPE_TEXT_PCREL32:
3080 return "text rel32";
3085 // For use with the SegIndex of a checked Mach-O Rebase entry
3086 // to get the segment name.
3087 StringRef MachORebaseEntry::segmentName() const {
3088 return O->BindRebaseSegmentName(SegmentIndex);
3091 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3092 // to get the section name.
3093 StringRef MachORebaseEntry::sectionName() const {
3094 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3097 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3098 // to get the address.
3099 uint64_t MachORebaseEntry::address() const {
3100 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3103 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
3104 #ifdef EXPENSIVE_CHECKS
3105 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3107 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3109 return (Ptr == Other.Ptr) &&
3110 (RemainingLoopCount == Other.RemainingLoopCount) &&
3111 (Done == Other.Done);
3114 iterator_range<rebase_iterator>
3115 MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3116 ArrayRef<uint8_t> Opcodes, bool is64) {
3117 if (O->BindRebaseSectionTable == nullptr)
3118 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3119 MachORebaseEntry Start(&Err, O, Opcodes, is64);
3120 Start.moveToFirst();
3122 MachORebaseEntry Finish(&Err, O, Opcodes, is64);
3125 return make_range(rebase_iterator(Start), rebase_iterator(Finish));
3128 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3129 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
3132 MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3133 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
3134 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0),
3135 SegmentIndex(-1), LibraryOrdinalSet(false), Ordinal(0), Flags(0),
3136 Addend(0), RemainingLoopCount(0), AdvanceAmount(0), BindType(0),
3137 PointerSize(is64Bit ? 8 : 4), TableKind(BK), Done(false) {}
3139 void MachOBindEntry::moveToFirst() {
3140 Ptr = Opcodes.begin();
3144 void MachOBindEntry::moveToEnd() {
3145 Ptr = Opcodes.end();
3146 RemainingLoopCount = 0;
3150 void MachOBindEntry::moveNext() {
3151 ErrorAsOutParameter ErrAsOutParam(E);
3152 // If in the middle of some loop, move to next binding in loop.
3153 SegmentOffset += AdvanceAmount;
3154 if (RemainingLoopCount) {
3155 --RemainingLoopCount;
3158 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3159 // pointer size. Therefore it is possible to reach the end without ever having
3160 // seen BIND_OPCODE_DONE.
3161 if (Ptr == Opcodes.end()) {
3167 // Parse next opcode and set up next loop.
3168 const uint8_t *OpcodeStart = Ptr;
3169 uint8_t Byte = *Ptr++;
3170 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3171 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3172 int8_t SignExtended;
3173 const uint8_t *SymStart;
3174 uint32_t Count, Skip;
3175 const char *error = nullptr;
3177 case MachO::BIND_OPCODE_DONE:
3178 if (TableKind == Kind::Lazy) {
3179 // Lazying bindings have a DONE opcode between entries. Need to ignore
3180 // it to advance to next entry. But need not if this is last entry.
3181 bool NotLastEntry = false;
3182 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3184 NotLastEntry = true;
3192 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
3194 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
3195 if (TableKind == Kind::Weak) {
3196 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3197 "weak bind table for opcode at: 0x" +
3198 utohexstr(OpcodeStart - Opcodes.begin()));
3203 LibraryOrdinalSet = true;
3204 if (ImmValue > O->getLibraryCount()) {
3205 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3206 "library ordinal: " + Twine((int)ImmValue) + " (max " +
3207 Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
3208 utohexstr(OpcodeStart - Opcodes.begin()));
3214 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3215 << "Ordinal=" << Ordinal << "\n");
3217 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
3218 if (TableKind == Kind::Weak) {
3219 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3220 "weak bind table for opcode at: 0x" +
3221 utohexstr(OpcodeStart - Opcodes.begin()));
3225 Ordinal = readULEB128(&error);
3226 LibraryOrdinalSet = true;
3228 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3229 Twine(error) + " for opcode at: 0x" +
3230 utohexstr(OpcodeStart - Opcodes.begin()));
3234 if (Ordinal > (int)O->getLibraryCount()) {
3235 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3236 "library ordinal: " + Twine((int)Ordinal) + " (max " +
3237 Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
3238 utohexstr(OpcodeStart - Opcodes.begin()));
3244 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3245 << "Ordinal=" << Ordinal << "\n");
3247 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
3248 if (TableKind == Kind::Weak) {
3249 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3250 "weak bind table for opcode at: 0x" +
3251 utohexstr(OpcodeStart - Opcodes.begin()));
3256 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3257 Ordinal = SignExtended;
3258 LibraryOrdinalSet = true;
3259 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3260 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3261 "special ordinal: " + Twine((int)Ordinal) + " for opcode at: "
3262 "0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3270 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3271 << "Ordinal=" << Ordinal << "\n");
3273 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3276 while (*Ptr && (Ptr < Opcodes.end())) {
3279 if (Ptr == Opcodes.end()) {
3280 *E = malformedError("for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3281 "symbol name extends past opcodes for opcode at: 0x" +
3282 utohexstr(OpcodeStart - Opcodes.begin()));
3286 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3291 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3292 << "SymbolName=" << SymbolName << "\n");
3293 if (TableKind == Kind::Weak) {
3294 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3298 case MachO::BIND_OPCODE_SET_TYPE_IMM:
3299 BindType = ImmValue;
3300 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
3301 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3302 Twine((int)ImmValue) + " for opcode at: 0x" +
3303 utohexstr(OpcodeStart - Opcodes.begin()));
3309 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3310 << "BindType=" << (int)BindType << "\n");
3312 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
3313 Addend = readSLEB128(&error);
3315 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " +
3316 Twine(error) + " for opcode at: 0x" +
3317 utohexstr(OpcodeStart - Opcodes.begin()));
3323 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3324 << "Addend=" << Addend << "\n");
3326 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3327 SegmentIndex = ImmValue;
3328 SegmentOffset = readULEB128(&error);
3330 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3331 Twine(error) + " for opcode at: 0x" +
3332 utohexstr(OpcodeStart - Opcodes.begin()));
3336 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3338 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3339 Twine(error) + " for opcode at: 0x" +
3340 utohexstr(OpcodeStart - Opcodes.begin()));
3346 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3347 << "SegmentIndex=" << SegmentIndex << ", "
3348 << format("SegmentOffset=0x%06X", SegmentOffset)
3351 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
3352 SegmentOffset += readULEB128(&error);
3354 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
3355 Twine(error) + " for opcode at: 0x" +
3356 utohexstr(OpcodeStart - Opcodes.begin()));
3360 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3362 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
3363 Twine(error) + " for opcode at: 0x" +
3364 utohexstr(OpcodeStart - Opcodes.begin()));
3368 DEBUG_WITH_TYPE("mach-o-bind",
3369 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3370 << format("SegmentOffset=0x%06X",
3371 SegmentOffset) << "\n");
3373 case MachO::BIND_OPCODE_DO_BIND:
3374 AdvanceAmount = PointerSize;
3375 RemainingLoopCount = 0;
3376 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3378 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
3379 " for opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3383 if (SymbolName == StringRef()) {
3384 *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3385 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3386 utohexstr(OpcodeStart - Opcodes.begin()));
3390 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3391 *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3392 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3393 utohexstr(OpcodeStart - Opcodes.begin()));
3397 DEBUG_WITH_TYPE("mach-o-bind",
3398 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
3399 << format("SegmentOffset=0x%06X",
3400 SegmentOffset) << "\n");
3402 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
3403 if (TableKind == Kind::Lazy) {
3404 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3405 "lazy bind table for opcode at: 0x" +
3406 utohexstr(OpcodeStart - Opcodes.begin()));
3410 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3412 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3413 Twine(error) + " for opcode at: 0x" +
3414 utohexstr(OpcodeStart - Opcodes.begin()));
3418 if (SymbolName == StringRef()) {
3419 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3420 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3421 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3425 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3426 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3427 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3428 utohexstr(OpcodeStart - Opcodes.begin()));
3432 AdvanceAmount = readULEB128(&error) + PointerSize;
3434 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3435 Twine(error) + " for opcode at: 0x" +
3436 utohexstr(OpcodeStart - Opcodes.begin()));
3440 // Note, this is not really an error until the next bind but make no sense
3441 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3443 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3444 AdvanceAmount, false);
3446 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3447 "ULEB) " + Twine(error) + " for opcode at: 0x" +
3448 utohexstr(OpcodeStart - Opcodes.begin()));
3452 RemainingLoopCount = 0;
3455 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3456 << format("SegmentOffset=0x%06X", SegmentOffset)
3457 << ", AdvanceAmount=" << AdvanceAmount
3458 << ", RemainingLoopCount=" << RemainingLoopCount
3461 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
3462 if (TableKind == Kind::Lazy) {
3463 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3464 "allowed in lazy bind table for opcode at: 0x" +
3465 utohexstr(OpcodeStart - Opcodes.begin()));
3469 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3471 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3472 Twine(error) + " for opcode at: 0x" +
3473 utohexstr(OpcodeStart - Opcodes.begin()));
3477 if (SymbolName == StringRef()) {
3478 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3479 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3480 "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3484 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3485 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3486 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3487 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3491 AdvanceAmount = ImmValue * PointerSize + PointerSize;
3492 RemainingLoopCount = 0;
3493 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3494 AdvanceAmount, false);
3496 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3497 " (after adding immediate times the pointer size) " +
3498 Twine(error) + " for opcode at: 0x" +
3499 utohexstr(OpcodeStart - Opcodes.begin()));
3503 DEBUG_WITH_TYPE("mach-o-bind",
3505 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3506 << format("SegmentOffset=0x%06X",
3507 SegmentOffset) << "\n");
3509 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3510 if (TableKind == Kind::Lazy) {
3511 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3512 "allowed in lazy bind table for opcode at: 0x" +
3513 utohexstr(OpcodeStart - Opcodes.begin()));
3517 Count = readULEB128(&error);
3519 RemainingLoopCount = Count - 1;
3521 RemainingLoopCount = 0;
3523 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3524 " (count value) " + Twine(error) + " for opcode at"
3525 ": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3529 Skip = readULEB128(&error);
3530 AdvanceAmount = Skip + PointerSize;
3532 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3533 " (skip value) " + Twine(error) + " for opcode at"
3534 ": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3538 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3540 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3541 + Twine(error) + " for opcode at: 0x" +
3542 utohexstr(OpcodeStart - Opcodes.begin()));
3546 if (SymbolName == StringRef()) {
3547 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3548 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3549 "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3553 if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3554 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3555 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3556 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
3560 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
3561 SegmentIndex, SegmentOffset);
3563 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3564 + Twine(error) + " for opcode at: 0x" +
3565 utohexstr(OpcodeStart - Opcodes.begin()));
3571 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3572 << format("SegmentOffset=0x%06X", SegmentOffset)
3573 << ", AdvanceAmount=" << AdvanceAmount
3574 << ", RemainingLoopCount=" << RemainingLoopCount
3578 *E = malformedError("bad bind info (bad opcode value 0x" +
3579 utohexstr(Opcode) + " for opcode at: 0x" +
3580 utohexstr(OpcodeStart - Opcodes.begin()));
3587 uint64_t MachOBindEntry::readULEB128(const char **error) {
3589 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3591 if (Ptr > Opcodes.end())
3592 Ptr = Opcodes.end();
3596 int64_t MachOBindEntry::readSLEB128(const char **error) {
3598 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
3600 if (Ptr > Opcodes.end())
3601 Ptr = Opcodes.end();
3605 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3607 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3609 StringRef MachOBindEntry::typeName() const {
3611 case MachO::BIND_TYPE_POINTER:
3613 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3614 return "text abs32";
3615 case MachO::BIND_TYPE_TEXT_PCREL32:
3616 return "text rel32";
3621 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3623 int64_t MachOBindEntry::addend() const { return Addend; }
3625 uint32_t MachOBindEntry::flags() const { return Flags; }
3627 int MachOBindEntry::ordinal() const { return Ordinal; }
3629 // For use with the SegIndex of a checked Mach-O Bind entry
3630 // to get the segment name.
3631 StringRef MachOBindEntry::segmentName() const {
3632 return O->BindRebaseSegmentName(SegmentIndex);
3635 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3636 // to get the section name.
3637 StringRef MachOBindEntry::sectionName() const {
3638 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3641 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3642 // to get the address.
3643 uint64_t MachOBindEntry::address() const {
3644 return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3647 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3648 #ifdef EXPENSIVE_CHECKS
3649 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3651 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3653 return (Ptr == Other.Ptr) &&
3654 (RemainingLoopCount == Other.RemainingLoopCount) &&
3655 (Done == Other.Done);
3658 // Build table of sections so SegIndex/SegOffset pairs can be translated.
3659 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3660 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
3661 StringRef CurSegName;
3662 uint64_t CurSegAddress;
3663 for (const SectionRef &Section : Obj->sections()) {
3665 Section.getName(Info.SectionName);
3666 Info.Address = Section.getAddress();
3667 Info.Size = Section.getSize();
3669 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3670 if (!Info.SegmentName.equals(CurSegName)) {
3672 CurSegName = Info.SegmentName;
3673 CurSegAddress = Info.Address;
3675 Info.SegmentIndex = CurSegIndex - 1;
3676 Info.OffsetInSegment = Info.Address - CurSegAddress;
3677 Info.SegmentStartAddress = CurSegAddress;
3678 Sections.push_back(Info);
3680 MaxSegIndex = CurSegIndex;
3683 // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
3684 // validate a MachOBindEntry or MachORebaseEntry.
3685 const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
3689 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
3690 if (SegIndex >= MaxSegIndex)
3691 return "bad segIndex (too large)";
3692 for (const SectionInfo &SI : Sections) {
3693 if (SI.SegmentIndex != SegIndex)
3695 if (SI.OffsetInSegment > SegOffset)
3697 if (SegOffset > (SI.OffsetInSegment + SI.Size))
3699 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
3703 return "bad segOffset, too large";
3706 // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
3707 // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
3708 // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
3709 // REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
3710 // been already checked.
3711 const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
3712 uint8_t PointerSize,
3714 uint64_t SegOffset) {
3715 const SectionInfo &SI = findSection(SegIndex, SegOffset);
3716 uint64_t addr = SI.SegmentStartAddress + SegOffset;
3717 if (addr >= SI.Address + SI.Size)
3718 return "bad segOffset, too large";
3721 i = (Skip + PointerSize) * (Count - 1);
3722 else if (Count == 1)
3723 i = Skip + PointerSize;
3724 if (addr + i >= SI.Address + SI.Size) {
3725 // For rebase opcodes they can step from one section to another.
3726 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
3727 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
3729 return "bad count and skip, too large";
3734 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
3735 // to get the segment name.
3736 StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
3737 for (const SectionInfo &SI : Sections) {
3738 if (SI.SegmentIndex == SegIndex)
3739 return SI.SegmentName;
3741 llvm_unreachable("invalid SegIndex");
3744 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3745 // to get the SectionInfo.
3746 const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
3747 int32_t SegIndex, uint64_t SegOffset) {
3748 for (const SectionInfo &SI : Sections) {
3749 if (SI.SegmentIndex != SegIndex)
3751 if (SI.OffsetInSegment > SegOffset)
3753 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
3757 llvm_unreachable("SegIndex and SegOffset not in any section");
3760 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3761 // entry to get the section name.
3762 StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
3763 uint64_t SegOffset) {
3764 return findSection(SegIndex, SegOffset).SectionName;
3767 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
3768 // entry to get the address.
3769 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
3770 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
3771 return SI.SegmentStartAddress + OffsetInSeg;
3774 iterator_range<bind_iterator>
3775 MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
3776 ArrayRef<uint8_t> Opcodes, bool is64,
3777 MachOBindEntry::Kind BKind) {
3778 if (O->BindRebaseSectionTable == nullptr)
3779 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3780 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
3781 Start.moveToFirst();
3783 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
3786 return make_range(bind_iterator(Start), bind_iterator(Finish));
3789 iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
3790 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
3791 MachOBindEntry::Kind::Regular);
3794 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
3795 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
3796 MachOBindEntry::Kind::Lazy);
3799 iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
3800 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
3801 MachOBindEntry::Kind::Weak);
3804 MachOObjectFile::load_command_iterator
3805 MachOObjectFile::begin_load_commands() const {
3806 return LoadCommands.begin();
3809 MachOObjectFile::load_command_iterator
3810 MachOObjectFile::end_load_commands() const {
3811 return LoadCommands.end();
3814 iterator_range<MachOObjectFile::load_command_iterator>
3815 MachOObjectFile::load_commands() const {
3816 return make_range(begin_load_commands(), end_load_commands());
3820 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
3821 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
3822 return parseSegmentOrSectionName(Raw.data());
3826 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
3827 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
3828 const section_base *Base =
3829 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
3830 return makeArrayRef(Base->sectname);
3834 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
3835 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
3836 const section_base *Base =
3837 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
3838 return makeArrayRef(Base->segname);
3842 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
3844 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
3846 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
3849 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
3850 const MachO::any_relocation_info &RE) const {
3851 if (isLittleEndian())
3852 return RE.r_word1 & 0xffffff;
3853 return RE.r_word1 >> 8;
3856 bool MachOObjectFile::getPlainRelocationExternal(
3857 const MachO::any_relocation_info &RE) const {
3858 if (isLittleEndian())
3859 return (RE.r_word1 >> 27) & 1;
3860 return (RE.r_word1 >> 4) & 1;
3863 bool MachOObjectFile::getScatteredRelocationScattered(
3864 const MachO::any_relocation_info &RE) const {
3865 return RE.r_word0 >> 31;
3868 uint32_t MachOObjectFile::getScatteredRelocationValue(
3869 const MachO::any_relocation_info &RE) const {
3873 uint32_t MachOObjectFile::getScatteredRelocationType(
3874 const MachO::any_relocation_info &RE) const {
3875 return (RE.r_word0 >> 24) & 0xf;
3878 unsigned MachOObjectFile::getAnyRelocationAddress(
3879 const MachO::any_relocation_info &RE) const {
3880 if (isRelocationScattered(RE))
3881 return getScatteredRelocationAddress(RE);
3882 return getPlainRelocationAddress(RE);
3885 unsigned MachOObjectFile::getAnyRelocationPCRel(
3886 const MachO::any_relocation_info &RE) const {
3887 if (isRelocationScattered(RE))
3888 return getScatteredRelocationPCRel(RE);
3889 return getPlainRelocationPCRel(*this, RE);
3892 unsigned MachOObjectFile::getAnyRelocationLength(
3893 const MachO::any_relocation_info &RE) const {
3894 if (isRelocationScattered(RE))
3895 return getScatteredRelocationLength(RE);
3896 return getPlainRelocationLength(*this, RE);
3900 MachOObjectFile::getAnyRelocationType(
3901 const MachO::any_relocation_info &RE) const {
3902 if (isRelocationScattered(RE))
3903 return getScatteredRelocationType(RE);
3904 return getPlainRelocationType(*this, RE);
3908 MachOObjectFile::getAnyRelocationSection(
3909 const MachO::any_relocation_info &RE) const {
3910 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
3911 return *section_end();
3912 unsigned SecNum = getPlainRelocationSymbolNum(RE);
3913 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
3914 return *section_end();
3916 DRI.d.a = SecNum - 1;
3917 return SectionRef(DRI, this);
3920 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
3921 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
3922 return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
3925 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
3926 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
3927 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
3930 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
3931 unsigned Index) const {
3932 const char *Sec = getSectionPtr(*this, L, Index);
3933 return getStruct<MachO::section>(*this, Sec);
3936 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
3937 unsigned Index) const {
3938 const char *Sec = getSectionPtr(*this, L, Index);
3939 return getStruct<MachO::section_64>(*this, Sec);
3943 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
3944 const char *P = reinterpret_cast<const char *>(DRI.p);
3945 return getStruct<MachO::nlist>(*this, P);
3949 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
3950 const char *P = reinterpret_cast<const char *>(DRI.p);
3951 return getStruct<MachO::nlist_64>(*this, P);
3954 MachO::linkedit_data_command
3955 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
3956 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
3959 MachO::segment_command
3960 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
3961 return getStruct<MachO::segment_command>(*this, L.Ptr);
3964 MachO::segment_command_64
3965 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
3966 return getStruct<MachO::segment_command_64>(*this, L.Ptr);
3969 MachO::linker_option_command
3970 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
3971 return getStruct<MachO::linker_option_command>(*this, L.Ptr);
3974 MachO::version_min_command
3975 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
3976 return getStruct<MachO::version_min_command>(*this, L.Ptr);
3980 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
3981 return getStruct<MachO::note_command>(*this, L.Ptr);
3984 MachO::build_version_command
3985 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
3986 return getStruct<MachO::build_version_command>(*this, L.Ptr);
3989 MachO::build_tool_version
3990 MachOObjectFile::getBuildToolVersion(unsigned index) const {
3991 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
3994 MachO::dylib_command
3995 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
3996 return getStruct<MachO::dylib_command>(*this, L.Ptr);
3999 MachO::dyld_info_command
4000 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
4001 return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
4004 MachO::dylinker_command
4005 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
4006 return getStruct<MachO::dylinker_command>(*this, L.Ptr);
4010 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
4011 return getStruct<MachO::uuid_command>(*this, L.Ptr);
4014 MachO::rpath_command
4015 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
4016 return getStruct<MachO::rpath_command>(*this, L.Ptr);
4019 MachO::source_version_command
4020 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
4021 return getStruct<MachO::source_version_command>(*this, L.Ptr);
4024 MachO::entry_point_command
4025 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
4026 return getStruct<MachO::entry_point_command>(*this, L.Ptr);
4029 MachO::encryption_info_command
4030 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
4031 return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
4034 MachO::encryption_info_command_64
4035 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
4036 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
4039 MachO::sub_framework_command
4040 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
4041 return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
4044 MachO::sub_umbrella_command
4045 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
4046 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
4049 MachO::sub_library_command
4050 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
4051 return getStruct<MachO::sub_library_command>(*this, L.Ptr);
4054 MachO::sub_client_command
4055 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
4056 return getStruct<MachO::sub_client_command>(*this, L.Ptr);
4059 MachO::routines_command
4060 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
4061 return getStruct<MachO::routines_command>(*this, L.Ptr);
4064 MachO::routines_command_64
4065 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
4066 return getStruct<MachO::routines_command_64>(*this, L.Ptr);
4069 MachO::thread_command
4070 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
4071 return getStruct<MachO::thread_command>(*this, L.Ptr);
4074 MachO::any_relocation_info
4075 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
4080 MachO::section_64 Sect = getSection64(Sec);
4081 Offset = Sect.reloff;
4083 MachO::section Sect = getSection(Sec);
4084 Offset = Sect.reloff;
4087 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
4088 getPtr(*this, Offset)) + Rel.d.b;
4089 return getStruct<MachO::any_relocation_info>(
4090 *this, reinterpret_cast<const char *>(P));
4093 MachO::data_in_code_entry
4094 MachOObjectFile::getDice(DataRefImpl Rel) const {
4095 const char *P = reinterpret_cast<const char *>(Rel.p);
4096 return getStruct<MachO::data_in_code_entry>(*this, P);
4099 const MachO::mach_header &MachOObjectFile::getHeader() const {
4103 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4108 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4109 const MachO::dysymtab_command &DLC,
4110 unsigned Index) const {
4111 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
4112 return getStruct<uint32_t>(*this, getPtr(*this, Offset));
4115 MachO::data_in_code_entry
4116 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4117 unsigned Index) const {
4118 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
4119 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
4122 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
4124 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
4126 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4127 MachO::symtab_command Cmd;
4128 Cmd.cmd = MachO::LC_SYMTAB;
4129 Cmd.cmdsize = sizeof(MachO::symtab_command);
4137 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
4138 if (DysymtabLoadCmd)
4139 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
4141 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4142 MachO::dysymtab_command Cmd;
4143 Cmd.cmd = MachO::LC_DYSYMTAB;
4144 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4155 Cmd.extrefsymoff = 0;
4156 Cmd.nextrefsyms = 0;
4157 Cmd.indirectsymoff = 0;
4158 Cmd.nindirectsyms = 0;
4166 MachO::linkedit_data_command
4167 MachOObjectFile::getDataInCodeLoadCommand() const {
4168 if (DataInCodeLoadCmd)
4169 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
4171 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4172 MachO::linkedit_data_command Cmd;
4173 Cmd.cmd = MachO::LC_DATA_IN_CODE;
4174 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4180 MachO::linkedit_data_command
4181 MachOObjectFile::getLinkOptHintsLoadCommand() const {
4182 if (LinkOptHintsLoadCmd)
4183 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
4185 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4187 MachO::linkedit_data_command Cmd;
4188 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4189 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4195 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4196 if (!DyldInfoLoadCmd)
4199 MachO::dyld_info_command DyldInfo =
4200 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4201 const uint8_t *Ptr =
4202 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
4203 return makeArrayRef(Ptr, DyldInfo.rebase_size);
4206 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4207 if (!DyldInfoLoadCmd)
4210 MachO::dyld_info_command DyldInfo =
4211 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4212 const uint8_t *Ptr =
4213 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
4214 return makeArrayRef(Ptr, DyldInfo.bind_size);
4217 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4218 if (!DyldInfoLoadCmd)
4221 MachO::dyld_info_command DyldInfo =
4222 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4223 const uint8_t *Ptr =
4224 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
4225 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
4228 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4229 if (!DyldInfoLoadCmd)
4232 MachO::dyld_info_command DyldInfo =
4233 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4234 const uint8_t *Ptr =
4235 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
4236 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
4239 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4240 if (!DyldInfoLoadCmd)
4243 MachO::dyld_info_command DyldInfo =
4244 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4245 const uint8_t *Ptr =
4246 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
4247 return makeArrayRef(Ptr, DyldInfo.export_size);
4250 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4253 // Returning a pointer is fine as uuid doesn't need endian swapping.
4254 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
4255 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
4258 StringRef MachOObjectFile::getStringTableData() const {
4259 MachO::symtab_command S = getSymtabLoadCommand();
4260 return getData().substr(S.stroff, S.strsize);
4263 bool MachOObjectFile::is64Bit() const {
4264 return getType() == getMachOType(false, true) ||
4265 getType() == getMachOType(true, true);
4268 void MachOObjectFile::ReadULEB128s(uint64_t Index,
4269 SmallVectorImpl<uint64_t> &Out) const {
4270 DataExtractor extractor(ObjectFile::getData(), true, 0);
4272 uint32_t offset = Index;
4274 while (uint64_t delta = extractor.getULEB128(&offset)) {
4276 Out.push_back(data);
4280 bool MachOObjectFile::isRelocatableObject() const {
4281 return getHeader().filetype == MachO::MH_OBJECT;
4284 Expected<std::unique_ptr<MachOObjectFile>>
4285 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4286 uint32_t UniversalCputype,
4287 uint32_t UniversalIndex) {
4288 StringRef Magic = Buffer.getBuffer().slice(0, 4);
4289 if (Magic == "\xFE\xED\xFA\xCE")
4290 return MachOObjectFile::create(Buffer, false, false,
4291 UniversalCputype, UniversalIndex);
4292 if (Magic == "\xCE\xFA\xED\xFE")
4293 return MachOObjectFile::create(Buffer, true, false,
4294 UniversalCputype, UniversalIndex);
4295 if (Magic == "\xFE\xED\xFA\xCF")
4296 return MachOObjectFile::create(Buffer, false, true,
4297 UniversalCputype, UniversalIndex);
4298 if (Magic == "\xCF\xFA\xED\xFE")
4299 return MachOObjectFile::create(Buffer, true, true,
4300 UniversalCputype, UniversalIndex);
4301 return make_error<GenericBinaryError>("Unrecognized MachO magic number",
4302 object_error::invalid_file_type);