llvm.org GIT mirror llvm / 6469bc6
Updated llvm-objdump to display local relocations in Mach-O binaries Summary: llvm-objdump's Mach-O parser was updated in r306037 to display external relocations for MH_KEXT_BUNDLE file types. This change extends the Macho-O parser to display local relocations for MH_PRELOAD files. When used with the -macho option relocations will be displayed in a historical format. All tests are passing for llvm, clang, and lld. llvm-objdump builds without compiler warnings. rdar://35778019 Reviewers: enderby Reviewed By: enderby Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D41199 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320832 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Trent 2 years ago
7 changed file(s) with 371 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
328328 return make_range(extrel_begin(), extrel_end());
329329 }
330330
331 relocation_iterator locrel_begin() const;
332 relocation_iterator locrel_end() const;
333
331334 void moveRelocationNext(DataRefImpl &Rel) const override;
332335 uint64_t getRelocationOffset(DataRefImpl Rel) const override;
333336 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
19591959
19601960 relocation_iterator MachOObjectFile::extrel_begin() const {
19611961 DataRefImpl Ret;
1962 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
19621963 Ret.d.a = 0; // Would normally be a section index.
19631964 Ret.d.b = 0; // Index into the external relocations
19641965 return relocation_iterator(RelocationRef(Ret, this));
19671968 relocation_iterator MachOObjectFile::extrel_end() const {
19681969 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
19691970 DataRefImpl Ret;
1971 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
19701972 Ret.d.a = 0; // Would normally be a section index.
19711973 Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
1974 return relocation_iterator(RelocationRef(Ret, this));
1975 }
1976
1977 relocation_iterator MachOObjectFile::locrel_begin() const {
1978 DataRefImpl Ret;
1979 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
1980 Ret.d.a = 1; // Would normally be a section index.
1981 Ret.d.b = 0; // Index into the local relocations
1982 return relocation_iterator(RelocationRef(Ret, this));
1983 }
1984
1985 relocation_iterator MachOObjectFile::locrel_end() const {
1986 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
1987 DataRefImpl Ret;
1988 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
1989 Ret.d.a = 1; // Would normally be a section index.
1990 Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
19721991 return relocation_iterator(RelocationRef(Ret, this));
19731992 }
19741993
43004319 }
43014320 } else {
43024321 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
4303 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4322 if (Rel.d.a == 0)
4323 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4324 else
4325 Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
43044326 }
43054327
43064328 auto P = reinterpret_cast(
0 // RUN: llvm-objdump -macho -r %p/Inputs/macho-preload-x86_64 | FileCheck %s
1
2 CHECK: Local relocation information 1 entries
3 CHECK: address pcrel length extern type scattered symbolnum/value
4 CHECK: 00000000 False quad False UNSIGND False 2 (__TEXT,__cstring)
0 RUN: llvm-objdump -macho -r %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s
11
2 CHECK: RELOCATION RECORDS FOR [__text]:
3 CHECK: 0000000000000027 X86_64_RELOC_BRANCH _printf
4 CHECK: 000000000000000b X86_64_RELOC_SIGNED L_.str
5 CHECK: RELOCATION RECORDS FOR [__compact_unwind]:
6 CHECK: 0000000000000000 X86_64_RELOC_UNSIGNED __text
2 CHECK: Relocation information (__TEXT,__text) 2 entries
3 CHECK: address pcrel length extern type scattered symbolnum/value
4 CHECK: 00000027 True long True BRANCH False _printf
5 CHECK: 0000000b True long True SIGNED False L_.str
6 CHECK: Relocation information (__LD,__compact_unwind) 1 entries
7 CHECK: address pcrel length extern type scattered symbolnum/value
8 CHECK: 00000000 False quad False UNSIGND False 1 (__TEXT,__text)
6767 INVALID-BIND-ENTRY: macho-invalid-bind-entry': truncated or malformed object (for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad library ordinal: 83 (max 0) for opcode at: 0x0)
6868
6969 RUN: llvm-objdump -macho -r %p/Inputs/macho-invalid-reloc-section-index | FileCheck -check-prefix INVALID-RELOC-SECTION-INDEX %s
70 INVALID-RELOC-SECTION-INDEX: 0000000000000021 X86_64_RELOC_UNSIGNED 8388613 (?,?)
70 INVALID-RELOC-SECTION-INDEX: 00000021 False byte False UNSIGND False 8388613 (?,?)
460460 << Sec.sectname << ") " << count << " entries";
461461 uint32_t n = Sec.reserved1;
462462 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
463 }
464 }
465 }
466 }
467 }
468
469 static void PrintRType(const uint64_t cputype, const unsigned r_type) {
470 static char const *generic_r_types[] = {
471 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ",
472 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ",
473 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
474 };
475 static char const *x86_64_r_types[] = {
476 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ",
477 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ",
478 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
479 };
480 static char const *arm_r_types[] = {
481 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
482 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ",
483 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
484 };
485 static char const *arm64_r_types[] = {
486 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ",
487 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF",
488 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
489 };
490
491 if (r_type > 0xf){
492 outs() << format("%-7u", r_type) << " ";
493 return;
494 }
495 switch (cputype) {
496 case MachO::CPU_TYPE_I386:
497 outs() << generic_r_types[r_type];
498 break;
499 case MachO::CPU_TYPE_X86_64:
500 outs() << x86_64_r_types[r_type];
501 break;
502 case MachO::CPU_TYPE_ARM:
503 outs() << arm_r_types[r_type];
504 break;
505 case MachO::CPU_TYPE_ARM64:
506 outs() << arm64_r_types[r_type];
507 break;
508 default:
509 outs() << format("%-7u ", r_type);
510 }
511 }
512
513 static void PrintRLength(const uint64_t cputype, const unsigned r_type,
514 const unsigned r_length, const bool previous_arm_half){
515 if (cputype == MachO::CPU_TYPE_ARM &&
516 (r_type == llvm::MachO::ARM_RELOC_HALF ||
517 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF ||
518 previous_arm_half == true)) {
519 if ((r_length & 0x1) == 0)
520 outs() << "lo/";
521 else
522 outs() << "hi/";
523 if ((r_length & 0x1) == 0)
524 outs() << "arm ";
525 else
526 outs() << "thm ";
527 } else {
528 switch (r_length) {
529 case 0:
530 outs() << "byte ";
531 break;
532 case 1:
533 outs() << "word ";
534 break;
535 case 2:
536 outs() << "long ";
537 break;
538 case 3:
539 if (cputype == MachO::CPU_TYPE_X86_64)
540 outs() << "quad ";
541 else
542 outs() << format("?(%2d) ", r_length);
543 break;
544 default:
545 outs() << format("?(%2d) ", r_length);
546 }
547 }
548 }
549
550 static void PrintRelocationEntries(const MachOObjectFile *O,
551 const relocation_iterator Begin,
552 const relocation_iterator End,
553 const uint64_t cputype,
554 const bool verbose) {
555 const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
556 bool previous_arm_half = false;
557 bool previous_sectdiff = false;
558 uint32_t sectdiff_r_type = 0;
559
560 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
561 const DataRefImpl Rel = Reloc->getRawDataRefImpl();
562 const MachO::any_relocation_info RE = O->getRelocation(Rel);
563 const unsigned r_type = O->getAnyRelocationType(RE);
564 const bool r_scattered = O->isRelocationScattered(RE);
565 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
566 const unsigned r_length = O->getAnyRelocationLength(RE);
567 const unsigned r_address = O->getAnyRelocationAddress(RE);
568 const bool r_extern = (r_scattered ? false :
569 O->getPlainRelocationExternal(RE));
570 const uint32_t r_value = (r_scattered ?
571 O->getScatteredRelocationValue(RE) : 0);
572 const unsigned r_symbolnum = (r_scattered ? 0 :
573 O->getPlainRelocationSymbolNum(RE));
574
575 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
576 if (verbose) {
577 // scattered: address
578 if ((cputype == MachO::CPU_TYPE_I386 &&
579 r_type == llvm::MachO::GENERIC_RELOC_PAIR) ||
580 (cputype == MachO::CPU_TYPE_ARM &&
581 r_type == llvm::MachO::ARM_RELOC_PAIR))
582 outs() << " ";
583 else
584 outs() << format("%08x ", (unsigned int)r_address);
585
586 // scattered: pcrel
587 if (r_pcrel)
588 outs() << "True ";
589 else
590 outs() << "False ";
591
592 // scattered: length
593 PrintRLength(cputype, r_type, r_length, previous_arm_half);
594
595 // scattered: extern & type
596 outs() << "n/a ";
597 PrintRType(cputype, r_type);
598
599 // scattered: scattered & value
600 outs() << format("True 0x%08x", (unsigned int)r_value);
601 if (previous_sectdiff == false) {
602 if ((cputype == MachO::CPU_TYPE_ARM &&
603 r_type == llvm::MachO::ARM_RELOC_PAIR))
604 outs() << format(" half = 0x%04x ", (unsigned int)r_address);
605 }
606 else if (cputype == MachO::CPU_TYPE_ARM &&
607 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)
608 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
609 if ((cputype == MachO::CPU_TYPE_I386 &&
610 (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF ||
611 r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
612 (cputype == MachO::CPU_TYPE_ARM &&
613 (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF ||
614 sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF ||
615 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) {
616 previous_sectdiff = true;
617 sectdiff_r_type = r_type;
618 }
619 else {
620 previous_sectdiff = false;
621 sectdiff_r_type = 0;
622 }
623 if (cputype == MachO::CPU_TYPE_ARM &&
624 (r_type == llvm::MachO::ARM_RELOC_HALF ||
625 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
626 previous_arm_half = true;
627 else
628 previous_arm_half = false;
629 outs() << "\n";
630 }
631 else {
632 // scattered: address pcrel length extern type scattered value
633 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n",
634 (unsigned int)r_address, r_pcrel, r_length, r_type,
635 (unsigned int)r_value);
636 }
637 }
638 else {
639 if (verbose) {
640 // plain: address
641 if (cputype == MachO::CPU_TYPE_ARM &&
642 r_type == llvm::MachO::ARM_RELOC_PAIR)
643 outs() << " ";
644 else
645 outs() << format("%08x ", (unsigned int)r_address);
646
647 // plain: pcrel
648 if (r_pcrel)
649 outs() << "True ";
650 else
651 outs() << "False ";
652
653 // plain: length
654 PrintRLength(cputype, r_type, r_length, previous_arm_half);
655
656 if (r_extern) {
657 // plain: extern & type & scattered
658 outs() << "True ";
659 PrintRType(cputype, r_type);
660 outs() << "False ";
661
662 // plain: symbolnum/value
663 if (r_symbolnum > Symtab.nsyms)
664 outs() << format("?(%d)\n", r_symbolnum);
665 else {
666 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
667 Expected SymNameNext = Symbol.getName();
668 const char *name = NULL;
669 if (SymNameNext)
670 name = SymNameNext->data();
671 if (name == NULL)
672 outs() << format("?(%d)\n", r_symbolnum);
673 else
674 outs() << name << "\n";
675 }
676 }
677 else {
678 // plain: extern & type & scattered
679 outs() << "False ";
680 PrintRType(cputype, r_type);
681 outs() << "False ";
682
683 // plain: symbolnum/value
684 if (cputype == MachO::CPU_TYPE_ARM &&
685 r_type == llvm::MachO::ARM_RELOC_PAIR)
686 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
687 else if (cputype == MachO::CPU_TYPE_ARM64 &&
688 r_type == llvm::MachO::ARM64_RELOC_ADDEND)
689 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
690 else {
691 outs() << format("%d ", r_symbolnum);
692 if (r_symbolnum == llvm::MachO::R_ABS)
693 outs() << "R_ABS\n";
694 else {
695 // in this case, r_symbolnum is actually a 1-based section number
696 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
697 if (r_symbolnum > 0 && r_symbolnum <= nsects) {
698 llvm::object::DataRefImpl DRI;
699 DRI.d.a = r_symbolnum-1;
700 StringRef SegName = O->getSectionFinalSegmentName(DRI);
701 StringRef SectName;
702 if (O->getSectionName(DRI, SectName))
703 outs() << "(?,?)\n";
704 else
705 outs() << "(" << SegName << "," << SectName << ")\n";
706 }
707 else {
708 outs() << "(?,?)\n";
709 }
710 }
711 }
712 }
713 if (cputype == MachO::CPU_TYPE_ARM &&
714 (r_type == llvm::MachO::ARM_RELOC_HALF ||
715 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
716 previous_arm_half = true;
717 else
718 previous_arm_half = false;
719 }
720 else {
721 // plain: address pcrel length extern type scattered symbolnum/section
722 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n",
723 (unsigned int)r_address, r_pcrel, r_length, r_extern,
724 r_type, r_symbolnum);
725 }
726 }
727 }
728 }
729
730 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
731 const uint64_t cputype = O->getHeader().cputype;
732 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
733 if (Dysymtab.nextrel != 0) {
734 outs() << "External relocation information " << Dysymtab.nextrel
735 << " entries";
736 outs() << "\naddress pcrel length extern type scattered "
737 "symbolnum/value\n";
738 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
739 verbose);
740 }
741 if (Dysymtab.nlocrel != 0) {
742 outs() << format("Local relocation information %u entries",
743 Dysymtab.nlocrel);
744 outs() << "\naddress pcrel length extern type scattered "
745 "symbolnum/value\n";
746 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
747 verbose);
748 }
749 for (const auto &Load : O->load_commands()) {
750 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
751 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
752 for (unsigned J = 0; J < Seg.nsects; ++J) {
753 const MachO::section_64 Sec = O->getSection64(Load, J);
754 if (Sec.nreloc != 0) {
755 DataRefImpl DRI;
756 DRI.d.a = J;
757 const StringRef SegName = O->getSectionFinalSegmentName(DRI);
758 StringRef SectName;
759 if (O->getSectionName(DRI, SectName))
760 outs() << "Relocation information (" << SegName << ",?) "
761 << format("%u entries", Sec.nreloc);
762 else
763 outs() << "Relocation information (" << SegName << ","
764 << SectName << format(") %u entries", Sec.nreloc);
765 outs() << "\naddress pcrel length extern type scattered "
766 "symbolnum/value\n";
767 PrintRelocationEntries(O, O->section_rel_begin(DRI),
768 O->section_rel_end(DRI), cputype, verbose);
769 }
770 }
771 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
772 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
773 for (unsigned J = 0; J < Seg.nsects; ++J) {
774 const MachO::section Sec = O->getSection(Load, J);
775 if (Sec.nreloc != 0) {
776 DataRefImpl DRI;
777 DRI.d.a = J;
778 const StringRef SegName = O->getSectionFinalSegmentName(DRI);
779 StringRef SectName;
780 if (O->getSectionName(DRI, SectName))
781 outs() << "Relocation information (" << SegName << ",?) "
782 << format("%u entries", Sec.nreloc);
783 else
784 outs() << "Relocation information (" << SegName << ","
785 << SectName << format(") %u entries", Sec.nreloc);
786 outs() << "\naddress pcrel length extern type scattered "
787 "symbolnum/value\n";
788 PrintRelocationEntries(O, O->section_rel_begin(DRI),
789 O->section_rel_end(DRI), cputype, verbose);
463790 }
464791 }
465792 }
12201547 // If we are doing some processing here on the Mach-O file print the header
12211548 // info. And don't print it otherwise like in the case of printing the
12221549 // UniversalHeaders or ArchiveHeaders.
1223 if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable ||
1224 LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
1225 DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
1550 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
1551 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
1552 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData ||
1553 (FilterSections.size() != 0)) {
12261554 if (!NoLeadingHeaders) {
12271555 outs() << Name;
12281556 if (!ArchiveMemberName.empty())
12661594 if (LinkOptHints)
12671595 PrintLinkOptHints(MachOOF);
12681596 if (Relocations)
1269 PrintRelocations(MachOOF);
1597 PrintRelocations(MachOOF, !NonVerbose);
12701598 if (SectionHeaders)
12711599 PrintSectionHeaders(MachOOF);
12721600 if (SectionContents)