Changeset 2954 for trunk/kLdr/kLdrModMachO.c
- Timestamp:
- Feb 7, 2007, 5:42:32 AM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrModMachO.c
r2952 r2954 33 33 #include "kLdrInternal.h" 34 34 #include "kLdrModMachO.h" 35 36 /* quick hack for now. */ 37 typedef struct nlist 38 { 39 uint32_t n_strx; 40 uint8_t n_type; 41 int8_t n_other; 42 int16_t n_desc; 43 uint32_t n_value; 44 } nlist_t; 35 45 36 46 … … 75 85 *******************************************************************************/ 76 86 /** 77 * Instance data for the M ACH-O MH_OBJECT module interpreter.87 * Instance data for the Mach-O MH_OBJECT module interpreter. 78 88 * @todo interpret the other MH_* formats. 79 89 */ … … 121 131 122 132 static int kldrModMachODoCreate(PKLDRRDR pRdr, PKLDRMODMACHO *ppMod); 123 static int kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr, 133 static int kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr, PKLDRRDR pRdr, 124 134 uint32_t *pcSegments, uint32_t *pcbStringPool); 125 135 static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, uint32_t cbStringPool); … … 243 253 ? sizeof(mach_header_32_t) : sizeof(mach_header_64_t)); 244 254 if (!rc) 245 rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, &cSegments, &cbStringPool);255 rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, &cSegments, &cbStringPool); 246 256 if (rc) 247 257 { … … 375 385 * @param pbLoadCommands The load commands to parse. 376 386 * @param pHdr The header. 387 * @param pRdr The file reader. 377 388 * @param pcSegments Where to store the segment count. 378 389 * @param pcbStringPool Where to store the string pool size. 379 390 */ 380 static int kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr, 391 static int kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr, PKLDRRDR pRdr, 381 392 uint32_t *pcSegments, uint32_t *pcbStringPool) 382 393 { 394 union 395 { 396 uint8_t *pb; 397 load_command_t *pLoadCmd; 398 segment_command_32_t *pSeg32; 399 segment_command_64_t *pSeg64; 400 thread_command_t *pThread; 401 symtab_command_t *pSymTab; 402 uuid_command_t *pUuid; 403 } u; 404 const uint64_t cbFile = kLdrRdrSize(pRdr); 405 uint32_t cSegments = 0; 406 uint32_t cbStringPool = 0; 407 uint32_t cLeft = pHdr->ncmds; 408 uint32_t cbLeft = pHdr->sizeofcmds; 409 uint8_t *pb = pbLoadCommands; 410 int fConvertEndian = pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 411 || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE; 412 383 413 *pcSegments = 0; 384 414 *pcbStringPool = 0; 415 416 while (cLeft-- > 0) 417 { 418 u.pb = pb; 419 420 /* 421 * Convert and validate command header. 422 */ 423 if (cbLeft < sizeof(load_command_t)) 424 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 425 if (fConvertEndian) 426 { 427 u.pLoadCmd->cmd = KLDRHLP_E2E_U32(u.pLoadCmd->cmd); 428 u.pLoadCmd->cmdsize = KLDRHLP_E2E_U32(u.pLoadCmd->cmdsize); 429 } 430 if (u.pLoadCmd->cmdsize > cbLeft) 431 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 432 cbLeft -= u.pLoadCmd->cmdsize; 433 pb += u.pLoadCmd->cmdsize; 434 435 /* 436 * Convert endian if needed, parse and validate the command. 437 */ 438 switch (u.pLoadCmd->cmd) 439 { 440 case LC_SEGMENT_32: 441 { 442 section_32_t *pSect; 443 section_32_t *pFirstSect; 444 uint32_t cSectionsLeft; 445 446 /* convert and verify*/ 447 if (u.pLoadCmd->cmdsize < sizeof(segment_command_32_t)) 448 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 449 if (fConvertEndian) 450 { 451 u.pSeg32->vmaddr = KLDRHLP_E2E_U32(u.pSeg32->vmaddr); 452 u.pSeg32->vmsize = KLDRHLP_E2E_U32(u.pSeg32->vmsize); 453 u.pSeg32->fileoff = KLDRHLP_E2E_U32(u.pSeg32->fileoff); 454 u.pSeg32->filesize = KLDRHLP_E2E_U32(u.pSeg32->filesize); 455 u.pSeg32->maxprot = KLDRHLP_E2E_U32(u.pSeg32->maxprot); 456 u.pSeg32->initprot = KLDRHLP_E2E_U32(u.pSeg32->initprot); 457 u.pSeg32->nsects = KLDRHLP_E2E_U32(u.pSeg32->nsects); 458 u.pSeg32->flags = KLDRHLP_E2E_U32(u.pSeg32->flags); 459 } 460 461 if ( u.pSeg32->filesize 462 && ( u.pSeg32->fileoff > cbFile 463 || (uint64_t)u.pSeg32->fileoff + u.pSeg32->filesize > cbFile)) 464 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 465 if (!u.pSeg32->filesize && u.pSeg32->fileoff) 466 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 467 if (u.pSeg32->vmsize < u.pSeg32->filesize) 468 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 469 if ((u.pSeg32->maxprot & u.pSeg32->initprot) != u.pSeg32->initprot) 470 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 471 if (u.pSeg32->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1)) 472 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 473 if (u.pSeg32->nsects * sizeof(section_32_t) > u.pLoadCmd->cmdsize - sizeof(segment_command_32_t)) 474 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 475 476 /* 477 * convert, validate and parse the sections. 478 */ 479 cSectionsLeft = u.pSeg32->nsects; 480 pFirstSect = pSect = (section_32_t *)(u.pSeg32 + 1); 481 while (cSectionsLeft-- > 0) 482 { 483 int fFileBits; 484 485 if (fConvertEndian) 486 { 487 pSect->addr = KLDRHLP_E2E_U32(pSect->addr); 488 pSect->size = KLDRHLP_E2E_U32(pSect->size); 489 pSect->offset = KLDRHLP_E2E_U32(pSect->offset); 490 pSect->align = KLDRHLP_E2E_U32(pSect->align); 491 pSect->reloff = KLDRHLP_E2E_U32(pSect->reloff); 492 pSect->nreloc = KLDRHLP_E2E_U32(pSect->nreloc); 493 pSect->flags = KLDRHLP_E2E_U32(pSect->flags); 494 pSect->reserved1 = KLDRHLP_E2E_U32(pSect->reserved1); 495 pSect->reserved2 = KLDRHLP_E2E_U32(pSect->reserved2); 496 } 497 498 /* validate */ 499 switch (pSect->flags & SECTION_TYPE) 500 { 501 case S_ZEROFILL: 502 if (pSect->reserved1 || pSect->reserved2) 503 return KLDR_ERR_MACHO_BAD_SECTION; 504 fFileBits = 0; 505 break; 506 case S_REGULAR: 507 case S_CSTRING_LITERALS: 508 if (pSect->reserved1 || pSect->reserved2) 509 return KLDR_ERR_MACHO_BAD_SECTION; 510 fFileBits = 1; 511 break; 512 513 case S_LITERAL_POINTERS: 514 case S_INTERPOSING: 515 case S_GB_ZEROFILL: 516 case S_NON_LAZY_SYMBOL_POINTERS: 517 case S_LAZY_SYMBOL_POINTERS: 518 case S_4BYTE_LITERALS: 519 case S_8BYTE_LITERALS: 520 case S_16BYTE_LITERALS: 521 case S_SYMBOL_STUBS: 522 case S_COALESCED: 523 case S_MOD_INIT_FUNC_POINTERS: 524 case S_MOD_TERM_FUNC_POINTERS: 525 return KLDR_ERR_MACHO_UNSUPPORTED_SECTION; 526 527 default: 528 return KLDR_ERR_MACHO_UNKNOWN_SECTION; 529 } 530 if (pSect->flags & ~( S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS 531 | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE 532 | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC 533 | S_ATTR_LOC_RELOC | SECTION_TYPE)) 534 return KLDR_ERR_MACHO_BAD_SECTION; 535 if (!pSect->size) 536 return KLDR_ERR_MACHO_BAD_SECTION; 537 if ( pSect->addr - u.pSeg32->vmaddr > u.pSeg32->vmsize 538 || pSect->addr - u.pSeg32->vmaddr + pSect->size > u.pSeg32->vmsize) 539 return KLDR_ERR_MACHO_BAD_SECTION; 540 if ( pSect->align >= 31 541 || (((1 << pSect->align) - 1) & pSect->addr) 542 || (((1 << pSect->align) - 1) & u.pSeg32->vmaddr)) 543 return KLDR_ERR_MACHO_BAD_SECTION; 544 if ( fFileBits 545 && ( pSect->offset > cbFile 546 || (uint64_t)pSect->offset + pSect->size > cbFile)) 547 return KLDR_ERR_MACHO_BAD_SECTION; 548 if (!fFileBits && pSect->offset) 549 return KLDR_ERR_MACHO_BAD_SECTION; 550 if (!pSect->nreloc && pSect->reloff) 551 return KLDR_ERR_MACHO_BAD_SECTION; 552 if ( pSect->nreloc 553 && ( pSect->reloff > cbFile 554 || (uint64_t)pSect->reloff + (off_t)pSect->nreloc * sizeof(nlist_t)) > cbFile) 555 return KLDR_ERR_MACHO_BAD_SECTION; 556 557 558 /* count segments and strings */ 559 switch (pHdr->filetype) 560 { 561 case MH_OBJECT: 562 { 563 /* Don't load debug symbols. (test this) */ 564 if (pSect->flags & S_ATTR_DEBUG) 565 break; 566 567 /* a new segment? */ 568 if ( pSect == pFirstSect 569 || kLdrHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) 570 { 571 /* verify that the linker/assembler has ordered sections correctly. */ 572 section_32_t *pCur = (pSect - 2); 573 while ((uintptr_t)pCur >= (uintptr_t)pFirstSect) 574 { 575 if (!kLdrHlpStrNComp(pCur->segname, pSect->segname, sizeof(pSect->segname))) 576 return KLDR_ERR_MACHO_BAD_SECTION_ORDER; 577 pCur--; 578 } 579 580 /* ok. count it and the string. */ 581 cSegments++; 582 cbStringPool += kLdrHlpStrLen(pSect->segname) + 1; 583 } 584 break; 585 } 586 587 default: 588 return KLDR_ERR_INVALID_PARAMETER; 589 } 590 591 /* next */ 592 pSect++; 593 } 594 break; 595 } 596 597 case LC_SEGMENT_64: 598 /* copy 32-bit code */ 599 break; 600 601 case LC_SYMTAB: 602 if (fConvertEndian) 603 { 604 u.pSymTab->symoff = KLDRHLP_E2E_U32(u.pSymTab->symoff); 605 u.pSymTab->nsyms = KLDRHLP_E2E_U32(u.pSymTab->nsyms); 606 u.pSymTab->stroff = KLDRHLP_E2E_U32(u.pSymTab->stroff); 607 u.pSymTab->strsize = KLDRHLP_E2E_U32(u.pSymTab->strsize); 608 } 609 610 /* verify */ 611 if ( u.pSymTab->symoff >= cbFile 612 || (uint64_t)u.pSymTab->symoff + u.pSymTab->nsyms * sizeof(nlist_t) > kLdrRdrSize(pRdr)) 613 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 614 if ( u.pSymTab->stroff >= cbFile 615 || (uint64_t)u.pSymTab->stroff + u.pSymTab->strsize > cbFile) 616 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 617 break; 618 619 case LC_THREAD: 620 case LC_UNIXTHREAD: 621 { 622 uint32_t *pu32 = (uint32_t *)(u.pb + sizeof(load_command_t)); 623 uint32_t cItemsLeft = (u.pThread->cmdsize - sizeof(load_command_t)) / sizeof(uint32_t); 624 while (cItemsLeft) 625 { 626 /* convert & verify header items ([0] == flavor, [1] == uint32_t count). */ 627 if (cItemsLeft < 2) 628 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 629 if (fConvertEndian) 630 { 631 pu32[0] = KLDRHLP_E2E_U32(pu32[0]); 632 pu32[1] = KLDRHLP_E2E_U32(pu32[1]); 633 } 634 if (pu32[1] + 2 > cItemsLeft) 635 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 636 637 /* convert & verify according to flavor. */ 638 switch (pu32[0]) 639 { 640 /** @todo */ 641 default: 642 break; 643 } 644 645 /* next */ 646 cItemsLeft -= pu32[1] + 2; 647 pu32 += pu32[1] + 2; 648 } 649 break; 650 } 651 652 case LC_UUID: 653 if (u.pUuid->cmdsize != sizeof(uuid_command_t)) 654 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 655 /** @todo Check anything here need converting? */ 656 break; 657 658 case LC_LOADFVMLIB: 659 case LC_IDFVMLIB: 660 case LC_IDENT: 661 case LC_FVMFILE: 662 case LC_PREPAGE: 663 case LC_DYSYMTAB: 664 case LC_LOAD_DYLIB: 665 case LC_ID_DYLIB: 666 case LC_LOAD_DYLINKER: 667 case LC_ID_DYLINKER: 668 case LC_PREBOUND_DYLIB: 669 case LC_ROUTINES: 670 case LC_ROUTINES_64: 671 case LC_SUB_FRAMEWORK: 672 case LC_SUB_UMBRELLA: 673 case LC_SUB_CLIENT: 674 case LC_SUB_LIBRARY: 675 case LC_TWOLEVEL_HINTS: 676 case LC_PREBIND_CKSUM: 677 case LC_LOAD_WEAK_DYLIB: 678 case LC_SYMSEG: 679 return KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND; 680 681 default: 682 return KLDR_ERR_MACHO_UNKNOWN_LOAD_COMMAND; 683 } 684 } 685 686 /* be strict (for now). */ 687 if (cbLeft) 688 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 689 690 *pcSegments = cSegments; 691 *pcbStringPool = cLeft; 692 385 693 return 0; 386 694 } … … 1723 2031 /** @copydoc kLdrModRelocateBits */ 1724 2032 static int kldrModMachORelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, 1725 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)2033 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 1726 2034 { 1727 2035 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; … … 1740 2048 1741 2049 /** 1742 * The PEmodule interpreter method table.2050 * The Mach-O module interpreter method table. 1743 2051 */ 1744 KLDRMODOPS g_kLdrMod PEOps =1745 { 1746 " PE",2052 KLDRMODOPS g_kLdrModMachOOps = 2053 { 2054 "Mach-O", 1747 2055 NULL, 1748 2056 kldrModMachOCreate,
Note:
See TracChangeset
for help on using the changeset viewer.