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) {
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");
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.startswith(
"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);
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() {
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) {
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;
3507 if (
Ptr == Opcodes.
end()) {
3514 const uint8_t *OpcodeStart =
Ptr;
3515 uint8_t Byte = *
Ptr++;
3519 const char *
error =
nullptr;
3528 RebaseType = ImmValue;
3530 *E =
malformedError(
"for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3531 Twine((
int)RebaseType) +
" for opcode at: 0x" +
3538 dbgs() <<
"REBASE_OPCODE_SET_TYPE_IMM: "
3539 <<
"RebaseType=" << (
int) RebaseType <<
"\n");
3542 SegmentIndex = ImmValue;
3543 SegmentOffset = readULEB128(&
error);
3545 *E =
malformedError(
"for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3554 *E =
malformedError(
"for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3562 dbgs() <<
"REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3563 <<
"SegmentIndex=" << SegmentIndex <<
", "
3564 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3568 SegmentOffset += readULEB128(&
error);
3571 " for opcode at: 0x" +
3580 " for opcode at: 0x" +
3586 dbgs() <<
"REBASE_OPCODE_ADD_ADDR_ULEB: "
3587 <<
format(
"SegmentOffset=0x%06X",
3588 SegmentOffset) <<
"\n");
3591 SegmentOffset += ImmValue * PointerSize;
3602 dbgs() <<
"REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3603 <<
format(
"SegmentOffset=0x%06X",
3604 SegmentOffset) <<
"\n");
3607 AdvanceAmount = PointerSize;
3611 RemainingLoopCount = ImmValue - 1;
3613 RemainingLoopCount = 0;
3615 PointerSize, Count, Skip);
3625 dbgs() <<
"REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3626 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3627 <<
", AdvanceAmount=" << AdvanceAmount
3628 <<
", RemainingLoopCount=" << RemainingLoopCount
3632 AdvanceAmount = PointerSize;
3634 Count = readULEB128(&
error);
3643 RemainingLoopCount = Count - 1;
3645 RemainingLoopCount = 0;
3647 PointerSize, Count, Skip);
3657 dbgs() <<
"REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3658 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3659 <<
", AdvanceAmount=" << AdvanceAmount
3660 <<
", RemainingLoopCount=" << RemainingLoopCount
3664 Skip = readULEB128(&
error);
3666 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3672 AdvanceAmount = Skip + PointerSize;
3674 RemainingLoopCount = 0;
3676 PointerSize, Count, Skip);
3678 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3686 dbgs() <<
"REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3687 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3688 <<
", AdvanceAmount=" << AdvanceAmount
3689 <<
", RemainingLoopCount=" << RemainingLoopCount
3693 Count = readULEB128(&
error);
3695 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3703 RemainingLoopCount = Count - 1;
3705 RemainingLoopCount = 0;
3706 Skip = readULEB128(&
error);
3708 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3715 AdvanceAmount = Skip + PointerSize;
3718 PointerSize, Count, Skip);
3720 *E =
malformedError(
"for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3729 dbgs() <<
"REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3730 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
3731 <<
", AdvanceAmount=" << AdvanceAmount
3732 <<
", RemainingLoopCount=" << RemainingLoopCount
3749 if (Ptr > Opcodes.
end())
3759 switch (RebaseType) {
3763 return "text abs32";
3765 return "text rel32";
3789#ifdef EXPENSIVE_CHECKS
3790 assert(Opcodes ==
Other.Opcodes &&
"compare iterators of different files");
3792 assert(Opcodes.
data() ==
Other.Opcodes.data() &&
"compare iterators of different files");
3795 (RemainingLoopCount ==
Other.RemainingLoopCount) &&
3796 (Done ==
Other.Done);
3802 if (O->BindRebaseSectionTable ==
nullptr)
3803 O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
3805 Start.moveToFirst();
3819 :
E(
E), O(O), Opcodes(Bytes),
Ptr(Bytes.begin()),
3820 PointerSize(
is64Bit ? 8 : 4), TableKind(BK) {}
3822void MachOBindEntry::moveToFirst() {
3827void MachOBindEntry::moveToEnd() {
3829 RemainingLoopCount = 0;
3836 SegmentOffset += AdvanceAmount;
3837 if (RemainingLoopCount) {
3838 --RemainingLoopCount;
3844 if (
Ptr == Opcodes.
end()) {
3851 const uint8_t *OpcodeStart =
Ptr;
3852 uint8_t Byte = *
Ptr++;
3855 int8_t SignExtended;
3856 const uint8_t *SymStart;
3858 const char *
error =
nullptr;
3864 bool NotLastEntry =
false;
3865 for (
const uint8_t *
P =
Ptr;
P < Opcodes.
end(); ++
P) {
3867 NotLastEntry =
true;
3879 *E =
malformedError(
"BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3880 "weak bind table for opcode at: 0x" +
3886 LibraryOrdinalSet =
true;
3888 *E =
malformedError(
"for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3889 "library ordinal: " +
3890 Twine((
int)ImmValue) +
" (max " +
3892 ") for opcode at: 0x" +
3899 dbgs() <<
"BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3900 <<
"Ordinal=" << Ordinal <<
"\n");
3904 *E =
malformedError(
"BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3905 "weak bind table for opcode at: 0x" +
3910 Ordinal = readULEB128(&
error);
3911 LibraryOrdinalSet =
true;
3920 *E =
malformedError(
"for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3921 "library ordinal: " +
3922 Twine((
int)Ordinal) +
" (max " +
3924 ") for opcode at: 0x" +
3931 dbgs() <<
"BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3932 <<
"Ordinal=" << Ordinal <<
"\n");
3936 *E =
malformedError(
"BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3937 "weak bind table for opcode at: 0x" +
3944 Ordinal = SignExtended;
3946 *E =
malformedError(
"for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3947 "special ordinal: " +
3948 Twine((
int)Ordinal) +
" for opcode at: 0x" +
3955 LibraryOrdinalSet =
true;
3958 dbgs() <<
"BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3959 <<
"Ordinal=" << Ordinal <<
"\n");
3967 if (
Ptr == Opcodes.
end()) {
3969 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3970 "symbol name extends past opcodes for opcode at: 0x" +
3975 SymbolName =
StringRef(
reinterpret_cast<const char*
>(SymStart),
3980 dbgs() <<
"BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3981 <<
"SymbolName=" << SymbolName <<
"\n");
3988 BindType = ImmValue;
3990 *E =
malformedError(
"for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3991 Twine((
int)ImmValue) +
" for opcode at: 0x" +
3998 dbgs() <<
"BIND_OPCODE_SET_TYPE_IMM: "
3999 <<
"BindType=" << (
int)BindType <<
"\n");
4002 Addend = readSLEB128(&
error);
4005 " for opcode at: 0x" +
4012 dbgs() <<
"BIND_OPCODE_SET_ADDEND_SLEB: "
4013 <<
"Addend=" << Addend <<
"\n");
4016 SegmentIndex = ImmValue;
4017 SegmentOffset = readULEB128(&
error);
4019 *E =
malformedError(
"for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4028 *E =
malformedError(
"for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4036 dbgs() <<
"BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
4037 <<
"SegmentIndex=" << SegmentIndex <<
", "
4038 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
4042 SegmentOffset += readULEB128(&
error);
4045 " for opcode at: 0x" +
4054 " for opcode at: 0x" +
4060 dbgs() <<
"BIND_OPCODE_ADD_ADDR_ULEB: "
4061 <<
format(
"SegmentOffset=0x%06X",
4062 SegmentOffset) <<
"\n");
4065 AdvanceAmount = PointerSize;
4066 RemainingLoopCount = 0;
4071 " for opcode at: 0x" +
4078 "for BIND_OPCODE_DO_BIND missing preceding "
4079 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
4084 if (!LibraryOrdinalSet && TableKind !=
Kind::Weak) {
4087 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4093 dbgs() <<
"BIND_OPCODE_DO_BIND: "
4094 <<
format(
"SegmentOffset=0x%06X",
4095 SegmentOffset) <<
"\n");
4099 *E =
malformedError(
"BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
4100 "lazy bind table for opcode at: 0x" +
4116 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4117 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
4123 if (!LibraryOrdinalSet && TableKind !=
Kind::Weak) {
4125 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4126 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4131 AdvanceAmount = readULEB128(&
error) + PointerSize;
4143 AdvanceAmount, PointerSize);
4145 *E =
malformedError(
"for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
4152 RemainingLoopCount = 0;
4155 dbgs() <<
"BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
4156 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
4157 <<
", AdvanceAmount=" << AdvanceAmount
4158 <<
", RemainingLoopCount=" << RemainingLoopCount
4163 *E =
malformedError(
"BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
4164 "allowed in lazy bind table for opcode at: 0x" +
4171 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4172 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4178 if (!LibraryOrdinalSet && TableKind !=
Kind::Weak) {
4180 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4181 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4187 AdvanceAmount = ImmValue * PointerSize + PointerSize;
4188 RemainingLoopCount = 0;
4190 AdvanceAmount, PointerSize);
4192 *E =
malformedError(
"for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
4200 <<
"BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
4201 <<
format(
"SegmentOffset=0x%06X", SegmentOffset) <<
"\n");
4205 *E =
malformedError(
"BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
4206 "allowed in lazy bind table for opcode at: 0x" +
4211 Count = readULEB128(&
error);
4213 RemainingLoopCount = Count - 1;
4215 RemainingLoopCount = 0;
4217 *E =
malformedError(
"for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4224 Skip = readULEB128(&
error);
4225 AdvanceAmount = Skip + PointerSize;
4227 *E =
malformedError(
"for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4236 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4237 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4243 if (!LibraryOrdinalSet && TableKind !=
Kind::Weak) {
4245 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4246 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4253 PointerSize, Count, Skip);
4256 malformedError(
"for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
4264 dbgs() <<
"BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
4265 <<
format(
"SegmentOffset=0x%06X", SegmentOffset)
4266 <<
", AdvanceAmount=" << AdvanceAmount
4267 <<
", RemainingLoopCount=" << RemainingLoopCount
4284 if (Ptr > Opcodes.
end())
4289int64_t MachOBindEntry::readSLEB128(
const char **
error) {
4293 if (Ptr > Opcodes.
end())
4307 return "text abs32";
4309 return "text rel32";
4341#ifdef EXPENSIVE_CHECKS
4342 assert(Opcodes ==
Other.Opcodes &&
"compare iterators of different files");
4344 assert(Opcodes.
data() ==
Other.Opcodes.data() &&
"compare iterators of different files");
4347 (RemainingLoopCount ==
Other.RemainingLoopCount) &&
4348 (Done ==
Other.Done);
4362 Info.SectionName = *NameOrErr;
4363 Info.Address = Section.getAddress();
4364 Info.Size = Section.getSize();
4367 if (!
Info.SegmentName.equals(CurSegName)) {
4369 CurSegName =
Info.SegmentName;
4370 CurSegAddress =
Info.Address;
4372 Info.SegmentIndex = CurSegIndex - 1;
4373 Info.OffsetInSegment =
Info.Address - CurSegAddress;
4374 Info.SegmentStartAddress = CurSegAddress;
4377 MaxSegIndex = CurSegIndex;
4389 uint8_t PointerSize,
4393 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4394 if (SegIndex >= MaxSegIndex)
4395 return "bad segIndex (too large)";
4396 for (
uint32_t i = 0; i < Count; ++i) {
4397 uint32_t Start = SegOffset + i * (PointerSize + Skip);
4400 for (
const SectionInfo &SI : Sections) {
4401 if (SI.SegmentIndex != SegIndex)
4403 if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
4404 if (
End <= SI.OffsetInSegment + SI.Size) {
4409 return "bad offset, extends beyond section boundary";
4413 return "bad offset, not in section";
4421 for (
const SectionInfo &SI : Sections) {
4422 if (SI.SegmentIndex == SegIndex)
4423 return SI.SegmentName;
4430const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
4431 int32_t SegIndex,
uint64_t SegOffset) {
4432 for (
const SectionInfo &SI : Sections) {
4433 if (SI.SegmentIndex != SegIndex)
4435 if (SI.OffsetInSegment > SegOffset)
4437 if (SegOffset >= (SI.OffsetInSegment + SI.Size))