Changeset 74844 in vbox for trunk/src/VBox/Runtime/common/ldr/ldrMachO.cpp
- Timestamp:
- Oct 15, 2018 12:51:52 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/ldr/ldrMachO.cpp
r74760 r74844 81 81 * Define RTLDRMODMACHO_STRICT to enabled strict checks in RTLDRMODMACHO. */ 82 82 #define RTLDRMODMACHO_STRICT 1 83 #define RTLDRMODMACHO_STRICT2 83 84 84 85 /** @def RTLDRMODMACHO_ASSERT … … 98 99 # define RTLDRMODMACHO_CHECK_RETURN(expr, rc) AssertReturn(expr, rc) 99 100 #else 100 # define RTLDRMODMACHO_CHECK_RETURN(expr, rc) do { if ( !(expr)) { return (rc); }} while (0)101 # define RTLDRMODMACHO_CHECK_RETURN(expr, rc) do { if (RT_LIKELY(expr)) {/* likely */ } else return (rc); } while (0) 101 102 #endif 102 103 … … 132 133 uint32_t cFixups; 133 134 /** The array of fixups. (lazy loaded) */ 134 macho_relocation_info_t *paFixups; 135 macho_relocation_union_t *paFixups; 136 /** Array of virgin data running parallel to paFixups */ 137 PRTUINT64U pauFixupVirginData; 135 138 /** The file offset of the fixups for this section. 136 139 * This is -1 if the section doesn't have any fixups. */ … … 224 227 /** Pointer to the loaded string table. */ 225 228 char *pchStrings; 229 /** Pointer to the dynamic symbol table command if present. */ 230 dysymtab_command_t *pDySymTab; 231 /** The indirect symbol table (size given by pDySymTab->nindirectsymb). 232 * @remarks Host endian. */ 233 uint32_t *paidxIndirectSymbols; 234 /** Dynamic relocations, first pDySymTab->nextrel external relocs followed by 235 * pDySymTab->nlocrel local ones. */ 236 macho_relocation_union_t *paRelocations; 237 /** Array of virgin data running parallel to paRelocations */ 238 PRTUINT64U pauRelocationsVirginData; 226 239 227 240 /** The image UUID, all zeros if not found. */ … … 320 333 321 334 static int kldrModMachOLoadObjSymTab(PRTLDRMODMACHO pThis); 322 static int kldrModMachOLoadFixups(PRTLDRMODMACHO pThis, RTFOFF offFixups, uint32_t cFixups, macho_relocation_info_t **ppaFixups); 323 static int kldrModMachOMapVirginBits(PRTLDRMODMACHO pThis); 335 static int kldrModMachOLoadFixups(PRTLDRMODMACHO pThis, RTFOFF offFixups, uint32_t cFixups, macho_relocation_union_t **ppaFixups); 324 336 325 337 static int kldrModMachODoQuerySymbol32Bit(PRTLDRMODMACHO pThis, const macho_nlist_32_t *paSyms, uint32_t cSyms, const char *pchStrings, … … 337 349 static int kldrModMachOObjDoImports(PRTLDRMODMACHO pThis, RTLDRADDR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser); 338 350 static int kldrModMachOObjDoFixups(PRTLDRMODMACHO pThis, void *pvMapping, RTLDRADDR NewBaseAddress); 339 static int kldrModMachOFixupSectionGeneric32Bit(PRTLDRMODMACHO pThis, uint8_t *pbSectBits, PRTLDRMODMACHOSECT pFixupSect, 340 macho_nlist_32_t *paSyms, uint32_t cSyms, RTLDRADDR NewBaseAddress); 341 static int kldrModMachOFixupSectionAMD64(PRTLDRMODMACHO pThis, uint8_t *pbSectBits, PRTLDRMODMACHOSECT pFixupSect, 342 macho_nlist_64_t *paSyms, uint32_t cSyms, RTLDRADDR NewBaseAddress); 351 static int kldrModMachOApplyFixupsGeneric32Bit(PRTLDRMODMACHO pThis, uint8_t *pbSectBits, size_t cbSectBits, RTLDRADDR uBitsRva, 352 RTLDRADDR uBitsLinkAddr, const macho_relocation_union_t *paFixups, 353 const uint32_t cFixups, PCRTUINT64U const pauVirginData, 354 macho_nlist_32_t *paSyms, uint32_t cSyms, RTLDRADDR NewBaseAddress); 355 static int kldrModMachOApplyFixupsAMD64(PRTLDRMODMACHO pThis, uint8_t *pbSectBits, size_t cbSectBits, RTLDRADDR uBitsRva, 356 const macho_relocation_union_t *paFixups, 357 const uint32_t cFixups, PCRTUINT64U const pauVirginData, 358 macho_nlist_64_t *paSyms, uint32_t cSyms, RTLDRADDR NewBaseAddress); 343 359 344 360 static int kldrModMachOMakeGOT(PRTLDRMODMACHO pThis, void *pvBits, RTLDRADDR NewBaseAddress); … … 549 565 pThis->cSymbols = 0; 550 566 pThis->pvaSymbols = NULL; 567 pThis->pDySymTab = NULL; 568 pThis->paRelocations = NULL; 569 pThis->pauRelocationsVirginData = NULL; 570 pThis->paidxIndirectSymbols = NULL; 551 571 pThis->offStrings = 0; 552 572 pThis->cchStrings = 0; … … 621 641 thread_command_t *pThread; 622 642 symtab_command_t *pSymTab; 643 dysymtab_command_t *pDySymTab; 623 644 uuid_command_t *pUuid; 624 645 } u; 625 const uint64_t cbFile = pRdr->pfnSize(pRdr) - offImage; 646 const uint64_t cbFile = pRdr->pfnSize(pRdr) - offImage; 647 int const fConvertEndian = pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 648 || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE; 626 649 uint32_t cSegments = 0; 627 650 uint32_t cSections = 0; … … 632 655 int cSegmentCommands = 0; 633 656 int cSymbolTabs = 0; 634 int fConvertEndian = pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 635 || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE; 657 uint32_t cSymbols = 0; /* Copy of u.pSymTab->nsyms. */ 658 uint32_t cDySymbolTabs = 0; 659 bool fDySymbolTabWithRelocs = false; 660 uint32_t cSectionsWithRelocs = 0; 636 661 uint8_t uEffFileType = *puEffFileType = pHdr->filetype; 637 662 … … 658 683 cbLeft -= u.pLoadCmd->cmdsize; 659 684 pb += u.pLoadCmd->cmdsize; 685 686 /* 687 * Segment macros for avoiding code duplication. 688 */ 689 /* Validation code shared with the 64-bit variant. */ 690 #define VALIDATE_AND_ADD_SEGMENT(a_cBits) \ 691 do { \ 692 bool fSkipSeg = !strcmp(pSrcSeg->segname, "__DWARF") /* Note: Not for non-object files. */ \ 693 || ( !strcmp(pSrcSeg->segname, "__CTF") /* Their CTF tool did/does weird things, */ \ 694 && pSrcSeg->vmsize == 0) /* overlapping vmaddr and zero vmsize. */ \ 695 || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); \ 696 \ 697 /* MH_DSYM files for MH_OBJECT files must have MH_OBJECT segment translation. */ \ 698 if ( uEffFileType == MH_DSYM \ 699 && cSegmentCommands == 0 \ 700 && pSrcSeg->segname[0] == '\0') \ 701 *puEffFileType = uEffFileType = MH_OBJECT; \ 702 \ 703 RTLDRMODMACHO_CHECK_RETURN( pSrcSeg->filesize == 0 \ 704 || ( pSrcSeg->fileoff <= cbFile \ 705 && (uint64_t)pSrcSeg->fileoff + pSrcSeg->filesize <= cbFile), \ 706 VERR_LDRMACHO_BAD_LOAD_COMMAND); \ 707 RTLDRMODMACHO_CHECK_RETURN( pSrcSeg->filesize <= pSrcSeg->vmsize \ 708 || (fSkipSeg && !strcmp(pSrcSeg->segname, "__CTF") /* see above */), \ 709 VERR_LDRMACHO_BAD_LOAD_COMMAND); \ 710 RTLDRMODMACHO_CHECK_RETURN(!(~pSrcSeg->maxprot & pSrcSeg->initprot), \ 711 VERR_LDRMACHO_BAD_LOAD_COMMAND); \ 712 RTLDRMODMACHO_CHECK_RETURN(!(pSrcSeg->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1)), \ 713 VERR_LDRMACHO_BAD_LOAD_COMMAND); \ 714 RTLDRMODMACHO_CHECK_RETURN( pSrcSeg->nsects * sizeof(section_##a_cBits##_t) \ 715 <= u.pLoadCmd->cmdsize - sizeof(segment_command_##a_cBits##_t), \ 716 VERR_LDRMACHO_BAD_LOAD_COMMAND); \ 717 RTLDRMODMACHO_CHECK_RETURN( uEffFileType != MH_OBJECT \ 718 || cSegmentCommands == 0 \ 719 || ( cSegmentCommands == 1 \ 720 && uEffFileType == MH_OBJECT \ 721 && pHdr->filetype == MH_DSYM \ 722 && fSkipSeg), \ 723 VERR_LDRMACHO_BAD_OBJECT_FILE); \ 724 cSegmentCommands++; \ 725 \ 726 /* Add the segment, if not object file. */ \ 727 if (!fSkipSeg && uEffFileType != MH_OBJECT) \ 728 { \ 729 cbStringPool += RTStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)) + 1; \ 730 cSegments++; \ 731 if (cSegments == 1) /* The link address is set by the first segment. */ \ 732 *pLinkAddress = pSrcSeg->vmaddr; \ 733 } \ 734 } while (0) 735 736 737 /* Validation code shared with the 64-bit variant. */ 738 #define VALIDATE_AND_ADD_SECTION(a_cBits) \ 739 do { \ 740 int fFileBits; \ 741 \ 742 /* validate */ \ 743 if (uEffFileType != MH_OBJECT) \ 744 RTLDRMODMACHO_CHECK_RETURN(!strcmp(pSect->segname, pSrcSeg->segname),\ 745 VERR_LDRMACHO_BAD_SECTION); \ 746 \ 747 switch (pSect->flags & SECTION_TYPE) \ 748 { \ 749 case S_ZEROFILL: \ 750 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \ 751 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \ 752 fFileBits = 0; \ 753 break; \ 754 case S_REGULAR: \ 755 case S_CSTRING_LITERALS: \ 756 case S_COALESCED: \ 757 case S_4BYTE_LITERALS: \ 758 case S_8BYTE_LITERALS: \ 759 case S_16BYTE_LITERALS: \ 760 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \ 761 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \ 762 fFileBits = 1; \ 763 break; \ 764 \ 765 case S_SYMBOL_STUBS: \ 766 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \ 767 /* reserved2 == stub size. 0 has been seen (corecrypto.kext) */ \ 768 RTLDRMODMACHO_CHECK_RETURN(pSect->reserved2 < 64, VERR_LDRMACHO_BAD_SECTION); \ 769 fFileBits = 1; \ 770 break; \ 771 \ 772 case S_NON_LAZY_SYMBOL_POINTERS: \ 773 case S_LAZY_SYMBOL_POINTERS: \ 774 case S_LAZY_DYLIB_SYMBOL_POINTERS: \ 775 /* (reserved 1 = is indirect symbol table index) */ \ 776 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \ 777 Log(("ldrMachO: Can't load because of section flags: %#x\n", pSect->flags & SECTION_TYPE)); \ 778 *pfCanLoad = false; \ 779 fFileBits = -1; /* __DATA.__got in the 64-bit mach_kernel has bits, any things without bits? */ \ 780 break; \ 781 \ 782 case S_MOD_INIT_FUNC_POINTERS: \ 783 /** @todo this requires a query API or flag... (e.g. C++ constructors) */ \ 784 RTLDRMODMACHO_CHECK_RETURN(fOpenFlags & RTLDR_O_FOR_DEBUG, \ 785 VERR_LDRMACHO_UNSUPPORTED_INIT_SECTION); \ 786 RT_FALL_THRU(); \ 787 case S_MOD_TERM_FUNC_POINTERS: \ 788 /** @todo this requires a query API or flag... (e.g. C++ destructors) */ \ 789 RTLDRMODMACHO_CHECK_RETURN(fOpenFlags & RTLDR_O_FOR_DEBUG, \ 790 VERR_LDRMACHO_UNSUPPORTED_TERM_SECTION); \ 791 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \ 792 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \ 793 fFileBits = 1; \ 794 break; /* ignored */ \ 795 \ 796 case S_LITERAL_POINTERS: \ 797 case S_DTRACE_DOF: \ 798 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \ 799 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \ 800 fFileBits = 1; \ 801 break; \ 802 \ 803 case S_INTERPOSING: \ 804 case S_GB_ZEROFILL: \ 805 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_UNSUPPORTED_SECTION); \ 806 \ 807 default: \ 808 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_UNKNOWN_SECTION); \ 809 } \ 810 RTLDRMODMACHO_CHECK_RETURN(!(pSect->flags & ~( S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS \ 811 | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE \ 812 | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC \ 813 | S_ATTR_LOC_RELOC | SECTION_TYPE)), \ 814 VERR_LDRMACHO_BAD_SECTION); \ 815 RTLDRMODMACHO_CHECK_RETURN((pSect->flags & S_ATTR_DEBUG) == (pFirstSect->flags & S_ATTR_DEBUG), \ 816 VERR_LDRMACHO_MIXED_DEBUG_SECTION_FLAGS); \ 817 \ 818 RTLDRMODMACHO_CHECK_RETURN(pSect->addr - pSrcSeg->vmaddr <= pSrcSeg->vmsize, \ 819 VERR_LDRMACHO_BAD_SECTION); \ 820 RTLDRMODMACHO_CHECK_RETURN( pSect->addr - pSrcSeg->vmaddr + pSect->size <= pSrcSeg->vmsize \ 821 || !strcmp(pSrcSeg->segname, "__CTF") /* see above */, \ 822 VERR_LDRMACHO_BAD_SECTION); \ 823 RTLDRMODMACHO_CHECK_RETURN(pSect->align < 31, \ 824 VERR_LDRMACHO_BAD_SECTION); \ 825 /* Workaround for buggy ld64 (or as, llvm, ++) that produces a misaligned __TEXT.__unwind_info. */ \ 826 /* Seen: pSect->align = 4, pSect->addr = 0x5ebe14. Just adjust the alignment down. */ \ 827 if ( ((RT_BIT_32(pSect->align) - UINT32_C(1)) & pSect->addr) \ 828 && pSect->align == 4 \ 829 && strcmp(pSect->sectname, "__unwind_info") == 0) \ 830 pSect->align = 2; \ 831 RTLDRMODMACHO_CHECK_RETURN(!((RT_BIT_32(pSect->align) - UINT32_C(1)) & pSect->addr), \ 832 VERR_LDRMACHO_BAD_SECTION); \ 833 RTLDRMODMACHO_CHECK_RETURN(!((RT_BIT_32(pSect->align) - UINT32_C(1)) & pSrcSeg->vmaddr), \ 834 VERR_LDRMACHO_BAD_SECTION); \ 835 \ 836 /* Adjust the section offset before we check file offset. */ \ 837 offSect = (offSect + RT_BIT_64(pSect->align) - UINT64_C(1)) & ~(RT_BIT_64(pSect->align) - UINT64_C(1)); \ 838 if (pSect->addr) \ 839 { \ 840 RTLDRMODMACHO_CHECK_RETURN(offSect <= pSect->addr - pSrcSeg->vmaddr, VERR_LDRMACHO_BAD_SECTION); \ 841 if (offSect < pSect->addr - pSrcSeg->vmaddr) \ 842 offSect = pSect->addr - pSrcSeg->vmaddr; \ 843 } \ 844 \ 845 if (fFileBits && pSect->offset == 0 && pSrcSeg->fileoff == 0 && pHdr->filetype == MH_DSYM) \ 846 fFileBits = 0; \ 847 if (fFileBits) \ 848 { \ 849 if (uEffFileType != MH_OBJECT) \ 850 { \ 851 RTLDRMODMACHO_CHECK_RETURN(pSect->offset == pSrcSeg->fileoff + offSect, \ 852 VERR_LDRMACHO_NON_CONT_SEG_BITS); \ 853 RTLDRMODMACHO_CHECK_RETURN(pSect->offset - pSrcSeg->fileoff <= pSrcSeg->filesize, \ 854 VERR_LDRMACHO_BAD_SECTION); \ 855 } \ 856 RTLDRMODMACHO_CHECK_RETURN(pSect->offset <= cbFile, \ 857 VERR_LDRMACHO_BAD_SECTION); \ 858 RTLDRMODMACHO_CHECK_RETURN((uint64_t)pSect->offset + pSect->size <= cbFile, \ 859 VERR_LDRMACHO_BAD_SECTION); \ 860 } \ 861 else \ 862 RTLDRMODMACHO_CHECK_RETURN(pSect->offset == 0, VERR_LDRMACHO_BAD_SECTION); \ 863 \ 864 if (!pSect->nreloc) \ 865 RTLDRMODMACHO_CHECK_RETURN(!pSect->reloff, \ 866 VERR_LDRMACHO_BAD_SECTION); \ 867 else \ 868 { \ 869 RTLDRMODMACHO_CHECK_RETURN(pSect->reloff <= cbFile, \ 870 VERR_LDRMACHO_BAD_SECTION); \ 871 RTLDRMODMACHO_CHECK_RETURN( (uint64_t)pSect->reloff \ 872 + (RTFOFF)pSect->nreloc * sizeof(macho_relocation_info_t) \ 873 <= cbFile, \ 874 VERR_LDRMACHO_BAD_SECTION); \ 875 cSectionsWithRelocs++; \ 876 } \ 877 \ 878 /* Validate against file type (pointless?) and count the section, for object files add segment. */ \ 879 switch (uEffFileType) \ 880 { \ 881 case MH_OBJECT: \ 882 if ( !(pSect->flags & S_ATTR_DEBUG) \ 883 && strcmp(pSect->segname, "__DWARF")) \ 884 { \ 885 cbStringPool += RTStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; \ 886 cbStringPool += RTStrNLen(&pSect->sectname[0], sizeof(pSect->sectname)) + 1; \ 887 cSegments++; \ 888 if (cSegments == 1) /* The link address is set by the first segment. */ \ 889 *pLinkAddress = pSect->addr; \ 890 } \ 891 RT_FALL_THRU(); \ 892 case MH_EXECUTE: \ 893 case MH_DYLIB: \ 894 case MH_BUNDLE: \ 895 case MH_DSYM: \ 896 case MH_KEXT_BUNDLE: \ 897 cSections++; \ 898 break; \ 899 default: \ 900 RTLDRMODMACHO_FAILED_RETURN(VERR_INVALID_PARAMETER); \ 901 } \ 902 \ 903 /* Advance the section offset, since we're also aligning it. */ \ 904 offSect += pSect->size; \ 905 } while (0) /* VALIDATE_AND_ADD_SECTION */ 660 906 661 907 /* … … 675 921 RTLDRMODMACHO_CHECK_RETURN(u.pLoadCmd->cmdsize >= sizeof(segment_command_32_t), VERR_LDRMACHO_BAD_LOAD_COMMAND); 676 922 RTLDRMODMACHO_CHECK_RETURN( pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 677 || pHdr->magic == IMAGE_MACHO32_SIGNATURE, VERR_LDRMACHO_BIT_MIX);923 || pHdr->magic == IMAGE_MACHO32_SIGNATURE, VERR_LDRMACHO_BIT_MIX); 678 924 if (fConvertEndian) 679 925 { … … 688 934 } 689 935 690 /* Validation code shared with the 64-bit variant. */691 #define VALIDATE_AND_ADD_SEGMENT(a_cBits) \692 do { \693 bool fSkipSeg = !strcmp(pSrcSeg->segname, "__DWARF") /* Note: Not for non-object files. */ \694 || ( !strcmp(pSrcSeg->segname, "__CTF") /* Their CTF tool did/does weird things, */ \695 && pSrcSeg->vmsize == 0) /* overlapping vmaddr and zero vmsize. */ \696 || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); \697 \698 /* MH_DSYM files for MH_OBJECT files must have MH_OBJECT segment translation. */ \699 if ( uEffFileType == MH_DSYM \700 && cSegmentCommands == 0 \701 && pSrcSeg->segname[0] == '\0') \702 *puEffFileType = uEffFileType = MH_OBJECT; \703 \704 RTLDRMODMACHO_CHECK_RETURN( pSrcSeg->filesize == 0 \705 || ( pSrcSeg->fileoff <= cbFile \706 && (uint64_t)pSrcSeg->fileoff + pSrcSeg->filesize <= cbFile), \707 VERR_LDRMACHO_BAD_LOAD_COMMAND); \708 RTLDRMODMACHO_CHECK_RETURN( pSrcSeg->filesize <= pSrcSeg->vmsize \709 || (fSkipSeg && !strcmp(pSrcSeg->segname, "__CTF") /* see above */), \710 VERR_LDRMACHO_BAD_LOAD_COMMAND); \711 RTLDRMODMACHO_CHECK_RETURN(!(~pSrcSeg->maxprot & pSrcSeg->initprot), \712 VERR_LDRMACHO_BAD_LOAD_COMMAND); \713 RTLDRMODMACHO_CHECK_RETURN(!(pSrcSeg->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1)), \714 VERR_LDRMACHO_BAD_LOAD_COMMAND); \715 RTLDRMODMACHO_CHECK_RETURN( pSrcSeg->nsects * sizeof(section_##a_cBits##_t) \716 <= u.pLoadCmd->cmdsize - sizeof(segment_command_##a_cBits##_t), \717 VERR_LDRMACHO_BAD_LOAD_COMMAND); \718 RTLDRMODMACHO_CHECK_RETURN( uEffFileType != MH_OBJECT \719 || cSegmentCommands == 0 \720 || ( cSegmentCommands == 1 \721 && uEffFileType == MH_OBJECT \722 && pHdr->filetype == MH_DSYM \723 && fSkipSeg), \724 VERR_LDRMACHO_BAD_OBJECT_FILE); \725 cSegmentCommands++; \726 \727 /* Add the segment, if not object file. */ \728 if (!fSkipSeg && uEffFileType != MH_OBJECT) \729 { \730 cbStringPool += RTStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)) + 1; \731 cSegments++; \732 if (cSegments == 1) /* The link address is set by the first segment. */ \733 *pLinkAddress = pSrcSeg->vmaddr; \734 } \735 } while (0)736 737 936 VALIDATE_AND_ADD_SEGMENT(32); 937 738 938 739 939 /* … … 757 957 } 758 958 759 /* Validation code shared with the 64-bit variant. */760 #define VALIDATE_AND_ADD_SECTION(a_cBits) \761 do { \762 int fFileBits; \763 \764 /* validate */ \765 if (uEffFileType != MH_OBJECT) \766 RTLDRMODMACHO_CHECK_RETURN(!strcmp(pSect->segname, pSrcSeg->segname),\767 VERR_LDRMACHO_BAD_SECTION); \768 \769 switch (pSect->flags & SECTION_TYPE) \770 { \771 case S_ZEROFILL: \772 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \773 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \774 fFileBits = 0; \775 break; \776 case S_REGULAR: \777 case S_CSTRING_LITERALS: \778 case S_COALESCED: \779 case S_4BYTE_LITERALS: \780 case S_8BYTE_LITERALS: \781 case S_16BYTE_LITERALS: \782 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \783 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \784 fFileBits = 1; \785 break; \786 \787 case S_SYMBOL_STUBS: \788 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \789 /* reserved2 == stub size. 0 has been seen (corecrypto.kext) */ \790 RTLDRMODMACHO_CHECK_RETURN(pSect->reserved2 < 64, VERR_LDRMACHO_BAD_SECTION); \791 fFileBits = 1; \792 break; \793 \794 case S_NON_LAZY_SYMBOL_POINTERS: \795 case S_LAZY_SYMBOL_POINTERS: \796 case S_LAZY_DYLIB_SYMBOL_POINTERS: \797 /* (reserved 1 = is indirect symbol table index) */ \798 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \799 *pfCanLoad = false; \800 fFileBits = -1; /* __DATA.__got in the 64-bit mach_kernel has bits, any things without bits? */ \801 break; \802 \803 case S_MOD_INIT_FUNC_POINTERS: \804 /** @todo this requires a query API or flag... (e.g. C++ constructors) */ \805 RTLDRMODMACHO_CHECK_RETURN(fOpenFlags & RTLDR_O_FOR_DEBUG, \806 VERR_LDRMACHO_UNSUPPORTED_INIT_SECTION); \807 RT_FALL_THRU(); \808 case S_MOD_TERM_FUNC_POINTERS: \809 /** @todo this requires a query API or flag... (e.g. C++ destructors) */ \810 RTLDRMODMACHO_CHECK_RETURN(fOpenFlags & RTLDR_O_FOR_DEBUG, \811 VERR_LDRMACHO_UNSUPPORTED_TERM_SECTION); \812 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \813 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \814 fFileBits = 1; \815 break; /* ignored */ \816 \817 case S_LITERAL_POINTERS: \818 case S_DTRACE_DOF: \819 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, VERR_LDRMACHO_BAD_SECTION); \820 RTLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, VERR_LDRMACHO_BAD_SECTION); \821 fFileBits = 1; \822 break; \823 \824 case S_INTERPOSING: \825 case S_GB_ZEROFILL: \826 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_UNSUPPORTED_SECTION); \827 \828 default: \829 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_UNKNOWN_SECTION); \830 } \831 RTLDRMODMACHO_CHECK_RETURN(!(pSect->flags & ~( S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS \832 | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE \833 | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC \834 | S_ATTR_LOC_RELOC | SECTION_TYPE)), \835 VERR_LDRMACHO_BAD_SECTION); \836 RTLDRMODMACHO_CHECK_RETURN((pSect->flags & S_ATTR_DEBUG) == (pFirstSect->flags & S_ATTR_DEBUG), \837 VERR_LDRMACHO_MIXED_DEBUG_SECTION_FLAGS); \838 \839 RTLDRMODMACHO_CHECK_RETURN(pSect->addr - pSrcSeg->vmaddr <= pSrcSeg->vmsize, \840 VERR_LDRMACHO_BAD_SECTION); \841 RTLDRMODMACHO_CHECK_RETURN( pSect->addr - pSrcSeg->vmaddr + pSect->size <= pSrcSeg->vmsize \842 || !strcmp(pSrcSeg->segname, "__CTF") /* see above */, \843 VERR_LDRMACHO_BAD_SECTION); \844 RTLDRMODMACHO_CHECK_RETURN(pSect->align < 31, \845 VERR_LDRMACHO_BAD_SECTION); \846 /* Workaround for buggy ld64 (or as, llvm, ++) that produces a misaligned __TEXT.__unwind_info. */ \847 /* Seen: pSect->align = 4, pSect->addr = 0x5ebe14. Just adjust the alignment down. */ \848 if ( ((RT_BIT_32(pSect->align) - UINT32_C(1)) & pSect->addr) \849 && pSect->align == 4 \850 && strcmp(pSect->sectname, "__unwind_info") == 0) \851 pSect->align = 2; \852 RTLDRMODMACHO_CHECK_RETURN(!((RT_BIT_32(pSect->align) - UINT32_C(1)) & pSect->addr), \853 VERR_LDRMACHO_BAD_SECTION); \854 RTLDRMODMACHO_CHECK_RETURN(!((RT_BIT_32(pSect->align) - UINT32_C(1)) & pSrcSeg->vmaddr), \855 VERR_LDRMACHO_BAD_SECTION); \856 \857 /* Adjust the section offset before we check file offset. */ \858 offSect = (offSect + RT_BIT_64(pSect->align) - UINT64_C(1)) & ~(RT_BIT_64(pSect->align) - UINT64_C(1)); \859 if (pSect->addr) \860 { \861 RTLDRMODMACHO_CHECK_RETURN(offSect <= pSect->addr - pSrcSeg->vmaddr, VERR_LDRMACHO_BAD_SECTION); \862 if (offSect < pSect->addr - pSrcSeg->vmaddr) \863 offSect = pSect->addr - pSrcSeg->vmaddr; \864 } \865 \866 if (fFileBits && pSect->offset == 0 && pSrcSeg->fileoff == 0 && pHdr->filetype == MH_DSYM) \867 fFileBits = 0; \868 if (fFileBits) \869 { \870 if (uEffFileType != MH_OBJECT) \871 { \872 RTLDRMODMACHO_CHECK_RETURN(pSect->offset == pSrcSeg->fileoff + offSect, \873 VERR_LDRMACHO_NON_CONT_SEG_BITS); \874 RTLDRMODMACHO_CHECK_RETURN(pSect->offset - pSrcSeg->fileoff <= pSrcSeg->filesize, \875 VERR_LDRMACHO_BAD_SECTION); \876 } \877 RTLDRMODMACHO_CHECK_RETURN(pSect->offset <= cbFile, \878 VERR_LDRMACHO_BAD_SECTION); \879 RTLDRMODMACHO_CHECK_RETURN((uint64_t)pSect->offset + pSect->size <= cbFile, \880 VERR_LDRMACHO_BAD_SECTION); \881 } \882 else \883 RTLDRMODMACHO_CHECK_RETURN(pSect->offset == 0, VERR_LDRMACHO_BAD_SECTION); \884 \885 if (!pSect->nreloc) \886 RTLDRMODMACHO_CHECK_RETURN(!pSect->reloff, \887 VERR_LDRMACHO_BAD_SECTION); \888 else \889 { \890 RTLDRMODMACHO_CHECK_RETURN(pSect->reloff <= cbFile, \891 VERR_LDRMACHO_BAD_SECTION); \892 RTLDRMODMACHO_CHECK_RETURN( (uint64_t)pSect->reloff \893 + (RTFOFF)pSect->nreloc * sizeof(macho_relocation_info_t) \894 <= cbFile, \895 VERR_LDRMACHO_BAD_SECTION); \896 } \897 \898 /* Validate against file type (pointless?) and count the section, for object files add segment. */ \899 switch (uEffFileType) \900 { \901 case MH_OBJECT: \902 if ( !(pSect->flags & S_ATTR_DEBUG) \903 && strcmp(pSect->segname, "__DWARF")) \904 { \905 cbStringPool += RTStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; \906 cbStringPool += RTStrNLen(&pSect->sectname[0], sizeof(pSect->sectname)) + 1; \907 cSegments++; \908 if (cSegments == 1) /* The link address is set by the first segment. */ \909 *pLinkAddress = pSect->addr; \910 } \911 RT_FALL_THRU(); \912 case MH_EXECUTE: \913 case MH_DYLIB: \914 case MH_BUNDLE: \915 case MH_DSYM: \916 case MH_KEXT_BUNDLE: \917 cSections++; \918 break; \919 default: \920 RTLDRMODMACHO_FAILED_RETURN(VERR_INVALID_PARAMETER); \921 } \922 \923 /* Advance the section offset, since we're also aligning it. */ \924 offSect += pSect->size; \925 } while (0) /* VALIDATE_AND_ADD_SECTION */926 927 959 VALIDATE_AND_ADD_SECTION(32); 928 960 … … 944 976 RTLDRMODMACHO_CHECK_RETURN(u.pLoadCmd->cmdsize >= sizeof(segment_command_64_t), VERR_LDRMACHO_BAD_LOAD_COMMAND); 945 977 RTLDRMODMACHO_CHECK_RETURN( pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE 946 || pHdr->magic == IMAGE_MACHO64_SIGNATURE, VERR_LDRMACHO_BIT_MIX);978 || pHdr->magic == IMAGE_MACHO64_SIGNATURE, VERR_LDRMACHO_BIT_MIX); 947 979 if (fConvertEndian) 948 980 { … … 1009 1041 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_BAD_LOAD_COMMAND); 1010 1042 1011 /* only one string in objects, please. */1043 /* Only one object table, please. */ 1012 1044 cSymbolTabs++; 1013 if ( uEffFileType == MH_OBJECT 1014 && cSymbolTabs != 1) 1045 if (cSymbolTabs != 1) 1015 1046 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_BAD_OBJECT_FILE); 1047 1048 cSymbols = u.pSymTab->nsyms; 1016 1049 break; 1017 1050 } 1018 1051 1019 1052 case LC_DYSYMTAB: 1020 /** @todo deal with this! */ 1053 { 1054 if (pHdr->filetype == MH_OBJECT) 1055 RTLDRMODMACHO_FAILED_RETURN(RTErrInfoSet(pErrInfo, VERR_LDRMACHO_BAD_OBJECT_FILE, 1056 "Not expecting LC_DYSYMTAB in MH_OBJECT")); 1057 if (fConvertEndian) 1058 { 1059 u.pDySymTab->ilocalsym = RT_BSWAP_U32(u.pDySymTab->ilocalsym); 1060 u.pDySymTab->nlocalsym = RT_BSWAP_U32(u.pDySymTab->nlocalsym); 1061 u.pDySymTab->iextdefsym = RT_BSWAP_U32(u.pDySymTab->iextdefsym); 1062 u.pDySymTab->nextdefsym = RT_BSWAP_U32(u.pDySymTab->nextdefsym); 1063 u.pDySymTab->iundefsym = RT_BSWAP_U32(u.pDySymTab->iundefsym); 1064 u.pDySymTab->nundefsym = RT_BSWAP_U32(u.pDySymTab->nundefsym); 1065 u.pDySymTab->tocoff = RT_BSWAP_U32(u.pDySymTab->tocoff); 1066 u.pDySymTab->ntoc = RT_BSWAP_U32(u.pDySymTab->ntoc); 1067 u.pDySymTab->modtaboff = RT_BSWAP_U32(u.pDySymTab->modtaboff); 1068 u.pDySymTab->nmodtab = RT_BSWAP_U32(u.pDySymTab->nmodtab); 1069 u.pDySymTab->extrefsymoff = RT_BSWAP_U32(u.pDySymTab->extrefsymoff); 1070 u.pDySymTab->nextrefsym = RT_BSWAP_U32(u.pDySymTab->nextrefsym); 1071 u.pDySymTab->indirectsymboff = RT_BSWAP_U32(u.pDySymTab->indirectsymboff); 1072 u.pDySymTab->nindirectsymb = RT_BSWAP_U32(u.pDySymTab->nindirectsymb); 1073 u.pDySymTab->extreloff = RT_BSWAP_U32(u.pDySymTab->extreloff); 1074 u.pDySymTab->nextrel = RT_BSWAP_U32(u.pDySymTab->nextrel); 1075 u.pDySymTab->locreloff = RT_BSWAP_U32(u.pDySymTab->locreloff); 1076 u.pDySymTab->nlocrel = RT_BSWAP_U32(u.pDySymTab->nlocrel); 1077 } 1078 1079 /* verify */ 1080 RTLDRMODMACHO_CHECK_RETURN((uint64_t)u.pDySymTab->ilocalsym + u.pDySymTab->nlocalsym <= cSymbols, 1081 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1082 "ilocalsym=%#x + nlocalsym=%#x vs cSymbols=%#x", 1083 u.pDySymTab->ilocalsym, u.pDySymTab->nlocalsym, cSymbols)); 1084 RTLDRMODMACHO_CHECK_RETURN((uint64_t)u.pDySymTab->iextdefsym + u.pDySymTab->nextdefsym <= cSymbols, 1085 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1086 "iextdefsym=%#x + nextdefsym=%#x vs cSymbols=%#x", 1087 u.pDySymTab->iextdefsym, u.pDySymTab->nextdefsym, cSymbols)); 1088 RTLDRMODMACHO_CHECK_RETURN((uint64_t)u.pDySymTab->iundefsym + u.pDySymTab->nundefsym <= cSymbols, 1089 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1090 "iundefsym=%#x + nundefsym=%#x vs cSymbols=%#x", 1091 u.pDySymTab->iundefsym, u.pDySymTab->nundefsym, cSymbols)); 1092 RTLDRMODMACHO_CHECK_RETURN( (uint64_t)u.pDySymTab->tocoff + u.pDySymTab->ntoc * sizeof(dylib_table_of_contents_t) 1093 <= cbFile, 1094 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1095 "tocoff=%#x + ntoc=%#x vs cbFile=%#RX64", 1096 u.pDySymTab->tocoff, u.pDySymTab->ntoc, cbFile)); 1097 const uint32_t cbModTabEntry = pHdr->magic == IMAGE_MACHO32_SIGNATURE 1098 || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 1099 ? sizeof(dylib_module_32_t) : sizeof(dylib_module_64_t); 1100 RTLDRMODMACHO_CHECK_RETURN((uint64_t)u.pDySymTab->modtaboff + u.pDySymTab->nmodtab * cbModTabEntry <= cbFile, 1101 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1102 "modtaboff=%#x + nmodtab=%#x cbModTabEntry=%#x vs cbFile=%#RX64", 1103 u.pDySymTab->modtaboff, u.pDySymTab->nmodtab, cbModTabEntry, cbFile)); 1104 RTLDRMODMACHO_CHECK_RETURN( (uint64_t)u.pDySymTab->extrefsymoff + u.pDySymTab->nextrefsym * sizeof(dylib_reference_t) 1105 <= cbFile, 1106 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1107 "extrefsymoff=%#x + nextrefsym=%#x vs cbFile=%#RX64", 1108 u.pDySymTab->extrefsymoff, u.pDySymTab->nextrefsym, cbFile)); 1109 RTLDRMODMACHO_CHECK_RETURN( (uint64_t)u.pDySymTab->indirectsymboff + u.pDySymTab->nindirectsymb * sizeof(uint32_t) 1110 <= cbFile, 1111 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1112 "indirectsymboff=%#x + nindirectsymb=%#x vs cbFile=%#RX64", 1113 u.pDySymTab->indirectsymboff, u.pDySymTab->nindirectsymb, cbFile)); 1114 RTLDRMODMACHO_CHECK_RETURN((uint64_t)u.pDySymTab->extreloff + u.pDySymTab->nextrel * sizeof(macho_relocation_info_t) <= cbFile, 1115 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1116 "extreloff=%#x + nextrel=%#x vs cbFile=%#RX64", 1117 u.pDySymTab->extreloff, u.pDySymTab->nextrel, cbFile)); 1118 RTLDRMODMACHO_CHECK_RETURN((uint64_t)u.pDySymTab->locreloff + u.pDySymTab->nlocrel * sizeof(macho_relocation_info_t) <= cbFile, 1119 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1120 "locreloff=%#x + nlocrel=%#x vs cbFile=%#RX64", 1121 u.pDySymTab->locreloff, u.pDySymTab->nlocrel, cbFile)); 1122 cDySymbolTabs++; 1123 fDySymbolTabWithRelocs |= (u.pDySymTab->nlocrel + u.pDySymTab->nextrel) != 0; 1021 1124 break; 1125 } 1022 1126 1023 1127 case LC_THREAD: … … 1098 1202 RTLDRMODMACHO_FAILED_RETURN(RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_UNSUPPORTED_LOAD_COMMAND, 1099 1203 "cmd=%#x", u.pLoadCmd->cmd)); 1204 Log(("ldrMachO: Can't load because of load command: %#x\n", u.pLoadCmd->cmd)); 1100 1205 *pfCanLoad = false; 1101 1206 break; … … 1128 1233 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_BAD_LOAD_COMMAND); 1129 1234 1235 RTLDRMODMACHO_CHECK_RETURN(cDySymbolTabs <= 1, 1236 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1237 "More than one LC_DYSYMTAB command: %u", cDySymbolTabs)); 1238 RTLDRMODMACHO_CHECK_RETURN(!fDySymbolTabWithRelocs || cSectionsWithRelocs == 0, 1239 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1240 "Have relocations both in sections and LC_DYSYMTAB")); 1241 if (!cSegments) 1242 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_BAD_OBJECT_FILE); 1243 1130 1244 switch (uEffFileType) 1131 1245 { 1132 1246 case MH_OBJECT: 1133 1247 case MH_EXECUTE: 1248 RTLDRMODMACHO_CHECK_RETURN(!fDySymbolTabWithRelocs, 1249 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1250 "Did not expect relocations in LC_DYSYMTAB (file type %u)", uEffFileType)); 1251 break; 1252 1134 1253 case MH_DYLIB: 1135 1254 case MH_BUNDLE: 1255 case MH_KEXT_BUNDLE: 1256 RTLDRMODMACHO_CHECK_RETURN(cDySymbolTabs > 0, 1257 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1258 "No LC_DYSYMTAB command (file type %u)", uEffFileType)); 1259 RTLDRMODMACHO_CHECK_RETURN(fDySymbolTabWithRelocs || cSectionsWithRelocs == 0, 1260 RTErrInfoSetF(pErrInfo, VERR_LDRMACHO_BAD_LOAD_COMMAND, 1261 "Expected relocations in LC_DYSYMTAB (file type %u)", uEffFileType)); 1262 break; 1263 1136 1264 case MH_DSYM: 1137 case MH_KEXT_BUNDLE:1138 if (!cSegments)1139 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_BAD_OBJECT_FILE);1140 1265 break; 1141 1266 } 1142 1267 1268 /* 1269 * Set return values and return. 1270 */ 1143 1271 *pcSegments = cSegments; 1144 1272 *pcSections = cSections; … … 1201 1329 /* Adds a segment, used by the macro below and thus shared with the 64-bit segment variant. */ 1202 1330 #define NEW_SEGMENT(a_cBits, a_achName1, a_fObjFile, a_achName2, a_SegAddr, a_cbSeg, a_fFileBits, a_offFile, a_cbFile) \ 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1331 do { \ 1332 pDstSeg->SegInfo.pszName = pbStringPool; \ 1333 pDstSeg->SegInfo.cchName = (uint32_t)RTStrNLen(a_achName1, sizeof(a_achName1)); \ 1334 memcpy(pbStringPool, a_achName1, pDstSeg->SegInfo.cchName); \ 1335 pbStringPool += pDstSeg->SegInfo.cchName; \ 1336 if (a_fObjFile) \ 1337 { /* MH_OBJECT: Add '.sectname' - sections aren't sorted by segments. */ \ 1338 size_t cchName2 = RTStrNLen(a_achName2, sizeof(a_achName2)); \ 1339 *pbStringPool++ = '.'; \ 1340 memcpy(pbStringPool, a_achName2, cchName2); \ 1341 pbStringPool += cchName2; \ 1342 pDstSeg->SegInfo.cchName += (uint32_t)cchName2; \ 1343 } \ 1344 *pbStringPool++ = '\0'; \ 1345 pDstSeg->SegInfo.SelFlat = 0; \ 1346 pDstSeg->SegInfo.Sel16bit = 0; \ 1347 pDstSeg->SegInfo.fFlags = 0; \ 1348 pDstSeg->SegInfo.fProt = RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC; /** @todo fixme! */ \ 1349 pDstSeg->SegInfo.cb = (a_cbSeg); \ 1350 pDstSeg->SegInfo.Alignment = 1; /* updated while parsing sections. */ \ 1351 pDstSeg->SegInfo.LinkAddress = (a_SegAddr); \ 1352 if (a_fFileBits) \ 1353 { \ 1354 pDstSeg->SegInfo.offFile = (RTFOFF)((a_offFile) + pThis->offImage); \ 1355 pDstSeg->SegInfo.cbFile = (RTFOFF)(a_cbFile); \ 1356 } \ 1357 else \ 1358 { \ 1359 pDstSeg->SegInfo.offFile = -1; \ 1360 pDstSeg->SegInfo.cbFile = -1; \ 1361 } \ 1362 pDstSeg->SegInfo.RVA = (a_SegAddr) - pThis->LinkAddress; \ 1363 pDstSeg->SegInfo.cbMapped = 0; \ 1364 \ 1365 pDstSeg->iOrgSegNo = (uint32_t)(pDstSeg - &pThis->aSegments[0]); \ 1366 pDstSeg->cSections = 0; \ 1367 pDstSeg->paSections = pSectExtra; \ 1368 } while (0) 1369 1370 /* Closes the new segment - part of NEW_SEGMENT. */ 1243 1371 #define CLOSE_SEGMENT() \ 1244 1245 1246 1247 1248 1249 1250 1372 do { \ 1373 pDstSeg->cSections = (uint32_t)(pSectExtra - pDstSeg->paSections); \ 1374 pDstSeg++; \ 1375 } while (0) 1376 1377 1378 /* Shared with the 64-bit variant. */ 1251 1379 #define ADD_SEGMENT_AND_ITS_SECTIONS(a_cBits) \ 1252 do { \ 1253 bool fAddSegOuter = false; \ 1254 \ 1255 /* \ 1256 * Check that the segment name is unique. We couldn't do that \ 1257 * in the preparsing stage. \ 1258 */ \ 1259 if (pThis->uEffFileType != MH_OBJECT) \ 1260 for (pSegItr = &pThis->aSegments[0]; pSegItr != pDstSeg; pSegItr++) \ 1261 if (!strncmp(pSegItr->SegInfo.pszName, pSrcSeg->segname, sizeof(pSrcSeg->segname))) \ 1262 RTLDRMODMACHO_FAILED_RETURN(VERR_LDR_DUPLICATE_SEGMENT_NAME); \ 1263 \ 1264 /* \ 1265 * Create a new segment, unless we're supposed to skip this one. \ 1266 */ \ 1267 if ( pThis->uEffFileType != MH_OBJECT \ 1268 && (cSectionsLeft == 0 || !(pFirstSect->flags & S_ATTR_DEBUG)) \ 1269 && strcmp(pSrcSeg->segname, "__DWARF") \ 1270 && strcmp(pSrcSeg->segname, "__CTF") ) \ 1271 { \ 1272 NEW_SEGMENT(a_cBits, pSrcSeg->segname, false /*a_fObjFile*/, "" /*a_achName2*/, \ 1273 pSrcSeg->vmaddr, pSrcSeg->vmsize, \ 1274 pSrcSeg->filesize != 0, pSrcSeg->fileoff, pSrcSeg->filesize); \ 1275 fAddSegOuter = true; \ 1276 } \ 1277 \ 1278 /* \ 1279 * Convert and parse the sections. \ 1280 */ \ 1281 while (cSectionsLeft-- > 0) \ 1282 { \ 1283 /* New segment if object file. */ \ 1284 bool fAddSegInner = false; \ 1285 if ( pThis->uEffFileType == MH_OBJECT \ 1286 && !(pSect->flags & S_ATTR_DEBUG) \ 1287 && strcmp(pSrcSeg->segname, "__DWARF") \ 1288 && strcmp(pSrcSeg->segname, "__CTF") ) \ 1289 { \ 1290 Assert(!fAddSegOuter); \ 1291 NEW_SEGMENT(a_cBits, pSect->segname, true /*a_fObjFile*/, pSect->sectname, \ 1292 pSect->addr, pSect->size, \ 1293 pSect->offset != 0, pSect->offset, pSect->size); \ 1294 fAddSegInner = true; \ 1295 } \ 1296 \ 1297 /* Section data extract. */ \ 1298 pSectExtra->cb = pSect->size; \ 1299 pSectExtra->RVA = pSect->addr - pDstSeg->SegInfo.LinkAddress; \ 1300 pSectExtra->LinkAddress = pSect->addr; \ 1301 if (pSect->offset) \ 1302 pSectExtra->offFile = pSect->offset + pThis->offImage; \ 1303 else \ 1304 pSectExtra->offFile = -1; \ 1305 pSectExtra->cFixups = pSect->nreloc; \ 1306 pSectExtra->paFixups = NULL; \ 1307 if (pSect->nreloc) \ 1308 pSectExtra->offFixups = pSect->reloff + pThis->offImage; \ 1309 else \ 1310 pSectExtra->offFixups = -1; \ 1311 pSectExtra->fFlags = pSect->flags; \ 1312 pSectExtra->iSegment = (uint32_t)(pDstSeg - &pThis->aSegments[0]); \ 1313 pSectExtra->pvMachoSection = pSect; \ 1314 \ 1315 /* Update the segment alignment, if we're not skipping it. */ \ 1316 if ( (fAddSegOuter || fAddSegInner) \ 1317 && pDstSeg->SegInfo.Alignment < ((RTLDRADDR)1 << pSect->align)) \ 1318 pDstSeg->SegInfo.Alignment = (RTLDRADDR)1 << pSect->align; \ 1319 \ 1320 /* Next section, and if object file next segment. */ \ 1321 pSectExtra++; \ 1322 pSect++; \ 1323 if (fAddSegInner) \ 1324 CLOSE_SEGMENT(); \ 1325 } \ 1326 \ 1327 /* Close the segment and advance. */ \ 1328 if (fAddSegOuter) \ 1329 CLOSE_SEGMENT(); \ 1330 \ 1331 /* Take down 'execSeg' info for signing */ \ 1332 if (fFirstSeg) \ 1333 { \ 1334 fFirstSeg = false; \ 1335 pThis->offSeg0ForCodeSign = pSrcSeg->fileoff; \ 1336 pThis->cbSeg0ForCodeSign = pSrcSeg->filesize; /** @todo file or vm size? */ \ 1337 pThis->fSeg0ForCodeSign = pSrcSeg->flags; \ 1338 } \ 1339 } while (0) /* ADD_SEGMENT_AND_ITS_SECTIONS */ 1380 do { \ 1381 bool fAddSegOuter = false; \ 1382 \ 1383 /* \ 1384 * Check that the segment name is unique. We couldn't do that \ 1385 * in the preparsing stage. \ 1386 */ \ 1387 if (pThis->uEffFileType != MH_OBJECT) \ 1388 for (pSegItr = &pThis->aSegments[0]; pSegItr != pDstSeg; pSegItr++) \ 1389 if (!strncmp(pSegItr->SegInfo.pszName, pSrcSeg->segname, sizeof(pSrcSeg->segname))) \ 1390 RTLDRMODMACHO_FAILED_RETURN(VERR_LDR_DUPLICATE_SEGMENT_NAME); \ 1391 \ 1392 /* \ 1393 * Create a new segment, unless we're supposed to skip this one. \ 1394 */ \ 1395 if ( pThis->uEffFileType != MH_OBJECT \ 1396 && (cSectionsLeft == 0 || !(pFirstSect->flags & S_ATTR_DEBUG)) \ 1397 && strcmp(pSrcSeg->segname, "__DWARF") \ 1398 && strcmp(pSrcSeg->segname, "__CTF") ) \ 1399 { \ 1400 NEW_SEGMENT(a_cBits, pSrcSeg->segname, false /*a_fObjFile*/, "" /*a_achName2*/, \ 1401 pSrcSeg->vmaddr, pSrcSeg->vmsize, \ 1402 pSrcSeg->filesize != 0, pSrcSeg->fileoff, pSrcSeg->filesize); \ 1403 fAddSegOuter = true; \ 1404 } \ 1405 \ 1406 /* \ 1407 * Convert and parse the sections. \ 1408 */ \ 1409 while (cSectionsLeft-- > 0) \ 1410 { \ 1411 /* New segment if object file. */ \ 1412 bool fAddSegInner = false; \ 1413 if ( pThis->uEffFileType == MH_OBJECT \ 1414 && !(pSect->flags & S_ATTR_DEBUG) \ 1415 && strcmp(pSrcSeg->segname, "__DWARF") \ 1416 && strcmp(pSrcSeg->segname, "__CTF") ) \ 1417 { \ 1418 Assert(!fAddSegOuter); \ 1419 NEW_SEGMENT(a_cBits, pSect->segname, true /*a_fObjFile*/, pSect->sectname, \ 1420 pSect->addr, pSect->size, \ 1421 pSect->offset != 0, pSect->offset, pSect->size); \ 1422 fAddSegInner = true; \ 1423 } \ 1424 \ 1425 /* Section data extract. */ \ 1426 pSectExtra->cb = pSect->size; \ 1427 pSectExtra->RVA = pSect->addr - pDstSeg->SegInfo.LinkAddress; \ 1428 pSectExtra->LinkAddress = pSect->addr; \ 1429 if (pSect->offset) \ 1430 pSectExtra->offFile = pSect->offset + pThis->offImage; \ 1431 else \ 1432 pSectExtra->offFile = -1; \ 1433 pSectExtra->cFixups = pSect->nreloc; \ 1434 pSectExtra->paFixups = NULL; \ 1435 pSectExtra->pauFixupVirginData = NULL; \ 1436 if (pSect->nreloc) \ 1437 pSectExtra->offFixups = pSect->reloff + pThis->offImage; \ 1438 else \ 1439 pSectExtra->offFixups = -1; \ 1440 pSectExtra->fFlags = pSect->flags; \ 1441 pSectExtra->iSegment = (uint32_t)(pDstSeg - &pThis->aSegments[0]); \ 1442 pSectExtra->pvMachoSection = pSect; \ 1443 \ 1444 /* Update the segment alignment, if we're not skipping it. */ \ 1445 if ( (fAddSegOuter || fAddSegInner) \ 1446 && pDstSeg->SegInfo.Alignment < ((RTLDRADDR)1 << pSect->align)) \ 1447 pDstSeg->SegInfo.Alignment = (RTLDRADDR)1 << pSect->align; \ 1448 \ 1449 /* Next section, and if object file next segment. */ \ 1450 pSectExtra++; \ 1451 pSect++; \ 1452 if (fAddSegInner) \ 1453 CLOSE_SEGMENT(); \ 1454 } \ 1455 \ 1456 /* Close the segment and advance. */ \ 1457 if (fAddSegOuter) \ 1458 CLOSE_SEGMENT(); \ 1459 \ 1460 /* Take down 'execSeg' info for signing */ \ 1461 if (fFirstSeg) \ 1462 { \ 1463 fFirstSeg = false; \ 1464 pThis->offSeg0ForCodeSign = pSrcSeg->fileoff; \ 1465 pThis->cbSeg0ForCodeSign = pSrcSeg->filesize; /** @todo file or vm size? */ \ 1466 pThis->fSeg0ForCodeSign = pSrcSeg->flags; \ 1467 } \ 1468 } while (0) /* ADD_SEGMENT_AND_ITS_SECTIONS */ 1340 1469 1341 1470 ADD_SEGMENT_AND_ITS_SECTIONS(32); … … 1359 1488 case MH_OBJECT: 1360 1489 case MH_EXECUTE: 1361 case MH_DYLIB: /** @todo ??? */1362 case MH_BUNDLE: /** @todo ??? */1490 case MH_DYLIB: 1491 case MH_BUNDLE: 1363 1492 case MH_DSYM: 1364 1493 case MH_KEXT_BUNDLE: … … 1369 1498 break; 1370 1499 } 1500 break; 1501 1502 case LC_DYSYMTAB: 1503 pThis->pDySymTab = (dysymtab_command_t *)u.pb; 1371 1504 break; 1372 1505 … … 1539 1672 RTMemFree(pThis->aSegments[i].paSections[j].paFixups); 1540 1673 pThis->aSegments[i].paSections[j].paFixups = NULL; 1674 RTMemFree(pThis->aSegments[i].paSections[j].pauFixupVirginData); 1675 pThis->aSegments[i].paSections[j].pauFixupVirginData = NULL; 1541 1676 } 1542 1677 } … … 1548 1683 RTMemFree(pThis->pvaSymbols); 1549 1684 pThis->pvaSymbols = NULL; 1685 RTMemFree(pThis->paidxIndirectSymbols); 1686 pThis->paidxIndirectSymbols = NULL; 1687 RTMemFree(pThis->paRelocations); 1688 pThis->paRelocations = NULL; 1689 RTMemFree(pThis->pauRelocationsVirginData); 1690 pThis->pauRelocationsVirginData = NULL; 1550 1691 RTMemFree(pThis->PtrCodeSignature.pb); 1551 1692 pThis->PtrCodeSignature.pb = NULL; … … 2630 2771 #endif 2631 2772 2773 2774 /** 2775 * Worker for resolving an undefined 32-bit symbol table entry. 2776 * 2777 * @returns IPRT status code. 2778 * @param pThis The Mach-O module interpreter instance. 2779 * @param pSym The symbol table entry. 2780 * @param BaseAddress The module base address. 2781 * @param pfnGetImport The callback for resolving an imported symbol. 2782 * @param pvUser User argument to the callback. 2783 */ 2784 DECLINLINE(int) rtdlrModMachOHandleUndefinedSymbol32(PRTLDRMODMACHO pThis, macho_nlist_32_t *pSym, 2785 RTLDRADDR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser) 2786 { 2787 RTLDRADDR Value = NIL_RTLDRADDR; 2788 2789 /** @todo Implement N_REF_TO_WEAK. */ 2790 RTLDRMODMACHO_CHECK_RETURN(!(pSym->n_desc & N_REF_TO_WEAK), VERR_LDRMACHO_TODO); 2791 2792 /* Get the symbol name. */ 2793 RTLDRMODMACHO_CHECK_RETURN((uint32_t)pSym->n_un.n_strx < pThis->cchStrings, VERR_LDRMACHO_BAD_SYMBOL); 2794 const char *pszSymbol = &pThis->pchStrings[pSym->n_un.n_strx]; 2795 size_t cchSymbol = strlen(pszSymbol); 2796 2797 /* Check for linker defined symbols relating to sections and segments. */ 2798 int rc; 2799 if ( cchSymbol <= sizeof("section$end$") - 1 2800 || *pszSymbol != 's' 2801 || memchr(pszSymbol, '$', cchSymbol) == NULL) 2802 rc = VERR_SYMBOL_NOT_FOUND; 2803 else 2804 rc = kldrModMachOQueryLinkerSymbol(pThis, pszSymbol, cchSymbol, BaseAddress, &Value); 2805 2806 /* Ask the user for an address to the symbol. */ 2807 //uint32_t fKind = RTLDRSYMKIND_REQ_FLAT; 2808 /** @todo figure out a better way to deal with underscore prefixes. sigh. */ 2809 if (RT_FAILURE_NP(rc)) 2810 rc = pfnGetImport(&pThis->Core, NULL /*pszModule*/, pszSymbol + (pszSymbol[0] == '_'), 2811 UINT32_MAX, &Value/*, &fKind*/, pvUser); 2812 if (RT_SUCCESS(rc)) 2813 { /* likely */ } 2814 /* If weak reference we can continue, otherwise fail? */ 2815 else if (pSym->n_desc & N_WEAK_REF) 2816 Value = 0; 2817 else 2818 return rc; 2819 2820 /* Update the symbol. */ 2821 pSym->n_value = (uint32_t)Value; 2822 if (pSym->n_value == Value) 2823 return VINF_SUCCESS; 2824 return VERR_LDR_ADDRESS_OVERFLOW; 2825 } 2826 2827 2828 /** 2829 * Worker for resolving an undefined 64-bit symbol table entry. 2830 * 2831 * @returns IPRT status code. 2832 * @param pThis The Mach-O module interpreter instance. 2833 * @param pSym The symbol table entry. 2834 * @param BaseAddress The module base address. 2835 * @param pfnGetImport The callback for resolving an imported symbol. 2836 * @param pvUser User argument to the callback. 2837 */ 2838 DECLINLINE(int) rtdlrModMachOHandleUndefinedSymbol64(PRTLDRMODMACHO pThis, macho_nlist_64_t *pSym, 2839 RTLDRADDR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser) 2840 { 2841 RTLDRADDR Value = NIL_RTLDRADDR; 2842 2843 /** @todo Implement N_REF_TO_WEAK. */ 2844 RTLDRMODMACHO_CHECK_RETURN(!(pSym->n_desc & N_REF_TO_WEAK), VERR_LDRMACHO_TODO); 2845 2846 /* Get the symbol name. */ 2847 RTLDRMODMACHO_CHECK_RETURN((uint32_t)pSym->n_un.n_strx < pThis->cchStrings, VERR_LDRMACHO_BAD_SYMBOL); 2848 const char *pszSymbol = &pThis->pchStrings[pSym->n_un.n_strx]; 2849 size_t cchSymbol = strlen(pszSymbol); 2850 2851 /* Check for linker defined symbols relating to sections and segments. */ 2852 int rc; 2853 if ( cchSymbol <= sizeof("section$end$") - 1 2854 || *pszSymbol != 's' 2855 || memchr(pszSymbol, '$', cchSymbol) == NULL) 2856 rc = VERR_SYMBOL_NOT_FOUND; 2857 else 2858 rc = kldrModMachOQueryLinkerSymbol(pThis, pszSymbol, cchSymbol, BaseAddress, &Value); 2859 2860 /* Ask the user for an address to the symbol. */ 2861 //uint32_t fKind = RTLDRSYMKIND_REQ_FLAT; 2862 /** @todo figure out a better way to deal with underscore prefixes. sigh. */ 2863 if (RT_FAILURE_NP(rc)) 2864 rc = pfnGetImport(&pThis->Core, NULL /*pszModule*/, pszSymbol + (pszSymbol[0] == '_'), 2865 UINT32_MAX, &Value/*, &fKind*/, pvUser); 2866 if (RT_SUCCESS(rc)) 2867 { /* likely */ } 2868 /* If weak reference we can continue, otherwise fail? */ 2869 else if (pSym->n_desc & N_WEAK_REF) 2870 Value = 0; 2871 else 2872 return rc; 2873 2874 /* Update the symbol. */ 2875 pSym->n_value = (uint64_t)Value; 2876 if (pSym->n_value == Value) 2877 return VINF_SUCCESS; 2878 return VERR_LDR_ADDRESS_OVERFLOW; 2879 } 2880 2881 2632 2882 /** 2633 2883 * MH_OBJECT: Resolves undefined symbols (imports). … … 2641 2891 static int kldrModMachOObjDoImports(PRTLDRMODMACHO pThis, RTLDRADDR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser) 2642 2892 { 2643 const uint32_t cSyms = pThis->cSymbols; 2644 uint32_t iSym; 2645 2646 /* 2647 * Ensure that we've got the symbol table and section fixups handy. 2893 2894 /* 2895 * Ensure that we've got the symbol table. 2648 2896 */ 2649 2897 int rc = kldrModMachOLoadObjSymTab(pThis); … … 2655 2903 * We currently ignore REFERENCE_TYPE. 2656 2904 */ 2905 const uint32_t cSyms = pThis->cSymbols; 2657 2906 if ( pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE 2658 2907 || pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 2659 2908 { 2660 2909 macho_nlist_32_t *paSyms = (macho_nlist_32_t *)pThis->pvaSymbols; 2661 for ( iSym = 0; iSym < cSyms; iSym++)2910 for (uint32_t iSym = 0; iSym < cSyms; iSym++) 2662 2911 { 2663 2912 /* skip stabs */ … … 2667 2916 if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 2668 2917 { 2669 const char *pszSymbol; 2670 size_t cchSymbol; 2671 //uint32_t fKind = RTLDRSYMKIND_REQ_FLAT; 2672 RTLDRADDR Value = NIL_RTLDRADDR; 2673 2674 /** @todo Implement N_REF_TO_WEAK. */ 2675 RTLDRMODMACHO_CHECK_RETURN(!(paSyms[iSym].n_desc & N_REF_TO_WEAK), VERR_LDRMACHO_TODO); 2676 2677 /* Get the symbol name. */ 2678 RTLDRMODMACHO_CHECK_RETURN((uint32_t)paSyms[iSym].n_un.n_strx < pThis->cchStrings, VERR_LDRMACHO_BAD_SYMBOL); 2679 pszSymbol = &pThis->pchStrings[paSyms[iSym].n_un.n_strx]; 2680 cchSymbol = strlen(pszSymbol); 2681 2682 /* Check for linker defined symbols relating to sections and segments. */ 2683 if ( cchSymbol > sizeof("section$end$") - 1 2684 && *pszSymbol == 's' 2685 && memchr(pszSymbol, '$', cchSymbol)) 2686 rc = kldrModMachOQueryLinkerSymbol(pThis, pszSymbol, cchSymbol, BaseAddress, &Value); 2687 else 2688 rc = VERR_SYMBOL_NOT_FOUND; 2689 2690 /* Ask the user for an address to the symbol. */ 2691 /** @todo figure out a better way to deal with underscore prefixes. sigh. */ 2692 if (RT_FAILURE_NP(rc)) 2693 rc = pfnGetImport(&pThis->Core, NULL /*pszModule*/, pszSymbol + (pszSymbol[0] == '_'), 2694 UINT32_MAX, &Value/*, &fKind*/, pvUser); 2918 rc = rtdlrModMachOHandleUndefinedSymbol32(pThis, &paSyms[iSym], BaseAddress, pfnGetImport, pvUser); 2695 2919 if (RT_FAILURE(rc)) 2696 {2697 /* weak reference? */2698 if (!(paSyms[iSym].n_desc & N_WEAK_REF))2699 break;2700 Value = 0;2701 }2702 2703 /* Update the symbol. */2704 paSyms[iSym].n_value = (uint32_t)Value;2705 if (paSyms[iSym].n_value != Value)2706 {2707 rc = VERR_LDR_ADDRESS_OVERFLOW;2708 2920 break; 2709 }2710 2921 } 2711 2922 else if (paSyms[iSym].n_desc & N_WEAK_DEF) … … 2720 2931 /* (Identical to the 32-bit code, just different paSym type. (and n_strx is unsigned)) */ 2721 2932 macho_nlist_64_t *paSyms = (macho_nlist_64_t *)pThis->pvaSymbols; 2722 for ( iSym = 0; iSym < cSyms; iSym++)2933 for (uint32_t iSym = 0; iSym < cSyms; iSym++) 2723 2934 { 2724 2935 /* skip stabs */ … … 2728 2939 if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 2729 2940 { 2730 const char *pszSymbol; 2731 size_t cchSymbol; 2732 //uint32_t fKind = RTLDRSYMKIND_REQ_FLAT; 2733 RTLDRADDR Value = NIL_RTLDRADDR; 2734 2735 /** @todo Implement N_REF_TO_WEAK. */ 2736 RTLDRMODMACHO_CHECK_RETURN(!(paSyms[iSym].n_desc & N_REF_TO_WEAK), VERR_LDRMACHO_TODO); 2737 2738 /* Get the symbol name. */ 2739 RTLDRMODMACHO_CHECK_RETURN(paSyms[iSym].n_un.n_strx < pThis->cchStrings, VERR_LDRMACHO_BAD_SYMBOL); 2740 pszSymbol = &pThis->pchStrings[paSyms[iSym].n_un.n_strx]; 2741 cchSymbol = strlen(pszSymbol); 2742 2743 /* Check for linker defined symbols relating to sections and segments. */ 2744 if ( cchSymbol > sizeof("section$end$") - 1 2745 && *pszSymbol == 's' 2746 && memchr(pszSymbol, '$', cchSymbol)) 2747 rc = kldrModMachOQueryLinkerSymbol(pThis, pszSymbol, cchSymbol, BaseAddress, &Value); 2748 else 2749 rc = VERR_SYMBOL_NOT_FOUND; 2750 2751 /* Ask the user for an address to the symbol. */ 2752 /** @todo figure out a better way to deal with underscore prefixes. sigh. */ 2753 if (RT_FAILURE_NP(rc)) 2754 rc = pfnGetImport(&pThis->Core, NULL, pszSymbol + (*pszSymbol == '_'), 2755 UINT32_MAX, &Value, /*&fKind,*/ pvUser); 2941 rc = rtdlrModMachOHandleUndefinedSymbol64(pThis, &paSyms[iSym], BaseAddress, pfnGetImport, pvUser); 2756 2942 if (RT_FAILURE(rc)) 2757 {2758 /* weak reference? */2759 if (!(paSyms[iSym].n_desc & N_WEAK_REF))2760 break;2761 Value = 0;2762 }2763 2764 /* Update the symbol. */2765 paSyms[iSym].n_value = Value;2766 if (paSyms[iSym].n_value != Value)2767 {2768 rc = VERR_LDR_ADDRESS_OVERFLOW;2769 2943 break; 2770 }2771 2944 } 2772 2945 else if (paSyms[iSym].n_desc & N_WEAK_DEF) … … 2783 2956 2784 2957 /** 2785 * MH_OBJECT: Applies base relocations to a (unprotected) image mapping. 2958 * Dylib: Resolves undefined symbols (imports). 2959 * 2960 * This is conceptually identically to kldrModMachOObjDoImports, only 2961 * LC_DYSYMTAB helps us avoid working over the whole symbol table. 2962 * 2963 * @returns IPRT status code. 2964 * @param pThis The Mach-O module interpreter instance. 2965 * @param BaseAddress The module base address. 2966 * @param pfnGetImport The callback for resolving an imported symbol. 2967 * @param pvUser User argument to the callback. 2968 */ 2969 static int kldrModMachODylibDoImports(PRTLDRMODMACHO pThis, RTLDRADDR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser) 2970 { 2971 /* 2972 * There must be a LC_DYSYMTAB. 2973 * We might be lucky, though, and not have any imports. 2974 */ 2975 dysymtab_command_t const *pDySymTab = pThis->pDySymTab; 2976 AssertReturn(pDySymTab, VERR_INTERNAL_ERROR_2); 2977 if (pDySymTab->nundefsym == 0) 2978 return VINF_SUCCESS; 2979 2980 /* 2981 * Ensure that we've got the symbol table. 2982 */ 2983 int rc = kldrModMachOLoadObjSymTab(pThis); 2984 if (RT_FAILURE(rc)) 2985 return rc; 2986 2987 /* 2988 * Iterate the give symbol table section containing undefined symbols and resolve them. 2989 */ 2990 uint32_t const cSyms = pDySymTab->iundefsym + pDySymTab->nundefsym; 2991 if ( pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE 2992 || pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 2993 { 2994 macho_nlist_32_t *paSyms = (macho_nlist_32_t *)pThis->pvaSymbols; 2995 for (uint32_t iSym = pDySymTab->iundefsym; RT_SUCCESS(rc) && iSym < cSyms; iSym++) 2996 { 2997 AssertContinue((paSyms[iSym].n_type & (MACHO_N_TYPE | MACHO_N_STAB)) == MACHO_N_UNDF); 2998 rc = rtdlrModMachOHandleUndefinedSymbol32(pThis, &paSyms[iSym], BaseAddress, pfnGetImport, pvUser); 2999 } 3000 } 3001 else 3002 { 3003 /* (Identical to the 32-bit code, just different paSym type. (and n_strx is unsigned)) */ 3004 macho_nlist_64_t *paSyms = (macho_nlist_64_t *)pThis->pvaSymbols; 3005 for (uint32_t iSym = pDySymTab->iundefsym; RT_SUCCESS(rc) && iSym < cSyms; iSym++) 3006 { 3007 AssertContinue((paSyms[iSym].n_type & (MACHO_N_TYPE | MACHO_N_STAB)) == MACHO_N_UNDF); 3008 rc = rtdlrModMachOHandleUndefinedSymbol64(pThis, &paSyms[iSym], BaseAddress, pfnGetImport, pvUser); 3009 } 3010 } 3011 3012 return rc; 3013 } 3014 3015 3016 static int kldrModMachODylibDoIndirectSymbols(PRTLDRMODMACHO pThis, void *pvBits, RTLDRADDR offDelta) 3017 { 3018 /* 3019 * There must be a LC_DYSYMTAB. 3020 * We might be lucky, though, and not have any imports. 3021 */ 3022 dysymtab_command_t const *pDySymTab = pThis->pDySymTab; 3023 AssertReturn(pDySymTab, VERR_INTERNAL_ERROR_2); 3024 uint32_t const cIndirectSymbols = pDySymTab->nindirectsymb; 3025 if (cIndirectSymbols == 0) 3026 return VINF_SUCCESS; 3027 3028 /* 3029 * Ensure that we've got the symbol table. 3030 */ 3031 int rc = kldrModMachOLoadObjSymTab(pThis); 3032 if (RT_FAILURE(rc)) 3033 return rc; 3034 3035 /* 3036 * Load the indirect symbol table. 3037 */ 3038 if (!pThis->paidxIndirectSymbols) 3039 { 3040 uint32_t *paidxIndirectSymbols = (uint32_t *)RTMemAlloc(cIndirectSymbols * sizeof(uint32_t)); 3041 if (!paidxIndirectSymbols) 3042 return VERR_NO_MEMORY; 3043 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, paidxIndirectSymbols, cIndirectSymbols * sizeof(uint32_t), 3044 pDySymTab->indirectsymboff); 3045 if (RT_SUCCESS(rc)) 3046 pThis->paidxIndirectSymbols = paidxIndirectSymbols; 3047 else 3048 { 3049 RTMemFree(paidxIndirectSymbols); 3050 return rc; 3051 } 3052 3053 /* Byte swap if needed. */ 3054 if ( pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 3055 || pThis->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 3056 for (uint32_t i = 0; i < cIndirectSymbols; i++) 3057 paidxIndirectSymbols[i] = RT_BSWAP_U32(paidxIndirectSymbols[i]); 3058 } 3059 uint32_t const *paidxIndirectSymbols = pThis->paidxIndirectSymbols; 3060 3061 /* 3062 * Process the sections using indirect symbols. 3063 */ 3064 const uint32_t cSymbols = pThis->cSymbols; 3065 if ( pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE 3066 || pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 3067 { 3068 macho_nlist_32_t const *paSymbols = (macho_nlist_32_t *)pThis->pvaSymbols; 3069 for (uint32_t iSect = 0; iSect < pThis->cSections; iSect++) 3070 { 3071 section_32_t const *pSect = (section_32_t const *)pThis->paSections[iSect].pvMachoSection; 3072 switch (pSect->flags & SECTION_TYPE) 3073 { 3074 case S_NON_LAZY_SYMBOL_POINTERS: 3075 case S_LAZY_SYMBOL_POINTERS: 3076 { 3077 uint32_t *pauDstPtrs = (uint32_t *)((uintptr_t)pvBits + pThis->paSections[iSect].RVA); 3078 uint32_t const cDstPtrs = pThis->paSections[iSect].cb / sizeof(pauDstPtrs[0]); 3079 uint32_t const idxSrcSkip = pSect->reserved1; 3080 if ((uint64_t)idxSrcSkip + cDstPtrs > cIndirectSymbols) 3081 return VERR_BAD_EXE_FORMAT; /// @todo better error code. 3082 3083 for (uint32_t i = 0; i < cDstPtrs; i++) 3084 { 3085 uint32_t const idxSym = paidxIndirectSymbols[idxSrcSkip + i]; 3086 if (idxSym == INDIRECT_SYMBOL_LOCAL) 3087 pauDstPtrs[i] += (int32_t)offDelta; 3088 else if (idxSym != INDIRECT_SYMBOL_ABS) 3089 { 3090 AssertMsgReturn(idxSym < cSymbols, 3091 ("i=%#x idxSym=%#x cSymbols=%#x iSect=%#x\n", i, idxSym, cSymbols, iSect), 3092 VERR_BAD_EXE_FORMAT); /// @todo better error code. 3093 pauDstPtrs[i] = paSymbols[idxSym].n_value; 3094 } 3095 } 3096 break; 3097 } 3098 3099 case S_SYMBOL_STUBS: 3100 if ( pThis->Core.enmArch == RTLDRARCH_X86_32 3101 && (pSect->flags & S_ATTR_SELF_MODIFYING_CODE) 3102 && pSect->reserved2 == 5) 3103 { 3104 uint32_t uDstRva = pThis->paSections[iSect].RVA; 3105 uint8_t *pbDst = (uint8_t *)((uintptr_t)pvBits + uDstRva); 3106 uint32_t const cDstPtrs = pThis->paSections[iSect].cb / 5; 3107 uint32_t const idxSrcSkip = pSect->reserved1; 3108 if ((uint64_t)idxSrcSkip + cDstPtrs > cIndirectSymbols) 3109 return VERR_BAD_EXE_FORMAT; /// @todo better error code. 3110 3111 for (uint32_t i = 0; i < cDstPtrs; i++, uDstRva += 5, pbDst += 5) 3112 { 3113 uint32_t const idxSym = paidxIndirectSymbols[idxSrcSkip + i]; 3114 if (idxSym != INDIRECT_SYMBOL_ABS && idxSym != INDIRECT_SYMBOL_LOCAL) 3115 { 3116 AssertMsgReturn(idxSym < cSymbols, 3117 ("i=%#x idxSym=%#x cSymbols=%#x iSect=%#x\n", i, idxSym, cSymbols, iSect), 3118 VERR_BAD_EXE_FORMAT); /// @todo better error code. 3119 pbDst[0] = 0xeb; /* JMP rel32 */ 3120 uint32_t offDisp = paSymbols[idxSym].n_value - (uint32_t)uDstRva - 5; 3121 pbDst[1] = (uint8_t)offDisp; 3122 offDisp >>= 8; 3123 pbDst[2] = (uint8_t)offDisp; 3124 offDisp >>= 8; 3125 pbDst[3] = (uint8_t)offDisp; 3126 offDisp >>= 8; 3127 pbDst[4] = (uint8_t)offDisp; 3128 } 3129 } 3130 break; 3131 } 3132 break; 3133 } 3134 3135 } 3136 } 3137 else 3138 { 3139 /* Exact like for 32-bit, except for 64-bit symbol table, 64-bit addresses and no need to process S_SYMBOL_STUBS. */ 3140 macho_nlist_64_t const *paSymbols = (macho_nlist_64_t *)pThis->pvaSymbols; 3141 for (uint32_t iSect = 0; iSect < pThis->cSections; iSect++) 3142 { 3143 section_64_t const *pSect = (section_64_t const *)pThis->paSections[iSect].pvMachoSection; 3144 switch (pSect->flags & SECTION_TYPE) 3145 { 3146 case S_NON_LAZY_SYMBOL_POINTERS: 3147 case S_LAZY_SYMBOL_POINTERS: 3148 { 3149 uint64_t *pauDstPtrs = (uint64_t *)((uintptr_t)pvBits + pThis->paSections[iSect].RVA); 3150 uint32_t const cDstPtrs = pThis->paSections[iSect].cb / sizeof(pauDstPtrs[0]); 3151 uint32_t const idxSrcSkip = pSect->reserved1; 3152 if ((uint64_t)idxSrcSkip + cDstPtrs > cIndirectSymbols) 3153 return VERR_BAD_EXE_FORMAT; /// @todo better error code. 3154 3155 for (uint32_t i = 0; i < cDstPtrs; i++) 3156 { 3157 uint32_t const idxSym = paidxIndirectSymbols[idxSrcSkip + i]; 3158 if (idxSym == INDIRECT_SYMBOL_LOCAL) 3159 pauDstPtrs[i] += (int64_t)offDelta; 3160 else if (idxSym != INDIRECT_SYMBOL_ABS) 3161 { 3162 AssertMsgReturn(idxSym < cSymbols, 3163 ("i=%#x idxSym=%#x cSymbols=%#x iSect=%#x\n", i, idxSym, cSymbols, iSect), 3164 VERR_BAD_EXE_FORMAT); /// @todo better error code. 3165 pauDstPtrs[i] = paSymbols[idxSym].n_value; 3166 } 3167 } 3168 break; 3169 } 3170 3171 case S_SYMBOL_STUBS: 3172 if ( pThis->Core.enmArch == RTLDRARCH_X86_32 3173 && (pSect->flags & S_ATTR_SELF_MODIFYING_CODE) 3174 && pSect->reserved2 == 5) 3175 return VERR_BAD_EXE_FORMAT; 3176 break; 3177 } 3178 } 3179 } 3180 3181 return VINF_SUCCESS; 3182 } 3183 3184 3185 /** 3186 * MH_OBJECT: Applies base relocations to an (unprotected) image mapping. 2786 3187 * 2787 3188 * @returns IPRT status code. … … 2793 3194 { 2794 3195 /* 2795 * Ensure that we've got the symbol table and section fixups handy.3196 * Ensure that we've got the symbol table. 2796 3197 */ 2797 3198 int rc = kldrModMachOLoadObjSymTab(pThis); … … 2813 3214 if (!pSect->cFixups) 2814 3215 continue; 2815 2816 /* lazy load (and endian convert) the fixups. */ 2817 if (!pSect->paFixups) 2818 { 2819 rc = kldrModMachOLoadFixups(pThis, pSect->offFixups, pSect->cFixups, &pSect->paFixups); 2820 if (RT_FAILURE(rc)) 2821 break; 2822 } 3216 AssertReturn(pSect->paFixups, VERR_INTERNAL_ERROR_4); 3217 AssertReturn(pSect->pauFixupVirginData, VERR_INTERNAL_ERROR_4); 2823 3218 2824 3219 /* … … 2827 3222 uint8_t *pbSectBits = (uint8_t *)pvMapping + (uintptr_t)pSect->RVA; 2828 3223 if (pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE) /** @todo this aint right. */ 2829 rc = kldrModMachO FixupSectionGeneric32Bit(pThis, pbSectBits, pSect,2830 (macho_nlist_32_t *)pThis->pvaSymbols,2831 pThis->cSymbols, NewBaseAddress);3224 rc = kldrModMachOApplyFixupsGeneric32Bit(pThis, pbSectBits, (size_t)pSect->cb, pSect->RVA, pSect->LinkAddress, 3225 pSect->paFixups, pSect->cFixups, pSect->pauFixupVirginData, 3226 (macho_nlist_32_t *)pThis->pvaSymbols, pThis->cSymbols, NewBaseAddress); 2832 3227 else if ( pThis->Hdr.magic == IMAGE_MACHO64_SIGNATURE 2833 3228 && pThis->Hdr.cputype == CPU_TYPE_X86_64) 2834 rc = kldrModMachO FixupSectionAMD64(pThis, pbSectBits, pSect,2835 (macho_nlist_64_t *)pThis->pvaSymbols,2836 pThis->cSymbols, NewBaseAddress);3229 rc = kldrModMachOApplyFixupsAMD64(pThis, pbSectBits, (size_t)pSect->cb, pSect->RVA, 3230 pSect->paFixups, pSect->cFixups, pSect->pauFixupVirginData, 3231 (macho_nlist_64_t *)pThis->pvaSymbols, pThis->cSymbols, NewBaseAddress); 2837 3232 else 2838 3233 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_TODO); … … 2843 3238 2844 3239 return rc; 3240 } 3241 3242 3243 /** 3244 * Dylib: Applies base relocations to an (unprotected) image mapping. 3245 * 3246 * @returns IPRT status code. 3247 * @param pThis The Mach-O module interpreter instance. 3248 * @param pvMapping The mapping to fixup. 3249 * @param NewBaseAddress The address to fixup the mapping to. 3250 */ 3251 static int kldrModMachODylibDoFixups(PRTLDRMODMACHO pThis, void *pvMapping, RTLDRADDR NewBaseAddress) 3252 { 3253 /* 3254 * There must be a LC_DYSYMTAB. 3255 * We might be lucky, though, and not have any imports. 3256 */ 3257 dysymtab_command_t const *pDySymTab = pThis->pDySymTab; 3258 AssertReturn(pDySymTab, VERR_INTERNAL_ERROR_2); 3259 uint32_t cRelocations = pDySymTab->nlocrel + pDySymTab->nextrel; 3260 if (cRelocations == 0) 3261 return VINF_SUCCESS; 3262 3263 /* 3264 * Ensure that we've got the symbol table. 3265 */ 3266 int rc = kldrModMachOLoadObjSymTab(pThis); 3267 if (RT_FAILURE(rc)) 3268 return rc; 3269 3270 /* 3271 * Load the relocations if needed. 3272 */ 3273 macho_relocation_union_t const *paRelocations = pThis->paRelocations; 3274 if (!paRelocations) 3275 { 3276 uint32_t *paRawRelocs = (uint32_t *)RTMemAlloc(cRelocations * sizeof(macho_relocation_union_t)); 3277 if (!paRawRelocs) 3278 return VERR_NO_MEMORY; 3279 if (pDySymTab->nextrel) 3280 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, paRawRelocs, pDySymTab->nextrel * sizeof(macho_relocation_union_t), 3281 pDySymTab->extreloff); 3282 if (pDySymTab->nlocrel && RT_SUCCESS(rc)) 3283 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, 3284 (uint8_t *)paRawRelocs + pDySymTab->nextrel * sizeof(macho_relocation_union_t), 3285 pDySymTab->nlocrel * sizeof(macho_relocation_union_t), pDySymTab->locreloff); 3286 if (RT_SUCCESS(rc)) 3287 pThis->paRelocations = (macho_relocation_union_t *)paRawRelocs; 3288 else 3289 { 3290 RTMemFree(paRawRelocs); 3291 return rc; 3292 } 3293 3294 /* Byte swap if needed. */ 3295 if ( pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 3296 || pThis->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 3297 { 3298 for (uint32_t i = 0; i < cRelocations; i++) 3299 { 3300 paRawRelocs[i * 2] = RT_BSWAP_U32(paRawRelocs[i * 2]); 3301 paRawRelocs[i * 2 + 1] = RT_BSWAP_U32(paRawRelocs[i * 2 + 1]); 3302 } 3303 ASMCompilerBarrier(); 3304 } 3305 3306 paRelocations = pThis->paRelocations; 3307 } 3308 3309 /* 3310 * Apply the fixups. 3311 */ 3312 if (pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE) /** @todo this aint right. */ 3313 return kldrModMachOApplyFixupsGeneric32Bit(pThis, (uint8_t *)pvMapping, (size_t)pThis->cbImage, 0, pThis->LinkAddress, 3314 paRelocations, cRelocations, pThis->pauRelocationsVirginData, 3315 (macho_nlist_32_t *)pThis->pvaSymbols, pThis->cSymbols, NewBaseAddress); 3316 if ( pThis->Hdr.magic == IMAGE_MACHO64_SIGNATURE 3317 && pThis->Hdr.cputype == CPU_TYPE_X86_64) 3318 return kldrModMachOApplyFixupsAMD64(pThis, (uint8_t *)pvMapping, (size_t)pThis->cbImage, 0, 3319 paRelocations, cRelocations, pThis->pauRelocationsVirginData, 3320 (macho_nlist_64_t *)pThis->pvaSymbols, pThis->cSymbols, NewBaseAddress); 3321 RTLDRMODMACHO_FAILED_RETURN(VERR_LDRMACHO_TODO); 2845 3322 } 2846 3323 … … 2852 3329 * @returns IPRT status code. 2853 3330 * @param pThis The Mach-O module interpreter instance. 2854 * @param pbSectBits Pointer to the section bits. 2855 * @param pFixupSect The section being fixed up. 3331 * @param pbBits Pointer to the bits to fix up. 3332 * @param cbBits Size of the bits to fix up. 3333 * @param uBitsRva The RVA of the bits. 3334 * @param uBitsLinkAddr The link address of the bits. 3335 * @param paFixups The fixups. 3336 * @param cFixups Number of fixups. 3337 * @param pauVirginData The virgin data / addends. Parallel to paFixups. 2856 3338 * @param paSyms Pointer to the symbol table. 2857 3339 * @param cSyms Number of symbols. 2858 3340 * @param NewBaseAddress The new base image address. 2859 3341 */ 2860 static int kldrModMachOFixupSectionGeneric32Bit(PRTLDRMODMACHO pThis, uint8_t *pbSectBits, PRTLDRMODMACHOSECT pFixupSect, 2861 macho_nlist_32_t *paSyms, uint32_t cSyms, RTLDRADDR NewBaseAddress) 2862 { 2863 const macho_relocation_info_t *paFixups = pFixupSect->paFixups; 2864 const uint32_t cFixups = pFixupSect->cFixups; 2865 size_t cbSectBits = (size_t)pFixupSect->cb; 2866 const uint8_t *pbSectVirginBits; 2867 uint32_t iFixup; 2868 RTLDRADDR SymAddr = ~(RTLDRADDR)0; 2869 int rc; 2870 2871 /* 2872 * Find the virgin bits. 2873 */ 2874 if (pFixupSect->offFile != -1) 2875 { 2876 rc = kldrModMachOMapVirginBits(pThis); 2877 if (RT_FAILURE(rc)) 2878 return rc; 2879 pbSectVirginBits = (const uint8_t *)pThis->pvBits + pFixupSect->offFile; 2880 } 2881 else 2882 pbSectVirginBits = NULL; 2883 3342 static int kldrModMachOApplyFixupsGeneric32Bit(PRTLDRMODMACHO pThis, uint8_t *pbBits, size_t cbBits, RTLDRADDR uBitsRva, 3343 RTLDRADDR uBitsLinkAddr, const macho_relocation_union_t *paFixups, 3344 const uint32_t cFixups, PCRTUINT64U const pauVirginData, 3345 macho_nlist_32_t *paSyms, uint32_t cSyms, RTLDRADDR NewBaseAddress) 3346 { 2884 3347 /* 2885 3348 * Iterate the fixups and apply them. 2886 3349 */ 2887 for (iFixup = 0; iFixup < cFixups; iFixup++) 2888 { 2889 RTPTRUNION uFix; 2890 RTPTRUNION uFixVirgin; 2891 union 2892 { 2893 macho_relocation_info_t r; 2894 scattered_relocation_info_t s; 2895 } Fixup; 2896 Fixup.r = paFixups[iFixup]; 3350 for (uint32_t iFixup = 0; iFixup < cFixups; iFixup++) 3351 { 3352 macho_relocation_union_t Fixup = paFixups[iFixup]; 3353 RTLDRADDR SymAddr = ~(RTLDRADDR)0; 3354 RTPTRUNION uFix; 2897 3355 2898 3356 if (!(Fixup.r.r_address & R_SCATTERED)) 2899 3357 { 2900 3358 /* sanity */ 2901 if ((uint32_t)Fixup.r.r_address >= cbSectBits) 2902 return VERR_LDR_BAD_FIXUP; 2903 2904 /* calc fixup addresses. */ 2905 uFix.pv = pbSectBits + Fixup.r.r_address; 2906 uFixVirgin.pv = pbSectVirginBits ? (uint8_t *)pbSectVirginBits + Fixup.r.r_address : 0; 3359 RTLDRMODMACHO_CHECK_RETURN((uint32_t)Fixup.r.r_address + RT_BIT_32(Fixup.r.r_length) <= cbBits, VERR_LDR_BAD_FIXUP); 3360 3361 /* Calc the fixup address. */ 3362 uFix.pv = pbBits + Fixup.r.r_address; 2907 3363 2908 3364 /* … … 2912 3368 switch (Fixup.r.r_length) 2913 3369 { 2914 /** @todo Deal with unaligned accesses on non x86 platforms. */2915 case 0: SymAddr = *uFixVirgin.pi8; break;2916 case 1: SymAddr = *uFixVirgin.pi16; break;2917 case 2: SymAddr = *uFixVirgin.pi32; break;2918 case 3: SymAddr = *uFixVirgin.pi64; break;3370 case 0: SymAddr = (int8_t)pauVirginData[iFixup].au8[0]; break; 3371 case 1: SymAddr = (int16_t)pauVirginData[iFixup].au16[0]; break; 3372 case 2: SymAddr = (int32_t)pauVirginData[iFixup].au32[0]; break; 3373 case 3: SymAddr = (int64_t)pauVirginData[iFixup].u; break; 3374 default: RTLDRMODMACHO_FAILED_RETURN(VERR_LDR_BAD_FIXUP); 2919 3375 } 2920 3376 if (Fixup.r.r_pcrel) 2921 SymAddr += Fixup.r.r_address + pFixupSect->LinkAddress;3377 SymAddr += Fixup.r.r_address + uBitsLinkAddr; 2922 3378 2923 3379 /* Add symbol / section address. */ … … 2969 3425 /* adjust for PC relative */ 2970 3426 if (Fixup.r.r_pcrel) 2971 SymAddr -= Fixup.r.r_address + pFixupSect->RVA+ NewBaseAddress;3427 SymAddr -= Fixup.r.r_address + uBitsRva + NewBaseAddress; 2972 3428 } 2973 3429 else … … 2979 3435 /* sanity */ 2980 3436 RTLDRMODMACHO_ASSERT(Fixup.s.r_scattered); 2981 if ((uint32_t)Fixup.s.r_address >= cbSectBits) 2982 return VERR_LDR_BAD_FIXUP; 2983 2984 /* calc fixup addresses. */ 2985 uFix.pv = pbSectBits + Fixup.s.r_address; 2986 uFixVirgin.pv = pbSectVirginBits ? (uint8_t *)pbSectVirginBits + Fixup.s.r_address : 0; 3437 RTLDRMODMACHO_CHECK_RETURN((uint32_t)Fixup.s.r_address + RT_BIT_32(Fixup.s.r_length) <= cbBits, VERR_LDR_BAD_FIXUP); 3438 3439 /* Calc the fixup address. */ 3440 uFix.pv = pbBits + Fixup.s.r_address; 2987 3441 2988 3442 /* … … 2992 3446 switch (Fixup.s.r_length) 2993 3447 { 2994 case 0: SymAddr = *uFixVirgin.pi8; break; 2995 case 1: SymAddr = *uFixVirgin.pi16; break; 2996 case 2: SymAddr = *uFixVirgin.pi32; break; 2997 case 3: SymAddr = *uFixVirgin.pi64; break; 3448 case 0: SymAddr = (int8_t)pauVirginData[iFixup].au8[0]; break; 3449 case 1: SymAddr = (int16_t)pauVirginData[iFixup].au16[0]; break; 3450 case 2: SymAddr = (int32_t)pauVirginData[iFixup].au32[0]; break; 3451 case 3: SymAddr = (int64_t)pauVirginData[iFixup].u; break; 3452 default: RTLDRMODMACHO_FAILED_RETURN(VERR_LDR_BAD_FIXUP); 2998 3453 } 2999 3454 if (Fixup.s.r_pcrel) … … 3021 3476 SymAddr += Value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress; 3022 3477 if (Fixup.s.r_pcrel) 3023 SymAddr -= Fixup.s.r_address + pFixupSect->RVA+ NewBaseAddress;3478 SymAddr -= Fixup.s.r_address + uBitsRva + NewBaseAddress; 3024 3479 3025 3480 Fixup.r.r_length = ((scattered_relocation_info_t *)&paFixups[iFixup])->r_length; … … 3055 3510 * @returns IPRT status code. 3056 3511 * @param pThis The Mach-O module interpreter instance. 3057 * @param pbSectBits Pointer to the section bits. 3512 * @param pbBits Pointer to the section bits. 3513 * @param cbBits Size of the bits to fix up. 3514 * @param uBitsRva The RVA of the bits. 3515 * @param paFixups The fixups. 3516 * @param cFixups Number of fixups. 3517 * @param pauVirginData The virgin data / addends. Parallel to paFixups. 3058 3518 * @param pFixupSect The section being fixed up. 3059 3519 * @param paSyms Pointer to the symbol table. … … 3061 3521 * @param NewBaseAddress The new base image address. 3062 3522 */ 3063 static int kldrModMachOFixupSectionAMD64(PRTLDRMODMACHO pThis, uint8_t *pbSectBits, PRTLDRMODMACHOSECT pFixupSect, 3064 macho_nlist_64_t *paSyms, uint32_t cSyms, RTLDRADDR NewBaseAddress) 3065 { 3066 const macho_relocation_info_t *paFixups = pFixupSect->paFixups; 3067 const uint32_t cFixups = pFixupSect->cFixups; 3068 size_t cbSectBits = (size_t)pFixupSect->cb; 3069 const uint8_t *pbSectVirginBits; 3070 uint32_t iFixup; 3071 RTLDRADDR SymAddr; 3072 int rc; 3073 3074 /* 3075 * Find the virgin bits. 3076 */ 3077 if (pFixupSect->offFile != -1) 3078 { 3079 rc = kldrModMachOMapVirginBits(pThis); 3080 if (RT_FAILURE(rc)) 3081 return rc; 3082 pbSectVirginBits = (const uint8_t *)pThis->pvBits + pFixupSect->offFile; 3083 } 3084 else 3085 pbSectVirginBits = NULL; 3086 3523 static int kldrModMachOApplyFixupsAMD64(PRTLDRMODMACHO pThis, uint8_t *pbBits, size_t cbBits, RTLDRADDR uBitsRva, 3524 const macho_relocation_union_t *paFixups, 3525 const uint32_t cFixups, PCRTUINT64U const pauVirginData, 3526 macho_nlist_64_t *paSyms, uint32_t cSyms, RTLDRADDR NewBaseAddress) 3527 { 3087 3528 /* 3088 3529 * Iterate the fixups and apply them. 3089 3530 */ 3090 for (iFixup = 0; iFixup < cFixups; iFixup++) 3091 { 3092 union 3093 { 3094 macho_relocation_info_t r; 3095 scattered_relocation_info_t s; 3096 } Fixup; 3097 Fixup.r = paFixups[iFixup]; 3531 for (uint32_t iFixup = 0; iFixup < cFixups; iFixup++) 3532 { 3533 macho_relocation_union_t Fixup = paFixups[iFixup]; 3098 3534 3099 3535 /* AMD64 doesn't use scattered fixups. */ … … 3101 3537 3102 3538 /* sanity */ 3103 RTLDRMODMACHO_CHECK_RETURN((uint32_t)Fixup.r.r_address < cbSectBits, VERR_LDR_BAD_FIXUP);3539 RTLDRMODMACHO_CHECK_RETURN((uint32_t)Fixup.r.r_address + RT_BIT_32(Fixup.r.r_length) <= cbBits, VERR_LDR_BAD_FIXUP); 3104 3540 3105 3541 /* calc fixup addresses. */ 3106 3542 RTPTRUNION uFix; 3107 uFix.pv = pbSectBits + Fixup.r.r_address; 3108 RTPTRUNION uFixVirgin; 3109 uFixVirgin.pv = pbSectVirginBits ? (uint8_t *)pbSectVirginBits + Fixup.r.r_address : 0; 3543 uFix.pv = pbBits + Fixup.r.r_address; 3110 3544 3111 3545 /* … … 3113 3547 */ 3114 3548 /* Calc the linked symbol address / addend. */ 3549 RTLDRADDR SymAddr; 3115 3550 switch (Fixup.r.r_length) 3116 3551 { 3117 /** @todo Deal with unaligned accesses on non x86 platforms. */ 3118 case 2: SymAddr = *uFixVirgin.pi32; break; 3119 case 3: SymAddr = *uFixVirgin.pi64; break; 3552 case 2: SymAddr = (int32_t)pauVirginData[iFixup].au32[0]; break; 3553 case 3: SymAddr = (int64_t)pauVirginData[iFixup].u; break; 3120 3554 default: 3121 3555 RTLDRMODMACHO_FAILED_RETURN(VERR_LDR_BAD_FIXUP); … … 3164 3598 default: 3165 3599 { 3166 /* Adjust with fixup specific addend and v ierfy unsigned/r_pcrel. */3600 /* Adjust with fixup specific addend and verify unsigned/r_pcrel. */ 3167 3601 switch (Fixup.r.r_type) 3168 3602 { … … 3198 3632 /* branch to an external symbol may have to take a short detour. */ 3199 3633 if ( Fixup.r.r_type == X86_64_RELOC_BRANCH 3200 && SymAddr + Fixup.r.r_address + pFixupSect->RVA+ NewBaseAddress3634 && SymAddr + Fixup.r.r_address + uBitsRva + NewBaseAddress 3201 3635 - pSym->n_value 3202 3636 + UINT64_C(0x80000000) … … 3222 3656 /* 3223 3657 * This is a weird customer, it will always be follows by an UNSIGNED fixup. 3658 * The value is calculated: target - pair_target. 3659 * Note! The linker generally eliminate these when linking modules rather 3660 * than objects (-r). 3224 3661 */ 3225 3662 case X86_64_RELOC_SUBTRACTOR: 3226 3663 { 3227 macho_relocation_info_t Fixup2;3228 3229 3664 /* Deal with the SUBTRACT symbol first, by subtracting it from SymAddr. */ 3230 3665 switch (pSym->n_type & MACHO_N_TYPE) … … 3254 3689 iFixup++; 3255 3690 RTLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel && iFixup < cFixups, VERR_LDR_BAD_FIXUP); 3256 Fixup2 = paFixups[iFixup];3691 macho_relocation_info_t const Fixup2 = paFixups[iFixup].r; 3257 3692 RTLDRMODMACHO_CHECK_RETURN( Fixup2.r_address == Fixup.r.r_address 3258 3693 && Fixup2.r_length == Fixup.r.r_length … … 3268 3703 RTLDRMODMACHO_CHECK_RETURN(!(pSym->n_type & MACHO_N_STAB), VERR_LDR_BAD_FIXUP); 3269 3704 3270 /* Add it 's value to SymAddr. */3705 /* Add its value to SymAddr. */ 3271 3706 switch (pSym->n_type & MACHO_N_TYPE) 3272 3707 { … … 3297 3732 RTLDRMODMACHO_CHECK_RETURN(Fixup2.r_symbolnum <= pThis->cSections, VERR_LDR_BAD_FIXUP); 3298 3733 pSymSect = &pThis->paSections[Fixup2.r_symbolnum - 1]; 3299 SymAddr += pSymSect->RVA + NewBaseAddress;3734 SymAddr += pSymSect->RVA - pSymSect->LinkAddress + NewBaseAddress; 3300 3735 } 3301 3736 else … … 3344 3779 /* adjust for PC relative */ 3345 3780 if (Fixup.r.r_pcrel) 3346 SymAddr -= Fixup.r.r_address + pFixupSect->RVA+ NewBaseAddress;3781 SymAddr -= Fixup.r.r_address + uBitsRva + NewBaseAddress; 3347 3782 3348 3783 /* … … 3369 3804 3370 3805 /** 3371 * Loads the symbol table for a MH_OBJECT file.3806 * Loads the symbol table (LC_SYMTAB). 3372 3807 * 3373 3808 * The symbol table is pointed to by RTLDRMODMACHO::pvaSymbols. … … 3413 3848 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvSyms, cbSyms, pThis->offSymbols); 3414 3849 if (RT_SUCCESS(rc) && pThis->cchStrings) 3415 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvStrings, 3416 pThis->cchStrings, pThis->offStrings); 3850 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvStrings, pThis->cchStrings, pThis->offStrings); 3417 3851 if (RT_SUCCESS(rc)) 3418 3852 { … … 3470 3904 * @param ppaFixups Where to put the pointer to the allocated fixup array. 3471 3905 */ 3472 static int kldrModMachOLoadFixups(PRTLDRMODMACHO pThis, RTFOFF offFixups, uint32_t cFixups, macho_relocation_info_t **ppaFixups)3473 { 3474 macho_relocation_ info_t *paFixups;3906 static int kldrModMachOLoadFixups(PRTLDRMODMACHO pThis, RTFOFF offFixups, uint32_t cFixups, macho_relocation_union_t **ppaFixups) 3907 { 3908 macho_relocation_union_t *paFixups; 3475 3909 size_t cbFixups; 3476 3910 … … 3478 3912 cbFixups = cFixups * sizeof(*paFixups); 3479 3913 RTLDRMODMACHO_CHECK_RETURN(cbFixups / sizeof(*paFixups) == cFixups, VERR_LDRMACHO_BAD_SYMTAB_SIZE); 3480 paFixups = (macho_relocation_ info_t *)RTMemAlloc(cbFixups);3914 paFixups = (macho_relocation_union_t *)RTMemAlloc(cbFixups); 3481 3915 if (!paFixups) 3482 3916 return VERR_NO_MEMORY; … … 3489 3923 3490 3924 /* do endian conversion if necessary. */ 3491 if ( 3492 || 3925 if ( pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 3926 || pThis->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 3493 3927 { 3494 3928 uint32_t iFixup; … … 3508 3942 3509 3943 /** 3510 * Maps the virgin file bits into memory if not already done.3944 * Loads virgin data (addends) for an array of fixups. 3511 3945 * 3512 3946 * @returns IPRT status code. 3513 * @param pThis The Mach-O module interpreter instance. 3514 */ 3515 static int kldrModMachOMapVirginBits(PRTLDRMODMACHO pThis) 3516 { 3947 * @param pThis The Mach-O module interpreter instance. 3948 * @param pbBits The virgin bits to lift the data from 3949 * @param cbBits The number of virgin bytes. 3950 * @param paFixups The fixups. 3951 * @param cFixups Number of fixups 3952 * @param pszName Name for logging. 3953 * @param ppauVirginData Where to return the virgin data. 3954 */ 3955 static int rtldrMachOLoadVirginData(PRTLDRMODMACHO pThis, uint8_t const *pbBits, size_t cbBits, 3956 macho_relocation_union_t const *paFixups, uint32_t cFixups, const char *pszName, 3957 PRTUINT64U *ppauVirginData) 3958 { 3959 /* 3960 * In case we jettisoned the fixups, we will leave virgin data. 3961 */ 3962 if (*ppauVirginData) 3963 return VINF_SUCCESS; 3964 3965 #ifdef LOG_ENABLED 3966 /* 3967 * Ensure that we've got the symbol table if we're logging fixups. 3968 */ 3969 if (LogIs5Enabled()) 3970 { 3971 int rc = kldrModMachOLoadObjSymTab(pThis); 3972 if (RT_FAILURE(rc)) 3973 return rc; 3974 } 3975 #endif 3976 3977 3978 /* 3979 * Allocate memory and iterate the fixups to get the data. 3980 */ 3981 PRTUINT64U pauVirginData = *ppauVirginData = (PRTUINT64U)RTMemAllocZ(sizeof(uint64_t) * cFixups); 3982 if (pauVirginData) 3983 { 3984 Log5(("Fixups for %s: (%u)\n", pszName, cFixups)); 3985 for (uint32_t i = 0; i < cFixups; i++) 3986 { 3987 uint32_t off; 3988 uint32_t cShift; 3989 if (!paFixups[i].s.r_scattered) 3990 { 3991 off = paFixups[i].r.r_address; 3992 cShift = paFixups[i].r.r_length; 3993 } 3994 else 3995 { 3996 off = paFixups[i].s.r_address; 3997 cShift = paFixups[i].s.r_length; 3998 } 3999 RTLDRMODMACHO_CHECK_RETURN(off + RT_BIT_32(cShift) <= cbBits, VERR_LDR_BAD_FIXUP); 4000 4001 /** @todo This ASSUMES same endian in the image and on the host. Would need 4002 * to check target cpu (pThis->Core.enmArch) endianness against host to get 4003 * it right... (outside the loop, obviously) */ 4004 switch (cShift) 4005 { 4006 case 3: 4007 pauVirginData[i].u = RT_MAKE_U64_FROM_U8(pbBits[off], pbBits[off + 1], pbBits[off + 2], pbBits[off + 3], 4008 pbBits[off + 4], pbBits[off + 5], pbBits[off + 6], pbBits[off + 7]); 4009 break; 4010 case 2: 4011 pauVirginData[i].u = (int32_t)RT_MAKE_U32_FROM_U8(pbBits[off], pbBits[off + 1], pbBits[off + 2], pbBits[off + 3]); 4012 break; 4013 case 1: 4014 pauVirginData[i].u = (int16_t)RT_MAKE_U16(pbBits[off], pbBits[off + 1]); 4015 break; 4016 case 0: 4017 pauVirginData[i].u = (int8_t)pbBits[off]; 4018 break; 4019 default: 4020 RTLDRMODMACHO_FAILED_RETURN(VERR_LDR_BAD_FIXUP); 4021 } 4022 4023 #ifdef LOG_ENABLED 4024 if (LogIs5Enabled()) 4025 { 4026 if (!paFixups[i].s.r_scattered) 4027 { 4028 Log5((" #%06x: %#08x LB %u: t=%#x pc=%u ex=%u sym=%#010x add=%#RX64\n", 4029 i, off, RT_BIT_32(cShift), paFixups[i].r.r_type, paFixups[i].r.r_pcrel, paFixups[i].r.r_extern, 4030 paFixups[i].r.r_symbolnum, pauVirginData[i].u)); 4031 if (paFixups[i].r.r_symbolnum < pThis->cSymbols) 4032 { 4033 if (pThis->Hdr.magic == IMAGE_MACHO64_SIGNATURE || pThis->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 4034 { 4035 macho_nlist_64_t const *pSym = (macho_nlist_64_t const *)pThis->pvaSymbols + paFixups[i].r.r_symbolnum; 4036 Log5((" sym: %#04x:%#018RX64 t=%#04x d=%#06x %s\n", 4037 pSym->n_sect, pSym->n_value, pSym->n_type, pSym->n_desc, 4038 pSym->n_un.n_strx < pThis->cchStrings ? &pThis->pchStrings[pSym->n_un.n_strx] : "")); 4039 4040 } 4041 else 4042 { 4043 macho_nlist_32_t const *pSym = (macho_nlist_32_t const *)pThis->pvaSymbols + paFixups[i].r.r_symbolnum; 4044 Log5((" sym: %#04x:%#010RX32 t=%#04x d=%#06x %s\n", 4045 pSym->n_sect, pSym->n_value, pSym->n_type, pSym->n_desc, 4046 (uint32_t)pSym->n_un.n_strx < pThis->cchStrings ? &pThis->pchStrings[pSym->n_un.n_strx] : "")); 4047 } 4048 } 4049 } 4050 else 4051 Log5((" #%06x: %#08x LB %u: t=%#x pc=%u val=%#010x add=%#RX64\n", i, off, RT_BIT_32(cShift), 4052 paFixups[i].s.r_type, paFixups[i].s.r_pcrel, paFixups[i].s.r_value, pauVirginData[i].u)); 4053 } 4054 #endif 4055 } 4056 return VINF_SUCCESS; 4057 } 4058 RT_NOREF(pThis, pszName); 4059 return VERR_NO_MEMORY; 4060 } 4061 4062 4063 /** 4064 * MH_OBJECT: Loads fixups and addends for each section. 4065 * 4066 * @returns IPRT status code. 4067 * @param pThis The Mach-O module interpreter instance. 4068 * @param pbBits The image bits. First time we're called, these are 4069 * ASSUMED to be in virgin state and suitable for 4070 * saving addends. 4071 */ 4072 static int rtldrMachOObjLoadFixupsAndVirginData(PRTLDRMODMACHO pThis, uint8_t const *pbBits) 4073 { 4074 PRTLDRMODMACHOSECT pSect = pThis->paSections; 4075 for (uint32_t i = 0; i < pThis->cSections; i++, pSect++) 4076 if ( !pSect->paFixups 4077 && pSect->cFixups > 0) 4078 { 4079 /* 4080 * Load and endian convert the fixups. 4081 */ 4082 int rc = kldrModMachOLoadFixups(pThis, pSect->offFixups, pSect->cFixups, &pSect->paFixups); 4083 if (RT_SUCCESS(rc)) 4084 { 4085 /* 4086 * Save virgin data (addends) for each fixup. 4087 */ 4088 rc = rtldrMachOLoadVirginData(pThis, &pbBits[(size_t)pSect->RVA], (size_t)pSect->cb, pSect->paFixups, pSect->cFixups, 4089 pThis->aSegments[pSect->iSegment].SegInfo.pszName, &pSect->pauFixupVirginData); 4090 if (RT_SUCCESS(rc)) 4091 continue; 4092 4093 RTMemFree(pSect->pauFixupVirginData); 4094 pSect->pauFixupVirginData = NULL; 4095 RTMemFree(pSect->paFixups); 4096 pSect->paFixups = NULL; 4097 } 4098 return rc; 4099 } 4100 4101 return VINF_SUCCESS; 4102 } 4103 4104 4105 /** 4106 * Dylib: Loads fixups and addends. 4107 * 4108 * @returns IPRT status code. 4109 * @param pThis The Mach-O module interpreter instance. 4110 * @param pbBits The image bits. First time we're called, these are 4111 * ASSUMED to be in virgin state and suitable for 4112 * saving addends. 4113 */ 4114 static int rtldrMachODylibLoadFixupsAndVirginData(PRTLDRMODMACHO pThis, uint8_t const *pbBits) 4115 { 4116 /* 4117 * Don't do it again if we already loaded them. 4118 */ 4119 if (pThis->paRelocations) 4120 { 4121 Assert(pThis->pauRelocationsVirginData); 4122 return VINF_SUCCESS; 4123 } 4124 4125 /* 4126 * There must be a LC_DYSYMTAB. Fixups are optionals. 4127 */ 4128 dysymtab_command_t const *pDySymTab = pThis->pDySymTab; 4129 AssertReturn(pDySymTab, VERR_INTERNAL_ERROR_2); 4130 uint32_t cRelocations = pDySymTab->nlocrel + pDySymTab->nextrel; 4131 if (cRelocations == 0) 4132 return VINF_SUCCESS; 4133 4134 /* 4135 * Load fixups. 4136 */ 3517 4137 int rc = VINF_SUCCESS; 3518 if (!pThis->pvBits) 3519 rc = pThis->Core.pReader->pfnMap(pThis->Core.pReader, &pThis->pvBits); 4138 uint32_t *paRawRelocs = (uint32_t *)RTMemAlloc(cRelocations * sizeof(macho_relocation_union_t)); 4139 if (paRawRelocs) 4140 { 4141 pThis->paRelocations = (macho_relocation_union_t *)paRawRelocs; 4142 4143 if (pDySymTab->nextrel) 4144 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, paRawRelocs, 4145 pDySymTab->nextrel * sizeof(macho_relocation_union_t), pDySymTab->extreloff); 4146 if (pDySymTab->nlocrel && RT_SUCCESS(rc)) 4147 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, 4148 (uint8_t *)paRawRelocs + pDySymTab->nextrel * sizeof(macho_relocation_union_t), 4149 pDySymTab->nlocrel * sizeof(macho_relocation_union_t), pDySymTab->locreloff); 4150 if (RT_SUCCESS(rc)) 4151 { 4152 /* Byte swap if needed. */ 4153 if ( pThis->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 4154 || pThis->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 4155 { 4156 for (uint32_t i = 0; i < cRelocations; i++) 4157 { 4158 paRawRelocs[i * 2] = RT_BSWAP_U32(paRawRelocs[i * 2]); 4159 paRawRelocs[i * 2 + 1] = RT_BSWAP_U32(paRawRelocs[i * 2 + 1]); 4160 } 4161 ASMCompilerBarrier(); 4162 } 4163 4164 /* 4165 * Load virgin data (addends). 4166 */ 4167 rc = rtldrMachOLoadVirginData(pThis, pbBits, (size_t)pThis->cbImage, pThis->paRelocations, cRelocations, 4168 "whole-image", &pThis->pauRelocationsVirginData); 4169 if (RT_SUCCESS(rc)) 4170 return VINF_SUCCESS; 4171 4172 RTMemFree(pThis->pauRelocationsVirginData); 4173 pThis->pauRelocationsVirginData = NULL; 4174 } 4175 RTMemFree(pThis->paRelocations); 4176 pThis->paRelocations = NULL; 4177 } 4178 else 4179 rc = VERR_NO_MEMORY; 3520 4180 return rc; 3521 4181 } … … 3558 4218 #endif 3559 4219 3560 3561 4220 /** 3562 4221 * @interface_method_impl{RTLDROPS,pfnGetImageSize} … … 3593 4252 if ( pThis->aSegments[i].SegInfo.cbFile == -1 3594 4253 || pThis->aSegments[i].SegInfo.offFile == -1 3595 || pThis->aSegments[i].SegInfo.LinkAddress == NIL_RTLDRADDR 4254 || pThis->aSegments[i].SegInfo.RVA == NIL_RTLDRADDR 4255 || pThis->aSegments[i].SegInfo.cbMapped == 0 3596 4256 || !pThis->aSegments[i].SegInfo.Alignment) 3597 4257 continue; … … 3619 4279 PRTLDRMODMACHO pThis = RT_FROM_MEMBER(pMod, RTLDRMODMACHO, Core); 3620 4280 int rc; 3621 RT_NOREF(OldBaseAddress);3622 4281 3623 4282 /* … … 3626 4285 if (pThis->Hdr.filetype == MH_OBJECT) 3627 4286 { 3628 rc = kldrModMachOObjDoImports(pThis, NewBaseAddress, pfnGetImport, pvUser); 4287 rc = rtldrMachOObjLoadFixupsAndVirginData(pThis, (uint8_t const *)pvBits); 4288 if (RT_SUCCESS(rc)) 4289 rc = kldrModMachOObjDoImports(pThis, NewBaseAddress, pfnGetImport, pvUser); 3629 4290 if (RT_SUCCESS(rc)) 3630 4291 rc = kldrModMachOObjDoFixups(pThis, pvBits, NewBaseAddress); … … 3632 4293 } 3633 4294 else 3634 rc = VERR_LDRMACHO_TODO; 3635 /*{ 3636 rc = kldrModMachODoFixups(pThis, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser); 4295 { 4296 rc = rtldrMachODylibLoadFixupsAndVirginData(pThis, (uint8_t const *)pvBits); 3637 4297 if (RT_SUCCESS(rc)) 3638 rc = kldrModMachODoImports(pThis, pvBits, pfnGetImport, pvUser); 3639 }*/ 4298 rc = kldrModMachODylibDoImports(pThis, NewBaseAddress, pfnGetImport, pvUser); 4299 if (RT_SUCCESS(rc)) 4300 rc = kldrModMachODylibDoIndirectSymbols(pThis, pvBits, NewBaseAddress - OldBaseAddress); 4301 if (RT_SUCCESS(rc)) 4302 rc = kldrModMachODylibDoFixups(pThis, pvBits, NewBaseAddress); 4303 } 3640 4304 3641 4305 /* … … 4069 4733 for (uint32_t iSlot = 0; iSlot < cSlots; iSlot++) 4070 4734 { 4735 /* 4736 * Check that the data offset is valid. There appears to be no alignment 4737 * requirements here, which is a little weird consindering the PPC heritage. 4738 */ 4071 4739 uint32_t const offData = RT_BE2H_U32(pSuper->aSlots[iSlot].offData); 4072 4740 if ( offData < offFirst 4073 || offData > cbBlob - sizeof(RTCRAPLCSHDR) 4074 || (offData & 3)) 4741 || offData > cbBlob - sizeof(RTCRAPLCSHDR)) 4075 4742 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT, 4076 4743 "Slot #%u has an invalid data offset: %#x (min %#x, max %#x-4)",
Note:
See TracChangeset
for help on using the changeset viewer.