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.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) {
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))
4448 return findSection(SegIndex, SegOffset).SectionName;
4454 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4455 return SI.SegmentStartAddress + OffsetInSeg;
4462 if (O->BindRebaseSectionTable ==
nullptr)
4463 O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
4465 Start.moveToFirst();
4489 if (BindRebaseSectionTable ==
nullptr)
4490 BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(
this);
4493 Start.moveToFirst();
4503 return LoadCommands.
begin();
4508 return LoadCommands.
end();
4524 assert(Sec.
d.
a < Sections.size() &&
"Should have detected this earlier");
4525 const section_base *
Base =
4526 reinterpret_cast<const section_base *
>(Sections[Sec.
d.
a]);
4532 assert(Sec.
d.
a < Sections.size() &&
"Should have detected this earlier");
4533 const section_base *
Base =
4534 reinterpret_cast<const section_base *
>(Sections[Sec.
d.
a]);
4556 return (RE.
r_word1 >> 27) & 1;
4572 return (RE.
r_word0 >> 24) & 0xf;
4610 if (SecNum ==
MachO::R_ABS || SecNum > Sections.size())
4613 DRI.
d.
a = SecNum - 1;
4618 assert(DRI.
d.
a < Sections.size() &&
"Should have detected this earlier");
4619 return getStruct<MachO::section>(*
this, Sections[DRI.
d.
a]);
4623 assert(DRI.
d.
a < Sections.size() &&
"Should have detected this earlier");
4624 return getStruct<MachO::section_64>(*
this, Sections[DRI.
d.
a]);
4628 unsigned Index)
const {
4630 return getStruct<MachO::section>(*
this, Sec);
4634 unsigned Index)
const {
4636 return getStruct<MachO::section_64>(*
this, Sec);
4641 const char *
P =
reinterpret_cast<const char *
>(DRI.
p);
4642 return getStruct<MachO::nlist>(*
this,
P);
4647 const char *
P =
reinterpret_cast<const char *
>(DRI.
p);
4648 return getStruct<MachO::nlist_64>(*
this,
P);
4653 return getStruct<MachO::linkedit_data_command>(*
this, L.Ptr);
4658 return getStruct<MachO::segment_command>(*
this, L.Ptr);
4663 return getStruct<MachO::segment_command_64>(*
this, L.Ptr);
4668 return getStruct<MachO::linker_option_command>(*
this, L.Ptr);
4673 return getStruct<MachO::version_min_command>(*
this, L.Ptr);
4678 return getStruct<MachO::note_command>(*
this, L.Ptr);
4683 return getStruct<MachO::build_version_command>(*
this, L.Ptr);
4688 return getStruct<MachO::build_tool_version>(*
this, BuildTools[index]);
4693 return getStruct<MachO::dylib_command>(*
this, L.Ptr);
4698 return getStruct<MachO::dyld_info_command>(*
this, L.Ptr);
4703 return getStruct<MachO::dylinker_command>(*
this, L.Ptr);
4708 return getStruct<MachO::uuid_command>(*
this, L.Ptr);
4713 return getStruct<MachO::rpath_command>(*
this, L.Ptr);
4718 return getStruct<MachO::source_version_command>(*
this, L.Ptr);
4723 return getStruct<MachO::entry_point_command>(*
this, L.Ptr);
4728 return getStruct<MachO::encryption_info_command>(*
this, L.Ptr);
4733 return getStruct<MachO::encryption_info_command_64>(*
this, L.Ptr);
4738 return getStruct<MachO::sub_framework_command>(*
this, L.Ptr);
4743 return getStruct<MachO::sub_umbrella_command>(*
this, L.Ptr);
4748 return getStruct<MachO::sub_library_command>(*
this, L.Ptr);
4753 return getStruct<MachO::sub_client_command>(*
this, L.Ptr);
4758 return getStruct<MachO::routines_command>(*
this, L.Ptr);
4763 return getStruct<MachO::routines_command_64>(*
this, L.Ptr);
4768 return getStruct<MachO::thread_command>(*
this, L.Ptr);
4773 return getStruct<MachO::fileset_entry_command>(*
this, L.Ptr);
4799 return getStruct<MachO::any_relocation_info>(
4800 *
this,
reinterpret_cast<const char *
>(
P));
4805 const char *
P =
reinterpret_cast<const char *
>(Rel.
p);
4806 return getStruct<MachO::data_in_code_entry>(*
this,
P);
4820 unsigned Index)
const {
4822 return getStruct<uint32_t>(*
this,
getPtr(*
this,
Offset));
4827 unsigned Index)
const {
4829 return getStruct<MachO::data_in_code_entry>(*
this,
getPtr(*
this,
Offset));
4834 return getStruct<MachO::symtab_command>(*
this, SymtabLoadCmd);
4838 Cmd.
cmd = MachO::LC_SYMTAB;
4848 if (DysymtabLoadCmd)
4849 return getStruct<MachO::dysymtab_command>(*
this, DysymtabLoadCmd);
4853 Cmd.
cmd = MachO::LC_DYSYMTAB;
4878 if (DataInCodeLoadCmd)
4879 return getStruct<MachO::linkedit_data_command>(*
this, DataInCodeLoadCmd);
4883 Cmd.
cmd = MachO::LC_DATA_IN_CODE;
4892 if (LinkOptHintsLoadCmd)
4893 return getStruct<MachO::linkedit_data_command>(*
this, LinkOptHintsLoadCmd);
4898 Cmd.
cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4906 if (!DyldInfoLoadCmd)
4907 return std::nullopt;
4909 auto DyldInfoOrErr =
4910 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4912 return std::nullopt;
4914 const uint8_t *
Ptr =
4920 if (!DyldInfoLoadCmd)
4921 return std::nullopt;
4923 auto DyldInfoOrErr =
4924 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4926 return std::nullopt;
4928 const uint8_t *
Ptr =
4929 reinterpret_cast<const uint8_t *
>(
getPtr(*
this, DyldInfo.
bind_off));
4934 if (!DyldInfoLoadCmd)
4935 return std::nullopt;
4937 auto DyldInfoOrErr =
4938 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4940 return std::nullopt;
4942 const uint8_t *
Ptr =
4948 if (!DyldInfoLoadCmd)
4949 return std::nullopt;
4951 auto DyldInfoOrErr =
4952 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4954 return std::nullopt;
4956 const uint8_t *
Ptr =
4962 if (!DyldInfoLoadCmd)
4963 return std::nullopt;
4965 auto DyldInfoOrErr =
4966 getStructOrErr<MachO::dyld_info_command>(*
this, DyldInfoLoadCmd);
4968 return std::nullopt;
4970 const uint8_t *
Ptr =
4978 if (!DyldChainedFixupsLoadCmd)
4979 return std::nullopt;
4980 auto DyldChainedFixupsOrErr = getStructOrErr<MachO::linkedit_data_command>(
4981 *
this, DyldChainedFixupsLoadCmd);
4982 if (!DyldChainedFixupsOrErr)
4983 return DyldChainedFixupsOrErr.takeError();
4985 *DyldChainedFixupsOrErr;
4989 if (!DyldChainedFixups.
dataoff)
4990 return std::nullopt;
4991 return DyldChainedFixups;
4998 return CFOrErr.takeError();
4999 if (!CFOrErr->has_value())
5000 return std::nullopt;
5008 const char *CFHeaderPtr =
getPtr(*
this, CFHeaderOffset);
5009 auto CFHeaderOrErr =
5010 getStructOrErr<MachO::dyld_chained_fixups_header>(*
this, CFHeaderPtr);
5012 return CFHeaderOrErr.takeError();
5021 Twine(
"bad chained fixups: unknown imports format: ") +
5031 " overlaps with chained fixups header");
5033 uint32_t EndOffset = CFHeaderOffset + CFSize;
5037 Twine(CFImageStartsOffset +
5039 " extends past end " +
Twine(EndOffset));
5049 return CFOrErr.takeError();
5051 std::vector<ChainedFixupsSegment> Segments;
5052 if (!CFOrErr->has_value())
5053 return std::make_pair(0, Segments);
5059 return HeaderOrErr.takeError();
5060 if (!HeaderOrErr->has_value())
5061 return std::make_pair(0, Segments);
5064 const char *Contents =
getPtr(*
this, DyldChainedFixups.
dataoff);
5066 auto ImageStartsOrErr = getStructOrErr<MachO::dyld_chained_starts_in_image>(
5067 *
this, Contents +
Header.starts_offset);
5068 if (!ImageStartsOrErr)
5069 return ImageStartsOrErr.takeError();
5072 const char *SegOffsPtr =
5073 Contents +
Header.starts_offset +
5075 const char *SegOffsEnd =
5077 if (SegOffsEnd > Contents + DyldChainedFixups.
datasize)
5079 "bad chained fixups: seg_info_offset extends past end");
5081 const char *LastSegEnd =
nullptr;
5084 getStructOrErr<uint32_t>(*
this, SegOffsPtr +
I *
sizeof(
uint32_t));
5086 return OffOrErr.takeError();
5094 " at offset " +
Twine(*OffOrErr) + Message);
5097 const char *SegPtr = Contents +
Header.starts_offset + *OffOrErr;
5098 if (LastSegEnd && SegPtr < LastSegEnd)
5099 return Fail(
" overlaps with previous segment info");
5102 getStructOrErr<MachO::dyld_chained_starts_in_segment>(*
this, SegPtr);
5104 return SegOrErr.takeError();
5107 LastSegEnd = SegPtr + Seg.
size;
5111 const char *PageStart =
5114 if (PageEnd > SegPtr + Seg.
size)
5115 return Fail(
" : page_starts extend past seg_info size");
5119 std::vector<uint16_t> PageStarts;
5120 for (
size_t PageIdx = 0; PageIdx < Seg.
page_count; ++PageIdx) {
5125 PageStarts.push_back(Start);
5128 Segments.emplace_back(
I, *OffOrErr, Seg, std::move(PageStarts));
5131 return std::make_pair(ImageStarts.
seg_count, Segments);
5140 return SignExtend32<sizeof(T) * CHAR_BIT>(
Value);
5144template <
typename T,
unsigned N>
5146 std::array<T, N> RawValue;
5147 memcpy(RawValue.data(),
Ptr,
N *
sizeof(
T));
5149 for (
auto &Element : RawValue)
5158 return CFOrErr.takeError();
5160 std::vector<ChainedFixupTarget> Targets;
5161 if (!CFOrErr->has_value())
5168 return CFHeaderOrErr.takeError();
5169 if (!(*CFHeaderOrErr))
5173 size_t ImportSize = 0;
5181 return malformedError(
"bad chained fixups: unknown imports format: " +
5184 const char *Contents =
getPtr(*
this, DyldChainedFixups.
dataoff);
5185 const char *Imports = Contents +
Header.imports_offset;
5186 size_t ImportsEndOffset =
5187 Header.imports_offset + ImportSize *
Header.imports_count;
5188 const char *ImportsEnd = Contents + ImportsEndOffset;
5189 const char *Symbols = Contents +
Header.symbols_offset;
5190 const char *SymbolsEnd = Contents + DyldChainedFixups.
datasize;
5192 if (ImportsEnd > Symbols)
5194 Twine(ImportsEndOffset) +
" extends past end " +
5197 if (ImportsEnd > Symbols)
5199 Twine(ImportsEndOffset) +
" overlaps with symbols");
5204 return createError(
"parsing big-endian chained fixups is not implemented");
5205 for (
const char *ImportPtr = Imports; ImportPtr < ImportsEnd;
5206 ImportPtr += ImportSize) {
5213 auto RawValue = getArray<uint32_t, 1>(*
this, ImportPtr);
5215 LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5216 WeakImport = (RawValue[0] >> 8) & 1;
5217 NameOffset = RawValue[0] >> 9;
5222 auto RawValue = getArray<uint32_t, 2>(*
this, ImportPtr);
5224 LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5225 WeakImport = (RawValue[0] >> 8) & 1;
5226 NameOffset = RawValue[0] >> 9;
5227 Addend = bit_cast<int32_t>(RawValue[1]);
5229 static_assert(2 *
sizeof(
uint64_t) ==
5231 auto RawValue = getArray<uint64_t, 2>(*
this, ImportPtr);
5233 LibOrdinal = getEncodedOrdinal<uint16_t>(RawValue[0] & 0xFFFF);
5234 NameOffset = (RawValue[0] >> 16) & 1;
5235 WeakImport = RawValue[0] >> 17;
5236 Addend = RawValue[1];
5241 const char *Str = Symbols + NameOffset;
5242 if (Str >= SymbolsEnd)
5244 Twine(NameOffset) +
" extends past end " +
5246 Targets.emplace_back(LibOrdinal, NameOffset, Str, Addend, WeakImport);
5249 return std::move(Targets);
5253 if (!DyldExportsTrieLoadCmd)
5254 return std::nullopt;
5256 auto DyldExportsTrieOrError = getStructOrErr<MachO::linkedit_data_command>(
5257 *
this, DyldExportsTrieLoadCmd);
5258 if (!DyldExportsTrieOrError)
5259 return std::nullopt;
5261 const uint8_t *
Ptr =
5262 reinterpret_cast<const uint8_t *
>(
getPtr(*
this, DyldExportsTrie.
dataoff));
5267 if (!FuncStartsLoadCmd)
5271 getStructOrErr<MachO::linkedit_data_command>(*
this, FuncStartsLoadCmd);
5278 return std::move(FunctionStarts);
5283 return std::nullopt;
5286 return ArrayRef(
reinterpret_cast<const uint8_t *
>(
Ptr), 16);
5324 size_t MachOFilesetEntryOffset) {
5326 if (Magic ==
"\xFE\xED\xFA\xCE")
5328 UniversalIndex, MachOFilesetEntryOffset);
5329 if (Magic ==
"\xCE\xFA\xED\xFE")
5331 UniversalIndex, MachOFilesetEntryOffset);
5332 if (Magic ==
"\xFE\xED\xFA\xCF")
5334 UniversalIndex, MachOFilesetEntryOffset);
5335 if (Magic ==
"\xCF\xFA\xED\xFE")
5337 UniversalIndex, MachOFilesetEntryOffset);
5338 return make_error<GenericBinaryError>(
"Unrecognized MachO magic number",
5344 .
Case(
"debug_str_offs",
"debug_str_offsets")
5355 return std::vector<std::string>();
5361 EC,
"%s: expected directory 'Contents/Resources/DWARF' in dSYM bundle",
5362 Path.str().c_str());
5366 std::vector<std::string> ObjectPaths;
5368 Dir != DirEnd && !EC; Dir.increment(EC)) {
5377 ObjectPaths.push_back(ObjectPath.
str());
5384 if (ObjectPaths.empty())
5386 "%s: no objects found in dSYM bundle",
5387 Path.str().c_str());
5394#define HANDLE_SWIFT_SECTION(KIND, MACHO, ELF, COFF) \
5395 .Case(MACHO, llvm::binaryformat::Swift5ReflectionSectionKind::KIND)
5398#include "llvm/BinaryFormat/Swift.def"
5400#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.
bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
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)
const char * checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, uint8_t PointerSize, uint32_t Count=1, uint32_t Skip=0)
BindRebaseSegInfo(const MachOObjectFile *Obj)
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
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
const char * BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, uint8_t PointerSize, uint32_t Count=1, uint32_t Skip=0) const
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
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.
const char * RebaseEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, uint8_t PointerSize, uint32_t Count=1, uint32_t Skip=0) const
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
@ BIND_SYMBOL_FLAGS_WEAK_IMPORT
@ BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
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
@ REBASE_TYPE_TEXT_ABSOLUTE32
@ REBASE_TYPE_TEXT_PCREL32
@ 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
@ DYLD_CHAINED_PTR_64_OFFSET
@ 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
@ S_ATTR_PURE_INSTRUCTIONS
S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine instructions.
@ EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_KIND_MASK
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
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)
const uint32_t x86_EXCEPTION_STATE64_COUNT
const uint32_t x86_THREAD_STATE64_COUNT
@ DYLD_CHAINED_PTR_START_NONE
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::@353 d