Changeset 3667


Ignore:
Timestamp:
Sep 18, 2010, 3:06:59 AM (15 years ago)
Author:
bird
Message:

emxomfld/weakld: working on AR and ELF support.

Location:
trunk/emx/src/emxomf
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/emx/src/emxomf/emxomfld.c

    r3462 r3667  
    3737#include <alloca.h>
    3838#include <sys/omflib.h>
     39#include <sys/elf.h>
     40#include <ar.h>
    3941#include "defs.h"
    4042#include "weakld.h"
     
    5153} name_list;
    5254
     55/* OMF record header. */
     56#pragma pack(1)
     57typedef struct omf_rec_hdr
     58{
     59    byte type;
     60    word len;
     61} omf_rec_hdr;
     62#pragma pack()
    5363
    5464/* Whether or not linker tracing is enabled. */
     
    504514
    505515/**
     516 * Reports archive parsing error.
     517 * @returns 0.
     518 * @param   pszError    The parsing error.
     519 */
     520static 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 */
     538static 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 */
     572static 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 */
     596static 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 */
     619static 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 */
     653static 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/**
    506757 * Checks if the stream phFile is an OMF library.
    507758 *
     
    546797 * @param   phFile  Filestream to check.
    547798 */
    548 static int check_omf(FILE *phFile)
     799static int check_omf_or_elf(FILE *phFile)
    549800{
    550801#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;
    556812#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) )
    562821        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;
    566845}
    567846
     
    637916
    638917    /* 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])
    640919    {
    641920        const char *    pszTmp = getenv("TMP");
     
    8631142     */
    8641143    if (    autoconvert_flag
    865         &&  !check_omf(phFile))
     1144        &&  !check_omf_or_elf(phFile))
    8661145        phFile = aout_to_omf(phFile, pszFullname, FALSE);
    8671146
     
    10061285                        if (check_lx_dll(phFile))
    10071286                            phFile = lx_to_omf(phFile, pszFullname);
    1008                         else if (!check_omf(phFile))
     1287                        else if (!check_omf_or_elf(phFile))
    10091288                            phFile = aout_to_omf(phFile, pszFullname, TRUE);
    10101289                    }
     
    13671646      case _MD_STUB:
    13681647        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          }
    13701652        else
    13711653          fprintf (stderr, "emxomfld: warning: \"STUB NONE\" is not supported by wlink. ignoring\n");
     
    20852367    {
    20862368      unsigned uPMType = 0;
     2369      int need_stub = 1;
    20872370
    20882371      open_response_file ();
     
    22752558        fprintf (response_file, "OPTION OFFSET=%s\n", base);
    22762559
    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 
    22842560      /* Add the /INFORMATION option if the -i or -t option was given.  This is
    22852561         for debugging. */
     
    23052581
    23062582      /* Translate the essentials of the module definition file into wlink lingo. */
     2583     
    23072584      if (def_fname)
    23082585        {
     
    23142591            }
    23152592          _md_next_token (pMd);
    2316           _md_parse (pMd, def_2_watcom, NULL);
     2593          _md_parse (pMd, def_2_watcom, &need_stub);
    23172594          _md_close (pMd);
    23182595        }
     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
    23192607    }
    23202608
  • trunk/emx/src/emxomf/weakld.c

    r3462 r3667  
    3535 * There is a couple of symbol types, but we can skip most of them for this
    3636 * pre-linking operation. We use one symbol type which is public or global
    37  * symbols if you like. Perhaps it would be wise to devide them into separat
     37 * symbols if you like. Perhaps it would be wise to divide them into separat
    3838 * type groups, but the choice was made to differenciate this using flags.
    3939 * So, symbol enumeration is done using flag masks.
     
    101101#include <sys/omflib.h>
    102102#include <sys/moddef.h>
     103#include <sys/elf.h>
     104#include <ar.h>
    103105#include "defs.h"
    104106#include "grow.h"
     
    155157    const char *pszLibName;
    156158    /** 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;
    162177    /** Linked list next pointer. */
    163     struct wldlib * pNext;
     178    struct wldlib *pNext;
    164179} WLDLIB, *PWLDLIB;
    165180
     
    414429static void         wldIntErr(PWLD pWld, PWLDMOD pMod, const char *pszFile, unsigned iLine, const char *pszFunction);
    415430static unsigned     pass1ReadOMFMod(PWLD pWld, PWLDMOD pMod, int fLibSearch);
     431static unsigned     pass1ReadELFMod(PWLD pWld, PWLDMOD pMod, int fLibSearch);
    416432/** Parameter structure for wldDefCallback(). */
    417433typedef struct wldDefCallback_param
     
    434450static void         libCloseDict(PWLDLIB pLib);
    435451static int          libTryLoadSymbolThruDictionary(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded);
     452static int          libLoadUndefSymbolsFromOmfLib(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded);
     453/**
     454 * Callback parameter structure used between libLoadUndefSymbolsFromArchLib
     455 * and libLoadUndefSymbolsFromArchLibCallback
     456 */
     457typedef 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;
     468static int          libLoadUndefSymbolsFromArchLibCallback(FILE *pFile, const char *pszName, off_t cbFile, void *pvUser);
     469static int          libLoadUndefSymbolsFromArchLib(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded);
    436470static 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 */
     479typedef int (* PFNLIBENUMFILE)(FILE *pFile, const char *pszName, off_t cbFile, void *pvUser);
     480static int          libEnumFilesArch(PWLDLIB pLib, int fAll, PFNLIBENUMFILE pfnCallback, void *pvUser);
    437481static int          libErr(PWLDLIB pLib, const char *pszFormat, ...);
    438482#if 0
     
    678722#if 0
    679723    FILE *phFile;
     724
    680725    /* been here, done that? */
    681     if (pLib->pDict)
     726    if (pLib->upDict)
    682727        return 0;
    683728
    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   
    690741    /* ensure it's open. */
    691742    phFile = libOpen(pLib);
    692743    if (!phFile)
    693744        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   
    704760    free(pLib->pDict);
    705761    pLib->pDict = NULL;
    706762    return -1;
     763
    707764#else
    708765    /* till we support processing the dictionary, we pretend there is none. */
    709766    pLib->pDict = NULL;
    710     return -1;
     767    return 1;
    711768#endif
    712769}
     
    741798static int          libTryLoadSymbolThruDictionary(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded)
    742799{
    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.
    759811 * @param   pcLoaded    Number of modules which was loaded from this library.
    760812 */
    761 static int          libLoadUndefSymbols(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded)
     813static int          libLoadUndefSymbolsFromOmfLib(PWLD pWld, PWLDLIB pLib, PWLDSYM pSym, unsigned *pcLoaded)
    762814{
    763815    FILE *          phFile = pLib->phFile;
     
    774826
    775827    /* 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))
    777829        return libErr(pLib, "Error when seeking to first module.");
    778830
    779     if (pLib->LibHdr.chType != LIBHDR)
     831    if (pLib->u.Omf.LibHdr.chType != LIBHDR)
    780832    {
    781833        uchEnd1 = MODEND;
     
    10041056            if (OmfRec.chType == MODEND || OmfRec.chType == (MODEND | REC32))
    10051057            {
    1006                 unsigned    cbPage = pLib->LibHdr.cb + 3;
     1058                unsigned    cbPage = pLib->u.Omf.LibHdr.cb + 3;
    10071059                off_t       off = ftell(phFile) + offSkip;
    10081060                off -= cbPage * (off / cbPage); /* don't trust this to be 2**n. */
     
    10311083
    10321084/**
     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 */
     1093static 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 */
     1110static 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 */
     1136static 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 */
     1156static 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 */
     1190static 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 */
     1215static 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 */
     1243static 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/**
    10331338 * Put out an error for this library.
     1339 * @returns -1.
    10341340 * @param   pLib        Library which the warning occured in.
    10351341 * @param   pszFormat   Message format.
     
    25692875
    25702876
    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 */
     2886static unsigned     pass1ReadELFMod(PWLD pWld, PWLDMOD pMod, int fLibSearch)
     2887{
     2888    /** @todo implement me. */
     2889    return 0;
     2890}
    25722891
    25732892
     
    26873006
    26883007/**
     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 */
     3014static 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/**
    26893050 * Adds a object module to the linking process.
    26903051 * The object module will be analysed and the file handle closed.
     
    27033064int     WLDAddObject(PWLD pWld, FILE *phFile, const char *pszName)
    27043065{
    2705     OMFREC  OmfRec = {0,0};
     3066    union
     3067    {
     3068        OMFREC          OmfRec;
     3069        Elf32_Ehdr      Ehdr;
     3070    }       uBuf;
    27063071    int     rc = 0;
    27073072    if (!phFile)
     
    27133078    }
    27143079    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    }
    27153086
    27163087    /*
    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).
    27183089     * In anycase all the modules it contains is to be added to the link.
    27193090     */
    2720     fread(&OmfRec, sizeof(OmfRec), 1, phFile);
    2721     if (OmfRec.chType == THEADR)
     3091    if (uBuf.OmfRec.chType == THEADR)
    27223092    {
    27233093        /* Single Object */
     
    27313101        modClose(pMod);
    27323102    }
    2733     else if (OmfRec.chType == LIBHDR)
     3103    else if (uBuf.OmfRec.chType == LIBHDR)
    27343104    {
    27353105        /* 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))
    27393109            {
    27403110                PWLDMOD     pMod = xmalloc(sizeof(*pMod));
     
    27423112                pMod->pszModName = strpool_add(pWld->pStrMisc, pszName);
    27433113                pMod->phFile = phFile;
    2744                 pMod->off = ftell(phFile) - sizeof(OmfRec);
     3114                pMod->off = ftell(phFile) - sizeof(uBuf.OmfRec);
    27453115                *pWld->ppObjsAdd = pMod;
    27463116                pWld->ppObjsAdd = &pMod->pNext;
     
    27613131            {
    27623132                /* skip to the net record */
    2763                 fseek(phFile, OmfRec.cb, SEEK_CUR);
     3133                fseek(phFile, uBuf.OmfRec.cb, SEEK_CUR);
    27643134            }
    27653135
    27663136            /* read next record */
    2767             fread(&OmfRec, sizeof(OmfRec), 1, phFile);
     3137            fread(&uBuf.OmfRec, sizeof(uBuf.OmfRec), 1, phFile);
    27683138        }
    27693139        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        }
    27703165    }
    27713166    else
     
    29463341int     WLDAddLibrary(PWLD pWld, FILE *phFile, const char *pszName)
    29473342{
    2948     PWLDLIB     pLib;
    2949     int         rc = 0;
     3343    PWLDLIB pLib;
    29503344
    29513345    if (!phFile)
     
    29653359    pLib->pNext = NULL;
    29663360
    2967     /* read the library header. */
     3361    /* read the library header, detect the format. */
    29683362    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        }
    29793405    }
    29803406    else
     
    29823408        /* We failed. */
    29833409        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;
    29903415}
    29913416
     
    36124037    pid_t           pid = getpid();
    36134038    static char     s_szTmp[_MAX_PATH + 1];
    3614    
     4039
    36154040    /* We need to apply _realrealpath to the tmpdir, so resolve that once and for all. */
    36164041    if (!s_szTmp[0])
Note: See TracChangeset for help on using the changeset viewer.