Changeset 3667 for trunk/emx/src/emxomf/emxomfld.c
- Timestamp:
- Sep 18, 2010, 3:06:59 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/emx/src/emxomf/emxomfld.c
r3462 r3667 37 37 #include <alloca.h> 38 38 #include <sys/omflib.h> 39 #include <sys/elf.h> 40 #include <ar.h> 39 41 #include "defs.h" 40 42 #include "weakld.h" … … 51 53 } name_list; 52 54 55 /* OMF record header. */ 56 #pragma pack(1) 57 typedef struct omf_rec_hdr 58 { 59 byte type; 60 word len; 61 } omf_rec_hdr; 62 #pragma pack() 53 63 54 64 /* Whether or not linker tracing is enabled. */ … … 504 514 505 515 /** 516 * Reports archive parsing error. 517 * @returns 0. 518 * @param pszError The parsing error. 519 */ 520 static int bad_arch(const char *pszError) 521 { 522 fprintf(stderr, "emxomfld: failed parsing archive: %s\n", pszError); 523 return 0; 524 } 525 526 /** 527 * Validates a numeric ar_hdr field. 528 * 529 * These are supposed to be padded with spaces, however, emximp seems to be 530 * using null terminators as well (ar_mode for instance). 531 * 532 * @returns 1 if valid, 0 if invalid. 533 * @param pachField The field. 534 * @param cchField The field length. 535 * @param uBase 10 for decimal, 8 for octal. 536 * @param pszName The field name. 537 */ 538 static int is_arch_num_field_valid(char const *pachField, size_t cchField, unsigned uBase, const char *pszName) 539 { 540 while (cchField > 0) 541 { 542 unsigned ch = *pachField; 543 if (ch - '0' >= uBase) 544 { 545 if (ch == ' ' || !ch) 546 break; 547 return bad_arch(pszName); 548 } 549 cchField--; 550 pachField++; 551 } 552 553 while (cchField > 0) 554 { 555 char ch = *pachField; 556 if (ch != ' ' && ch) 557 return bad_arch(pszName); 558 cchField--; 559 pachField++; 560 } 561 562 return 1; 563 } 564 565 /** 566 * Checks the name field to see if there is a BSD style variable sized name 567 * field following the header. 568 569 * @returns 0 if none, length if something. 570 * @param pArHdr The archive header. 571 */ 572 static unsigned arch_hdr_get_ext_name_len(struct ar_hdr *pArHdr) 573 { 574 unsigned cchExtName = 0; 575 if (!memcmp(&pArHdr->ar_name[0], AR_EFMT1, sizeof(AR_EFMT1) - 1)) 576 { 577 int cch = sizeof(pArHdr->ar_name) - sizeof(AR_EFMT1) - 1; 578 const char *pch = &pArHdr->ar_name[sizeof(AR_EFMT1) - 1]; 579 while (cch-- > 0) 580 { 581 unsigned uDig = (unsigned char)*pch++ - '0'; 582 if (uDig > 10) 583 break; 584 cchExtName *= 10; 585 cchExtName += uDig; 586 } 587 } 588 return cchExtName; 589 } 590 591 /** 592 * Converts the size field of the header into something we can use. 593 * @returns ar_size as off_t. 594 * @param pArHdr The archive header. 595 */ 596 static off_t arch_hdr_get_size(struct ar_hdr *pArHdr) 597 { 598 off_t cb = 0; 599 int cch = sizeof(pArHdr->ar_size); 600 const char *pch = &pArHdr->ar_size[0]; 601 while (cch-- > 0) 602 { 603 unsigned uDig = (unsigned char)*pch++ - '0'; 604 if (uDig > 10) 605 break; 606 cb *= 10; 607 cb += uDig; 608 } 609 return cb; 610 } 611 612 /** 613 * Matches @a pszName with the name in the archive header. 614 * 615 * @returns 1 if matches, 0 if not. 616 * @param pArHdr The archive header. 617 * @param pszName The name to match it with. 618 */ 619 static int arch_hdr_match_name(struct ar_hdr *pArHdr, const char *pszName) 620 { 621 size_t cch = sizeof(pArHdr->ar_name); 622 const char *pch = &pArHdr->ar_name[0]; 623 while (cch > 0) 624 { 625 if (*pszName != *pch) 626 { 627 if (*pszName) 628 return 0; 629 break; 630 } 631 cch--; 632 pszName++; 633 pch++; 634 } 635 636 while (cch-- > 0) 637 { 638 char ch = *pch++; 639 if (ch != ' ' && ch) 640 return 0; 641 } 642 643 return 1; 644 } 645 646 /** 647 * Checks if the stream @a pFile is an archive only containing ELF and OMF 648 * files. 649 * 650 * @returns 1 if so, 0 if not. 651 * @param pFile The file stream to check. The caller rewinds the stream. 652 */ 653 static int check_arch_library_with_omf_and_or_elf(FILE *pFile) 654 { 655 union 656 { 657 char achMagic[SARMAG]; 658 struct ar_hdr ArHdr; 659 Elf32_Ehdr Elfhdr; 660 omf_rec_hdr OmfHdr; 661 /*struct exec AoutHdr;*/ 662 } uBuf; 663 off_t offArchive; 664 665 /* 666 * Read+reverify the magic. 667 */ 668 if (fread(&uBuf.achMagic[0], SARMAG, 1, pFile) != 1) 669 return 0; 670 if (memcmp(&uBuf.achMagic[0], ARMAG, SARMAG) != 0) 671 return 0; 672 673 /* 674 * Process the archive, file by file. 675 */ 676 offArchive = SARMAG; 677 while (!feof(pFile)) 678 { 679 off_t cbFile; 680 off_t offNext; 681 size_t cbRead; 682 int cchExtraName; 683 684 /* read + verify the archive header */ 685 cbRead = fread(&uBuf.ArHdr, 1, sizeof(uBuf.ArHdr), pFile); 686 if (cbRead != sizeof(uBuf.ArHdr)) 687 return cbRead == 0 && feof(pFile) ? 1 : bad_arch("fread"); 688 offArchive += sizeof(uBuf.ArHdr); 689 690 if (memcmp(uBuf.ArHdr.ar_fmag, ARFMAG, sizeof(uBuf.ArHdr.ar_fmag))) 691 return bad_arch("ar_fmag"); 692 if ( !is_arch_num_field_valid(uBuf.ArHdr.ar_date, sizeof(uBuf.ArHdr.ar_date), 10, "ar_date") 693 || !is_arch_num_field_valid(uBuf.ArHdr.ar_uid, sizeof(uBuf.ArHdr.ar_uid), 10, "ar_uid") 694 || !is_arch_num_field_valid(uBuf.ArHdr.ar_gid, sizeof(uBuf.ArHdr.ar_gid), 10, "ar_gid") 695 || !is_arch_num_field_valid(uBuf.ArHdr.ar_mode, sizeof(uBuf.ArHdr.ar_mode), 8, "ar_mode") 696 || !is_arch_num_field_valid(uBuf.ArHdr.ar_size, sizeof(uBuf.ArHdr.ar_size), 10, "ar_size") ) 697 return 0; /* bitched already */ 698 699 cbFile = arch_hdr_get_size(&uBuf.ArHdr); 700 offNext = offArchive + cbFile; 701 offNext += offNext & 1; /* make even */ 702 703 /* skip the extended name field if present (BSD). */ 704 cchExtraName = arch_hdr_get_ext_name_len(&uBuf.ArHdr); 705 /*fprintf(stderr, "%#06x '%.16s' offNext=%#x cb=%#x ext=%d\n", (unsigned)offArchive, &uBuf.ArHdr.ar_name[0], (unsigned)offNext, (unsigned)cbFile, cchExtraName);*/ 706 if (cchExtraName) 707 { 708 cbFile -= cchExtraName; 709 offArchive += cchExtraName; 710 if (fseek(pFile, offArchive, SEEK_SET)) 711 return bad_arch("fseek-ext-name"); 712 } 713 714 /* ignore the archive symbol table. */ 715 if ( !arch_hdr_match_name(&uBuf.ArHdr, "__.SYMDEF") 716 && !arch_hdr_match_name(&uBuf.ArHdr, "/") 717 && !arch_hdr_match_name(&uBuf.ArHdr, "ARFILENAMES/") 718 && !arch_hdr_match_name(&uBuf.ArHdr, "//")) 719 { 720 cbRead = sizeof(uBuf); 721 if (cbRead > cbFile) 722 { 723 cbRead = cbFile; 724 memset(&uBuf, 0, sizeof(uBuf)); 725 } 726 if (fread(&uBuf, 1, cbRead, pFile) != cbRead) 727 return bad_arch("fread-member-hdr"); 728 729 if ( ( uBuf.OmfHdr.len >= sizeof(uBuf.OmfHdr) 730 && cbRead > sizeof(sizeof(uBuf.OmfHdr)) ) 731 && ( uBuf.OmfHdr.type == THEADR 732 /*|| uBuf.OmfHdr.type == LIBADR - doubt wlink can handle this */) 733 || IS_ELF(uBuf.Elfhdr) ) 734 { 735 /* nothing */ 736 /*fprintf(stderr, IS_ELF(uBuf.Elfhdr) ? "ELF\n" : "OMF\n");*/ 737 } 738 else 739 { 740 /*fprintf(stderr, "not omf or elf\n");*/ 741 return 0; 742 } 743 } 744 /*else 745 fprintf(stderr, "skip archive symbol table\n");*/ 746 747 /* advance to the next file */ 748 if (fseek(pFile, offNext, SEEK_SET)) 749 return bad_arch("fseek-next"); 750 offArchive = offNext; 751 } 752 753 return 1; 754 } 755 756 /** 506 757 * Checks if the stream phFile is an OMF library. 507 758 * … … 546 797 * @param phFile Filestream to check. 547 798 */ 548 static int check_omf (FILE *phFile)799 static int check_omf_or_elf(FILE *phFile) 549 800 { 550 801 #pragma pack(1) 551 struct 552 { 553 byte rec_type; 554 word rec_len; 555 } omfhdr; 802 union 803 { 804 struct 805 { 806 byte rec_type; 807 word rec_len; 808 } omfhdr; 809 byte elfmagic[4]; 810 char arch[7]; 811 } u; 556 812 #pragma pack() 557 if ( fread(&omfhdr, 1, sizeof(omfhdr), phFile) == sizeof (omfhdr) 558 && omfhdr.rec_type == THEADR 559 && omfhdr.rec_len >= sizeof(omfhdr) 560 && !fseek(phFile, 0, SEEK_SET) 561 ) 813 size_t cbRead = fread(&u.omfhdr, 1, sizeof(u), phFile); 814 if (fseek(phFile, 0, SEEK_SET)) 815 return 0; 816 817 /* OMF object or library? */ 818 if ( cbRead >= sizeof(u.omfhdr) 819 && u.omfhdr.rec_type == THEADR 820 && u.omfhdr.rec_len >= sizeof(u.omfhdr) ) 562 821 return 1; 563 564 return !fseek(phFile, 0, SEEK_SET) 565 && check_omf_library(phFile); 822 if ( cbRead >= sizeof(u.omfhdr) 823 && u.omfhdr.rec_type == LIBHDR) 824 return check_omf_library(phFile); 825 826 /* ELF object? */ 827 if ( u.elfmagic[0] == ELFMAG0 828 && u.elfmagic[1] == ELFMAG1 829 && u.elfmagic[2] == ELFMAG2 830 && u.elfmagic[3] == ELFMAG3) 831 return 1; 832 833 /* AR archive with OMF and/or ELF content? */ 834 if ( cbRead >= sizeof("!<arch>") - 1 835 && !memcmp(u.arch, "!<arch>", sizeof(u.arch))) 836 { 837 int rc = check_arch_library_with_omf_and_or_elf(phFile); 838 if (fseek(phFile, 0, SEEK_SET)) 839 rc = 0; 840 return rc; 841 } 842 843 /* Not anything we know */ 844 return 0; 566 845 } 567 846 … … 637 916 638 917 /* We need to apply _realrealpath to the tmpdir, so resolve that once and for all. */ 639 if (!s_szTmp[0]) 918 if (!s_szTmp[0]) 640 919 { 641 920 const char * pszTmp = getenv("TMP"); … … 863 1142 */ 864 1143 if ( autoconvert_flag 865 && !check_omf (phFile))1144 && !check_omf_or_elf(phFile)) 866 1145 phFile = aout_to_omf(phFile, pszFullname, FALSE); 867 1146 … … 1006 1285 if (check_lx_dll(phFile)) 1007 1286 phFile = lx_to_omf(phFile, pszFullname); 1008 else if (!check_omf (phFile))1287 else if (!check_omf_or_elf(phFile)) 1009 1288 phFile = aout_to_omf(phFile, pszFullname, TRUE); 1010 1289 } … … 1367 1646 case _MD_STUB: 1368 1647 if (!stmt->stub.none) 1369 fprintf (response_file, "OPTION STUB='%s'\n", stmt->stub.name); 1648 { 1649 fprintf (response_file, "OPTION STUB='%s'\n", stmt->stub.name); 1650 *(int*)(arg) = 0; /*need_stub*/ 1651 } 1370 1652 else 1371 1653 fprintf (stderr, "emxomfld: warning: \"STUB NONE\" is not supported by wlink. ignoring\n"); … … 2085 2367 { 2086 2368 unsigned uPMType = 0; 2369 int need_stub = 1; 2087 2370 2088 2371 open_response_file (); … … 2275 2558 fprintf (response_file, "OPTION OFFSET=%s\n", base); 2276 2559 2277 /* the stub */2278 2279 _execname(&execname[0], sizeof(execname));2280 strcpy (_getname (&execname[0]), "os2stub.bin");2281 if (!stat (execname, &s))2282 fprintf (response_file, "OPTION STUB='%s'\n", execname);2283 2284 2560 /* Add the /INFORMATION option if the -i or -t option was given. This is 2285 2561 for debugging. */ … … 2305 2581 2306 2582 /* Translate the essentials of the module definition file into wlink lingo. */ 2583 2307 2584 if (def_fname) 2308 2585 { … … 2314 2591 } 2315 2592 _md_next_token (pMd); 2316 _md_parse (pMd, def_2_watcom, NULL);2593 _md_parse (pMd, def_2_watcom, &need_stub); 2317 2594 _md_close (pMd); 2318 2595 } 2596 2597 /* the stub */ 2598 2599 if (need_stub) 2600 { 2601 _execname(&execname[0], sizeof(execname)); 2602 strcpy (_getname (&execname[0]), "os2stub.bin"); 2603 if (!stat (execname, &s)) 2604 fprintf (response_file, "OPTION STUB='%s'\n", execname); 2605 } 2606 2319 2607 } 2320 2608
Note:
See TracChangeset
for help on using the changeset viewer.