Changeset 3667
- Timestamp:
- Sep 18, 2010, 3:06:59 AM (15 years ago)
- Location:
- trunk/emx/src/emxomf
- Files:
-
- 1 added
- 2 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 -
trunk/emx/src/emxomf/weakld.c
r3462 r3667 35 35 * There is a couple of symbol types, but we can skip most of them for this 36 36 * pre-linking operation. We use one symbol type which is public or global 37 * symbols if you like. Perhaps it would be wise to d evide them into separat37 * symbols if you like. Perhaps it would be wise to divide them into separat 38 38 * type groups, but the choice was made to differenciate this using flags. 39 39 * So, symbol enumeration is done using flag masks. … … 101 101 #include <sys/omflib.h> 102 102 #include <sys/moddef.h> 103 #include <sys/elf.h> 104 #include <ar.h> 103 105 #include "defs.h" 104 106 #include "grow.h" … … 155 157 const char *pszLibName; 156 158 /** Filehandle if open */ 157 FILE * phFile; 158 /** Pointer to extended dictiorary. */ 159 void * pDict; 160 /** Library header. */ 161 OMFLIBHDR LibHdr; 159 FILE *phFile; 160 /** Set if it's a OMF library, clear if it's a unix archive. */ 161 unsigned fOmfLib; 162 /** Pointer to the extended dictionary (OMF) / symbol table (AR). */ 163 void *pDict; 164 union 165 { 166 struct 167 { 168 /** Library header. */ 169 OMFLIBHDR LibHdr; 170 } Omf; 171 struct 172 { 173 /** Later. */ 174 unsigned uDummy; 175 } Ar; 176 } u; 162 177 /** Linked list next pointer. */ 163 struct wldlib * 178 struct wldlib *pNext; 164 179 } WLDLIB, *PWLDLIB; 165 180 … … 414 429 static void wldIntErr(PWLD pWld, PWLDMOD pMod, const char *pszFile, unsigned iLine, const char *pszFunction); 415 430 static unsigned pass1ReadOMFMod(PWLD pWld, PWLDMOD pMod, int fLibSearch); 431 static unsigned pass1ReadELFMod(PWLD pWld, PWLDMOD pMod, int fLibSearch); 416 432 /** Parameter structure for wldDefCallback(). */ 417 433 typedef struct wldDefCallback_param … … 434 450 static void libCloseDict(PWLDLIB pLib); 435 451 static int libTryLoadSymbolThruDictionary(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded); 452 static int libLoadUndefSymbolsFromOmfLib(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded); 453 /** 454 * Callback parameter structure used between libLoadUndefSymbolsFromArchLib 455 * and libLoadUndefSymbolsFromArchLibCallback 456 */ 457 typedef struct libLoadUndefSymbolsFromArchLib_param 458 { 459 /** The linker instance. */ 460 PWLD pWld; 461 /** The library. */ 462 PWLDLIB pLib; 463 /** See libLoadUndefSymbols. */ 464 PWLDSYM pSym; 465 /** See libLoadUndefSymbols. */ 466 unsigned *pcLoaded; 467 } WLDLIBLOADUSFALPARAM, *PWLDLIBLOADUSFALPARAM; 468 static int libLoadUndefSymbolsFromArchLibCallback(FILE *pFile, const char *pszName, off_t cbFile, void *pvUser); 469 static int libLoadUndefSymbolsFromArchLib(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded); 436 470 static int libLoadUndefSymbols(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded); 471 /** 472 * Enumeration callback routine. 473 * @returns Any non-zero value stops the enumeration and is passed to the caller. 474 * @param pFile Stream positioned at the start of the file. Don't close. 475 * @param pszName The file name. 476 * @param cbFile The file size. 477 * @param pvUser The user parameter. 478 */ 479 typedef int (* PFNLIBENUMFILE)(FILE *pFile, const char *pszName, off_t cbFile, void *pvUser); 480 static int libEnumFilesArch(PWLDLIB pLib, int fAll, PFNLIBENUMFILE pfnCallback, void *pvUser); 437 481 static int libErr(PWLDLIB pLib, const char *pszFormat, ...); 438 482 #if 0 … … 678 722 #if 0 679 723 FILE *phFile; 724 680 725 /* been here, done that? */ 681 if (pLib-> pDict)726 if (pLib->upDict) 682 727 return 0; 683 728 684 /* check if it acutally is a library and have an ext dict */ 685 if ( pLib->LibHdr.chType != LIBHDR 686 || pLib->LibHdr.offDict != 0 687 || pLib->LibHdr.cDictBlocks != 0) 688 return 1; 689 729 if (pLib->fOmfLib) 730 { 731 /* check if it acutally is a library and have an ext dict */ 732 if ( pLib->u.Omf.LibHdr.chType != LIBHDR 733 || pLib->u.Omf.LibHdr.offDict != 0 734 || pLib->u.Omf.LibHdr.cDictBlocks != 0) 735 return 1; 736 } 737 else 738 { 739 } 740 690 741 /* ensure it's open. */ 691 742 phFile = libOpen(pLib); 692 743 if (!phFile) 693 744 return -1; 694 695 /* position us */ 696 if (fseek(phFile, pLib->LibHdr.offDict, SEEK_SET)) 697 return libErr(pLib, "Failed to seek to extended dictionary (offset %d).", (int)pLib->LibHdr.offDict); 698 699 /* read it */ 700 pLib->pDict = xmalloc(pLib->LibHdr.cDictBlocks * 512); 701 if (fread(pLib->pDict, 512, pLib->LibHdr.cDictBlocks, phFile) == pLib->LibHdr.cDictBlocks) 702 return 0; 703 libErr(pLib, "Failed to read extended dictionary."); 745 746 if (pLib->fOmfLib) 747 { 748 /* position us */ 749 if (fseek(phFile, pLib->LibHdr.offDict, SEEK_SET)) 750 return libErr(pLib, "Failed to seek to extended dictionary (offset %d).", (int)pLib->LibHdr.offDict); 751 752 /* read it */ 753 pLib->pDict = xmalloc(pLib->LibHdr.cDictBlocks * 512); 754 if (fread(pLib->pDict, 512, pLib->LibHdr.cDictBlocks, phFile) == pLib->LibHdr.cDictBlocks) 755 return 0; 756 757 libErr(pLib, "Failed to read extended dictionary."); 758 } 759 704 760 free(pLib->pDict); 705 761 pLib->pDict = NULL; 706 762 return -1; 763 707 764 #else 708 765 /* till we support processing the dictionary, we pretend there is none. */ 709 766 pLib->pDict = NULL; 710 return -1;767 return 1; 711 768 #endif 712 769 } … … 741 798 static int libTryLoadSymbolThruDictionary(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded) 742 799 { 743 return libLoadUndefSymbols(pWld, pLib, pSym, pcLoaded); /* @todo implement this function! */ 744 } 745 746 747 /** 748 * Read thru an module looking for definitions for undef symbols. 749 * If a definition is found we'll load the module containing it. 750 * 751 * @returns 0 on non failure. 752 * @returns 42 if none found. 753 * @returns -1 on link abort error. 754 * @param pWld Linker instance. 755 * @param pLib Library to search. 756 * @param pSym Undefined symbol to search for. 757 * If NULL we'll try and see if any defined global symbol we 758 * encounter is undefined. 800 return libLoadUndefSymbols(pWld, pLib, pSym, pcLoaded); /** @todo implement this function! */ 801 } 802 803 804 /** 805 * Implementation of libLoadUndefSymbols for unix archives. 806 * 807 * @returns see libLoadUndefSymbols 808 * @param pWld Linker instance. 809 * @param pLib Library to search. 810 * @param pSym See libLoadUndefSymbols. 759 811 * @param pcLoaded Number of modules which was loaded from this library. 760 812 */ 761 static int libLoadUndefSymbols (PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded)813 static int libLoadUndefSymbolsFromOmfLib(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded) 762 814 { 763 815 FILE * phFile = pLib->phFile; … … 774 826 775 827 /* Position the library at the first module record. */ 776 if (fseek(phFile, pLib-> LibHdr.chType == LIBHDR ? pLib->LibHdr.cb + 3 : 0, SEEK_SET))828 if (fseek(phFile, pLib->u.Omf.LibHdr.chType == LIBHDR ? pLib->u.Omf.LibHdr.cb + 3 : 0, SEEK_SET)) 777 829 return libErr(pLib, "Error when seeking to first module."); 778 830 779 if (pLib-> LibHdr.chType != LIBHDR)831 if (pLib->u.Omf.LibHdr.chType != LIBHDR) 780 832 { 781 833 uchEnd1 = MODEND; … … 1004 1056 if (OmfRec.chType == MODEND || OmfRec.chType == (MODEND | REC32)) 1005 1057 { 1006 unsigned cbPage = pLib-> LibHdr.cb + 3;1058 unsigned cbPage = pLib->u.Omf.LibHdr.cb + 3; 1007 1059 off_t off = ftell(phFile) + offSkip; 1008 1060 off -= cbPage * (off / cbPage); /* don't trust this to be 2**n. */ … … 1031 1083 1032 1084 /** 1085 * Callback used by libLoadUndefSymbolsFromArchLib 1086 * 1087 * @returns 0 or -1 see libLoadUndefSymbols. 1088 * @param phFile The library stream, positioned at the start of the file. 1089 * @param pszName The (short) file name. 1090 * @param cbFile The file size. 1091 * @param pvUser Parameters. 1092 */ 1093 static int libLoadUndefSymbolsFromArchLibCallback(FILE *pFile, const char *pszName, off_t cbFile, void *pvUser) 1094 { 1095 PWLDLIBLOADUSFALPARAM pParam = (PWLDLIBLOADUSFALPARAM)pvUser; 1096 /** @todo */ 1097 return 0; 1098 } 1099 1100 1101 /** 1102 * Implementation of libLoadUndefSymbols for unix archives. 1103 * 1104 * @returns see libLoadUndefSymbols 1105 * @param pWld Linker instance. 1106 * @param pLib Library to search. 1107 * @param pSym See libLoadUndefSymbols. 1108 * @param pcLoaded Number of modules which was loaded from this library. 1109 */ 1110 static int libLoadUndefSymbolsFromArchLib(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded) 1111 { 1112 WLDLIBLOADUSFALPARAM Param; 1113 1114 Param.pWld = pWld; 1115 Param.pLib = pLib; 1116 Param.pSym = pSym; 1117 Param.pcLoaded = pcLoaded; 1118 return libEnumFilesArch(pLib, 0 /*fAll*/, libLoadUndefSymbolsFromArchLibCallback, &Param); 1119 } 1120 1121 1122 /** 1123 * Read thru a library looking for definitions for undef symbols. 1124 * If a definition is found we'll load the module containing it. 1125 * 1126 * @returns 0 on non failure. 1127 * @returns 42 if none found. 1128 * @returns -1 on link abort error. 1129 * @param pWld Linker instance. 1130 * @param pLib Library to search. 1131 * @param pSym Undefined symbol to search for. 1132 * If NULL we'll try and see if any defined global symbol we 1133 * encounter is undefined. 1134 * @param pcLoaded Number of modules which was loaded from this library. 1135 */ 1136 static int libLoadUndefSymbols(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded) 1137 { 1138 if (!pLib->fOmfLib) 1139 return libLoadUndefSymbolsFromArchLib(pWld, pLib, pSym, pcLoaded); 1140 return libLoadUndefSymbolsFromOmfLib(pWld, pLib, pSym, pcLoaded); 1141 } 1142 1143 1144 /** 1145 * Validates a numeric ar_hdr field. 1146 * 1147 * These are supposed to be padded with spaces, however, emximp seems to be 1148 * using null terminators as well (ar_mode for instance). 1149 * 1150 * @returns 0 if valid, -1 if invalid (error shown). 1151 * @param pachField The field. 1152 * @param cchField The field length. 1153 * @param uBase 10 for decimal, 8 for octal. 1154 * @param pszName The field name. 1155 */ 1156 static int libArchValidateNumField(PWLDLIB pLib, char const *pachField, size_t cchField, unsigned uBase, const char *pszName) 1157 { 1158 while (cchField > 0) 1159 { 1160 unsigned ch = *pachField; 1161 if (ch - '0' >= uBase) 1162 { 1163 if (ch == ' ' || !ch) 1164 break; 1165 return libErr(pLib, "bad archive header field: %s", pszName); 1166 } 1167 cchField--; 1168 pachField++; 1169 } 1170 1171 while (cchField > 0) 1172 { 1173 char ch = *pachField; 1174 if (ch != ' ' && ch) 1175 return libErr(pLib, "bad archive header field: %s", pszName); 1176 cchField--; 1177 pachField++; 1178 } 1179 1180 return 0; 1181 } 1182 1183 /** 1184 * Checks the name field to see if there is a BSD style variable sized name 1185 * field following the header. 1186 * 1187 * @returns 0 if none, length if something. 1188 * @param pArHdr The archive header. 1189 */ 1190 static unsigned libArchHdrGetExtNameLen(struct ar_hdr *pArHdr) 1191 { 1192 unsigned cchExtName = 0; 1193 if (!memcmp(&pArHdr->ar_name[0], AR_EFMT1, sizeof(AR_EFMT1) - 1)) 1194 { 1195 int cch = sizeof(pArHdr->ar_name) - sizeof(AR_EFMT1) - 1; 1196 const char *pch = &pArHdr->ar_name[sizeof(AR_EFMT1) - 1]; 1197 while (cch-- > 0) 1198 { 1199 unsigned uDig = (unsigned char)*pch++ - '0'; 1200 if (uDig > 10) 1201 break; 1202 cchExtName *= 10; 1203 cchExtName += uDig; 1204 } 1205 } 1206 return cchExtName; 1207 } 1208 1209 1210 /** 1211 * Converts the size field of the header into something we can use. 1212 * @returns ar_size as off_t. 1213 * @param pArHdr The archive header. 1214 */ 1215 static off_t libArchHdrGetSize(struct ar_hdr *pArHdr) 1216 { 1217 off_t cb = 0; 1218 int cch = sizeof(pArHdr->ar_size); 1219 const char *pch = &pArHdr->ar_size[0]; 1220 while (cch-- > 0) 1221 { 1222 unsigned uDig = (unsigned char)*pch++ - '0'; 1223 if (uDig > 10) 1224 break; 1225 cb *= 10; 1226 cb += uDig; 1227 } 1228 return cb; 1229 } 1230 1231 1232 /** 1233 * Enumerates the files in the unix archive. 1234 * 1235 * @returns 0 if pfnCallback returned 0 for all the files. 1236 * @returns first non-zero value pfnCallback returns (stops enumeration). 1237 * @returns -1 if the library is invalid. 1238 * @param pLib The Library to enumerate 1239 * @param fAll Whether to include the special files or not. 1240 * @param pfnCallback The callback to invoke for each file. 1241 * @param pvUser The user argument to pass to the callback. 1242 */ 1243 static int libEnumFilesArch(PWLDLIB pLib, int fAll, PFNLIBENUMFILE pfnCallback, void *pvUser) 1244 { 1245 int rc = 0; 1246 FILE *pFile = pLib->phFile; 1247 off_t offNext; 1248 char szMagic[SARMAG + 1]; 1249 1250 if (pLib->fOmfLib) 1251 return libErr(pLib, "OMF library, expected ARCH!"); 1252 1253 /* 1254 * Read+reverify the magic. 1255 */ 1256 if ( fseek(pFile, 0, SEEK_SET) != 0 1257 || fread(&szMagic[0], SARMAG, 1, pFile) != 1) 1258 return libErr(pLib, "failed to read library magic"); 1259 szMagic[SARMAG] = '\0'; 1260 if (strcmp(szMagic, ARMAG) != 0) 1261 return libErr(pLib, "invalid library magic"); 1262 1263 /* 1264 * Process the archive, file by file. 1265 */ 1266 offNext = SARMAG; 1267 while (!feof(pFile)) 1268 { 1269 struct ar_hdr ArHdr; 1270 off_t cbFile; 1271 size_t cbRead; 1272 int cchExtraName; 1273 int fSpecial; 1274 int i; 1275 1276 /* read + verify the archive header */ 1277 cbRead = fread(&ArHdr, 1, sizeof(ArHdr), pFile); 1278 if (cbRead != sizeof(ArHdr)) 1279 return cbRead == 0 && feof(pFile) ? 0 : libErr(pLib, "fread error"); 1280 offNext += sizeof(ArHdr); 1281 1282 if (memcmp(ArHdr.ar_fmag, ARFMAG, sizeof(ArHdr.ar_fmag))) 1283 return libErr(pLib, "Bad ar_fmag value"); 1284 if ( libArchValidateNumField(pLib, ArHdr.ar_date, sizeof(ArHdr.ar_date), 10, "ar_date") 1285 || libArchValidateNumField(pLib, ArHdr.ar_uid, sizeof(ArHdr.ar_uid), 10, "ar_uid") 1286 || libArchValidateNumField(pLib, ArHdr.ar_gid, sizeof(ArHdr.ar_gid), 10, "ar_gid") 1287 || libArchValidateNumField(pLib, ArHdr.ar_mode, sizeof(ArHdr.ar_mode), 8, "ar_mode") 1288 || libArchValidateNumField(pLib, ArHdr.ar_size, sizeof(ArHdr.ar_size), 10, "ar_size") ) 1289 return 0; /* bitched already */ 1290 1291 cbFile = libArchHdrGetSize(&ArHdr); 1292 offNext += cbFile; 1293 offNext += offNext & 1; /* make even */ 1294 1295 /* skip the extended name field if present (BSD). */ 1296 cchExtraName = libArchHdrGetExtNameLen(&ArHdr); 1297 if (cchExtraName) 1298 { 1299 cbFile -= cchExtraName; 1300 if (fseek(pFile, cchExtraName, SEEK_CUR)) 1301 return libErr(pLib, "fseek past the extended name failed"); 1302 } 1303 1304 /* strip trailing spaces from the header name. */ 1305 i = sizeof(ArHdr.ar_name); 1306 ArHdr.ar_name[i] = '\0'; 1307 while (i-- > 0 && ArHdr.ar_name[i] == ' ') 1308 ArHdr.ar_name[i] = '\0'; 1309 1310 fSpecial = !strcmp(ArHdr.ar_name, "__.SYMDEF") 1311 || !strcmp(ArHdr.ar_name, "/") 1312 || !strcmp(ArHdr.ar_name, "//") 1313 || !strcmp(ArHdr.ar_name, "ARFILENAMES"); 1314 1315 /* trailing slashes used to be fashionable. */ 1316 if (!fSpecial && i > 0 && ArHdr.ar_name[i] == '/') 1317 ArHdr.ar_name[i] = '\0'; 1318 1319 /* ignore the archive symbol table. */ 1320 if ( fAll 1321 || !fSpecial) 1322 { 1323 rc = pfnCallback(pFile, ArHdr.ar_name, cbFile, pvUser); 1324 if (rc) 1325 return rc; 1326 } 1327 1328 /* advance to the next file */ 1329 if (fseek(pFile, offNext, SEEK_SET)) 1330 return libErr(pLib, "seek next failed."); 1331 } 1332 1333 return 0; 1334 } 1335 1336 1337 /** 1033 1338 * Put out an error for this library. 1339 * @returns -1. 1034 1340 * @param pLib Library which the warning occured in. 1035 1341 * @param pszFormat Message format. … … 2569 2875 2570 2876 2571 2877 /** 2878 * Reads an ELF module from a file. 2879 * 2880 * @returns 0 on success. 2881 * @returns non zero on failure. 2882 * @param pWld Pointer to linker instance. 2883 * @param pMod Pointer to module 2884 * @param fLibSearch Set if we're doing library search at this time. 2885 */ 2886 static unsigned pass1ReadELFMod(PWLD pWld, PWLDMOD pMod, int fLibSearch) 2887 { 2888 /** @todo implement me. */ 2889 return 0; 2890 } 2572 2891 2573 2892 … … 2687 3006 2688 3007 /** 3008 * Checks if the ELF header is valid. 3009 * 3010 * @returns 1 if it is, 0 if it isn't. 3011 * @param pEhdr The ELF header. 3012 * @param pszName The file name to use when reporting errors. 3013 */ 3014 static int wldIsValidElfHdr(Elf32_Ehdr const *pEhdr, const char *pszName) 3015 { 3016 if (!IS_ELF(*pEhdr)) 3017 fprintf(stderr, "weakld: '%s': not ELF file..\n", pszName); 3018 else if ( pEhdr->e_ident[EI_CLASS] != ELFCLASS32 3019 && pEhdr->e_ident[EI_CLASS] != ELFCLASSNONE) 3020 fprintf(stderr, "weakld: '%s': wrong ELF class.\n", pszName); 3021 else if ( pEhdr->e_ident[EI_DATA] != ELFDATA2LSB 3022 && pEhdr->e_ident[EI_DATA] != ELFDATANONE) 3023 fprintf(stderr, "weakld: '%s': wrong ELF endian.\n", pszName); 3024 else if (pEhdr->e_ident[EI_VERSION] != EV_CURRENT) 3025 fprintf(stderr, "weakld: '%s': wrong ELF version.\n", pszName); 3026 /* Ignore EI_OSABI, EI_ABIVERSION and EI_PAD. */ 3027 else if (pEhdr->e_type != ET_REL) 3028 fprintf(stderr, "weakld: '%s': not relocatable ELF file.\n", pszName); 3029 else if ( pEhdr->e_machine != EM_386 3030 && pEhdr->e_machine != EM_486) 3031 fprintf(stderr, "weakld: '%s': not 386 or 486 ELF file.\n", pszName); 3032 else if (pEhdr->e_version != EV_CURRENT) 3033 fprintf(stderr, "weakld: '%s': wrong ELF version (#2).\n", pszName); 3034 else if (pEhdr->e_ehsize != sizeof(*pEhdr)) 3035 fprintf(stderr, "weakld: '%s': wrong ELF header size.\n", pszName); 3036 else if (pEhdr->e_phoff && pEhdr->e_phoff < sizeof(*pEhdr)) 3037 fprintf(stderr, "weakld: '%s': bad ELF program header offset.\n", pszName); 3038 else if (pEhdr->e_shoff && pEhdr->e_shoff < sizeof(*pEhdr)) 3039 fprintf(stderr, "weakld: '%s': bad ELF section header offset.\n", pszName); 3040 else if (pEhdr->e_phentsize != sizeof(Elf32_Phdr) && (pEhdr->e_phnum || pEhdr->e_phentsize)) 3041 fprintf(stderr, "weakld: '%s': wrong ELF program header size: %d\n", pszName, pEhdr->e_phentsize); 3042 else if (pEhdr->e_shentsize != sizeof(Elf32_Shdr) && (pEhdr->e_shnum || pEhdr->e_shentsize)) 3043 fprintf(stderr, "weakld: '%s': wrong ELF section header size: %d\n", pszName, pEhdr->e_shentsize); 3044 else 3045 return 1; 3046 return 0; 3047 } 3048 3049 /** 2689 3050 * Adds a object module to the linking process. 2690 3051 * The object module will be analysed and the file handle closed. … … 2703 3064 int WLDAddObject(PWLD pWld, FILE *phFile, const char *pszName) 2704 3065 { 2705 OMFREC OmfRec = {0,0}; 3066 union 3067 { 3068 OMFREC OmfRec; 3069 Elf32_Ehdr Ehdr; 3070 } uBuf; 2706 3071 int rc = 0; 2707 3072 if (!phFile) … … 2713 3078 } 2714 3079 WLDINFO(pWld, ("adding object %s.", pszName)); 3080 if (fread(&uBuf.OmfRec, sizeof(uBuf.OmfRec), 1, phFile) != 1) 3081 { 3082 fprintf(stderr, "weakld: error reading object file '%s'.\n", pszName); 3083 fclose(phFile); 3084 return -1; 3085 } 2715 3086 2716 3087 /* 2717 * An object module is either a object or a library.3088 * An object module is either a object (OMF or ELF) or a library (OMF). 2718 3089 * In anycase all the modules it contains is to be added to the link. 2719 3090 */ 2720 fread(&OmfRec, sizeof(OmfRec), 1, phFile); 2721 if (OmfRec.chType == THEADR) 3091 if (uBuf.OmfRec.chType == THEADR) 2722 3092 { 2723 3093 /* Single Object */ … … 2731 3101 modClose(pMod); 2732 3102 } 2733 else if ( OmfRec.chType == LIBHDR)3103 else if (uBuf.OmfRec.chType == LIBHDR) 2734 3104 { 2735 3105 /* Library of object modules */ 2736 while ( OmfRec.chType != LIBEND &&OmfRec.chType != (LIBEND | REC32))2737 { 2738 if ( OmfRec.chType == THEADR ||OmfRec.chType == (THEADR | REC32))3106 while (uBuf.OmfRec.chType != LIBEND && uBuf.OmfRec.chType != (LIBEND | REC32)) 3107 { 3108 if (uBuf.OmfRec.chType == THEADR || uBuf.OmfRec.chType == (THEADR | REC32)) 2739 3109 { 2740 3110 PWLDMOD pMod = xmalloc(sizeof(*pMod)); … … 2742 3112 pMod->pszModName = strpool_add(pWld->pStrMisc, pszName); 2743 3113 pMod->phFile = phFile; 2744 pMod->off = ftell(phFile) - sizeof( OmfRec);3114 pMod->off = ftell(phFile) - sizeof(uBuf.OmfRec); 2745 3115 *pWld->ppObjsAdd = pMod; 2746 3116 pWld->ppObjsAdd = &pMod->pNext; … … 2761 3131 { 2762 3132 /* skip to the net record */ 2763 fseek(phFile, OmfRec.cb, SEEK_CUR);3133 fseek(phFile, uBuf.OmfRec.cb, SEEK_CUR); 2764 3134 } 2765 3135 2766 3136 /* read next record */ 2767 fread(& OmfRec, sizeof(OmfRec), 1, phFile);3137 fread(&uBuf.OmfRec, sizeof(uBuf.OmfRec), 1, phFile); 2768 3138 } 2769 3139 fclose(phFile); 3140 } 3141 else if ( uBuf.Ehdr.e_ident[EI_MAG0] == ELFMAG0 3142 && uBuf.Ehdr.e_ident[EI_MAG1] == ELFMAG1 3143 && uBuf.Ehdr.e_ident[EI_MAG2] == ELFMAG2 3144 && fread((char *)&uBuf.Ehdr + sizeof(uBuf.OmfRec), 3145 sizeof(uBuf.Ehdr) - sizeof(uBuf.OmfRec), 1, phFile) == 1 3146 && uBuf.Ehdr.e_ident[EI_MAG3] == ELFMAG3) 3147 { 3148 if (wldIsValidElfHdr(&uBuf.Ehdr, pszName)) 3149 { 3150 /* Single Object */ 3151 PWLDMOD pMod = xmalloc(sizeof(*pMod)); 3152 memset(pMod, 0, sizeof(*pMod)); 3153 pMod->pszModName = strpool_add(pWld->pStrMisc, pszName); 3154 pMod->phFile = phFile; 3155 *pWld->ppObjsAdd = pMod; 3156 pWld->ppObjsAdd = &pMod->pNext; 3157 rc = pass1ReadELFMod(pWld, pMod, 0); 3158 modClose(pMod); 3159 } 3160 else 3161 { 3162 fclose(phFile); 3163 rc = -1; 3164 } 2770 3165 } 2771 3166 else … … 2946 3341 int WLDAddLibrary(PWLD pWld, FILE *phFile, const char *pszName) 2947 3342 { 2948 PWLDLIB pLib; 2949 int rc = 0; 3343 PWLDLIB pLib; 2950 3344 2951 3345 if (!phFile) … … 2965 3359 pLib->pNext = NULL; 2966 3360 2967 /* read the library header . */3361 /* read the library header, detect the format. */ 2968 3362 if ( !fseek(phFile, 0, SEEK_SET) 2969 && fread(&pLib->LibHdr, sizeof(OMFREC), 1, phFile) == 1 2970 && ( pLib->LibHdr.chType != LIBHDR 2971 || fread(&pLib->LibHdr.offDict, sizeof(pLib->LibHdr) - sizeof(OMFREC), 1, phFile) == 1 2972 ) 2973 ) 2974 { 2975 /* link it in */ 2976 *pWld->ppLibsAdd = pLib; 2977 pWld->ppLibsAdd = &pLib->pNext; 2978 libClose(pLib); 3363 && fread(&pLib->u.Omf.LibHdr, sizeof(OMFREC), 1, phFile) == 1) 3364 { 3365 int rc; 3366 if (pLib->u.Omf.LibHdr.chType == LIBHDR) 3367 { 3368 pLib->fOmfLib = 1; 3369 if (fread(&pLib->u.Omf.LibHdr.offDict, sizeof(pLib->u.Omf.LibHdr) - sizeof(OMFREC), 1, phFile) == 1) 3370 rc = 0; 3371 else 3372 rc = libErr(pLib, "Failed reading OMF library header."); 3373 } 3374 else if (pLib->u.Omf.LibHdr.chType == THEADR) 3375 pLib->fOmfLib = 1; 3376 else if (!memcmp(&pLib->u.Omf.LibHdr, ARMAG, sizeof(OMFREC))) 3377 { 3378 char achMagic[SARMAG]; 3379 if (fread(achMagic, SARMAG - sizeof(OMFREC), 1, phFile) == 1) 3380 { 3381 if (!memcmp(achMagic, ARMAG + sizeof(OMFREC), SARMAG - sizeof(OMFREC))) 3382 { 3383 pLib->fOmfLib = 0; 3384 pLib->u.Ar.uDummy = 0; 3385 rc = 0; 3386 } 3387 else 3388 rc = libErr(pLib, "Invalid library format."); 3389 } 3390 else 3391 rc = libErr(pLib, "Failed reading AR library magic."); 3392 } 3393 else 3394 rc = libErr(pLib, "Invalid library format."); 3395 3396 if (rc == 0) 3397 { 3398 /* link it in */ 3399 *pWld->ppLibsAdd = pLib; 3400 pWld->ppLibsAdd = &pLib->pNext; 3401 libClose(pLib); 3402 3403 return 0; 3404 } 2979 3405 } 2980 3406 else … … 2982 3408 /* We failed. */ 2983 3409 libErr(pLib, "Invalid library format or read error."); 2984 fclose(phFile); 2985 free(pLib); 2986 rc = -1; 2987 } 2988 2989 return rc; 3410 } 3411 3412 fclose(phFile); 3413 free(pLib); 3414 return -1; 2990 3415 } 2991 3416 … … 3612 4037 pid_t pid = getpid(); 3613 4038 static char s_szTmp[_MAX_PATH + 1]; 3614 4039 3615 4040 /* We need to apply _realrealpath to the tmpdir, so resolve that once and for all. */ 3616 4041 if (!s_szTmp[0])
Note:
See TracChangeset
for help on using the changeset viewer.