49#include <system_error>
52using namespace object;
64 return make_error<GenericBinaryError>(
"truncated or malformed object (" +
66 object_error::parse_failed);
73 if (
P < O.getData().begin() ||
P +
sizeof(
T) > O.getData().end())
77 memcpy(&Cmd,
P,
sizeof(
T));
86 if (
P < O.getData().begin() ||
P +
sizeof(
T) > O.getData().end())
90 memcpy(&Cmd,
P,
sizeof(
T));
99 uintptr_t CommandAddr =
reinterpret_cast<uintptr_t
>(L.Ptr);
101 bool Is64 = O.is64Bit();
107 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
108 return reinterpret_cast<const char*
>(SectionAddr);
112 size_t MachOFilesetEntryOffset = 0) {
114 MachOFilesetEntryOffset <= O.getData().size());
115 return O.getData().data() +
Offset + MachOFilesetEntryOffset;
120 const char *
P =
reinterpret_cast<const char *
>(DRI.
p);
121 return getStruct<MachO::nlist_base>(O,
P);
133 return O.getHeader().cputype;
137 return O.getHeader().cpusubtype;
152 if (O.isLittleEndian())
164 if (O.isLittleEndian())
176 if (O.isLittleEndian())
194 if (
auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj,
Ptr)) {
197 " extends past end of file");
198 if (CmdOrErr->cmdsize < 8)
200 " with size less than 8 bytes");
203 return CmdOrErr.takeError();
211 return malformedError(
"load command 0 extends past the end all load "
212 "commands in the file");
226 " extends past the end all load commands in the file");
234 Err =
malformedError(
"the mach header extends past the end of the "
238 if (
auto HeaderOrErr = getStructOrErr<T>(
240 Header = *HeaderOrErr;
242 Err = HeaderOrErr.takeError();
258 for (
auto it = Elements.begin(); it != Elements.end(); ++it) {
260 if ((
Offset >= E.Offset &&
Offset < E.Offset + E.Size) ||
262 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
264 " with a size of " +
Twine(
Size) +
", overlaps " +
265 E.Name +
" at offset " +
Twine(E.Offset) +
" with "
266 "a size of " +
Twine(E.Size));
269 if (nt != Elements.end()) {
284template <
typename Segment,
typename Section>
289 std::list<MachOElement> &Elements) {
290 const unsigned SegmentLoadSize =
sizeof(Segment);
291 if (Load.C.cmdsize < SegmentLoadSize)
293 " " + CmdName +
" cmdsize too small");
294 if (
auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
295 Segment S = SegOrErr.get();
296 const unsigned SectionSize =
sizeof(Section);
298 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
299 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
301 " inconsistent cmdsize in " + CmdName +
302 " for the number of sections");
303 for (
unsigned J = 0; J < S.nsects; ++J) {
306 auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
308 return SectionOrErr.takeError();
309 Section s = SectionOrErr.get();
316 CmdName +
" command " +
Twine(LoadCommandIndex) +
317 " extends past the end of the file");
322 s.offset < SizeOfHeaders && s.size != 0)
324 CmdName +
" command " +
Twine(LoadCommandIndex) +
325 " not past the headers of the file");
333 return malformedError(
"offset field plus size field of section " +
334 Twine(J) +
" in " + CmdName +
" command " +
335 Twine(LoadCommandIndex) +
336 " extends past the end of the file");
343 Twine(J) +
" in " + CmdName +
" command " +
344 Twine(LoadCommandIndex) +
345 " greater than the segment");
350 CmdName +
" command " +
Twine(LoadCommandIndex) +
351 " less than the segment's vmaddr");
356 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
358 " in " + CmdName +
" command " +
359 Twine(LoadCommandIndex) +
360 " greater than than "
361 "the segment's vmaddr plus vmsize");
369 if (s.reloff > FileSize)
371 CmdName +
" command " +
Twine(LoadCommandIndex) +
372 " extends past the end of the file");
376 if (BigSize > FileSize)
377 return malformedError(
"reloff field plus nreloc field times sizeof("
378 "struct relocation_info) of section " +
379 Twine(J) +
" in " + CmdName +
" command " +
380 Twine(LoadCommandIndex) +
381 " extends past the end of the file");
385 "section relocation entries"))
388 if (S.fileoff > FileSize)
390 " fileoff field in " + CmdName +
391 " extends past the end of the file");
393 BigSize += S.filesize;
394 if (BigSize > FileSize)
396 " fileoff field plus filesize field in " +
397 CmdName +
" extends past the end of the file");
398 if (S.vmsize != 0 && S.filesize > S.vmsize)
400 " filesize field in " + CmdName +
401 " greater than vmsize field");
402 IsPageZeroSegment |=
StringRef(
"__PAGEZERO") == S.segname;
404 return SegOrErr.takeError();
412 const char **SymtabLoadCmd,
413 std::list<MachOElement> &Elements) {
416 " LC_SYMTAB cmdsize too small");
417 if (*SymtabLoadCmd !=
nullptr)
419 auto SymtabOrErr = getStructOrErr<MachO::symtab_command>(Obj, Load.Ptr);
421 return SymtabOrErr.takeError();
425 " has incorrect cmdsize");
427 if (Symtab.
symoff > FileSize)
429 Twine(LoadCommandIndex) +
" extends past the end "
432 const char *struct_nlist_name;
435 struct_nlist_name =
"struct nlist_64";
438 struct_nlist_name =
"struct nlist";
442 if (BigSize > FileSize)
443 return malformedError(
"symoff field plus nsyms field times sizeof(" +
444 Twine(struct_nlist_name) +
") of LC_SYMTAB command " +
445 Twine(LoadCommandIndex) +
" extends past the end "
450 if (Symtab.
stroff > FileSize)
452 Twine(LoadCommandIndex) +
" extends past the end "
456 if (BigSize > FileSize)
457 return malformedError(
"stroff field plus strsize field of LC_SYMTAB "
458 "command " +
Twine(LoadCommandIndex) +
" extends "
459 "past the end of the file");
461 Symtab.
strsize,
"string table"))
463 *SymtabLoadCmd = Load.Ptr;
470 const char **DysymtabLoadCmd,
471 std::list<MachOElement> &Elements) {
474 " LC_DYSYMTAB cmdsize too small");
475 if (*DysymtabLoadCmd !=
nullptr)
478 getStructOrErr<MachO::dysymtab_command>(Obj, Load.Ptr);
480 return DysymtabOrErr.takeError();
484 " has incorrect cmdsize");
486 if (Dysymtab.
tocoff > FileSize)
488 Twine(LoadCommandIndex) +
" extends past the end of "
492 BigSize += Dysymtab.
tocoff;
493 if (BigSize > FileSize)
494 return malformedError(
"tocoff field plus ntoc field times sizeof(struct "
495 "dylib_table_of_contents) of LC_DYSYMTAB command " +
496 Twine(LoadCommandIndex) +
" extends past the end of "
499 Dysymtab.
ntoc *
sizeof(
struct
501 "table of contents"))
505 Twine(LoadCommandIndex) +
" extends past the end of "
508 const char *struct_dylib_module_name;
512 struct_dylib_module_name =
"struct dylib_module_64";
515 struct_dylib_module_name =
"struct dylib_module";
517 BigSize *= sizeof_modtab;
519 if (BigSize > FileSize)
520 return malformedError(
"modtaboff field plus nmodtab field times sizeof(" +
521 Twine(struct_dylib_module_name) +
") of LC_DYSYMTAB "
522 "command " +
Twine(LoadCommandIndex) +
" extends "
523 "past the end of the file");
525 Dysymtab.
nmodtab * sizeof_modtab,
529 return malformedError(
"extrefsymoff field of LC_DYSYMTAB command " +
530 Twine(LoadCommandIndex) +
" extends past the end of "
535 if (BigSize > FileSize)
536 return malformedError(
"extrefsymoff field plus nextrefsyms field times "
537 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
538 "command " +
Twine(LoadCommandIndex) +
" extends "
539 "past the end of the file");
546 return malformedError(
"indirectsymoff field of LC_DYSYMTAB command " +
547 Twine(LoadCommandIndex) +
" extends past the end of "
552 if (BigSize > FileSize)
553 return malformedError(
"indirectsymoff field plus nindirectsyms field times "
554 "sizeof(uint32_t) of LC_DYSYMTAB command " +
555 Twine(LoadCommandIndex) +
" extends past the end of "
564 Twine(LoadCommandIndex) +
" extends past the end of "
569 if (BigSize > FileSize)
570 return malformedError(
"extreloff field plus nextrel field times sizeof"
571 "(struct relocation_info) of LC_DYSYMTAB command " +
572 Twine(LoadCommandIndex) +
" extends past the end of "
577 "external relocation table"))
581 Twine(LoadCommandIndex) +
" extends past the end of "
586 if (BigSize > FileSize)
587 return malformedError(
"locreloff field plus nlocrel field times sizeof"
588 "(struct relocation_info) of LC_DYSYMTAB command " +
589 Twine(LoadCommandIndex) +
" extends past the end of "
594 "local relocation table"))
596 *DysymtabLoadCmd = Load.Ptr;
603 const char **LoadCmd,
const char *CmdName,
604 std::list<MachOElement> &Elements,
605 const char *ElementName) {
608 CmdName +
" cmdsize too small");
609 if (*LoadCmd !=
nullptr)
611 auto LinkDataOrError =
612 getStructOrErr<MachO::linkedit_data_command>(Obj, Load.Ptr);
613 if (!LinkDataOrError)
614 return LinkDataOrError.takeError();
618 Twine(LoadCommandIndex) +
" has incorrect cmdsize");
620 if (LinkData.
dataoff > FileSize)
622 Twine(LoadCommandIndex) +
" extends past the end of "
626 if (BigSize > FileSize)
628 Twine(CmdName) +
" command " +
629 Twine(LoadCommandIndex) +
" extends past the end of "
641 const char **LoadCmd,
const char *CmdName,
642 std::list<MachOElement> &Elements) {
645 CmdName +
" cmdsize too small");
646 if (*LoadCmd !=
nullptr)
647 return malformedError(
"more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
650 getStructOrErr<MachO::dyld_info_command>(Obj, Load.Ptr);
652 return DyldInfoOrErr.takeError();
656 Twine(LoadCommandIndex) +
" has incorrect cmdsize");
660 " command " +
Twine(LoadCommandIndex) +
" extends "
661 "past the end of the file");
664 if (BigSize > FileSize)
665 return malformedError(
"rebase_off field plus rebase_size field of " +
666 Twine(CmdName) +
" command " +
667 Twine(LoadCommandIndex) +
" extends past the end of "
675 " command " +
Twine(LoadCommandIndex) +
" extends "
676 "past the end of the file");
679 if (BigSize > FileSize)
681 Twine(CmdName) +
" command " +
682 Twine(LoadCommandIndex) +
" extends past the end of "
690 " command " +
Twine(LoadCommandIndex) +
" extends "
691 "past the end of the file");
694 if (BigSize > FileSize)
695 return malformedError(
"weak_bind_off field plus weak_bind_size field of " +
696 Twine(CmdName) +
" command " +
697 Twine(LoadCommandIndex) +
" extends past the end of "
701 "dyld weak bind info"))
705 " command " +
Twine(LoadCommandIndex) +
" extends "
706 "past the end of the file");
709 if (BigSize > FileSize)
710 return malformedError(
"lazy_bind_off field plus lazy_bind_size field of " +
711 Twine(CmdName) +
" command " +
712 Twine(LoadCommandIndex) +
" extends past the end of "
716 "dyld lazy bind info"))
720 " command " +
Twine(LoadCommandIndex) +
" extends "
721 "past the end of the file");
724 if (BigSize > FileSize)
725 return malformedError(
"export_off field plus export_size field of " +
726 Twine(CmdName) +
" command " +
727 Twine(LoadCommandIndex) +
" extends past the end of "
739 uint32_t LoadCommandIndex,
const char *CmdName) {
742 CmdName +
" cmdsize too small");
743 auto CommandOrErr = getStructOrErr<MachO::dylib_command>(Obj, Load.Ptr);
745 return CommandOrErr.takeError();
749 CmdName +
" name.offset field too small, not past "
750 "the end of the dylib_command struct");
751 if (
D.dylib.name >=
D.cmdsize)
753 CmdName +
" name.offset field extends past the end "
754 "of the load command");
758 const char *
P = (
const char *)Load.Ptr;
759 for (i =
D.dylib.name; i <
D.cmdsize; i++)
764 CmdName +
" library name extends past the end of the "
772 const char **LoadCmd) {
776 if (*LoadCmd !=
nullptr)
780 return malformedError(
"LC_ID_DYLIB load command in non-dynamic library "
788 uint32_t LoadCommandIndex,
const char *CmdName) {
791 CmdName +
" cmdsize too small");
792 auto CommandOrErr = getStructOrErr<MachO::dylinker_command>(Obj, Load.Ptr);
794 return CommandOrErr.takeError();
798 CmdName +
" name.offset field too small, not past "
799 "the end of the dylinker_command struct");
800 if (
D.name >=
D.cmdsize)
802 CmdName +
" name.offset field extends past the end "
803 "of the load command");
807 const char *
P = (
const char *)Load.Ptr;
808 for (i =
D.name; i <
D.cmdsize; i++)
813 CmdName +
" dyld name extends past the end of the "
821 const char **LoadCmd,
const char *CmdName) {
824 CmdName +
" has incorrect cmdsize");
825 if (*LoadCmd !=
nullptr)
827 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
828 "LC_VERSION_MIN_WATCHOS command");
836 std::list<MachOElement> &Elements) {
839 " LC_NOTE has incorrect cmdsize");
840 auto NoteCmdOrErr = getStructOrErr<MachO::note_command>(Obj, Load.Ptr);
842 return NoteCmdOrErr.takeError();
847 Twine(LoadCommandIndex) +
" extends "
848 "past the end of the file");
851 if (BigSize > FileSize)
852 return malformedError(
"size field plus offset field of LC_NOTE command " +
853 Twine(LoadCommandIndex) +
" extends past the end of "
867 getStructOrErr<MachO::build_version_command>(Obj, Load.Ptr);
869 return BVCOrErr.takeError();
871 if (Load.C.cmdsize !=
875 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
879 for (
unsigned i = 0; i < BVC.
ntools; ++i)
890 " LC_RPATH cmdsize too small");
891 auto ROrErr = getStructOrErr<MachO::rpath_command>(Obj, Load.Ptr);
893 return ROrErr.takeError();
897 " LC_RPATH path.offset field too small, not past "
898 "the end of the rpath_command struct");
899 if (R.path >= R.cmdsize)
901 " LC_RPATH path.offset field extends past the end "
902 "of the load command");
906 const char *
P = (
const char *)Load.Ptr;
907 for (i = R.path; i < R.cmdsize; i++)
912 " LC_RPATH library name extends past the end of the "
921 const char **LoadCmd,
const char *CmdName) {
922 if (*LoadCmd !=
nullptr)
924 "LC_ENCRYPTION_INFO_64 command");
926 if (cryptoff > FileSize)
928 " command " +
Twine(LoadCommandIndex) +
" extends "
929 "past the end of the file");
931 BigSize += cryptsize;
932 if (BigSize > FileSize)
934 Twine(CmdName) +
" command " +
935 Twine(LoadCommandIndex) +
" extends past the end of "
946 " LC_LINKER_OPTION cmdsize too small");
947 auto LinkOptionOrErr =
948 getStructOrErr<MachO::linker_option_command>(Obj, Load.Ptr);
949 if (!LinkOptionOrErr)
950 return LinkOptionOrErr.takeError();
953 const char *
string = (
const char *)Load.Ptr +
958 while (*
string ==
'\0' && left > 0) {
965 if (0xffffffff == NullPos)
967 " LC_LINKER_OPTION string #" +
Twine(i) +
968 " is not NULL terminated");
969 uint32_t len = std::min(NullPos, left) + 1;
976 " LC_LINKER_OPTION string count " +
Twine(L.count) +
977 " does not match number of strings");
983 uint32_t LoadCommandIndex,
const char *CmdName,
984 size_t SizeOfCmd,
const char *CmdStructName,
985 uint32_t PathOffset,
const char *PathFieldName) {
986 if (PathOffset < SizeOfCmd)
988 CmdName +
" " + PathFieldName +
".offset field too "
989 "small, not past the end of the " + CmdStructName);
990 if (PathOffset >= Load.C.cmdsize)
992 CmdName +
" " + PathFieldName +
".offset field "
993 "extends past the end of the load command");
997 const char *
P = (
const char *)Load.Ptr;
998 for (i = PathOffset; i < Load.C.cmdsize; i++)
1001 if (i >= Load.C.cmdsize)
1003 CmdName +
" " + PathFieldName +
" name extends past "
1004 "the end of the load command");
1011 const char *CmdName) {
1014 CmdName +
" cmdsize too small");
1015 auto ThreadCommandOrErr =
1016 getStructOrErr<MachO::thread_command>(Obj, Load.Ptr);
1017 if (!ThreadCommandOrErr)
1018 return ThreadCommandOrErr.takeError();
1021 const char *end = Load.Ptr +
T.cmdsize;
1024 while (state < end) {
1027 "flavor in " + CmdName +
" extends past end of "
1030 memcpy(&flavor, state,
sizeof(
uint32_t));
1037 " count in " + CmdName +
" extends past end of "
1049 " count not x86_THREAD_STATE32_COUNT for "
1050 "flavor number " +
Twine(nflavor) +
" which is "
1051 "a x86_THREAD_STATE32 flavor in " + CmdName +
1055 " x86_THREAD_STATE32 extends past end of "
1056 "command in " + CmdName +
" command");
1060 " unknown flavor (" +
Twine(flavor) +
") for "
1061 "flavor number " +
Twine(nflavor) +
" in " +
1062 CmdName +
" command");
1068 " count not x86_THREAD_STATE_COUNT for "
1069 "flavor number " +
Twine(nflavor) +
" which is "
1070 "a x86_THREAD_STATE flavor in " + CmdName +
1074 " x86_THREAD_STATE extends past end of "
1075 "command in " + CmdName +
" command");
1080 " count not x86_FLOAT_STATE_COUNT for "
1081 "flavor number " +
Twine(nflavor) +
" which is "
1082 "a x86_FLOAT_STATE flavor in " + CmdName +
1086 " x86_FLOAT_STATE extends past end of "
1087 "command in " + CmdName +
" command");
1092 " count not x86_EXCEPTION_STATE_COUNT for "
1093 "flavor number " +
Twine(nflavor) +
" which is "
1094 "a x86_EXCEPTION_STATE flavor in " + CmdName +
1098 " x86_EXCEPTION_STATE extends past end of "
1099 "command in " + CmdName +
" command");
1104 " count not x86_THREAD_STATE64_COUNT for "
1105 "flavor number " +
Twine(nflavor) +
" which is "
1106 "a x86_THREAD_STATE64 flavor in " + CmdName +
1110 " x86_THREAD_STATE64 extends past end of "
1111 "command in " + CmdName +
" command");
1116 " count not x86_EXCEPTION_STATE64_COUNT for "
1117 "flavor number " +
Twine(nflavor) +
" which is "
1118 "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
1122 " x86_EXCEPTION_STATE64 extends past end of "
1123 "command in " + CmdName +
" command");
1127 " unknown flavor (" +
Twine(flavor) +
") for "
1128 "flavor number " +
Twine(nflavor) +
" in " +
1129 CmdName +
" command");
1135 " count not ARM_THREAD_STATE_COUNT for "
1136 "flavor number " +
Twine(nflavor) +
" which is "
1137 "a ARM_THREAD_STATE flavor in " + CmdName +
1141 " ARM_THREAD_STATE extends past end of "
1142 "command in " + CmdName +
" command");
1146 " unknown flavor (" +
Twine(flavor) +
") for "
1147 "flavor number " +
Twine(nflavor) +
" in " +
1148 CmdName +
" command");
1155 " count not ARM_THREAD_STATE64_COUNT for "
1156 "flavor number " +
Twine(nflavor) +
" which is "
1157 "a ARM_THREAD_STATE64 flavor in " + CmdName +
1161 " ARM_THREAD_STATE64 extends past end of "
1162 "command in " + CmdName +
" command");
1166 " unknown flavor (" +
Twine(flavor) +
") for "
1167 "flavor number " +
Twine(nflavor) +
" in " +
1168 CmdName +
" command");
1174 " count not PPC_THREAD_STATE_COUNT for "
1175 "flavor number " +
Twine(nflavor) +
" which is "
1176 "a PPC_THREAD_STATE flavor in " + CmdName +
1180 " PPC_THREAD_STATE extends past end of "
1181 "command in " + CmdName +
" command");
1185 " unknown flavor (" +
Twine(flavor) +
") for "
1186 "flavor number " +
Twine(nflavor) +
" in " +
1187 CmdName +
" command");
1191 "command " +
Twine(LoadCommandIndex) +
" for " +
1192 CmdName +
" command can't be checked");
1203 const char **LoadCmd,
1204 std::list<MachOElement> &Elements) {
1207 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1208 if (*LoadCmd !=
nullptr)
1209 return malformedError(
"more than one LC_TWOLEVEL_HINTS command");
1210 auto HintsOrErr = getStructOrErr<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1212 return HintsOrErr.takeError();
1215 if (Hints.
offset > FileSize)
1216 return malformedError(
"offset field of LC_TWOLEVEL_HINTS command " +
1217 Twine(LoadCommandIndex) +
" extends past the end of "
1222 if (BigSize > FileSize)
1223 return malformedError(
"offset field plus nhints times sizeof(struct "
1224 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1225 Twine(LoadCommandIndex) +
" extends past the end of "
1231 *LoadCmd = Load.Ptr;
1239 if (
cmd == MachO::LC_SYMSEG ||
1240 cmd == MachO::LC_LOADFVMLIB ||
1241 cmd == MachO::LC_IDFVMLIB ||
1242 cmd == MachO::LC_IDENT ||
1243 cmd == MachO::LC_FVMFILE ||
1244 cmd == MachO::LC_PREPAGE ||
1245 cmd == MachO::LC_PREBOUND_DYLIB ||
1246 cmd == MachO::LC_TWOLEVEL_HINTS ||
1247 cmd == MachO::LC_PREBIND_CKSUM)
1254 bool Is64Bits,
uint32_t UniversalCputype,
1256 size_t MachOFilesetEntryOffset) {
1259 std::move(Object), IsLittleEndian, Is64Bits, Err, UniversalCputype,
1260 UniversalIndex, MachOFilesetEntryOffset));
1262 return std::move(Err);
1263 return std::move(Obj);
1266MachOObjectFile::MachOObjectFile(
MemoryBufferRef Object,
bool IsLittleEndian,
1267 bool Is64bits,
Error &Err,
1270 size_t MachOFilesetEntryOffset)
1271 :
ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
1272 MachOFilesetEntryOffset(MachOFilesetEntryOffset) {
1289 Err =
malformedError(
"load commands extend past the end of the file");
1292 if (UniversalCputype != 0 && cputype != UniversalCputype) {
1294 Twine(UniversalIndex) +
"'s cputype does not match "
1295 "object file's mach header");
1299 Elements.push_back({0, SizeOfHeaders,
"Mach-O headers"});
1302 LoadCommandInfo
Load;
1303 if (LoadCommandCount != 0) {
1307 Err = LoadOrErr.takeError();
1312 const char *DyldIdLoadCmd =
nullptr;
1313 const char *SplitInfoLoadCmd =
nullptr;
1314 const char *CodeSignDrsLoadCmd =
nullptr;
1315 const char *CodeSignLoadCmd =
nullptr;
1316 const char *VersLoadCmd =
nullptr;
1317 const char *SourceLoadCmd =
nullptr;
1318 const char *EntryPointLoadCmd =
nullptr;
1319 const char *EncryptLoadCmd =
nullptr;
1320 const char *RoutinesLoadCmd =
nullptr;
1321 const char *UnixThreadLoadCmd =
nullptr;
1322 const char *TwoLevelHintsLoadCmd =
nullptr;
1323 for (
unsigned I = 0;
I < LoadCommandCount; ++
I) {
1325 if (
Load.C.cmdsize % 8 != 0) {
1330 Load.C.cmd != MachO::LC_THREAD ||
Load.C.cmdsize % 4) {
1337 if (
Load.C.cmdsize % 4 != 0) {
1344 if (
Load.C.cmd == MachO::LC_SYMTAB) {
1347 }
else if (
Load.C.cmd == MachO::LC_DYSYMTAB) {
1351 }
else if (
Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1353 "LC_DATA_IN_CODE", Elements,
1354 "data in code info")))
1356 }
else if (
Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1358 "LC_LINKER_OPTIMIZATION_HINT",
1359 Elements,
"linker optimization "
1362 }
else if (
Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1364 "LC_FUNCTION_STARTS", Elements,
1365 "function starts data")))
1367 }
else if (
Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1369 "LC_SEGMENT_SPLIT_INFO", Elements,
1370 "split info data")))
1372 }
else if (
Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1374 "LC_DYLIB_CODE_SIGN_DRS", Elements,
1375 "code signing RDs data")))
1377 }
else if (
Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1379 "LC_CODE_SIGNATURE", Elements,
1380 "code signature data")))
1382 }
else if (
Load.C.cmd == MachO::LC_DYLD_INFO) {
1384 "LC_DYLD_INFO", Elements)))
1386 }
else if (
Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1388 "LC_DYLD_INFO_ONLY", Elements)))
1390 }
else if (
Load.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) {
1392 *
this, Load,
I, &DyldChainedFixupsLoadCmd,
1393 "LC_DYLD_CHAINED_FIXUPS", Elements,
"chained fixups")))
1395 }
else if (
Load.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE) {
1397 *
this, Load,
I, &DyldExportsTrieLoadCmd,
"LC_DYLD_EXPORTS_TRIE",
1398 Elements,
"exports trie")))
1400 }
else if (
Load.C.cmd == MachO::LC_UUID) {
1410 UuidLoadCmd =
Load.Ptr;
1411 }
else if (
Load.C.cmd == MachO::LC_SEGMENT_64) {
1414 *
this, Load, Sections, HasPageZeroSegment,
I,
1415 "LC_SEGMENT_64", SizeOfHeaders, Elements)))
1417 }
else if (
Load.C.cmd == MachO::LC_SEGMENT) {
1420 *
this, Load, Sections, HasPageZeroSegment,
I,
1421 "LC_SEGMENT", SizeOfHeaders, Elements)))
1423 }
else if (
Load.C.cmd == MachO::LC_ID_DYLIB) {
1426 }
else if (
Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1430 }
else if (
Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1434 }
else if (
Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1438 }
else if (
Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1442 }
else if (
Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1446 }
else if (
Load.C.cmd == MachO::LC_ID_DYLINKER) {
1449 }
else if (
Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1452 }
else if (
Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1455 }
else if (
Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1457 "LC_VERSION_MIN_MACOSX")))
1459 }
else if (
Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1461 "LC_VERSION_MIN_IPHONEOS")))
1463 }
else if (
Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1465 "LC_VERSION_MIN_TVOS")))
1467 }
else if (
Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1469 "LC_VERSION_MIN_WATCHOS")))
1471 }
else if (
Load.C.cmd == MachO::LC_NOTE) {
1474 }
else if (
Load.C.cmd == MachO::LC_BUILD_VERSION) {
1477 }
else if (
Load.C.cmd == MachO::LC_RPATH) {
1480 }
else if (
Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1483 " has incorrect cmdsize");
1486 if (SourceLoadCmd) {
1490 SourceLoadCmd =
Load.Ptr;
1491 }
else if (
Load.C.cmd == MachO::LC_MAIN) {
1494 " has incorrect cmdsize");
1497 if (EntryPointLoadCmd) {
1501 EntryPointLoadCmd =
Load.Ptr;
1502 }
else if (
Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1505 " has incorrect cmdsize");
1509 getStruct<MachO::encryption_info_command>(*
this,
Load.Ptr);
1511 &EncryptLoadCmd,
"LC_ENCRYPTION_INFO")))
1513 }
else if (
Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1516 " has incorrect cmdsize");
1520 getStruct<MachO::encryption_info_command_64>(*
this,
Load.Ptr);
1522 &EncryptLoadCmd,
"LC_ENCRYPTION_INFO_64")))
1524 }
else if (
Load.C.cmd == MachO::LC_LINKER_OPTION) {
1527 }
else if (
Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1530 " LC_SUB_FRAMEWORK cmdsize too small");
1534 getStruct<MachO::sub_framework_command>(*
this,
Load.Ptr);
1537 "sub_framework_command", S.
umbrella,
1540 }
else if (
Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1543 " LC_SUB_UMBRELLA cmdsize too small");
1547 getStruct<MachO::sub_umbrella_command>(*
this,
Load.Ptr);
1553 }
else if (
Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1556 " LC_SUB_LIBRARY cmdsize too small");
1560 getStruct<MachO::sub_library_command>(*
this,
Load.Ptr);
1566 }
else if (
Load.C.cmd == MachO::LC_SUB_CLIENT) {
1569 " LC_SUB_CLIENT cmdsize too small");
1573 getStruct<MachO::sub_client_command>(*
this,
Load.Ptr);
1576 "sub_client_command", S.
client,
"client")))
1578 }
else if (
Load.C.cmd == MachO::LC_ROUTINES) {
1581 " has incorrect cmdsize");
1584 if (RoutinesLoadCmd) {
1585 Err =
malformedError(
"more than one LC_ROUTINES and or LC_ROUTINES_64 "
1589 RoutinesLoadCmd =
Load.Ptr;
1590 }
else if (
Load.C.cmd == MachO::LC_ROUTINES_64) {
1593 " has incorrect cmdsize");
1596 if (RoutinesLoadCmd) {
1597 Err =
malformedError(
"more than one LC_ROUTINES_64 and or LC_ROUTINES "
1601 RoutinesLoadCmd =
Load.Ptr;
1602 }
else if (
Load.C.cmd == MachO::LC_UNIXTHREAD) {
1605 if (UnixThreadLoadCmd) {
1609 UnixThreadLoadCmd =
Load.Ptr;
1610 }
else if (
Load.C.cmd == MachO::LC_THREAD) {
1614 }
else if (
Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1616 &TwoLevelHintsLoadCmd, Elements)))
1618 }
else if (
Load.C.cmd == MachO::LC_IDENT) {
1623 Twine(
Load.C.cmd) +
" is obsolete and not "
1630 if (
I < LoadCommandCount - 1) {
1634 Err = LoadOrErr.takeError();
1639 if (!SymtabLoadCmd) {
1640 if (DysymtabLoadCmd) {
1641 Err =
malformedError(
"contains LC_DYSYMTAB load command without a "
1642 "LC_SYMTAB load command");
1645 }
else if (DysymtabLoadCmd) {
1647 getStruct<MachO::symtab_command>(*
this, SymtabLoadCmd);
1649 getStruct<MachO::dysymtab_command>(*
this, DysymtabLoadCmd);
1652 "extends past the end of the symbol table");
1658 Err =
malformedError(
"ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1659 "command extends past the end of the symbol table");
1664 "extends past the end of the symbol table");
1670 Err =
malformedError(
"iextdefsym plus nextdefsym in LC_DYSYMTAB "
1671 "load command extends past the end of the symbol "
1677 "extends past the end of the symbol table");
1683 Err =
malformedError(
"iundefsym plus nundefsym in LC_DYSYMTAB load "
1684 " command extends past the end of the symbol table");
1690 DyldIdLoadCmd ==
nullptr) {
1691 Err =
malformedError(
"no LC_ID_DYLIB load command in dynamic library "
1695 assert(LoadCommands.
size() == LoadCommandCount);
1735 if (NSect == 0 || NSect > Sections.
size())
1737 " for symbol at index " +
Twine(SymbolIndex));
1742 "the end of string table, for N_INDR symbol at "
1743 "index " +
Twine(SymbolIndex));
1749 if (LibraryOrdinal != 0 &&
1752 LibraryOrdinal - 1 >= Libraries.
size() ) {
1754 " for symbol at index " +
Twine(SymbolIndex));
1760 " past the end of string table, for symbol at "
1761 "index " +
Twine(SymbolIndex));
1777 if (Entry.n_strx == 0)
1781 const char *Start = &StringTable.data()[Entry.n_strx];
1798 return Entry.n_value;
1801 return Entry.n_value;
1813 if (NValue >= StringTable.size())
1815 const char *Start = &StringTable.data()[NValue];
1817 return std::error_code();
1844 uint8_t n_type = Entry.n_type;
1870 uint8_t MachOType = Entry.n_type;
1871 uint16_t MachOFlags = Entry.n_desc;
1913 uint8_t index = Entry.n_sect;
1918 DRI.
d.
a = index - 1;
1919 if (DRI.
d.
a >= Sections.
size()){
1929 return Entry.n_sect - 1;
1961 SectOffset = Sect.
offset;
1962 SectSize = Sect.
size;
1966 SectOffset = Sect.
offset;
1967 SectSize = Sect.
size;
1973 if (SectOffset > FileSize)
1975 if (FileSize - SectOffset < SectSize)
1976 return FileSize - SectOffset;
2017 if (SectionIndex < 1 || SectionIndex > Sections.
size())
2021 DRI.
d.
a = SectionIndex - 1;
2027 auto NameOrErr = Section.getName();
2029 return NameOrErr.takeError();
2063 if (!SectionNameOrErr) {
2076template <
typename LoadCommandType>
2080 auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.
Ptr);
2081 if (!SegmentOrErr) {
2085 auto &Segment = SegmentOrErr.get();
2088 Segment.fileoff, Segment.fileoff + Segment.filesize));
2092template <
typename LoadCommandType>
2095 auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.
Ptr);
2096 if (!SegmentOrErr) {
2100 auto &Segment = SegmentOrErr.get();
2101 return arrayRefFromStringRef(
2102 Obj.
getData().
slice(Segment.fileoff, Segment.fileoff + Segment.filesize));
2110 switch (LoadCmd.
C.
cmd) {
2111 case MachO::LC_SEGMENT:
2112 Contents = ::getSegmentContents<MachO::segment_command>(*
this, LoadCmd,
2115 case MachO::LC_SEGMENT_64:
2116 Contents = ::getSegmentContents<MachO::segment_command_64>(*
this, LoadCmd,
2122 if (!Contents.
empty())
2132 switch (LoadCmd.
C.
cmd) {
2133 case MachO::LC_SEGMENT:
2134 if (
Idx == SegmentIndex)
2135 return ::getSegmentContents<MachO::segment_command>(*
this, LoadCmd);
2138 case MachO::LC_SEGMENT_64:
2139 if (
Idx == SegmentIndex)
2140 return ::getSegmentContents<MachO::segment_command_64>(*
this, LoadCmd);
2164 return (SegmentName ==
"__LLVM" && *NameOrErr ==
"__bitcode");
2211 Ret.d.b = DysymtabLoadCmd.
nextrel;
2228 Ret.d.b = DysymtabLoadCmd.
nlocrel;
2239 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2280 unsigned Arch = this->
getArch();
2284 static const char *
const Table[] = {
2285 "GENERIC_RELOC_VANILLA",
2286 "GENERIC_RELOC_PAIR",
2287 "GENERIC_RELOC_SECTDIFF",
2288 "GENERIC_RELOC_PB_LA_PTR",
2289 "GENERIC_RELOC_LOCAL_SECTDIFF",
2290 "GENERIC_RELOC_TLV" };
2299 static const char *
const Table[] = {
2300 "X86_64_RELOC_UNSIGNED",
2301 "X86_64_RELOC_SIGNED",
2302 "X86_64_RELOC_BRANCH",
2303 "X86_64_RELOC_GOT_LOAD",
2305 "X86_64_RELOC_SUBTRACTOR",
2306 "X86_64_RELOC_SIGNED_1",
2307 "X86_64_RELOC_SIGNED_2",
2308 "X86_64_RELOC_SIGNED_4",
2309 "X86_64_RELOC_TLV" };
2318 static const char *
const Table[] = {
2319 "ARM_RELOC_VANILLA",
2321 "ARM_RELOC_SECTDIFF",
2322 "ARM_RELOC_LOCAL_SECTDIFF",
2323 "ARM_RELOC_PB_LA_PTR",
2325 "ARM_THUMB_RELOC_BR22",
2326 "ARM_THUMB_32BIT_BRANCH",
2328 "ARM_RELOC_HALF_SECTDIFF" };
2338 static const char *
const Table[] = {
2339 "ARM64_RELOC_UNSIGNED",
"ARM64_RELOC_SUBTRACTOR",
2340 "ARM64_RELOC_BRANCH26",
"ARM64_RELOC_PAGE21",
2341 "ARM64_RELOC_PAGEOFF12",
"ARM64_RELOC_GOT_LOAD_PAGE21",
2342 "ARM64_RELOC_GOT_LOAD_PAGEOFF12",
"ARM64_RELOC_POINTER_TO_GOT",
2343 "ARM64_RELOC_TLVP_LOAD_PAGE21",
"ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2344 "ARM64_RELOC_ADDEND"
2347 if (RType >= std::size(Table))
2354 static const char *
const Table[] = {
2355 "PPC_RELOC_VANILLA",
2363 "PPC_RELOC_SECTDIFF",
2364 "PPC_RELOC_PB_LA_PTR",
2365 "PPC_RELOC_HI16_SECTDIFF",
2366 "PPC_RELOC_LO16_SECTDIFF",
2367 "PPC_RELOC_HA16_SECTDIFF",
2369 "PPC_RELOC_LO14_SECTDIFF",
2370 "PPC_RELOC_LOCAL_SECTDIFF" };
2382 Result.append(res.
begin(), res.
end());
2430 size_t a, b, c, d,
Idx;
2432 isFramework =
false;
2436 a =
Name.rfind(
'/');
2437 if (a ==
Name.npos || a == 0)
2445 if (Suffix !=
"_debug" && Suffix !=
"_profile")
2452 b =
Name.rfind(
'/', a);
2459 Idx + Foo.
size() +
sizeof(
".framework/")-1);
2460 if (
F == Foo && DotFramework ==
".framework/") {
2468 c =
Name.rfind(
'/', b);
2469 if (c ==
Name.npos || c == 0)
2472 if (!V.starts_with(
"Versions/"))
2474 d =
Name.rfind(
'/', c);
2481 Idx + Foo.
size() +
sizeof(
".framework/")-1);
2482 if (
F == Foo && DotFramework ==
".framework/") {
2489 a =
Name.rfind(
'.');
2490 if (a ==
Name.npos || a == 0)
2493 if (Dylib !=
".dylib")
2498 Dot =
Name.slice(a-2, a-1);
2503 b =
Name.rfind(
'/', a);
2513 if (Suffix !=
"_debug" && Suffix !=
"_profile") {
2522 if (
Lib.size() >= 3) {
2523 Dot =
Lib.slice(
Lib.size()-2,
Lib.size()-1);
2533 b =
Name.rfind(
'/', a);
2539 if (
Lib.size() >= 3) {
2540 Dot =
Lib.slice(
Lib.size()-2,
Lib.size()-1);
2559 if (LibrariesShortNames.
size() == 0) {
2560 for (
unsigned i = 0; i < Libraries.
size(); i++) {
2562 getStructOrErr<MachO::dylib_command>(*
this, Libraries[i]);
2566 if (
D.dylib.name >=
D.cmdsize)
2568 const char *
P = (
const char *)(Libraries[i]) +
D.dylib.name;
2570 if (
D.dylib.name+
Name.size() >=
D.cmdsize)
2575 if (shortName.
empty())
2578 LibrariesShortNames.
push_back(shortName);
2582 Res = LibrariesShortNames[
Index];
2583 return std::error_code();
2587 return Libraries.
size();
2593 Sec.
d.
a = Rel->getRawDataRefImpl().d.a;
2600 if (!SymtabLoadCmd || Symtab.
nsyms == 0)
2609 if (!SymtabLoadCmd || Symtab.
nsyms == 0)
2628 DRI.
p =
reinterpret_cast<uintptr_t
>(
getPtr(*
this, Symtab.
symoff));
2640 DRIstart.
p =
reinterpret_cast<uintptr_t
>(
getPtr(*
this, Symtab.
symoff));
2652 DRI.
d.
a = Sections.
size();
2665 return "Mach-O 32-bit i386";
2667 return "Mach-O arm";
2669 return "Mach-O arm64 (ILP32)";
2671 return "Mach-O 32-bit ppc";
2673 return "Mach-O 32-bit unknown";
2679 return "Mach-O 64-bit x86-64";
2681 return "Mach-O arm64";
2683 return "Mach-O 64-bit ppc64";
2685 return "Mach-O 64-bit unknown";
2711 const char **McpuDefault,
2712 const char **ArchFlag) {
2714 *McpuDefault =
nullptr;
2716 *ArchFlag =
nullptr;
2724 return Triple(
"i386-apple-darwin");
2732 *ArchFlag =
"x86_64";
2733 return Triple(
"x86_64-apple-darwin");
2736 *ArchFlag =
"x86_64h";
2737 return Triple(
"x86_64h-apple-darwin");
2745 *ArchFlag =
"armv4t";
2746 return Triple(
"armv4t-apple-darwin");
2749 *ArchFlag =
"armv5e";
2750 return Triple(
"armv5e-apple-darwin");
2753 *ArchFlag =
"xscale";
2754 return Triple(
"xscale-apple-darwin");
2757 *ArchFlag =
"armv6";
2758 return Triple(
"armv6-apple-darwin");
2761 *McpuDefault =
"cortex-m0";
2763 *ArchFlag =
"armv6m";
2764 return Triple(
"armv6m-apple-darwin");
2767 *ArchFlag =
"armv7";
2768 return Triple(
"armv7-apple-darwin");
2771 *McpuDefault =
"cortex-m4";
2773 *ArchFlag =
"armv7em";
2774 return Triple(
"thumbv7em-apple-darwin");
2777 *McpuDefault =
"cortex-a7";
2779 *ArchFlag =
"armv7k";
2780 return Triple(
"armv7k-apple-darwin");
2783 *McpuDefault =
"cortex-m3";
2785 *ArchFlag =
"armv7m";
2786 return Triple(
"thumbv7m-apple-darwin");
2789 *McpuDefault =
"cortex-a7";
2791 *ArchFlag =
"armv7s";
2792 return Triple(
"armv7s-apple-darwin");
2800 *McpuDefault =
"cyclone";
2802 *ArchFlag =
"arm64";
2803 return Triple(
"arm64-apple-darwin");
2806 *McpuDefault =
"apple-a12";
2808 *ArchFlag =
"arm64e";
2809 return Triple(
"arm64e-apple-darwin");
2817 *McpuDefault =
"cyclone";
2819 *ArchFlag =
"arm64_32";
2820 return Triple(
"arm64_32-apple-darwin");
2829 return Triple(
"ppc-apple-darwin");
2837 *ArchFlag =
"ppc64";
2838 return Triple(
"ppc64-apple-darwin");
2857 static const std::array<StringRef, 18> ValidArchs = {{
2903 if (!DataInCodeLoadCmd)
2907 DRI.
p =
reinterpret_cast<uintptr_t
>(
getPtr(*
this, DicLC.
dataoff));
2913 if (!DataInCodeLoadCmd)
2925void ExportEntry::moveToFirst() {
2930 pushDownUntilBottom();
2933void ExportEntry::moveToEnd() {
2940 if (Done ||
Other.Done)
2941 return (Done ==
Other.Done);
2946 if (!CumulativeString.
equals(
Other.CumulativeString))
2949 for (
unsigned i=0; i < Stack.
size(); ++i) {
2950 if (Stack[i].Start !=
Other.Stack[i].Start)
2956uint64_t ExportEntry::readULEB128(
const uint8_t *&
Ptr,
const char **
error) {
2966 return CumulativeString;
2970 return Stack.
back().Flags;
2974 return Stack.
back().Address;
2978 return Stack.
back().Other;
2982 const char* ImportName = Stack.
back().ImportName;
2989 return Stack.
back().Start - Trie.
begin();
2992ExportEntry::NodeState::NodeState(
const uint8_t *
Ptr)
2993 : Start(
Ptr), Current(
Ptr) {}
2995void ExportEntry::pushNode(
uint64_t offset) {
2997 const uint8_t *
Ptr = Trie.
begin() + offset;
2998 NodeState State(
Ptr);
2999 const char *
error =
nullptr;
3000 uint64_t ExportInfoSize = readULEB128(State.Current, &
error);
3003 " in export trie data at node: 0x" +
3008 State.IsExportNode = (ExportInfoSize != 0);
3009 const uint8_t* Children = State.Current + ExportInfoSize;
3010 if (Children > Trie.
end()) {
3014 " too big and extends past end of trie data");
3018 if (State.IsExportNode) {
3019 const uint8_t *ExportStart = State.Current;
3020 State.Flags = readULEB128(State.Current, &
error);
3023 " in export trie data at node: 0x" +
3029 if (State.Flags != 0 &&
3034 "unsupported exported symbol kind: " +
Twine((
int)
Kind) +
3042 State.Other = readULEB128(State.Current, &
error);
3045 " in export trie data at node: 0x" +
3055 "bad library ordinal: " +
Twine((
int)State.Other) +
" (max " +
3062 State.ImportName =
reinterpret_cast<const char*
>(State.Current);
3063 if (*State.ImportName ==
'\0') {
3066 const uint8_t *
End = State.Current + 1;
3068 *E =
malformedError(
"import name of re-export in export trie data at "
3071 " starts past end of trie data");
3078 *E =
malformedError(
"import name of re-export in export trie data at "
3081 " extends past end of trie data");
3085 State.Current =
End + 1;
3088 State.Address = readULEB128(State.Current, &
error);
3091 " in export trie data at node: 0x" +
3097 State.Other = readULEB128(State.Current, &
error);
3100 " in export trie data at node: 0x" +
3107 if (ExportStart + ExportInfoSize < State.Current) {
3109 "inconsistent export info size: 0x" +
3118 if (State.ChildCount != 0 && Children + 1 >= Trie.
end()) {
3119 *E =
malformedError(
"byte for count of childern in export trie data at "
3122 " extends past end of trie data");
3127 State.NextChildIndex = 0;
3128 State.ParentStringLength = CumulativeString.
size();
3132void ExportEntry::pushDownUntilBottom() {
3134 const char *
error =
nullptr;
3135 while (Stack.
back().NextChildIndex < Stack.
back().ChildCount) {
3136 NodeState &Top = Stack.
back();
3137 CumulativeString.
resize(Top.ParentStringLength);
3138 for (;*Top.Current != 0 && Top.Current < Trie.
end(); Top.Current++) {
3139 char C = *Top.Current;
3142 if (Top.Current >= Trie.
end()) {
3143 *E =
malformedError(
"edge sub-string in export trie data at node: 0x" +
3145 " for child #" +
Twine((
int)Top.NextChildIndex) +
3146 " extends past end of trie data");
3154 " in export trie data at node: 0x" +
3159 for (
const NodeState &node : nodes()) {
3160 if (node.Start == Trie.
begin() + childNodeIndex){
3161 *E =
malformedError(
"loop in childern in export trie data at node: 0x" +
3163 " back to node: 0x" +
3169 Top.NextChildIndex += 1;
3170 pushNode(childNodeIndex);
3174 if (!Stack.
back().IsExportNode) {
3175 *E =
malformedError(
"node is not an export node in export trie data at "
3199 assert(!Stack.
empty() &&
"ExportEntry::moveNext() with empty node stack");
3200 if (!Stack.
back().IsExportNode) {
3201 *E =
malformedError(
"node is not an export node in export trie data at "
3209 while (!Stack.
empty()) {
3210 NodeState &Top = Stack.
back();
3211 if (Top.NextChildIndex < Top.ChildCount) {
3212 pushDownUntilBottom();
3216 if (Top.IsExportNode) {
3218 CumulativeString.
resize(Top.ParentStringLength);
3234 Start.moveToFirst();
3244 if (DyldInfoLoadCmd)
3246 else if (DyldExportsTrieLoadCmd)
3249 return exports(Err, Trie,
this);
3257 if (Command.C.cmd == MachO::LC_SEGMENT) {
3259 if (
StringRef(SLC.segname) ==
"__TEXT") {
3260 TextAddress = SLC.vmaddr;
3263 }
else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
3266 TextAddress = SLC_64.
vmaddr;
3327 FixupTargets = *FixupTargetsOrErr;
3329 *
E = FixupTargetsOrErr.takeError();
3334 Segments = std::move(SegmentsOrErr->second);
3336 *
E = SegmentsOrErr.takeError();
3341void MachOChainedFixupEntry::findNextPageWithFixups() {
3342 auto FindInSegment = [
this]() {
3344 while (PageIndex < SegInfo.
PageStarts.size() &&
3347 return PageIndex < SegInfo.
PageStarts.size();
3350 while (InfoSegIndex < Segments.size()) {
3351 if (FindInSegment()) {
3352 PageOffset = Segments[InfoSegIndex].PageStarts[PageIndex];
3364 if (Segments.empty()) {
3372 findNextPageWithFixups();
3383 if (InfoSegIndex == Segments.size()) {
3397 " has unsupported chained fixup pointer_format " +
3398 Twine(PointerFormat));
3412 " extends past segment's end");
3424 "by getDyldChainedFixupTargets()");
3425 auto Field = [
this](uint8_t
Right, uint8_t Count) {
3431 bool IsBind =
Field(63, 1);
3436 uint8_t InlineAddend =
Field(24, 8);
3438 if (ImportOrdinal >= FixupTargets.size()) {
3441 " has out-of range import ordinal " +
3442 Twine(ImportOrdinal));
3449 Addend = InlineAddend ? InlineAddend :
Target.addend();
3463 PageOffset += 4 * Next;
3466 findNextPageWithFixups();
3476 return InfoSegIndex ==
Other.InfoSegIndex && PageIndex ==
Other.PageIndex &&
3477 PageOffset ==
Other.PageOffset;
3482 : E(E), O(O), Opcodes(Bytes),
Ptr(Bytes.begin()),
3483 PointerSize(
is64Bit ? 8 : 4) {}
3485void MachORebaseEntry::moveToFirst() {
3490void MachORebaseEntry::moveToEnd() {
3492 RemainingLoopCount = 0;
3499 SegmentOffset += AdvanceAmount;
3500 if (RemainingLoopCount) {
3501 --RemainingLoopCount;
3510 if (
Ptr == Opcodes.
end()) {
3516 const uint8_t *OpcodeStart =
Ptr;
3517 uint8_t Byte = *
Ptr++;
3521 const char *
error =
nullptr;
3530 RebaseType = ImmValue;
3532 *E =
malformedError(
"for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3533 Twine((
int)RebaseType) +
" for opcode at: 0x" +
3540 dbgs() <<
"REBASE_OPCODE_SET_TYPE_IMM: "
3541 <<
"RebaseType=" << (
int) RebaseType <<
"\n");
3544 SegmentIndex = ImmValue;
3545 SegmentOffset = readULEB128(&
error);
3547 *E =
malformedError(
"for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3556 *E =
malformedError(
"for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3564 dbgs() <<
"REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3565 <<
"SegmentIndex=" << SegmentIndex <<
", "
3566 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3570 SegmentOffset += readULEB128(&
error);
3573 " for opcode at: 0x" +
3582 " for opcode at: 0x" +
3588 dbgs() <<
"REBASE_OPCODE_ADD_ADDR_ULEB: "
3589 <<
format(
"SegmentOffset=0x%06X",
3590 SegmentOffset) <<
"\n");
3593 SegmentOffset += ImmValue * PointerSize;
3604 dbgs() <<
"REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3605 <<
format(
"SegmentOffset=0x%06X",
3606 SegmentOffset) <<
"\n");
3609 AdvanceAmount = PointerSize;
3613 RemainingLoopCount = ImmValue - 1;
3615 RemainingLoopCount = 0;
3617 PointerSize, Count, Skip);
3627 dbgs() <<
"REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3628 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3629 <<
", AdvanceAmount=" << AdvanceAmount
3630 <<
", RemainingLoopCount=" << RemainingLoopCount
3634 AdvanceAmount = PointerSize;
3636 Count = readULEB128(&
error);
3645 RemainingLoopCount = Count - 1;
3647 RemainingLoopCount = 0;
3649 PointerSize, Count, Skip);
3659 dbgs() <<
"REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3660 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3661 <<
", AdvanceAmount=" << AdvanceAmount
3662 <<
", RemainingLoopCount=" << RemainingLoopCount
3666 Skip = readULEB128(&
error);
3668 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3674 AdvanceAmount = Skip + PointerSize;
3676 RemainingLoopCount = 0;
3678 PointerSize, Count, Skip);
3680 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3688 dbgs() <<
"REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3689 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3690 <<
", AdvanceAmount=" << AdvanceAmount
3691 <<
", RemainingLoopCount=" << RemainingLoopCount
3695 Count = readULEB128(&
error);
3697 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3705 RemainingLoopCount = Count - 1;
3707 RemainingLoopCount = 0;
3708 Skip = readULEB128(&
error);
3710 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3717 AdvanceAmount = Skip + PointerSize;
3720 PointerSize, Count, Skip);
3722 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3731 dbgs() <<
"REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3732 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3733 <<
", AdvanceAmount=" << AdvanceAmount
3734 <<
", RemainingLoopCount=" << RemainingLoopCount
3751 if (Ptr > Opcodes.
end())
3761 switch (RebaseType) {
3765 return "text abs32";
3767 return "text rel32";
3791#ifdef EXPENSIVE_CHECKS
3792 assert(Opcodes ==
Other.Opcodes &&
"compare iterators of different files");
3794 assert(Opcodes.
data() ==
Other.Opcodes.data() &&
"compare iterators of different files");
3797 (RemainingLoopCount ==
Other.RemainingLoopCount) &&
3798 (Done ==
Other.Done);
3804 if (O->BindRebaseSectionTable ==
nullptr)
3805 O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
3807 Start.moveToFirst();
3821 : E(E), O(O), Opcodes(Bytes),
Ptr(Bytes.begin()),
3822 PointerSize(
is64Bit ? 8 : 4), TableKind(BK) {}
3824void MachOBindEntry::moveToFirst() {
3829void MachOBindEntry::moveToEnd() {
3831 RemainingLoopCount = 0;
3838 SegmentOffset += AdvanceAmount;
3839 if (RemainingLoopCount) {
3840 --RemainingLoopCount;
3849 if (
Ptr == Opcodes.
end()) {
3855 const uint8_t *OpcodeStart =
Ptr;
3856 uint8_t Byte = *
Ptr++;
3859 int8_t SignExtended;
3860 const uint8_t *SymStart;
3862 const char *
error =
nullptr;
3868 bool NotLastEntry =
false;
3869 for (
const uint8_t *
P =
Ptr;
P < Opcodes.
end(); ++
P) {
3871 NotLastEntry =
true;
3883 *E =
malformedError(
"BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3884 "weak bind table for opcode at: 0x" +
3890 LibraryOrdinalSet =
true;
3892 *E =
malformedError(
"for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3893 "library ordinal: " +
3894 Twine((
int)ImmValue) +
" (max " +
3896 ") for opcode at: 0x" +
3903 dbgs() <<
"BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3904 <<
"Ordinal=" << Ordinal <<
"\n");
3908 *E =
malformedError(
"BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3909 "weak bind table for opcode at: 0x" +
3914 Ordinal = readULEB128(&
error);
3915 LibraryOrdinalSet =
true;
3924 *E =
malformedError(
"for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3925 "library ordinal: " +
3926 Twine((
int)Ordinal) +
" (max " +
3928 ") for opcode at: 0x" +
3935 dbgs() <<
"BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3936 <<
"Ordinal=" << Ordinal <<
"\n");
3940 *E =
malformedError(
"BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3941 "weak bind table for opcode at: 0x" +
3948 Ordinal = SignExtended;
3950 *E =
malformedError(
"for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3951 "special ordinal: " +
3952 Twine((
int)Ordinal) +
" for opcode at: 0x" +
3959 LibraryOrdinalSet =
true;
3962 dbgs() <<
"BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3963 <<
"Ordinal=" << Ordinal <<
"\n");
3971 if (
Ptr == Opcodes.
end()) {
3973 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3974 "symbol name extends past opcodes for opcode at: 0x" +
3979 SymbolName =
StringRef(
reinterpret_cast<const char*
>(SymStart),
3984 dbgs() <<
"BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3985 <<
"SymbolName=" << SymbolName <<
"\n");
3992 BindType = ImmValue;
3994 *E =
malformedError(
"for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3995 Twine((
int)ImmValue) +
" for opcode at: 0x" +
4002 dbgs() <<
"BIND_OPCODE_SET_TYPE_IMM: "
4003 <<
"BindType=" << (
int)BindType <<
"\n");
4006 Addend = readSLEB128(&
error);
4009 " for opcode at: 0x" +
4016 dbgs() <<
"BIND_OPCODE_SET_ADDEND_SLEB: "
4017 <<
"Addend=" << Addend <<
"\n");
4020 SegmentIndex = ImmValue;
4021 SegmentOffset = readULEB128(&
error);
4023 *E =
malformedError(
"for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4032 *E =
malformedError(
"for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4040 dbgs() <<
"BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
4041 <<
"SegmentIndex=" << SegmentIndex <<
", "
4042 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
4046 SegmentOffset += readULEB128(&
error);
4049 " for opcode at: 0x" +
4058 " for opcode at: 0x" +
4064 dbgs() <<
"BIND_OPCODE_ADD_ADDR_ULEB: "
4065 <<
format(
"SegmentOffset=0x%06X",
4066 SegmentOffset) <<
"\n");
4069 AdvanceAmount = PointerSize;
4070 RemainingLoopCount = 0;
4075 " for opcode at: 0x" +
4082 "for BIND_OPCODE_DO_BIND missing preceding "
4083 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
4088 if (!LibraryOrdinalSet && TableKind !=
Kind::Weak) {
4091 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4097 dbgs() <<
"BIND_OPCODE_DO_BIND: "
4098 <<
format(
"SegmentOffset=0x%06X",
4099 SegmentOffset) <<
"\n");
4103 *E =
malformedError(
"BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
4104 "lazy bind table for opcode at: 0x" +
4120 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4121 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
4127 if (!LibraryOrdinalSet && TableKind !=
Kind::Weak) {
4129 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4130 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4135 AdvanceAmount = readULEB128(&
error) + PointerSize;
4147 AdvanceAmount, PointerSize);
4149 *E =
malformedError(
"for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
4156 RemainingLoopCount = 0;
4159 dbgs() <<
"BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
4160 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
4161 <<
", AdvanceAmount=" << AdvanceAmount
4162 <<
", RemainingLoopCount=" << RemainingLoopCount
4167 *E =
malformedError(
"BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
4168 "allowed in lazy bind table for opcode at: 0x" +
4175 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4176 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4182 if (!LibraryOrdinalSet && TableKind !=
Kind::Weak) {
4184 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4185 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4191 AdvanceAmount = ImmValue * PointerSize + PointerSize;
4192 RemainingLoopCount = 0;
4194 AdvanceAmount, PointerSize);
4196 *E =
malformedError(
"for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
4204 <<
"BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
4205 <<
format(
"SegmentOffset=0x%06X", SegmentOffset) <<
"\n");
4209 *E =
malformedError(
"BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
4210 "allowed in lazy bind table for opcode at: 0x" +
4215 Count = readULEB128(&
error);
4217 RemainingLoopCount = Count - 1;
4219 RemainingLoopCount = 0;
4221 *E =
malformedError(
"for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4228 Skip = readULEB128(&
error);
4229 AdvanceAmount = Skip + PointerSize;
4231 *E =
malformedError(
"for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4240 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4241 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4247 if (!LibraryOrdinalSet && TableKind !=
Kind::Weak) {
4249 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4250 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4257 PointerSize, Count, Skip);
4260 malformedError(
"for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
4268 dbgs() <<
"BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
4269 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
4270 <<
", AdvanceAmount=" << AdvanceAmount
4271 <<
", RemainingLoopCount=" << RemainingLoopCount
4288 if (Ptr > Opcodes.
end())
4293int64_t MachOBindEntry::readSLEB128(
const char **
error) {
4297 if (Ptr > Opcodes.
end())
4311 return "text abs32";
4313 return "text rel32";
4345#ifdef EXPENSIVE_CHECKS
4346 assert(Opcodes ==
Other.Opcodes &&
"compare iterators of different files");
4348 assert(Opcodes.
data() ==
Other.Opcodes.data() &&
"compare iterators of different files");
4351 (RemainingLoopCount ==
Other.RemainingLoopCount) &&
4352 (Done ==
Other.Done);
4366 Info.SectionName = *NameOrErr;
4367 Info.Address = Section.getAddress();
4368 Info.Size = Section.getSize();
4371 if (
Info.SegmentName != CurSegName) {
4373 CurSegName =
Info.SegmentName;
4374 CurSegAddress =
Info.Address;
4376 Info.SegmentIndex = CurSegIndex - 1;
4377 Info.OffsetInSegment =
Info.Address - CurSegAddress;
4378 Info.SegmentStartAddress = CurSegAddress;
4381 MaxSegIndex = CurSegIndex;
4393 uint8_t PointerSize,
4397 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4398 if (SegIndex >= MaxSegIndex)
4399 return "bad segIndex (too large)";
4400 for (
uint64_t i = 0; i < Count; ++i) {
4401 uint64_t Start = SegOffset + i * (PointerSize + Skip);
4404 for (
const SectionInfo &SI : Sections) {
4405 if (SI.SegmentIndex != SegIndex)
4407 if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
4408 if (
End <= SI.OffsetInSegment + SI.Size) {
4413 return "bad offset, extends beyond section boundary";
4417 return "bad offset, not in section";
4425 for (
const SectionInfo &SI : Sections) {
4426 if (SI.SegmentIndex == SegIndex)
4427 return SI.SegmentName;
4434const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
4435 int32_t SegIndex,
uint64_t SegOffset) {
4436 for (
const SectionInfo &SI : Sections) {
4437 if (SI.SegmentIndex != SegIndex)
4439 if (SI.OffsetInSegment > SegOffset)
4441 if (SegOffset >= (SI.OffsetInSegment + SI.Size))
4452 return findSection(SegIndex, SegOffset).SectionName;
4458 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4459 return SI.SegmentStartAddress + OffsetInSeg;
4466 if (O->BindRebaseSectionTable ==
nullptr)
4467 O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
4469 Start.moveToFirst();
4493 if (BindRebaseSectionTable ==
nullptr)
4494 BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(
this);
4497 Start.moveToFirst();
4507 return LoadCommands.
begin();
4512 return LoadCommands.
end();
4528 assert(Sec.
d.
a < Sections.size() &&
"Should have detected this earlier");
4529 const section_base *
Base =
4530 reinterpret_cast<const section_base *
>(Sections[Sec.
d.
a]);
4536 assert(Sec.
d.
a < Sections.size() &&
"Should have detected this earlier");
4537 const section_base *
Base =
4538 reinterpret_cast<const section_base *
>(Sections[Sec.
d.
a]);
4560 return (RE.
r_word1 >> 27) & 1;
4576 return (RE.
r_word0 >> 24) & 0xf;
4614 if (SecNum ==
MachO::R_ABS || SecNum > Sections.size())
4617 DRI.
d.
a = SecNum - 1;
4622 assert(DRI.
d.
a < Sections.size() &&
"Should have detected this earlier");
4623 return getStruct<MachO::section>(*
this, Sections[DRI.
d.
a]);
4627 assert(DRI.
d.
a < Sections.size() &&
"Should have detected this earlier");
4628 return getStruct<MachO::section_64>(*
this, Sections[DRI.
d.
a]);
4632 unsigned Index)
const {
4634 return getStruct<MachO::section>(*
this, Sec);
4638 unsigned Index)
const {
4640 return getStruct<MachO::section_64>(*
this, Sec);
4645 const char *
P =
reinterpret_cast<const char *
>(DRI.
p);
4646 return getStruct<MachO::nlist>(*
this,
P);
4651 const char *
P =
reinterpret_cast<const char *
>(DRI.
p);
4652 return getStruct<MachO::nlist_64>(*
this,
P);
4657 return getStruct<MachO::linkedit_data_command>(*
this, L.Ptr);
4662 return getStruct<MachO::segment_command>(*
this, L.Ptr);
4667 return getStruct<MachO::segment_command_64>(*
this, L.Ptr);
4672 return getStruct<MachO::linker_option_command>(*
this, L.Ptr);
4677 return getStruct<MachO::version_min_command>(*
this, L.Ptr);
4682 return getStruct<MachO::note_command>(*
this, L.Ptr);
4687 return getStruct<MachO::build_version_command>(*
this, L.Ptr);
4692 return getStruct<MachO::build_tool_version>(*
this, BuildTools[index]);
4697 return getStruct<MachO::dylib_command>(*
this, L.Ptr);
4702 return getStruct<MachO::dyld_info_command>(*
this, L.Ptr);
4707 return getStruct<MachO::dylinker_command>(*
this, L.Ptr);
4712 return getStruct<MachO::uuid_command>(*
this, L.Ptr);
4717 return getStruct<MachO::rpath_command>(*
this, L.Ptr);
4722 return getStruct<MachO::source_version_command>(*
this, L.Ptr);
4727 return getStruct<MachO::entry_point_command>(*
this, L.Ptr);
4732 return getStruct<MachO::encryption_info_command>(*
this, L.Ptr);
4737 return getStruct<MachO::encryption_info_command_64>(*
this, L.Ptr);
4742 return getStruct<MachO::sub_framework_command>(*
this, L.Ptr);
4747 return getStruct<MachO::sub_umbrella_command>(*
this, L.Ptr);
4752 return getStruct<MachO::sub_library_command>(*
this, L.Ptr);
4757 return getStruct<MachO::sub_client_command>(*
this, L.Ptr);
4762 return getStruct<MachO::routines_command>(*
this, L.Ptr);
4767 return getStruct<MachO::routines_command_64>(*
this, L.Ptr);
4772 return getStruct<MachO::thread_command>(*
this, L.Ptr);
4777 return getStruct<MachO::fileset_entry_command>(*
this, L.Ptr);
4803 return getStruct<MachO::any_relocation_info>(
4804 *
this,
reinterpret_cast<const char *
>(
P));
4809 const char *
P =
reinterpret_cast<const char *
>(Rel.
p);
4810 return getStruct<MachO::data_in_code_entry>(*
this,
P);
4824 unsigned Index)
const {
4826 return getStruct<uint32_t>(*
this,
getPtr(*
this,
Offset));
4831 unsigned Index)
const {
4833 return getStruct<MachO::data_in_code_entry>(*
this,
getPtr(*
this,
Offset));
4838 return getStruct<MachO::symtab_command>(*
this, SymtabLoadCmd);
4842 Cmd.
cmd = MachO::LC_SYMTAB;
4852 if (DysymtabLoadCmd)
4853 return getStruct<MachO::dysymtab_command>(*
this, DysymtabLoadCmd);
4857 Cmd.
cmd = MachO::LC_DYSYMTAB;
4882 if (DataInCodeLoadCmd)
4883 return getStruct<MachO::linkedit_data_command>(*
this, DataInCodeLoadCmd);
4887 Cmd.
cmd = MachO::LC_DATA_IN_CODE;
4896 if (LinkOptHintsLoadCmd)
4897 return getStruct<MachO::linkedit_data_command>(*
this, LinkOptHintsLoadCmd);
4902 Cmd.
cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4910 if (!DyldInfoLoadCmd)
4911 return std::nullopt;
4913 auto DyldInfoOrErr =
4914 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4916 return std::nullopt;
4918 const uint8_t *
Ptr =
4924 if (!DyldInfoLoadCmd)
4925 return std::nullopt;
4927 auto DyldInfoOrErr =
4928 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4930 return std::nullopt;
4932 const uint8_t *
Ptr =
4933 reinterpret_cast<const uint8_t *
>(
getPtr(*
this, DyldInfo.
bind_off));
4938 if (!DyldInfoLoadCmd)
4939 return std::nullopt;
4941 auto DyldInfoOrErr =
4942 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4944 return std::nullopt;
4946 const uint8_t *
Ptr =
4952 if (!DyldInfoLoadCmd)
4953 return std::nullopt;
4955 auto DyldInfoOrErr =
4956 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4958 return std::nullopt;
4960 const uint8_t *
Ptr =
4966 if (!DyldInfoLoadCmd)
4967 return std::nullopt;
4969 auto DyldInfoOrErr =
4970 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4972 return std::nullopt;
4974 const uint8_t *
Ptr =
4982 if (!DyldChainedFixupsLoadCmd)
4983 return std::nullopt;
4984 auto DyldChainedFixupsOrErr = getStructOrErr<MachO::linkedit_data_command>(
4985 *
this, DyldChainedFixupsLoadCmd);
4986 if (!DyldChainedFixupsOrErr)
4987 return DyldChainedFixupsOrErr.takeError();
4989 *DyldChainedFixupsOrErr;
4993 if (!DyldChainedFixups.
dataoff)
4994 return std::nullopt;
4995 return DyldChainedFixups;
5002 return CFOrErr.takeError();
5003 if (!CFOrErr->has_value())
5004 return std::nullopt;
5012 const char *CFHeaderPtr =
getPtr(*
this, CFHeaderOffset);
5013 auto CFHeaderOrErr =
5014 getStructOrErr<MachO::dyld_chained_fixups_header>(*
this, CFHeaderPtr);
5016 return CFHeaderOrErr.takeError();
5025 Twine(
"bad chained fixups: unknown imports format: ") +
5035 " overlaps with chained fixups header");
5037 uint32_t EndOffset = CFHeaderOffset + CFSize;
5041 Twine(CFImageStartsOffset +
5043 " extends past end " +
Twine(EndOffset));
5053 return CFOrErr.takeError();
5055 std::vector<ChainedFixupsSegment> Segments;
5056 if (!CFOrErr->has_value())
5057 return std::make_pair(0, Segments);
5063 return HeaderOrErr.takeError();
5064 if (!HeaderOrErr->has_value())
5065 return std::make_pair(0, Segments);
5068 const char *Contents =
getPtr(*
this, DyldChainedFixups.
dataoff);
5070 auto ImageStartsOrErr = getStructOrErr<MachO::dyld_chained_starts_in_image>(
5071 *
this, Contents +
Header.starts_offset);
5072 if (!ImageStartsOrErr)
5073 return ImageStartsOrErr.takeError();
5076 const char *SegOffsPtr =
5077 Contents +
Header.starts_offset +
5079 const char *SegOffsEnd =
5081 if (SegOffsEnd > Contents + DyldChainedFixups.
datasize)
5083 "bad chained fixups: seg_info_offset extends past end");
5085 const char *LastSegEnd =
nullptr;
5088 getStructOrErr<uint32_t>(*
this, SegOffsPtr +
I *
sizeof(
uint32_t));
5090 return OffOrErr.takeError();
5098 " at offset " +
Twine(*OffOrErr) + Message);
5101 const char *SegPtr = Contents +
Header.starts_offset + *OffOrErr;
5102 if (LastSegEnd && SegPtr < LastSegEnd)
5103 return Fail(
" overlaps with previous segment info");
5106 getStructOrErr<MachO::dyld_chained_starts_in_segment>(*
this, SegPtr);
5108 return SegOrErr.takeError();
5111 LastSegEnd = SegPtr + Seg.
size;
5115 const char *PageStart =
5118 if (PageEnd > SegPtr + Seg.
size)
5119 return Fail(
" : page_starts extend past seg_info size");
5123 std::vector<uint16_t> PageStarts;
5124 for (
size_t PageIdx = 0; PageIdx < Seg.
page_count; ++PageIdx) {
5129 PageStarts.push_back(Start);
5132 Segments.emplace_back(
I, *OffOrErr, Seg, std::move(PageStarts));
5135 return std::make_pair(ImageStarts.
seg_count, Segments);
5144 return SignExtend32<sizeof(T) * CHAR_BIT>(
Value);
5148template <
typename T,
unsigned N>
5150 std::array<T, N> RawValue;
5151 memcpy(RawValue.data(),
Ptr,
N *
sizeof(
T));
5153 for (
auto &Element : RawValue)
5162 return CFOrErr.takeError();
5164 std::vector<ChainedFixupTarget> Targets;
5165 if (!CFOrErr->has_value())
5172 return CFHeaderOrErr.takeError();
5173 if (!(*CFHeaderOrErr))
5177 size_t ImportSize = 0;
5185 return malformedError(
"bad chained fixups: unknown imports format: " +
5188 const char *Contents =
getPtr(*
this, DyldChainedFixups.
dataoff);
5189 const char *Imports = Contents +
Header.imports_offset;
5190 size_t ImportsEndOffset =
5191 Header.imports_offset + ImportSize *
Header.imports_count;
5192 const char *ImportsEnd = Contents + ImportsEndOffset;
5193 const char *Symbols = Contents +
Header.symbols_offset;
5194 const char *SymbolsEnd = Contents + DyldChainedFixups.
datasize;
5196 if (ImportsEnd > Symbols)
5198 Twine(ImportsEndOffset) +
" overlaps with symbols");
5203 return createError(
"parsing big-endian chained fixups is not implemented");
5204 for (
const char *ImportPtr = Imports; ImportPtr < ImportsEnd;
5205 ImportPtr += ImportSize) {
5212 auto RawValue = getArray<uint32_t, 1>(*
this, ImportPtr);
5214 LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5215 WeakImport = (RawValue[0] >> 8) & 1;
5216 NameOffset = RawValue[0] >> 9;
5221 auto RawValue = getArray<uint32_t, 2>(*
this, ImportPtr);
5223 LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5224 WeakImport = (RawValue[0] >> 8) & 1;
5225 NameOffset = RawValue[0] >> 9;
5226 Addend = bit_cast<int32_t>(RawValue[1]);
5228 static_assert(2 *
sizeof(
uint64_t) ==
5230 auto RawValue = getArray<uint64_t, 2>(*
this, ImportPtr);
5232 LibOrdinal = getEncodedOrdinal<uint16_t>(RawValue[0] & 0xFFFF);
5233 NameOffset = (RawValue[0] >> 16) & 1;
5234 WeakImport = RawValue[0] >> 17;
5235 Addend = RawValue[1];
5240 const char *Str = Symbols + NameOffset;
5241 if (Str >= SymbolsEnd)
5243 Twine(NameOffset) +
" extends past end " +
5245 Targets.emplace_back(LibOrdinal, NameOffset, Str, Addend, WeakImport);
5248 return std::move(Targets);
5252 if (!DyldExportsTrieLoadCmd)
5253 return std::nullopt;
5255 auto DyldExportsTrieOrError = getStructOrErr<MachO::linkedit_data_command>(
5256 *
this, DyldExportsTrieLoadCmd);
5257 if (!DyldExportsTrieOrError)
5258 return std::nullopt;
5260 const uint8_t *
Ptr =
5261 reinterpret_cast<const uint8_t *
>(
getPtr(*
this, DyldExportsTrie.
dataoff));
5266 if (!FuncStartsLoadCmd)
5270 getStructOrErr<MachO::linkedit_data_command>(*
this, FuncStartsLoadCmd);
5277 return std::move(FunctionStarts);
5282 return std::nullopt;
5285 return ArrayRef(
reinterpret_cast<const uint8_t *
>(
Ptr), 16);
5323 size_t MachOFilesetEntryOffset) {
5325 if (Magic ==
"\xFE\xED\xFA\xCE")
5327 UniversalIndex, MachOFilesetEntryOffset);
5328 if (Magic ==
"\xCE\xFA\xED\xFE")
5330 UniversalIndex, MachOFilesetEntryOffset);
5331 if (Magic ==
"\xFE\xED\xFA\xCF")
5333 UniversalIndex, MachOFilesetEntryOffset);
5334 if (Magic ==
"\xCF\xFA\xED\xFE")
5336 UniversalIndex, MachOFilesetEntryOffset);
5337 return make_error<GenericBinaryError>(
"Unrecognized MachO magic number",
5343 .
Case(
"debug_str_offs",
"debug_str_offsets")
5354 return std::vector<std::string>();
5360 EC,
"%s: expected directory 'Contents/Resources/DWARF' in dSYM bundle",
5361 Path.str().c_str());
5365 std::vector<std::string> ObjectPaths;
5367 Dir != DirEnd && !EC; Dir.increment(EC)) {
5376 ObjectPaths.push_back(ObjectPath.
str());
5383 if (ObjectPaths.empty())
5385 "%s: no objects found in dSYM bundle",
5386 Path.str().c_str());
5393#define HANDLE_SWIFT_SECTION(KIND, MACHO, ELF, COFF) \
5394 .Case(MACHO, llvm::binaryformat::Swift5ReflectionSectionKind::KIND)
5397#include "llvm/BinaryFormat/Swift.def"
5399#undef HANDLE_SWIFT_SECTION
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
#define offsetof(TYPE, MEMBER)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static MachO::nlist_base getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI)
static Error checkVersCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char **LoadCmd, const char *CmdName)
static Error checkSymtabCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char **SymtabLoadCmd, std::list< MachOElement > &Elements)
static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char **LoadCmd, std::list< MachOElement > &Elements)
static Error parseBuildVersionCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, SmallVectorImpl< const char * > &BuildTools, uint32_t LoadCommandIndex)
static unsigned getPlainRelocationType(const MachOObjectFile &O, const MachO::any_relocation_info &RE)
static Error checkDysymtabCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char **DysymtabLoadCmd, std::list< MachOElement > &Elements)
static Error checkDylibCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char *CmdName)
static Expected< T > getStructOrErr(const MachOObjectFile &O, const char *P)
static Expected< MachOObjectFile::LoadCommandInfo > getFirstLoadCommandInfo(const MachOObjectFile &Obj)
static const char * getPtr(const MachOObjectFile &O, size_t Offset, size_t MachOFilesetEntryOffset=0)
static Error parseSegmentLoadCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, SmallVectorImpl< const char * > &Sections, bool &IsPageZeroSegment, uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders, std::list< MachOElement > &Elements)
static Error checkDyldInfoCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char **LoadCmd, const char *CmdName, std::list< MachOElement > &Elements)
static unsigned getScatteredRelocationLength(const MachO::any_relocation_info &RE)
static unsigned getPlainRelocationLength(const MachOObjectFile &O, const MachO::any_relocation_info &RE)
static Error checkSubCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char *CmdName, size_t SizeOfCmd, const char *CmdStructName, uint32_t PathOffset, const char *PathFieldName)
static Error checkRpathCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex)
static T getStruct(const MachOObjectFile &O, const char *P)
static uint32_t getPlainRelocationAddress(const MachO::any_relocation_info &RE)
static const char * getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L, unsigned Sec)
static Error checkLinkerOptCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex)
static bool getPlainRelocationPCRel(const MachOObjectFile &O, const MachO::any_relocation_info &RE)
static std::array< T, N > getArray(const MachOObjectFile &O, const void *Ptr)
static unsigned getScatteredRelocationAddress(const MachO::any_relocation_info &RE)
static Error checkThreadCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char *CmdName)
static Error checkLinkeditDataCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char **LoadCmd, const char *CmdName, std::list< MachOElement > &Elements, const char *ElementName)
static Error malformedError(const Twine &Msg)
static bool isLoadCommandObsolete(uint32_t cmd)
static uint32_t getSectionFlags(const MachOObjectFile &O, DataRefImpl Sec)
static int getEncodedOrdinal(T Value)
static bool getScatteredRelocationPCRel(const MachO::any_relocation_info &RE)
static Error checkOverlappingElement(std::list< MachOElement > &Elements, uint64_t Offset, uint64_t Size, const char *Name)
static StringRef parseSegmentOrSectionName(const char *P)
static Expected< MachOObjectFile::LoadCommandInfo > getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr, uint32_t LoadCommandIndex)
static void parseHeader(const MachOObjectFile &Obj, T &Header, Error &Err)
static unsigned getCPUType(const MachOObjectFile &O)
static Error checkDyldCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char *CmdName)
static Error checkNoteCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, std::list< MachOElement > &Elements)
static Error checkDylibIdCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, const char **LoadCmd)
static unsigned getCPUSubType(const MachOObjectFile &O)
static Error checkEncryptCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load, uint32_t LoadCommandIndex, uint64_t cryptoff, uint64_t cryptsize, const char **LoadCmd, const char *CmdName)
static Expected< MachOObjectFile::LoadCommandInfo > getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex, const MachOObjectFile::LoadCommandInfo &L)
static Error malformedError(Twine Msg)
OptimizedStructLayoutField Field
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static StringRef substr(StringRef Str, uint64_t Len)
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static bool is64Bit(const char *name)
This file implements the C++20 <bit> header.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Helper for Errors used as out-parameters.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
StringRef getBuffer() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
bool equals(StringRef RHS) const
Check for string equality.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
static constexpr size_t npos
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(const uint64_t &Val)
LLVM Value Representation.
A range adaptor for a pair of iterators.
StringRef getData() const
unsigned int getType() const
bool isLittleEndian() const
static unsigned int getMachOType(bool isLE, bool is64Bits)
StringRef segmentName(int32_t SegIndex)
StringRef sectionName(int32_t SegIndex, uint64_t SegOffset)
BindRebaseSegInfo(const MachOObjectFile *Obj)
const char * checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, uint8_t PointerSize, uint64_t Count=1, uint64_t Skip=0)
uint64_t address(uint32_t SegIndex, uint64_t SegOffset)
DiceRef - This is a value type class that represents a single data in code entry in the table in a Ma...
ExportEntry encapsulates the current-state-of-the-walk used when doing a non-recursive walk of the tr...
ExportEntry(Error *Err, const MachOObjectFile *O, ArrayRef< uint8_t > Trie)
bool operator==(const ExportEntry &) const
StringRef otherName() const
uint32_t nodeOffset() const
MachOAbstractFixupEntry is an abstract class representing a fixup in a MH_DYLDLINK file.
StringRef sectionName() const
uint64_t segmentAddress() const
int32_t segmentIndex() const
StringRef typeName() const
MachOAbstractFixupEntry(Error *Err, const MachOObjectFile *O)
uint64_t textAddress() const
StringRef symbolName() const
StringRef segmentName() const
const MachOObjectFile * O
uint64_t segmentOffset() const
MachOBindEntry encapsulates the current state in the decompression of binding opcodes.
bool operator==(const MachOBindEntry &) const
StringRef symbolName() const
StringRef sectionName() const
MachOBindEntry(Error *Err, const MachOObjectFile *O, ArrayRef< uint8_t > Opcodes, bool is64Bit, MachOBindEntry::Kind)
StringRef segmentName() const
uint64_t segmentOffset() const
int32_t segmentIndex() const
StringRef typeName() const
bool operator==(const MachOChainedFixupEntry &) const
MachOChainedFixupEntry(Error *Err, const MachOObjectFile *O, bool Parse)
MachO::sub_client_command getSubClientCommand(const LoadCommandInfo &L) const
void moveSectionNext(DataRefImpl &Sec) const override
ArrayRef< char > getSectionRawFinalSegmentName(DataRefImpl Sec) const
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
Triple::ArchType getArch() const override
MachO::mach_header_64 Header64
bool isSectionData(DataRefImpl Sec) const override
const MachO::mach_header_64 & getHeader64() const
Expected< std::vector< ChainedFixupTarget > > getDyldChainedFixupTargets() const
uint64_t getSectionAlignment(DataRefImpl Sec) const override
uint32_t getScatteredRelocationType(const MachO::any_relocation_info &RE) const
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
Expected< SectionRef > getSection(unsigned SectionIndex) const
iterator_range< rebase_iterator > rebaseTable(Error &Err)
For use iterating over all rebase table entries.
std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const
load_command_iterator begin_load_commands() const
MachO::encryption_info_command_64 getEncryptionInfoCommand64(const LoadCommandInfo &L) const
StringRef getFileFormatName() const override
dice_iterator begin_dices() const
basic_symbol_iterator symbol_begin() const override
Expected< std::optional< MachO::linkedit_data_command > > getChainedFixupsLoadCommand() const
iterator_range< export_iterator > exports(Error &Err) const
For use iterating over all exported symbols.
uint64_t getSymbolIndex(DataRefImpl Symb) const
MachO::build_version_command getBuildVersionLoadCommand(const LoadCommandInfo &L) const
section_iterator section_end() const override
MachO::build_tool_version getBuildToolVersion(unsigned index) const
MachO::linkedit_data_command getDataInCodeLoadCommand() const
MachO::routines_command getRoutinesCommand(const LoadCommandInfo &L) const
MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const
unsigned getSymbolSectionID(SymbolRef Symb) const
static Expected< std::vector< std::string > > findDsymObjectMembers(StringRef Path)
If the input path is a .dSYM bundle (as created by the dsymutil tool), return the paths to the object...
uint32_t getScatteredRelocationValue(const MachO::any_relocation_info &RE) const
MachO::linker_option_command getLinkerOptionLoadCommand(const LoadCommandInfo &L) const
uint32_t getLibraryCount() const
MachO::entry_point_command getEntryPointCommand(const LoadCommandInfo &L) const
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
const char * RebaseEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, uint8_t PointerSize, uint64_t Count=1, uint64_t Skip=0) const
uint64_t getRelocationOffset(DataRefImpl Rel) const override
ArrayRef< uint8_t > getDyldInfoLazyBindOpcodes() const
void moveSymbolNext(DataRefImpl &Symb) const override
SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const
MachO::dysymtab_command getDysymtabLoadCommand() const
iterator_range< bind_iterator > bindTable(Error &Err)
For use iterating over all bind table entries.
MachO::mach_header Header
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
MachO::section_64 getSection64(DataRefImpl DRI) const
MachO::fileset_entry_command getFilesetEntryLoadCommand(const LoadCommandInfo &L) const
MachO::note_command getNoteLoadCommand(const LoadCommandInfo &L) const
MachO::thread_command getThreadCommand(const LoadCommandInfo &L) const
ArrayRef< uint8_t > getSectionContents(uint32_t Offset, uint64_t Size) const
const char * BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, uint8_t PointerSize, uint64_t Count=1, uint64_t Skip=0) const
section_iterator section_begin() const override
Error checkSymbolTable() const
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
MachO::segment_command_64 getSegment64LoadCommand(const LoadCommandInfo &L) const
relocation_iterator section_rel_end(DataRefImpl Sec) const override
ArrayRef< uint8_t > getDyldInfoExportsTrie() const
bool isDebugSection(DataRefImpl Sec) const override
MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const
unsigned getSectionType(SectionRef Sec) const
MachO::segment_command getSegmentLoadCommand(const LoadCommandInfo &L) const
static Expected< std::unique_ptr< MachOObjectFile > > create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, uint32_t UniversalCputype=0, uint32_t UniversalIndex=0, size_t MachOFilesetEntryOffset=0)
StringRef getSectionFinalSegmentName(DataRefImpl Sec) const
MachO::linkedit_data_command getLinkOptHintsLoadCommand() const
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const
MachO::rpath_command getRpathCommand(const LoadCommandInfo &L) const
dice_iterator end_dices() const
MachO::routines_command_64 getRoutinesCommand64(const LoadCommandInfo &L) const
MachO::sub_framework_command getSubFrameworkCommand(const LoadCommandInfo &L) const
SmallVector< uint64_t > getFunctionStarts() const
MachO::sub_library_command getSubLibraryCommand(const LoadCommandInfo &L) const
MachO::dyld_info_command getDyldInfoLoadCommand(const LoadCommandInfo &L) const
MachO::sub_umbrella_command getSubUmbrellaCommand(const LoadCommandInfo &L) const
ArrayRef< uint8_t > getDyldExportsTrie() const
Expected< uint32_t > getSymbolFlags(DataRefImpl Symb) const override
section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const
bool isSectionBSS(DataRefImpl Sec) const override
Expected< std::pair< size_t, std::vector< ChainedFixupsSegment > > > getChainedFixupsSegments() const
bool isSectionVirtual(DataRefImpl Sec) const override
bool getScatteredRelocationScattered(const MachO::any_relocation_info &RE) const
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const
symbol_iterator getSymbolByIndex(unsigned Index) const
static Triple getHostArch()
MachO::encryption_info_command getEncryptionInfoCommand(const LoadCommandInfo &L) const
const MachO::mach_header & getHeader() const
unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const
iterator_range< bind_iterator > weakBindTable(Error &Err)
For use iterating over all weak bind table entries.
static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch)
ArrayRef< uint8_t > getDyldInfoRebaseOpcodes() const
iterator_range< load_command_iterator > load_commands() const
unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const
MachO::symtab_command getSymtabLoadCommand() const
Triple getArchTriple(const char **McpuDefault=nullptr) const
MachO::uuid_command getUuidCommand(const LoadCommandInfo &L) const
unsigned getPlainRelocationSymbolNum(const MachO::any_relocation_info &RE) const
ArrayRef< uint8_t > getUuid() const
uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const
For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase entry to get the address.
bool is64Bit() const override
MachO::version_min_command getVersionMinLoadCommand(const LoadCommandInfo &L) const
StringRef mapDebugSectionName(StringRef Name) const override
Maps a debug section name to a standard DWARF section name.
MachO::dylinker_command getDylinkerCommand(const LoadCommandInfo &L) const
uint64_t getRelocationType(DataRefImpl Rel) const override
StringRef BindRebaseSegmentName(int32_t SegIndex) const
For use with the SegIndex of a checked Mach-O Bind or Rebase entry to get the segment name.
relocation_iterator extrel_begin() const
void moveRelocationNext(DataRefImpl &Rel) const override
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const
basic_symbol_iterator symbol_end() const override
MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset, unsigned Index) const
MachO::data_in_code_entry getDice(DataRefImpl Rel) const
bool isSectionStripped(DataRefImpl Sec) const override
When dsymutil generates the companion file, it strips all unnecessary sections (e....
uint64_t getSectionIndex(DataRefImpl Sec) const override
iterator_range< fixup_iterator > fixupTable(Error &Err)
For iterating over all chained fixups.
void ReadULEB128s(uint64_t Index, SmallVectorImpl< uint64_t > &Out) const
StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const
For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase entry to get the section ...
iterator_range< bind_iterator > lazyBindTable(Error &Err)
For use iterating over all lazy bind table entries.
load_command_iterator end_load_commands() const
ArrayRef< uint8_t > getDyldInfoBindOpcodes() const
Expected< SymbolRef::Type > getSymbolType(DataRefImpl Symb) const override
uint64_t getSectionAddress(DataRefImpl Sec) const override
bool hasPageZeroSegment() const
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
uint8_t getRelocationLength(DataRefImpl Rel) const
llvm::binaryformat::Swift5ReflectionSectionKind mapReflectionSectionNameToEnumValue(StringRef SectionName) const override
ArrayRef< uint8_t > getDyldInfoWeakBindOpcodes() const
static bool isValidArch(StringRef ArchFlag)
bool isSectionText(DataRefImpl Sec) const override
bool isSectionCompressed(DataRefImpl Sec) const override
static ArrayRef< StringRef > getValidArchs()
bool isSectionBitcode(DataRefImpl Sec) const override
bool isRelocationScattered(const MachO::any_relocation_info &RE) const
relocation_iterator locrel_begin() const
Expected< std::optional< MachO::dyld_chained_fixups_header > > getChainedFixupsHeader() const
If the optional is std::nullopt, no header was found, but the object was well-formed.
uint32_t getSymbolAlignment(DataRefImpl Symb) const override
MachO::source_version_command getSourceVersionCommand(const LoadCommandInfo &L) const
unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const
StringRef getStringTableData() const
void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl< char > &Result) const override
ArrayRef< char > getSectionRawName(DataRefImpl Sec) const
uint64_t getNValue(DataRefImpl Sym) const
ArrayRef< uint8_t > getSegmentContents(StringRef SegmentName) const
Return the raw contents of an entire segment.
section_iterator getRelocationSection(DataRefImpl Rel) const
unsigned getSectionID(SectionRef Sec) const
MachO::linkedit_data_command getLinkeditDataLoadCommand(const LoadCommandInfo &L) const
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
MachO::dylib_command getDylibIDLoadCommand(const LoadCommandInfo &L) const
size_t getMachOFilesetEntryOffset() const
uint32_t getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC, unsigned Index) const
uint64_t getSectionSize(DataRefImpl Sec) const override
relocation_iterator extrel_end() const
static StringRef guessLibraryShortName(StringRef Name, bool &isFramework, StringRef &Suffix)
relocation_iterator locrel_end() const
std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const
MachORebaseEntry encapsulates the current state in the decompression of rebasing opcodes.
int32_t segmentIndex() const
StringRef segmentName() const
MachORebaseEntry(Error *Err, const MachOObjectFile *O, ArrayRef< uint8_t > opcodes, bool is64Bit)
bool operator==(const MachORebaseEntry &) const
StringRef sectionName() const
uint64_t segmentOffset() const
StringRef typeName() const
This class is the base class for all object file types.
friend class RelocationRef
static Expected< std::unique_ptr< MachOObjectFile > > createMachOObjectFile(MemoryBufferRef Object, uint32_t UniversalCputype=0, uint32_t UniversalIndex=0, size_t MachOFilesetEntryOffset=0)
Create a MachOObjectFile instance from a given buffer.
section_iterator_range sections() const
symbol_iterator_range symbols() const
Expected< uint64_t > getSymbolValue(DataRefImpl Symb) const
This is a value type class that represents a single section in the list of sections in the object fil...
DataRefImpl getRawDataRefImpl() const
bool isData() const
Whether this section contains data, not instructions.
bool isBSS() const
Whether this section contains BSS uninitialized data.
This is a value type class that represents a single symbol in the list of symbols in the object file.
directory_iterator - Iterates through the entries in path.
Represents the result of a call to sys::fs::status().
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
const uint32_t x86_FLOAT_STATE_COUNT
@ DYLD_CHAINED_IMPORT_ADDEND
@ DYLD_CHAINED_IMPORT_ADDEND64
const uint32_t ARM_THREAD_STATE64_COUNT
@ EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
@ EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
@ EXPORT_SYMBOL_FLAGS_KIND_REGULAR
@ BIND_TYPE_TEXT_ABSOLUTE32
const uint32_t x86_EXCEPTION_STATE_COUNT
@ S_ATTR_PURE_INSTRUCTIONS
S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine instructions.
@ REBASE_TYPE_TEXT_ABSOLUTE32
@ REBASE_TYPE_TEXT_PCREL32
@ EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_KIND_MASK
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
@ S_GB_ZEROFILL
S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 gigabytes).
@ S_THREAD_LOCAL_ZEROFILL
S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section.
@ S_ZEROFILL
S_ZEROFILL - Zero fill on demand section.
@ BIND_SPECIAL_DYLIB_WEAK_LOOKUP
@ BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE
@ BIND_SPECIAL_DYLIB_FLAT_LOOKUP
uint8_t GET_COMM_ALIGN(uint16_t n_desc)
void swapStruct(fat_header &mh)
const uint32_t x86_THREAD_STATE32_COUNT
@ BIND_SYMBOL_FLAGS_WEAK_IMPORT
@ BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
@ CPU_SUBTYPE_POWERPC_ALL
@ BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
@ BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
@ BIND_OPCODE_SET_ADDEND_SLEB
@ BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
@ BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
@ BIND_OPCODE_ADD_ADDR_ULEB
@ BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
@ BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
@ BIND_OPCODE_SET_TYPE_IMM
@ BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
@ BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
const uint32_t PPC_THREAD_STATE_COUNT
const uint32_t ARM_THREAD_STATE_COUNT
@ REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
@ REBASE_OPCODE_DO_REBASE_IMM_TIMES
@ REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB
@ REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
@ REBASE_OPCODE_DO_REBASE_ULEB_TIMES
@ REBASE_OPCODE_ADD_ADDR_ULEB
@ REBASE_OPCODE_SET_TYPE_IMM
@ REBASE_OPCODE_ADD_ADDR_IMM_SCALED
const uint32_t x86_THREAD_STATE_COUNT
@ CPU_SUBTYPE_ARM64_32_V8
@ GENERIC_RELOC_LOCAL_SECTDIFF
@ ARM_RELOC_LOCAL_SECTDIFF
@ ARM_RELOC_HALF_SECTDIFF
@ X86_64_RELOC_SUBTRACTOR
uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc)
@ DYLD_CHAINED_PTR_START_NONE
@ DYLD_CHAINED_PTR_64_OFFSET
const uint32_t x86_EXCEPTION_STATE64_COUNT
const uint32_t x86_THREAD_STATE64_COUNT
constexpr size_t SymbolTableEntrySize
Error createError(const Twine &Err)
content_iterator< ExportEntry > export_iterator
content_iterator< MachOChainedFixupEntry > fixup_iterator
content_iterator< DiceRef > dice_iterator
content_iterator< SectionRef > section_iterator
content_iterator< MachOBindEntry > bind_iterator
content_iterator< RelocationRef > relocation_iterator
content_iterator< BasicSymbolRef > basic_symbol_iterator
content_iterator< MachORebaseEntry > rebase_iterator
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
bool is_directory(const basic_file_status &status)
Does status represent a directory?
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
StringRef extension(StringRef path, Style style=Style::native)
Get extension.
static const bool IsLittleEndianHost
void swapByteOrder(T &Value)
std::string getDefaultTargetTriple()
getDefaultTargetTriple() - Return the default target triple the compiler has been configured to produ...
This is an optimization pass for GlobalISel generic memory operations.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
@ no_such_file_or_directory
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
This struct is a compact representation of a valid (non-zero power of two) alignment.
dyld_chained_starts_in_image is embedded in LC_DYLD_CHAINED_FIXUPS payload.
uint16_t page_count
Length of the page_start array.
uint16_t page_size
Page size in bytes (0x1000 or 0x4000)
uint16_t pointer_format
DYLD_CHAINED_PTR*.
uint32_t size
Size of this, including chain_starts entries.
ChainedFixupTarget holds all the information about an external symbol necessary to bind this binary t...
MachO::dyld_chained_starts_in_segment Header
std::vector< uint16_t > PageStarts
struct llvm::object::DataRefImpl::@368 d