Changeset 58 in kStuff
- Timestamp:
- Oct 12, 2013 8:18:21 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/k/kErrors.h
r54 r58 208 208 /** The image has no UUID. */ 209 209 #define KLDR_ERR_NO_IMAGE_UUID (KLDR_ERR_BASE + 38) 210 /** Duplicate segment name. */ 211 #define KLDR_ERR_DUPLICATE_SEGMENT_NAME (KLDR_ERR_BASE + 39) 210 212 /** @} */ 211 213 … … 214 216 */ 215 217 /** The base of the kLdrModPE specific status codes. */ 216 #define KLDR_ERR_PE_BASE (KLDR_ERR_BASE + 39)218 #define KLDR_ERR_PE_BASE (KLDR_ERR_BASE + 40) 217 219 /** The machine isn't supported by the interpreter. */ 218 220 #define KLDR_ERR_PE_UNSUPPORTED_MACHINE (KLDR_ERR_PE_BASE + 0) … … 303 305 /** Unsupported fixup type. */ 304 306 #define KLDR_ERR_MACHO_UNSUPPORTED_FIXUP_TYPE (KLDR_ERR_MACHO_BASE + 16) 307 /** Both debug and non-debug sections in segment. */ 308 #define KLDR_ERR_MACHO_MIXED_DEBUG_SECTION_FLAGS (KLDR_ERR_MACHO_BASE + 17) 309 /** The segment bits are non-contiguous in the file. */ 310 #define KLDR_ERR_MACHO_NON_CONT_SEG_BITS (KLDR_ERR_MACHO_BASE + 18) 305 311 /** @} */ 306 312 … … 309 315 */ 310 316 /** The base of the kCpu specific status codes. */ 311 #define KCPU_ERR_BASE (KLDR_ERR_MACHO_BASE + 1 8)317 #define KCPU_ERR_BASE (KLDR_ERR_MACHO_BASE + 19) 312 318 /** The specified ARCH+CPU pairs aren't compatible. */ 313 319 #define KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE (KCPU_ERR_BASE + 0) -
trunk/include/k/kLdr.h
r54 r58 366 366 367 367 368 /** @name KLDRMOD::fFlags 369 * @{ */ 370 /** The link address doesn't form a contiguous image, from the first to the 371 * last segment. */ 372 #define KLDRMOD_FLAGS_NON_CONTIGUOUS_LINK_ADDRS K_BIT32(0) 373 /** @} */ 374 368 375 /** Pointer to a module interpreter method table. */ 369 376 typedef struct KLDRMODOPS *PKLDRMODOPS; … … 390 397 /** The endian used by the module. */ 391 398 KLDRENDIAN enmEndian; 399 /** Module falgs. */ 400 KU32 fFlags; 392 401 /** The filename length (bytes). */ 393 402 KU32 cchFilename; -
trunk/kLdr/kLdrModLX.c
r54 r58 302 302 pMod->pszName = NULL; /* finalized further down */ 303 303 pMod->cchName = 0; 304 pMod->fFlags = 0; 304 305 switch (Hdr.e32_cpu) 305 306 { -
trunk/kLdr/kLdrModMachO.c
r57 r58 63 63 #endif 64 64 65 /** @def KLDRMODMACHO_CHECK_RETURN 66 * Checks that an expression is true and return if it isn't. 67 * This is a debug aid. 68 */ 69 #ifdef KLDRMODMACHO_STRICT2 70 # define KLDRMODMACHO_FAILED_RETURN(rc) kHlpAssertFailedReturn(rc) 71 #else 72 # define KLDRMODMACHO_FAILED_RETURN(rc) return (rc) 73 #endif 74 65 75 66 76 /******************************************************************************* … … 399 409 pMod->pszName = kHlpGetFilename(pMod->pszFilename); 400 410 pMod->cchName = cchFilename - (pMod->pszName - pMod->pszFilename); 411 pMod->fFlags = 0; 401 412 switch (s.Hdr32.cputype) 402 413 { … … 535 546 } u; 536 547 const KU64 cbFile = kRdrSize(pRdr) - offImage; 537 const char *pchCurSegName = NULL;538 548 KU32 cSegments = 0; 539 549 KU32 cSections = 0; … … 560 570 * Convert and validate command header. 561 571 */ 562 if (cbLeft < sizeof(load_command_t)) 563 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 572 KLDRMODMACHO_CHECK_RETURN(cbLeft >= sizeof(load_command_t), KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 564 573 if (fConvertEndian) 565 574 { … … 567 576 u.pLoadCmd->cmdsize = K_E2E_U32(u.pLoadCmd->cmdsize); 568 577 } 569 if (u.pLoadCmd->cmdsize > cbLeft) 570 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 578 KLDRMODMACHO_CHECK_RETURN(u.pLoadCmd->cmdsize <= cbLeft, KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 571 579 cbLeft -= u.pLoadCmd->cmdsize; 572 580 pb += u.pLoadCmd->cmdsize; … … 579 587 case LC_SEGMENT_32: 580 588 { 581 section_32_t *pSect; 582 section_32_t *pFirstSect; 583 KU32 cSectionsLeft; 584 585 /* convert and verify*/ 586 if (u.pLoadCmd->cmdsize < sizeof(segment_command_32_t)) 587 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 588 if ( pHdr->magic != IMAGE_MACHO32_SIGNATURE_OE 589 && pHdr->magic != IMAGE_MACHO32_SIGNATURE) 590 return KLDR_ERR_MACHO_BIT_MIX; 589 segment_command_32_t *pSrcSeg = (segment_command_32_t *)u.pLoadCmd; 590 section_32_t *pFirstSect = (section_32_t *)(pSrcSeg + 1); 591 section_32_t *pSect = pFirstSect; 592 KU32 cSectionsLeft = pSrcSeg->nsects; 593 KU64 offSect = 0; 594 KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF") 595 || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); 596 597 /* Convert and verify the segment. */ 598 KLDRMODMACHO_CHECK_RETURN(u.pLoadCmd->cmdsize >= sizeof(segment_command_32_t), KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 599 KLDRMODMACHO_CHECK_RETURN( pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 600 || pHdr->magic == IMAGE_MACHO32_SIGNATURE, KLDR_ERR_MACHO_BIT_MIX); 591 601 if (fConvertEndian) 592 602 { 593 u.pSeg32->vmaddr = K_E2E_U32(u.pSeg32->vmaddr);594 u.pSeg32->vmsize = K_E2E_U32(u.pSeg32->vmsize);595 u.pSeg32->fileoff = K_E2E_U32(u.pSeg32->fileoff);596 u.pSeg32->filesize = K_E2E_U32(u.pSeg32->filesize);597 u.pSeg32->maxprot = K_E2E_U32(u.pSeg32->maxprot);598 u.pSeg32->initprot = K_E2E_U32(u.pSeg32->initprot);599 u.pSeg32->nsects = K_E2E_U32(u.pSeg32->nsects);600 u.pSeg32->flags = K_E2E_U32(u.pSeg32->flags);603 pSrcSeg->vmaddr = K_E2E_U32(pSrcSeg->vmaddr); 604 pSrcSeg->vmsize = K_E2E_U32(pSrcSeg->vmsize); 605 pSrcSeg->fileoff = K_E2E_U32(pSrcSeg->fileoff); 606 pSrcSeg->filesize = K_E2E_U32(pSrcSeg->filesize); 607 pSrcSeg->maxprot = K_E2E_U32(pSrcSeg->maxprot); 608 pSrcSeg->initprot = K_E2E_U32(pSrcSeg->initprot); 609 pSrcSeg->nsects = K_E2E_U32(pSrcSeg->nsects); 610 pSrcSeg->flags = K_E2E_U32(pSrcSeg->flags); 601 611 } 602 612 603 if ( u.pSeg32->filesize 604 && ( u.pSeg32->fileoff > cbFile 605 || (KU64)u.pSeg32->fileoff + u.pSeg32->filesize > cbFile)) 606 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 607 if (u.pSeg32->vmsize < u.pSeg32->filesize) 608 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 609 if ((u.pSeg32->maxprot & u.pSeg32->initprot) != u.pSeg32->initprot) 610 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 611 if (u.pSeg32->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1)) 612 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 613 if (u.pSeg32->nsects * sizeof(section_32_t) > u.pLoadCmd->cmdsize - sizeof(segment_command_32_t)) 614 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 615 if ( pHdr->filetype == MH_OBJECT 616 && cSegmentCommands > 0) 617 return KLDR_ERR_MACHO_BAD_OBJECT_FILE; 618 cSegmentCommands++; 613 /* Validation code shared with the 64-bit variant. */ 614 #define VALIDATE_AND_ADD_SEGMENT(a_cBits) \ 615 do { \ 616 KLDRMODMACHO_CHECK_RETURN( pSrcSeg->filesize == 0 \ 617 || ( pSrcSeg->fileoff <= cbFile \ 618 && (KU64)pSrcSeg->fileoff + pSrcSeg->filesize <= cbFile), \ 619 KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \ 620 KLDRMODMACHO_CHECK_RETURN(pSrcSeg->filesize <= pSrcSeg->vmsize, \ 621 KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \ 622 KLDRMODMACHO_CHECK_RETURN((pSrcSeg->maxprot & pSrcSeg->initprot) == pSrcSeg->initprot, \ 623 KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \ 624 KLDRMODMACHO_CHECK_RETURN(!(pSrcSeg->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1)), \ 625 KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \ 626 KLDRMODMACHO_CHECK_RETURN( pSrcSeg->nsects * sizeof(section_##a_cBits##_t) \ 627 <= u.pLoadCmd->cmdsize - sizeof(segment_command_##a_cBits##_t), \ 628 KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \ 629 KLDRMODMACHO_CHECK_RETURN( pHdr->filetype != MH_OBJECT \ 630 || cSegmentCommands == 0,\ 631 KLDR_ERR_MACHO_BAD_OBJECT_FILE); \ 632 cSegmentCommands++; \ 633 \ 634 /* add the segment. */ \ 635 if (!fSkipSeg) \ 636 { \ 637 cbStringPool += kHlpStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)) + 1; \ 638 cSegments++; \ 639 \ 640 /* Link address lower? */ \ 641 if (*pLinkAddress > pSrcSeg->vmaddr) \ 642 *pLinkAddress = pSrcSeg->vmaddr; \ 643 } \ 644 } while (0) 645 646 VALIDATE_AND_ADD_SEGMENT(32); 619 647 620 648 /* 621 * convert, validate and parse the sections.649 * Convert, validate and parse the sections. 622 650 */ 623 cSectionsLeft = u.pSeg32->nsects;624 pFirstSect = pSect = (section_32_t *)( u.pSeg32+ 1);651 cSectionsLeft = pSrcSeg->nsects; 652 pFirstSect = pSect = (section_32_t *)(pSrcSeg + 1); 625 653 while (cSectionsLeft-- > 0) 626 654 { 627 int fFileBits;628 629 655 if (fConvertEndian) 630 656 { … … 640 666 } 641 667 642 /* validate */ 643 switch (pSect->flags & SECTION_TYPE) 644 { 645 case S_ZEROFILL: 646 if (pSect->reserved1 || pSect->reserved2) 647 return KLDR_ERR_MACHO_BAD_SECTION; 648 fFileBits = 0; 649 break; 650 case S_REGULAR: 651 case S_CSTRING_LITERALS: 652 case S_COALESCED: 653 case S_4BYTE_LITERALS: 654 case S_8BYTE_LITERALS: 655 case S_16BYTE_LITERALS: 656 if (pSect->reserved1 || pSect->reserved2) 657 return KLDR_ERR_MACHO_BAD_SECTION; 658 fFileBits = 1; 659 break; 660 661 case S_SYMBOL_STUBS: 662 if ( pSect->reserved1 663 || pSect->reserved2 > 64 /* stub size */ ) 664 return KLDR_ERR_MACHO_BAD_SECTION; 665 fFileBits = 1; 666 break; 667 668 case S_NON_LAZY_SYMBOL_POINTERS: 669 case S_LAZY_SYMBOL_POINTERS: 670 if (pSect->reserved2) /* (reserved 1 is indirect symbol table index)*/ 671 return KLDR_ERR_MACHO_BAD_SECTION; 672 *pfCanLoad = K_FALSE; 673 fFileBits = -1; /* __DATA.__got in the 64-bit mach_kernel has bits, any things without bits? */ 674 break; 675 676 case S_MOD_INIT_FUNC_POINTERS: /** @todo this requires a query API or flag... (e.g. C++ constructors) */ 677 if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) 678 return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION; 679 case S_MOD_TERM_FUNC_POINTERS: /** @todo this requires a query API or flag... (e.g. C++ destructors) */ 680 if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) 681 return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION; 682 if (pSect->reserved1 || pSect->reserved2) 683 return KLDR_ERR_MACHO_BAD_SECTION; 684 fFileBits = 1; 685 break; /* ignored */ 686 687 case S_LITERAL_POINTERS: 688 case S_INTERPOSING: 689 case S_GB_ZEROFILL: 690 return KLDR_ERR_MACHO_UNSUPPORTED_SECTION; 691 692 default: 693 return KLDR_ERR_MACHO_UNKNOWN_SECTION; 694 } 695 if (pSect->flags & ~( S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS 696 | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE 697 | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC 698 | S_ATTR_LOC_RELOC | SECTION_TYPE)) 699 return KLDR_ERR_MACHO_BAD_SECTION; 700 if ( pSect->addr - u.pSeg32->vmaddr > u.pSeg32->vmsize 701 || pSect->addr - u.pSeg32->vmaddr + pSect->size > u.pSeg32->vmsize) 702 return KLDR_ERR_MACHO_BAD_SECTION; 703 if ( pSect->align >= 31 704 || (((1 << pSect->align) - 1) & pSect->addr) 705 || (((1 << pSect->align) - 1) & u.pSeg32->vmaddr)) 706 return KLDR_ERR_MACHO_BAD_SECTION; 707 if ( fFileBits 708 && ( pSect->offset > cbFile 709 || (KU64)pSect->offset + pSect->size > cbFile)) 710 return KLDR_ERR_MACHO_BAD_SECTION; 711 if (!fFileBits && pSect->offset) 712 return KLDR_ERR_MACHO_BAD_SECTION; 713 if (!pSect->nreloc && pSect->reloff) 714 return KLDR_ERR_MACHO_BAD_SECTION; 715 if ( pSect->nreloc 716 && ( pSect->reloff > cbFile 717 || (KU64)pSect->reloff + (KLDRFOFF)pSect->nreloc * sizeof(macho_relocation_info_t)) > cbFile) 718 return KLDR_ERR_MACHO_BAD_SECTION; 719 720 721 /* count segments and strings, calculate image link address. */ 722 switch (pHdr->filetype) 723 { 724 case MH_OBJECT: 725 case MH_EXECUTE: 726 case MH_DYLIB: 727 case MH_DSYM: 728 case MH_KEXT_BUNDLE: 729 { 730 cSections++; 731 732 /* Don't load debug symbols. */ 733 if ( (pSect->flags & S_ATTR_DEBUG) 734 || !kHlpStrComp(pSect->segname, "__DWARF")) 735 break; 736 737 /* a new segment? */ 738 if ( !pchCurSegName 739 || kHlpStrNComp(pSect->segname, pchCurSegName, sizeof(pSect->segname))) 740 { 741 #if 0 /** @todo This doesn't work because of BSS. */ 742 /* verify that the linker/assembler has ordered sections correctly. */ 743 section_32_t *pCur = (pSect - 2); 744 while ((KUPTR)pCur >= (KUPTR)pFirstSect) 745 { 746 if (!kHlpStrNComp(pCur->segname, pSect->segname, sizeof(pSect->segname))) 747 return KLDR_ERR_MACHO_BAD_SECTION_ORDER; 748 pCur--; 749 } 750 #endif 751 752 /* ok. count it and the string. */ 753 pchCurSegName = &pSect->segname[0]; 754 cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; 755 cSegments++; 756 757 /* Link address lower? */ 758 if (*pLinkAddress > u.pSeg32->vmaddr) 759 *pLinkAddress = u.pSeg32->vmaddr; 760 } 761 break; 762 } 763 764 default: 765 return KERR_INVALID_PARAMETER; 766 } 668 /* Validation code shared with the 64-bit variant. */ 669 #define VALIDATE_AND_ADD_SECTION(a_cBits) \ 670 do { \ 671 int fFileBits; \ 672 \ 673 /* validate */ \ 674 KLDRMODMACHO_CHECK_RETURN(!kHlpStrComp(pSect->segname, pSrcSeg->segname),\ 675 KLDR_ERR_MACHO_BAD_SECTION); \ 676 \ 677 switch (pSect->flags & SECTION_TYPE) \ 678 { \ 679 case S_ZEROFILL: \ 680 KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \ 681 KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \ 682 fFileBits = 0; \ 683 break; \ 684 case S_REGULAR: \ 685 case S_CSTRING_LITERALS: \ 686 case S_COALESCED: \ 687 case S_4BYTE_LITERALS: \ 688 case S_8BYTE_LITERALS: \ 689 case S_16BYTE_LITERALS: \ 690 KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \ 691 KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \ 692 fFileBits = 1; \ 693 break; \ 694 \ 695 case S_SYMBOL_STUBS: \ 696 KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \ 697 /* reserved2 == stub size. 0 has been seen (corecrypto.kext) */ \ 698 KLDRMODMACHO_CHECK_RETURN(pSect->reserved2 > 64, KLDR_ERR_MACHO_BAD_SECTION); \ 699 fFileBits = 1; \ 700 break; \ 701 \ 702 case S_NON_LAZY_SYMBOL_POINTERS: \ 703 case S_LAZY_SYMBOL_POINTERS: \ 704 /* (reserved 1 = is indirect symbol table index) */ \ 705 KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \ 706 *pfCanLoad = K_FALSE; \ 707 fFileBits = -1; /* __DATA.__got in the 64-bit mach_kernel has bits, any things without bits? */ \ 708 break; \ 709 \ 710 case S_MOD_INIT_FUNC_POINTERS: \ 711 /** @todo this requires a query API or flag... (e.g. C++ constructors) */ \ 712 KLDRMODMACHO_CHECK_RETURN(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO, \ 713 KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION); \ 714 case S_MOD_TERM_FUNC_POINTERS: \ 715 /** @todo this requires a query API or flag... (e.g. C++ destructors) */ \ 716 KLDRMODMACHO_CHECK_RETURN(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO, \ 717 KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION); \ 718 KLDRMODMACHO_CHECK_RETURN(!pSect->reserved1, KLDR_ERR_MACHO_BAD_SECTION); \ 719 KLDRMODMACHO_CHECK_RETURN(!pSect->reserved2, KLDR_ERR_MACHO_BAD_SECTION); \ 720 fFileBits = 1; \ 721 break; /* ignored */ \ 722 \ 723 case S_LITERAL_POINTERS: \ 724 case S_INTERPOSING: \ 725 case S_GB_ZEROFILL: \ 726 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNSUPPORTED_SECTION); \ 727 \ 728 default: \ 729 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNKNOWN_SECTION); \ 730 } \ 731 KLDRMODMACHO_CHECK_RETURN(!(pSect->flags & ~( S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS \ 732 | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE \ 733 | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC \ 734 | S_ATTR_LOC_RELOC | SECTION_TYPE)), \ 735 KLDR_ERR_MACHO_BAD_SECTION); \ 736 KLDRMODMACHO_CHECK_RETURN((pSect->flags & S_ATTR_DEBUG) == (pSect->flags & S_ATTR_DEBUG), \ 737 KLDR_ERR_MACHO_MIXED_DEBUG_SECTION_FLAGS); \ 738 \ 739 KLDRMODMACHO_CHECK_RETURN(pSect->addr - pSrcSeg->vmaddr <= pSrcSeg->vmsize, \ 740 KLDR_ERR_MACHO_BAD_SECTION); \ 741 KLDRMODMACHO_CHECK_RETURN(pSect->addr - pSrcSeg->vmaddr + pSect->size <= pSrcSeg->vmsize, \ 742 KLDR_ERR_MACHO_BAD_SECTION); \ 743 KLDRMODMACHO_CHECK_RETURN(pSect->align < 31, \ 744 KLDR_ERR_MACHO_BAD_SECTION); \ 745 KLDRMODMACHO_CHECK_RETURN(!((K_BIT32(pSect->align) - KU32_C(1)) & pSect->addr), \ 746 KLDR_ERR_MACHO_BAD_SECTION); \ 747 KLDRMODMACHO_CHECK_RETURN(!((K_BIT32(pSect->align) - KU32_C(1)) & pSrcSeg->vmaddr), \ 748 KLDR_ERR_MACHO_BAD_SECTION); \ 749 \ 750 /* Adjust the section offset before we check file offset. */ \ 751 offSect = (offSect + K_BIT64(pSect->align) - KU64_C(1)) & ~(K_BIT64(pSect->align) - KU64_C(1)); \ 752 if (pSect->addr) \ 753 { \ 754 KLDRMODMACHO_CHECK_RETURN(offSect <= pSect->addr - pSrcSeg->vmaddr, KLDR_ERR_MACHO_BAD_SECTION); \ 755 if (offSect < pSect->addr - pSrcSeg->vmaddr) \ 756 offSect = pSect->addr - pSrcSeg->vmaddr; \ 757 } \ 758 \ 759 if (fFileBits && pSect->offset == 0 && pSrcSeg->fileoff == 0 && pHdr->filetype == MH_DSYM) \ 760 fFileBits = 0; \ 761 if (fFileBits) \ 762 { \ 763 KLDRMODMACHO_CHECK_RETURN(pSect->offset == pSrcSeg->fileoff + offSect, \ 764 KLDR_ERR_MACHO_NON_CONT_SEG_BITS); \ 765 KLDRMODMACHO_CHECK_RETURN(pSect->offset - pSrcSeg->fileoff <= pSrcSeg->filesize, \ 766 KLDR_ERR_MACHO_BAD_SECTION); \ 767 KLDRMODMACHO_CHECK_RETURN(pSect->offset <= cbFile, \ 768 KLDR_ERR_MACHO_BAD_SECTION); \ 769 KLDRMODMACHO_CHECK_RETURN((KU64)pSect->offset + pSect->size <= cbFile, \ 770 KLDR_ERR_MACHO_BAD_SECTION); \ 771 } \ 772 else \ 773 KLDRMODMACHO_CHECK_RETURN(pSect->offset == 0, KLDR_ERR_MACHO_BAD_SECTION); \ 774 \ 775 if (!pSect->nreloc) \ 776 KLDRMODMACHO_CHECK_RETURN(!pSect->reloff, \ 777 KLDR_ERR_MACHO_BAD_SECTION); \ 778 else \ 779 { \ 780 KLDRMODMACHO_CHECK_RETURN(pSect->reloff <= cbFile, \ 781 KLDR_ERR_MACHO_BAD_SECTION); \ 782 KLDRMODMACHO_CHECK_RETURN( (KU64)pSect->reloff \ 783 + (KLDRFOFF)pSect->nreloc * sizeof(macho_relocation_info_t) \ 784 <= cbFile, \ 785 KLDR_ERR_MACHO_BAD_SECTION); \ 786 } \ 787 \ 788 /* validate against file type (pointless?) and count the section. */ \ 789 switch (pHdr->filetype) \ 790 { \ 791 case MH_OBJECT: \ 792 case MH_EXECUTE: \ 793 case MH_DYLIB: \ 794 case MH_DSYM: \ 795 case MH_KEXT_BUNDLE: \ 796 cSections++; \ 797 break; \ 798 default: \ 799 KLDRMODMACHO_FAILED_RETURN(KERR_INVALID_PARAMETER); \ 800 } \ 801 \ 802 /* Advance the section offset, since we're also aligning it. */ \ 803 offSect += pSect->size; \ 804 } while (0) /* VALIDATE_AND_ADD_SECTION */ 805 806 VALIDATE_AND_ADD_SECTION(32); 767 807 768 808 /* next */ … … 774 814 case LC_SEGMENT_64: 775 815 { 776 section_64_t *pSect; 777 section_64_t *pFirstSect; 778 KU32 cSectionsLeft; 779 780 /* convert and verify*/ 781 if (u.pLoadCmd->cmdsize < sizeof(segment_command_64_t)) 782 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 783 if ( pHdr->magic != IMAGE_MACHO64_SIGNATURE_OE 784 && pHdr->magic != IMAGE_MACHO64_SIGNATURE) 785 return KLDR_ERR_MACHO_BIT_MIX; 816 segment_command_64_t *pSrcSeg = (segment_command_64_t *)u.pLoadCmd; 817 section_64_t *pFirstSect = (section_64_t *)(pSrcSeg + 1); 818 section_64_t *pSect = pFirstSect; 819 KU32 cSectionsLeft = pSrcSeg->nsects; 820 KU64 offSect = 0; 821 KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF") 822 || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); 823 824 /* Convert and verify the segment. */ 825 KLDRMODMACHO_CHECK_RETURN(u.pLoadCmd->cmdsize >= sizeof(segment_command_64_t), KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 826 KLDRMODMACHO_CHECK_RETURN( pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE 827 || pHdr->magic == IMAGE_MACHO64_SIGNATURE, KLDR_ERR_MACHO_BIT_MIX); 786 828 if (fConvertEndian) 787 829 { 788 u.pSeg64->vmaddr = K_E2E_U64(u.pSeg64->vmaddr);789 u.pSeg64->vmsize = K_E2E_U64(u.pSeg64->vmsize);790 u.pSeg64->fileoff = K_E2E_U64(u.pSeg64->fileoff);791 u.pSeg64->filesize = K_E2E_U64(u.pSeg64->filesize);792 u.pSeg64->maxprot = K_E2E_U32(u.pSeg64->maxprot);793 u.pSeg64->initprot = K_E2E_U32(u.pSeg64->initprot);794 u.pSeg64->nsects = K_E2E_U32(u.pSeg64->nsects);795 u.pSeg64->flags = K_E2E_U32(u.pSeg64->flags);830 pSrcSeg->vmaddr = K_E2E_U64(pSrcSeg->vmaddr); 831 pSrcSeg->vmsize = K_E2E_U64(pSrcSeg->vmsize); 832 pSrcSeg->fileoff = K_E2E_U64(pSrcSeg->fileoff); 833 pSrcSeg->filesize = K_E2E_U64(pSrcSeg->filesize); 834 pSrcSeg->maxprot = K_E2E_U32(pSrcSeg->maxprot); 835 pSrcSeg->initprot = K_E2E_U32(pSrcSeg->initprot); 836 pSrcSeg->nsects = K_E2E_U32(pSrcSeg->nsects); 837 pSrcSeg->flags = K_E2E_U32(pSrcSeg->flags); 796 838 } 797 839 798 if ( u.pSeg64->filesize 799 && ( u.pSeg64->fileoff > cbFile 800 || u.pSeg64->fileoff + u.pSeg64->filesize > cbFile)) 801 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 802 if (u.pSeg64->vmsize < u.pSeg64->filesize) 803 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 804 if ((u.pSeg64->maxprot & u.pSeg64->initprot) != u.pSeg64->initprot) 805 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 806 if (u.pSeg64->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1)) 807 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 808 if (u.pSeg64->nsects * sizeof(section_64_t) > u.pLoadCmd->cmdsize - sizeof(segment_command_64_t)) 809 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 810 if ( pHdr->filetype == MH_OBJECT 811 && cSegmentCommands > 0) 812 return KLDR_ERR_MACHO_BAD_OBJECT_FILE; 813 cSegmentCommands++; 840 VALIDATE_AND_ADD_SEGMENT(64); 814 841 815 842 /* 816 * convert, validate and parse the sections.843 * Convert, validate and parse the sections. 817 844 */ 818 cSectionsLeft = u.pSeg64->nsects;819 pFirstSect = pSect = (section_64_t *)(u.pSeg64 + 1);820 845 while (cSectionsLeft-- > 0) 821 846 { 822 int fFileBits;823 824 847 if (fConvertEndian) 825 848 { … … 835 858 } 836 859 837 /* validate */ 838 switch (pSect->flags & SECTION_TYPE) 839 { 840 case S_ZEROFILL: 841 if (pSect->reserved1 || pSect->reserved2) 842 return KLDR_ERR_MACHO_BAD_SECTION; 843 fFileBits = 0; 844 break; 845 case S_REGULAR: 846 case S_CSTRING_LITERALS: 847 case S_COALESCED: 848 case S_4BYTE_LITERALS: 849 case S_8BYTE_LITERALS: 850 case S_16BYTE_LITERALS: 851 if (pSect->reserved1 || pSect->reserved2) 852 return KLDR_ERR_MACHO_BAD_SECTION; 853 fFileBits = 1; 854 break; 855 856 case S_SYMBOL_STUBS: 857 if ( pSect->reserved1 858 || pSect->reserved2 > 64 /* stub size. 0 has been seen (corecrypto.kext) */ ) 859 return KLDR_ERR_MACHO_BAD_SECTION; 860 fFileBits = 1; 861 break; 862 863 case S_NON_LAZY_SYMBOL_POINTERS: 864 case S_LAZY_SYMBOL_POINTERS: 865 if (pSect->reserved2) /* (reserved 1 is indirect symbol table index)*/ 866 return KLDR_ERR_MACHO_BAD_SECTION; 867 *pfCanLoad = K_FALSE; 868 fFileBits = -1; /* __DATA.__got in the 64-bit mach_kernel has bits, any things without bits? */ 869 break; 870 871 case S_MOD_INIT_FUNC_POINTERS: /** @todo this requires a query API or flag... (e.g. C++ constructors) */ 872 if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) 873 return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION; 874 case S_MOD_TERM_FUNC_POINTERS: /** @todo this requires a query API or flag... (e.g. C++ destructors) */ 875 if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) 876 return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION; 877 if (pSect->reserved1 || pSect->reserved2) 878 return KLDR_ERR_MACHO_BAD_SECTION; 879 fFileBits = 1; 880 break; /* ignored */ 881 882 case S_LITERAL_POINTERS: 883 case S_INTERPOSING: 884 case S_GB_ZEROFILL: 885 return KLDR_ERR_MACHO_UNSUPPORTED_SECTION; 886 887 default: 888 return KLDR_ERR_MACHO_UNKNOWN_SECTION; 889 } 890 if (pSect->flags & ~( S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS 891 | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE 892 | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC 893 | S_ATTR_LOC_RELOC | SECTION_TYPE)) 894 return KLDR_ERR_MACHO_BAD_SECTION; 895 if ( pSect->addr - u.pSeg64->vmaddr > u.pSeg64->vmsize 896 || pSect->addr - u.pSeg64->vmaddr + pSect->size > u.pSeg64->vmsize) 897 return KLDR_ERR_MACHO_BAD_SECTION; 898 if ( pSect->align >= 31 899 || (((1 << pSect->align) - 1) & pSect->addr) 900 || (((1 << pSect->align) - 1) & u.pSeg64->vmaddr)) 901 return KLDR_ERR_MACHO_BAD_SECTION; 902 if ( fFileBits 903 && ( pSect->offset > cbFile 904 || (KU64)pSect->offset + pSect->size > cbFile)) 905 return KLDR_ERR_MACHO_BAD_SECTION; 906 if (!fFileBits && pSect->offset) 907 return KLDR_ERR_MACHO_BAD_SECTION; 908 if (!pSect->nreloc && pSect->reloff) 909 return KLDR_ERR_MACHO_BAD_SECTION; 910 if ( pSect->nreloc 911 && ( pSect->reloff > cbFile 912 || (KU64)pSect->reloff + (KLDRFOFF)pSect->nreloc * sizeof(macho_relocation_info_t)) > cbFile) 913 return KLDR_ERR_MACHO_BAD_SECTION; 914 915 916 /* count segments and strings, calculate image link address. */ 917 switch (pHdr->filetype) 918 { 919 case MH_OBJECT: 920 case MH_EXECUTE: 921 case MH_DYLIB: 922 case MH_DSYM: 923 case MH_KEXT_BUNDLE: 924 { 925 cSections++; 926 927 /* Don't load debug symbols. (test this) */ 928 if ( (pSect->flags & S_ATTR_DEBUG) 929 || !kHlpStrComp(pSect->segname, "__DWARF")) 930 break; 931 932 /* a new segment? */ 933 if ( !pchCurSegName 934 || kHlpStrNComp(pSect->segname, pchCurSegName, sizeof(pSect->segname))) 935 { 936 #if 0 /** @todo This doesn't work because of BSS. */ 937 /* verify that the linker/assembler has ordered sections correctly. */ 938 section_64_t *pCur = (pSect - 2); 939 while ((KUPTR)pCur >= (KUPTR)pFirstSect) 940 { 941 if (!kHlpStrNComp(pCur->segname, pSect->segname, sizeof(pSect->segname))) 942 return KLDR_ERR_MACHO_BAD_SECTION_ORDER; 943 pCur--; 944 } 945 #endif 946 947 /* ok. count it and the string. */ 948 pchCurSegName = &pSect->segname[0]; 949 cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; 950 cSegments++; 951 952 /* Link address lower? */ 953 if (*pLinkAddress > u.pSeg64->vmaddr) 954 *pLinkAddress = u.pSeg64->vmaddr; 955 } 956 break; 957 } 958 959 default: 960 return KERR_INVALID_PARAMETER; 961 } 860 VALIDATE_AND_ADD_SECTION(64); 962 861 963 862 /* next */ … … 986 885 if ( u.pSymTab->symoff >= cbFile 987 886 || (KU64)u.pSymTab->symoff + u.pSymTab->nsyms * cbSym > cbFile) 988 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;887 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 989 888 if ( u.pSymTab->stroff >= cbFile 990 889 || (KU64)u.pSymTab->stroff + u.pSymTab->strsize > cbFile) 991 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;890 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 992 891 993 892 /* only one string in objects, please. */ … … 995 894 if ( pHdr->filetype == MH_OBJECT 996 895 && cSymbolTabs != 1) 997 return KLDR_ERR_MACHO_BAD_OBJECT_FILE;896 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_OBJECT_FILE); 998 897 break; 999 898 } … … 1012 911 /* convert & verify header items ([0] == flavor, [1] == KU32 count). */ 1013 912 if (cItemsLeft < 2) 1014 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;913 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 1015 914 if (fConvertEndian) 1016 915 { … … 1019 918 } 1020 919 if (pu32[1] + 2 > cItemsLeft) 1021 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;920 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 1022 921 1023 922 /* convert & verify according to flavor. */ … … 1038 937 case LC_UUID: 1039 938 if (u.pUuid->cmdsize != sizeof(uuid_command_t)) 1040 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;939 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 1041 940 /** @todo Check anything here need converting? */ 1042 941 break; … … 1044 943 case LC_CODE_SIGNATURE: 1045 944 if (u.pUuid->cmdsize != sizeof(linkedit_data_command_t)) 1046 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;945 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 1047 946 break; 1048 947 … … 1050 949 case LC_VERSION_MIN_IPHONEOS: 1051 950 if (u.pUuid->cmdsize != sizeof(version_min_command_t)) 1052 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;951 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 1053 952 break; 1054 953 … … 1076 975 /** @todo valid command size. */ 1077 976 if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) 1078 return KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND;977 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND); 1079 978 break; 1080 979 … … 1093 992 case LC_PREBIND_CKSUM: 1094 993 case LC_SYMSEG: 1095 return KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND;994 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND); 1096 995 1097 996 default: 1098 return KLDR_ERR_MACHO_UNKNOWN_LOAD_COMMAND;997 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_UNKNOWN_LOAD_COMMAND); 1099 998 } 1100 999 } … … 1102 1001 /* be strict. */ 1103 1002 if (cbLeft) 1104 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;1003 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 1105 1004 1106 1005 switch (pHdr->filetype) … … 1112 1011 case MH_KEXT_BUNDLE: 1113 1012 if (!cSegments) 1114 return KLDR_ERR_MACHO_BAD_OBJECT_FILE;1013 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_OBJECT_FILE); 1115 1014 break; 1116 1015 } … … 1146 1045 const uuid_command_t *pUuid; 1147 1046 } u; 1148 const char *pchCurSegName = NULL;1149 1047 KU32 cLeft = pModMachO->Hdr.ncmds; 1150 1048 KU32 cbLeft = pModMachO->Hdr.sizeofcmds; 1151 1049 const KU8 *pb = pModMachO->pbLoadCommands; 1152 PKLDRSEG p Seg = &pModMachO->pMod->aSegments[0];1050 PKLDRSEG pDstSeg = &pModMachO->pMod->aSegments[0]; 1153 1051 PKLDRMODMACHOSEG pSegExtra = &pModMachO->aSegments[0]; 1154 1052 PKLDRMODMACHOSECT pSectExtra = pModMachO->paSections; 1155 1053 const KU32 cSegments = pModMachO->pMod->cSegments; 1156 KU32 i, c;1054 PKLDRSEG pSegItr; 1157 1055 1158 1056 while (cLeft-- > 0) … … 1169 1067 case LC_SEGMENT_32: 1170 1068 { 1171 section_32_t *pSect; 1172 section_32_t *pFirstSect; 1173 KU32 cSectionsLeft; 1174 1175 kHlpAssert(u.pSeg32->vmaddr >= pModMachO->LinkAddress); 1176 1177 /* 1178 * convert, validate and parse the sections. 1179 */ 1180 cSectionsLeft = u.pSeg32->nsects; 1181 pFirstSect = pSect = (section_32_t *)(u.pSeg32 + 1); 1182 while (cSectionsLeft-- > 0) 1183 { 1184 switch (pModMachO->Hdr.filetype) 1185 { 1186 case MH_OBJECT: 1187 case MH_EXECUTE: 1188 case MH_DYLIB: 1189 case MH_DSYM: 1190 case MH_KEXT_BUNDLE: 1191 { 1192 /* Section data extract. */ 1193 pSectExtra->cb = pSect->size; 1194 pSectExtra->RVA = pSect->addr; 1195 pSectExtra->LinkAddress = pSect->addr; 1196 if (pSect->offset) 1197 pSectExtra->offFile = pSect->offset + pModMachO->offImage; 1198 else 1199 pSectExtra->offFile = -1; 1200 pSectExtra->cFixups = pSect->nreloc; 1201 pSectExtra->paFixups = NULL; 1202 if (pSect->nreloc) 1203 pSectExtra->offFixups = pSect->reloff + pModMachO->offImage; 1204 else 1205 pSectExtra->offFixups = -1; 1206 pSectExtra->fFlags = pSect->flags; 1207 pSectExtra->iSegment = pSegExtra - &pModMachO->aSegments[0]; 1208 pSectExtra->pvMachoSection = pSect; 1209 1210 /* Don't load debug symbols. (test this!) */ 1211 if ( (pSect->flags & S_ATTR_DEBUG) 1212 || !kHlpStrComp(pSect->segname, "__DWARF")) 1213 { 1214 pSectExtra++; 1215 /** @todo */ 1216 break; 1217 } 1218 1219 if ( !pchCurSegName 1220 || kHlpStrNComp(pSect->segname, pchCurSegName, sizeof(pSect->segname))) 1221 { 1222 /* close the previous segment */ 1223 if (pSegExtra != &pModMachO->aSegments[0]) 1224 pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; 1225 1226 /* new segment. */ 1227 pSeg->pvUser = NULL; 1228 pSeg->pchName = pbStringPool; 1229 pSeg->cchName = (KU32)kHlpStrNLen(&pSect->segname[0], sizeof(pSect->sectname)); 1230 kHlpMemCopy(pbStringPool, &pSect->segname[0], pSeg->cchName); 1231 pbStringPool += pSeg->cchName; 1232 *pbStringPool++ = '\0'; 1233 pSeg->SelFlat = 0; 1234 pSeg->Sel16bit = 0; 1235 pSeg->fFlags = 0; 1236 pSeg->enmProt = KPROT_EXECUTE_WRITECOPY; /** @todo fixme! */ 1237 pSeg->cb = pSect->size; 1238 pSeg->Alignment = (KLDRADDR)1 << pSect->align; 1239 pSeg->LinkAddress = pSect->addr; 1240 if (pSect->offset) 1241 { 1242 pSeg->offFile = pSect->offset + pModMachO->offImage; 1243 pSeg->cbFile = pSect->size; 1244 } 1245 else 1246 { 1247 pSeg->offFile = -1; 1248 pSeg->cbFile = -1; 1249 } 1250 pSeg->RVA = pSect->addr - pModMachO->LinkAddress; 1251 pSeg->cbMapped = 0; 1252 pSeg->MapAddress = 0; 1253 1254 pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0]; 1255 pSegExtra->cSections = 0; 1256 pSegExtra->paSections = pSectExtra; 1257 1258 pSeg++; 1259 pSegExtra++; 1260 pchCurSegName = &pSect->segname[0]; 1261 } 1262 else 1263 { 1264 /* update exiting segment */ 1265 if (pSeg[-1].Alignment < K_BIT64(pSect->align)) 1266 pSeg[-1].Alignment = K_BIT64(pSect->align); 1267 if (pSect->addr < pSeg[-1].LinkAddress) 1268 return KLDR_ERR_MACHO_BAD_SECTION; /** @todo move up! */ 1269 1270 /* If there are file bits, ensure they are in the current flow. 1271 (yes, we are very very careful here, I know.) */ 1272 if ( pSect->offset 1273 && (KU64)pSeg[-1].cbFile == pSeg[-1].cb) 1274 { 1275 int fOk = (KU64)pSeg[-1].offFile + (pSect->addr - pSeg[-1].LinkAddress) == pSect->offset + (KU64)pModMachO->offImage 1276 && pSect[-1].offset 1277 && (KU64)pSeg[-1].offFile + pSeg[-1].cbFile == pSect[-1].offset + (KU64)pModMachO->offImage + pSect[-1].size; 1278 /* more checks? */ 1279 if (fOk) 1280 pSeg[-1].cbFile = (KLDRFOFF)(pSect->addr - pSeg[-1].LinkAddress) + pSect->size; 1281 else 1282 { 1283 1284 pSeg[-1].cbFile = pSeg[-1].offFile = -1; 1285 pModMachO->fMapUsingLoadCommandSections = K_TRUE; 1286 } 1287 } 1288 pSeg[-1].cb = pSect->addr - pSeg[-1].LinkAddress + pSect->size; 1289 1290 /** @todo update the protection... */ 1291 } 1292 pSectExtra++; 1293 break; 1294 } 1295 1296 default: 1297 return KERR_INVALID_PARAMETER; 1298 } 1299 1300 /* next */ 1301 pSect++; 1302 } 1069 const segment_command_32_t *pSrcSeg = (const segment_command_32_t *)u.pLoadCmd; 1070 section_32_t *pFirstSect = (section_32_t *)(pSrcSeg + 1); 1071 section_32_t *pSect = pFirstSect; 1072 KU32 cSectionsLeft = pSrcSeg->nsects; 1073 1074 /* Shared with the 64-bit variant. */ 1075 #define ADD_SEGMENT_AND_ITS_SECTIONS(a_cBits) \ 1076 do { \ 1077 KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF") \ 1078 || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); \ 1079 \ 1080 kHlpAssert(pSrcSeg->vmaddr >= pModMachO->LinkAddress); \ 1081 \ 1082 /* \ 1083 * Check that the segment name is unique. We couldn't do that \ 1084 * in the preparsing stage. \ 1085 */ \ 1086 for (pSegItr = &pModMachO->pMod->aSegments[0]; pSegItr != pDstSeg; pSegItr++) \ 1087 if (!kHlpStrNComp(pSegItr->pchName, pSrcSeg->segname, sizeof(pSrcSeg->segname))) \ 1088 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_DUPLICATE_SEGMENT_NAME); \ 1089 \ 1090 /* \ 1091 * Create a new segment, unless we're supposed to skip this one. \ 1092 */ \ 1093 if (!fSkipSeg) \ 1094 { \ 1095 pDstSeg->pvUser = NULL; \ 1096 pDstSeg->pchName = pbStringPool; \ 1097 pDstSeg->cchName = (KU32)kHlpStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)); \ 1098 kHlpMemCopy(pbStringPool, &pSrcSeg->segname[0], pDstSeg->cchName); \ 1099 pbStringPool += pDstSeg->cchName; \ 1100 *pbStringPool++ = '\0'; \ 1101 pDstSeg->SelFlat = 0; \ 1102 pDstSeg->Sel16bit = 0; \ 1103 pDstSeg->fFlags = 0; \ 1104 pDstSeg->enmProt = KPROT_EXECUTE_WRITECOPY; /** @todo fixme! */ \ 1105 pDstSeg->cb = pSrcSeg->vmsize; \ 1106 pDstSeg->Alignment = 1; /* updated while parsing sections. */ \ 1107 pDstSeg->LinkAddress = pSrcSeg->vmaddr; \ 1108 if (pSrcSeg->filesize > 0) \ 1109 { \ 1110 pDstSeg->offFile = pSrcSeg->fileoff + pModMachO->offImage; \ 1111 pDstSeg->cbFile = pSrcSeg->filesize; \ 1112 } \ 1113 else \ 1114 { \ 1115 pDstSeg->offFile = -1; \ 1116 pDstSeg->cbFile = -1; \ 1117 } \ 1118 pDstSeg->RVA = pSrcSeg->vmaddr - pModMachO->LinkAddress; \ 1119 pDstSeg->cbMapped = 0; \ 1120 pDstSeg->MapAddress = 0; \ 1121 \ 1122 pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0]; \ 1123 pSegExtra->cSections = 0; \ 1124 pSegExtra->paSections = pSectExtra; \ 1125 } \ 1126 \ 1127 /* \ 1128 * Convert and parse the sections. \ 1129 */ \ 1130 while (cSectionsLeft-- > 0) \ 1131 { \ 1132 /* Section data extract. */ \ 1133 pSectExtra->cb = pSect->size; \ 1134 pSectExtra->RVA = pSect->addr; \ 1135 pSectExtra->LinkAddress = pSect->addr; \ 1136 if (pSect->offset) \ 1137 pSectExtra->offFile = pSect->offset + pModMachO->offImage; \ 1138 else \ 1139 pSectExtra->offFile = -1; \ 1140 pSectExtra->cFixups = pSect->nreloc; \ 1141 pSectExtra->paFixups = NULL; \ 1142 if (pSect->nreloc) \ 1143 pSectExtra->offFixups = pSect->reloff + pModMachO->offImage; \ 1144 else \ 1145 pSectExtra->offFixups = -1; \ 1146 pSectExtra->fFlags = pSect->flags; \ 1147 pSectExtra->iSegment = pSegExtra - &pModMachO->aSegments[0]; \ 1148 pSectExtra->pvMachoSection = pSect; \ 1149 \ 1150 /* Update the segment alignment, if we're not skipping it. */ \ 1151 if (!fSkipSeg && pDstSeg->Alignment < ((KLDRADDR)1 << pSect->align)) \ 1152 pDstSeg->Alignment = (KLDRADDR)1 << pSect->align; \ 1153 \ 1154 /* Next section. */ \ 1155 pSectExtra++; \ 1156 pSect++; \ 1157 } \ 1158 \ 1159 /* Close the segment and advance. */ \ 1160 if (!fSkipSeg) \ 1161 { \ 1162 pSegExtra->cSections = pSectExtra - pSegExtra->paSections; \ 1163 pSegExtra++; \ 1164 pDstSeg++; \ 1165 } \ 1166 } while (0) /* ADD_SEGMENT_AND_ITS_SECTIONS */ 1167 1168 ADD_SEGMENT_AND_ITS_SECTIONS(32); 1303 1169 break; 1304 1170 } … … 1306 1172 case LC_SEGMENT_64: 1307 1173 { 1308 section_64_t *pSect; 1309 section_64_t *pFirstSect; 1310 KU32 cSectionsLeft; 1311 1312 kHlpAssert(u.pSeg64->vmaddr >= pModMachO->LinkAddress); 1313 1314 /* 1315 * convert, validate and parse the sections. 1316 */ 1317 cSectionsLeft = u.pSeg64->nsects; 1318 pFirstSect = pSect = (section_64_t *)(u.pSeg64 + 1); 1319 while (cSectionsLeft-- > 0) 1320 { 1321 switch (pModMachO->Hdr.filetype) 1322 { 1323 case MH_OBJECT: 1324 case MH_EXECUTE: 1325 case MH_DYLIB: 1326 case MH_DSYM: 1327 case MH_KEXT_BUNDLE: 1328 { 1329 /* Section data extract. */ 1330 pSectExtra->cb = pSect->size; 1331 pSectExtra->RVA = pSect->addr; 1332 pSectExtra->LinkAddress = pSect->addr; 1333 if (pSect->offset) 1334 pSectExtra->offFile = pSect->offset + pModMachO->offImage; 1335 else 1336 pSectExtra->offFile = -1; 1337 pSectExtra->cFixups = pSect->nreloc; 1338 pSectExtra->paFixups = NULL; 1339 if (pSect->nreloc) 1340 pSectExtra->offFixups = pSect->reloff + pModMachO->offImage; 1341 else 1342 pSectExtra->offFixups = -1; 1343 pSectExtra->fFlags = pSect->flags; 1344 pSectExtra->iSegment = pSegExtra - &pModMachO->aSegments[0]; 1345 pSectExtra->pvMachoSection = pSect; 1346 1347 /* Don't load debug symbols. (test this!) */ 1348 if ( (pSect->flags & S_ATTR_DEBUG) 1349 || !kHlpStrComp(pSect->segname, "__DWARF")) 1350 { 1351 pSectExtra++; 1352 /** @todo */ 1353 break; 1354 } 1355 1356 if ( !pchCurSegName 1357 || kHlpStrNComp(pSect->segname, pchCurSegName, sizeof(pSect->segname))) 1358 { 1359 /* close the previous segment */ 1360 if (pSegExtra != &pModMachO->aSegments[0]) 1361 pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; 1362 1363 /* new segment. */ 1364 pSeg->pvUser = NULL; 1365 pSeg->pchName = pbStringPool; 1366 pSeg->cchName = (KU32)kHlpStrNLen(&pSect->segname[0], sizeof(pSect->sectname)); 1367 kHlpMemCopy(pbStringPool, &pSect->segname[0], pSeg->cchName); 1368 pbStringPool += pSeg->cchName; 1369 *pbStringPool++ = '\0'; 1370 pSeg->SelFlat = 0; 1371 pSeg->Sel16bit = 0; 1372 pSeg->fFlags = 0; 1373 pSeg->enmProt = KPROT_EXECUTE_WRITECOPY; /** @todo fixme! */ 1374 pSeg->cb = pSect->size; 1375 pSeg->Alignment = (KLDRADDR)1 << pSect->align; 1376 pSeg->LinkAddress = pSect->addr; 1377 if (pSect->offset) 1378 { 1379 pSeg->offFile = pSect->offset + pModMachO->offImage; 1380 pSeg->cbFile = pSect->size; 1381 } 1382 else 1383 { 1384 pSeg->offFile = -1; 1385 pSeg->cbFile = -1; 1386 } 1387 pSeg->RVA = pSect->addr - pModMachO->LinkAddress; 1388 pSeg->cbMapped = 0; 1389 pSeg->MapAddress = 0; 1390 1391 pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0]; 1392 pSegExtra->cSections = 0; 1393 pSegExtra->paSections = pSectExtra; 1394 1395 pSeg++; 1396 pSegExtra++; 1397 pchCurSegName = &pSect->segname[0]; 1398 } 1399 else 1400 { 1401 /* update exiting segment */ 1402 if (pSeg[-1].Alignment < K_BIT64(pSect->align)) 1403 pSeg[-1].Alignment = K_BIT64(pSect->align); 1404 if (pSect->addr < pSeg[-1].LinkAddress) 1405 return KLDR_ERR_MACHO_BAD_SECTION; /** @todo move up! */ 1406 1407 /* If there are file bits, ensure they are in the current flow. 1408 (yes, we are very very careful here, I know.) */ 1409 if ( pSect->offset 1410 && (KU64)pSeg[-1].cbFile == pSeg[-1].cb) 1411 { 1412 int fOk = (KU64)pSeg[-1].offFile + (pSect->addr - pSeg[-1].LinkAddress) == pSect->offset + (KU64)pModMachO->offImage 1413 && pSect[-1].offset 1414 && (KU64)pSeg[-1].offFile + pSeg[-1].cbFile == pSect[-1].offset + (KU64)pModMachO->offImage + pSect[-1].size; 1415 /* more checks? */ 1416 if (fOk) 1417 pSeg[-1].cbFile = (KLDRFOFF)(pSect->addr - pSeg[-1].LinkAddress) + pSect->size; 1418 else 1419 { 1420 1421 pSeg[-1].cbFile = pSeg[-1].offFile = -1; 1422 pModMachO->fMapUsingLoadCommandSections = K_TRUE; 1423 } 1424 } 1425 pSeg[-1].cb = pSect->addr - pSeg[-1].LinkAddress + pSect->size; 1426 1427 /** @todo update the protection... */ 1428 } 1429 pSectExtra++; 1430 break; 1431 } 1432 1433 default: 1434 return KERR_INVALID_PARAMETER; 1435 } 1436 1437 /* next */ 1438 pSect++; 1439 } 1174 const segment_command_64_t *pSrcSeg = (const segment_command_64_t *)u.pLoadCmd; 1175 section_64_t *pFirstSect = (section_64_t *)(pSrcSeg + 1); 1176 section_64_t *pSect = pFirstSect; 1177 KU32 cSectionsLeft = pSrcSeg->nsects; 1178 1179 ADD_SEGMENT_AND_ITS_SECTIONS(64); 1440 1180 break; 1441 1181 } … … 1466 1206 } /* while more commands */ 1467 1207 1468 /* 1469 * Close the last segment (if any). 1470 */ 1471 if (pSegExtra != &pModMachO->aSegments[0]) 1472 pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; 1473 1474 /* 1475 * Make sure the segments are sorted, or we'll get screwed further down. 1476 */ 1477 c = pSeg - &pModMachO->pMod->aSegments[0]; 1478 pSeg = &pModMachO->pMod->aSegments[0]; 1479 for (i = 0; i < c - 1; i++) 1480 { 1481 KLDRADDR LinkAddress = pSeg[i + 1].LinkAddress; 1482 if (LinkAddress < pSeg[i].LinkAddress) 1483 { 1484 /* Gotta move the next segment, find the correct location. */ 1485 KLDRMODMACHOSEG TmpSegExtra; 1486 KLDRSEG TmpSeg; 1487 KU32 j = i; 1488 KU32 cShift = 1; 1489 1490 while (j > 0 && LinkAddress < pSeg[j - 1].LinkAddress) 1491 j--, cShift++; 1492 1493 TmpSegExtra = pModMachO->aSegments[i + 1]; 1494 kHlpMemMove(&pModMachO->aSegments[j + 1], &pModMachO->aSegments[j], 1495 cShift * sizeof(pModMachO->aSegments[0])); 1496 pModMachO->aSegments[j] = TmpSegExtra; 1497 1498 TmpSeg = pSeg[i + 1]; 1499 kHlpMemMove(&pSeg[j + 1], &pSeg[j], cShift * sizeof(pSeg[0])); 1500 pSeg[j] = TmpSeg; 1501 } 1502 } 1503 pSeg = &pModMachO->pMod->aSegments[c]; 1208 kHlpAssert(pDstSeg == &pModMachO->pMod->aSegments[cSegments - pModMachO->fMakeGot]); 1209 1210 #if 0 1211 { 1212 /* 1213 * Make sure the segments are sorted by link address, or we'll get screwed 1214 * further down. 1215 */ 1216 KLDRADDR cb1; 1217 KSIZE cb2; 1218 KU32 i; 1219 KU32 c = pDstSeg - &pModMachO->pMod->aSegments[0]; 1220 1221 pDstSeg = &pModMachO->pMod->aSegments[0]; 1222 for (i = 0; i < c - 1; i++) 1223 { 1224 KLDRADDR LinkAddress = pDstSeg[i + 1].LinkAddress; 1225 if (LinkAddress < pDstSeg[i].LinkAddress) 1226 { 1227 /* Gotta move the next segment, find the correct location. */ 1228 KLDRMODMACHOSEG TmpSegExtra; 1229 KLDRSEG TmpSeg; 1230 KU32 j = i; 1231 KU32 cShift = 1; 1232 1233 while (j > 0 && LinkAddress < pDstSeg[j - 1].LinkAddress) 1234 j--, cShift++; 1235 1236 TmpSegExtra = pModMachO->aSegments[i + 1]; 1237 kHlpMemMove(&pModMachO->aSegments[j + 1], &pModMachO->aSegments[j], 1238 cShift * sizeof(pModMachO->aSegments[0])); 1239 pModMachO->aSegments[j] = TmpSegExtra; 1240 1241 TmpSeg = pDstSeg[i + 1]; 1242 kHlpMemMove(&pDstSeg[j + 1], &pDstSeg[j], cShift * sizeof(pDstSeg[0])); 1243 pDstSeg[j] = TmpSeg; 1244 } 1245 } 1246 1247 /* 1248 * Adjust mapping addresses calculating the image size. 1249 */ 1250 pDstSeg = &pModMachO->pMod->aSegments[0]; 1251 for (i = 0; i < cSegments - 1; i++) 1252 { 1253 cb1 = pDstSeg[i + 1].LinkAddress - pDstSeg[i].LinkAddress; 1254 cb2 = (KSIZE)cb1; 1255 pDstSeg[i].cbMapped = cb2 == cb1 ? cb2 : ~(KSIZE)0; 1256 } 1257 cb1 = KLDR_ALIGN_ADDR(pDstSeg[i].cb, pDstSeg[i].Alignment); 1258 cb2 = (KSIZE)cb1; 1259 pDstSeg[i].cbMapped = cb2 == cb1 ? cb2 : ~(KSIZE)0; 1260 1261 pModMachO->cbImage = pDstSeg[i].RVA + cb1; 1262 } 1263 #else 1264 /* 1265 * Adjust mapping addresses calculating the image size. 1266 */ 1267 { 1268 KLDRADDR uNextRVA = 0; 1269 KLDRADDR cb; 1270 KU32 c; 1271 1272 /* Adjust RVAs. */ 1273 c = cSegments - pModMachO->fMakeGot; 1274 for (pDstSeg = &pModMachO->pMod->aSegments[0]; c-- > 0; pDstSeg++) 1275 { 1276 cb = pDstSeg->RVA - uNextRVA; 1277 if (cb >= 0x00100000) /* 1MB */ 1278 { 1279 pDstSeg->RVA = uNextRVA; 1280 pModMachO->pMod->fFlags |= KLDRMOD_FLAGS_NON_CONTIGUOUS_LINK_ADDRS; 1281 } 1282 uNextRVA = pDstSeg->RVA + KLDR_ALIGN_ADDR(pDstSeg->cb, pDstSeg->Alignment); 1283 } 1284 1285 /* Calculate the cbMapping members. */ 1286 c = cSegments - pModMachO->fMakeGot; 1287 for (pDstSeg = &pModMachO->pMod->aSegments[0]; c-- > 1; pDstSeg++) 1288 { 1289 cb = pDstSeg[1].RVA - pDstSeg->RVA; 1290 pDstSeg->cbMapped = (KSIZE)cb == cb ? cb : KSIZE_MAX; 1291 } 1292 1293 cb = KLDR_ALIGN_ADDR(pDstSeg->cb, pDstSeg->Alignment); 1294 pDstSeg->cbMapped = (KSIZE)cb == cb ? (KSIZE)cb : KSIZE_MAX; 1295 1296 /* And finally, the image size. */ 1297 pModMachO->cbImage = pDstSeg->RVA + cb; 1298 } 1299 #endif 1300 1504 1301 1505 1302 /* … … 1515 1312 KU32 cbJmpStubs; 1516 1313 1517 if (pSeg != &pModMachO->pMod->aSegments[0]) 1518 pModMachO->GotRVA = pSeg[-1].RVA + KLDR_ALIGN_ADDR(pSeg[-1].cb, pSeg[-1].Alignment); 1519 else 1520 pModMachO->GotRVA = 0; 1314 pModMachO->GotRVA = pModMachO->cbImage; 1521 1315 1522 1316 if (pModMachO->cbJmpStub) … … 1532 1326 } 1533 1327 1534 pSeg->pvUser = NULL; 1535 pSeg->pchName = "GOT"; 1536 pSeg->cchName = 3; 1537 pSeg->SelFlat = 0; 1538 pSeg->Sel16bit = 0; 1539 pSeg->fFlags = 0; 1540 pSeg->enmProt = KPROT_READONLY; 1541 pSeg->cb = cbGot + cbJmpStubs; 1542 pSeg->Alignment = 64; 1543 pSeg->LinkAddress = pModMachO->LinkAddress + pModMachO->GotRVA; 1544 pSeg->offFile = -1; 1545 pSeg->cbFile = -1; 1546 pSeg->RVA = pModMachO->GotRVA; 1547 pSeg->cbMapped = 0; 1548 pSeg->MapAddress = 0; 1328 pDstSeg = &pModMachO->pMod->aSegments[cSegments - 1]; 1329 pDstSeg->pvUser = NULL; 1330 pDstSeg->pchName = "GOT"; 1331 pDstSeg->cchName = 3; 1332 pDstSeg->SelFlat = 0; 1333 pDstSeg->Sel16bit = 0; 1334 pDstSeg->fFlags = 0; 1335 pDstSeg->enmProt = KPROT_READONLY; 1336 pDstSeg->cb = cbGot + cbJmpStubs; 1337 pDstSeg->Alignment = 64; 1338 pDstSeg->LinkAddress = pModMachO->LinkAddress + pModMachO->GotRVA; 1339 pDstSeg->offFile = -1; 1340 pDstSeg->cbFile = -1; 1341 pDstSeg->RVA = pModMachO->GotRVA; 1342 pDstSeg->cbMapped = KLDR_ALIGN_ADDR(cbGot + cbJmpStubs, pDstSeg->Alignment); 1343 pDstSeg->MapAddress = 0; 1549 1344 1550 1345 pSegExtra->iOrgSegNo = KU32_MAX; 1551 1346 pSegExtra->cSections = 0; 1552 1347 pSegExtra->paSections = NULL; 1553 } 1554 1555 /* 1556 * Adjust mapping addresses calculating the image size. 1557 */ 1558 pSeg = &pModMachO->pMod->aSegments[0]; 1559 switch (pModMachO->Hdr.filetype) 1560 { 1561 case MH_OBJECT: 1562 case MH_EXECUTE: 1563 case MH_DYLIB: /** @todo dylib */ 1564 case MH_DSYM: 1565 case MH_KEXT_BUNDLE: 1566 { 1567 KLDRADDR cb1; 1568 KSIZE cb2; 1569 1570 for (i = 0; i < cSegments - 1; i++) 1571 { 1572 cb1 = pSeg[i + 1].LinkAddress - pSeg[i].LinkAddress; 1573 cb2 = (KSIZE)cb1; 1574 pSeg[i].cbMapped = cb2 == cb1 ? cb2 : ~(KSIZE)0; 1575 } 1576 cb1 = KLDR_ALIGN_ADDR(pSeg[i].cb, pSeg[i].Alignment); 1577 cb2 = (KSIZE)cb1; 1578 pSeg[i].cbMapped = cb2 == cb1 ? cb2 : ~(KSIZE)0; 1579 1580 pModMachO->cbImage = pSeg[i].RVA + cb1; 1581 break; 1582 } 1583 } 1584 1348 1349 pModMachO->cbImage += pDstSeg->cbMapped; 1350 } 1585 1351 1586 1352 return 0; -
trunk/kLdr/kLdrModNative.c
r54 r58 322 322 pMod->pszName = kHlpGetFilename(pMod->pszFilename); /** @todo get soname */ 323 323 pMod->cchName = cchFilename - (pMod->pszName - pMod->pszFilename); 324 pMod->fFlags = 0; 324 325 #if defined(__i386__) || defined(__X86__) || defined(_M_IX86) 325 326 pMod->enmCpu = KCPU_I386; -
trunk/kLdr/kLdrModPE.c
r54 r58 234 234 pMod->pszName = kHlpGetFilename(pMod->pszFilename); 235 235 pMod->cchName = cchFilename - (pMod->pszName - pMod->pszFilename); 236 pMod->fFlags = 0; 236 237 switch (s.FileHdr.Machine) 237 238 {
Note:
See TracChangeset
for help on using the changeset viewer.