implib.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,023 行 · 第 1/3 页

C
1,023
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Import library creation.
*
****************************************************************************/


#include <wlib.h>

// must correspond to defines in implib.h
static char *procname[5] = { "", "AXP", "PPC", "X86","" };

static void coffAddImportOverhead( arch_header *arch, char *DLLName, short processor );

static void fillInShort( unsigned_16 value, char *out )
{
    out[0] = value & 255;
    out[1] = (value >> 8) & 255;
}

static void fillInLong( unsigned_32 value, char *out )
{
    out[0] = value & 255;
    out[1] = (value >> 8) & 255;
    out[2] = (value >> 16) & 255;
    out[3] = (value >> 24) & 255;
}

static orl_sec_handle found_sec_handle;
static orl_return FindHelper( orl_sec_handle sec )
{
    if( found_sec_handle == 0 ) {
        found_sec_handle = sec;
    }
    return( ORL_OKAY );
}


static unsigned long  export_table_rva;
static orl_return FindExportTableHelper( orl_sec_handle sec )
{
    if( found_sec_handle == 0 ) {
        unsigned long   base = ORLSecGetBase(sec);

        if( (base <= export_table_rva)
            && ((base + ORLSecGetSize(sec)) > export_table_rva) ) {
            found_sec_handle = sec;
        }
    }

    return( ORL_OKAY );
} /* FindExportTableHelper() */

static orl_sec_handle FindSec( obj_file *file, char *name )
{
    export_table_rva = 0;
    found_sec_handle = 0;

    ORLFileScan( file->orl, name, FindHelper );
    if( found_sec_handle == 0 ) {
        if( !stricmp( ".edata", name ) ) {
            export_table_rva = ORLExportTableRVA( file->orl );

            if( export_table_rva == 0L ) {
                FatalError( ERR_NO_EXPORTS, file->hdl->name );
            }

            ORLFileScan( file->orl, NULL, FindExportTableHelper );
        }

        if( found_sec_handle == 0 ) {
            FatalError( ERR_NO_EXPORTS, file->hdl->name );
        }
    }

    return( found_sec_handle );
}

static bool elfAddImport( arch_header *arch, libfile io )
{
    obj_file        *file;
    orl_sec_handle  sym_sec;
    orl_sec_handle  export_sec;
    orl_sec_handle  string_sec;
    Elf32_Export    *export_table;
    Elf32_Sym       *sym_table;
    orl_sec_size    export_size, sym_size;
    char            *strings;
    long            processor = 0;
    char            *oldname;
    char            *DLLname;
    Elf32_Word      ElfMagic;

    LibSeek( io, 0x00, SEEK_SET );
    if( !LibRead( io, &ElfMagic, sizeof( ElfMagic ) ) == sizeof( ElfMagic ) ) {
        return( FALSE );
    }
    if( !memcmp( &ElfMagic, ELF_SIGNATURE, sizeof( SEEK_CUR ) ) == 0 ) {
        return( FALSE );
    }
    LibSeek( io, 0x10 - sizeof( ElfMagic) , SEEK_CUR );
    if( LibRead( io, &ElfMagic, sizeof( ElfMagic ) ) != sizeof( ElfMagic ) ) {
        return( FALSE );
    }
    if( (ElfMagic & 0xff) != ET_DYN ) {
        return( FALSE );
    }
    LibSeek( io, 0x00, SEEK_SET );
    file = OpenObjFile( io->name );
    if( !file->orl ) {
        FatalError( ERR_CANT_READ, io->name, "Unknown error" );
    }
    switch( ORLFileGetMachineType( file->orl ) ) {
    case ORL_MACHINE_TYPE_PPC601:
       processor = WL_PROC_PPC;
       break;
    default:
        FatalError( ERR_CANT_READ, io->name, "Not a PPC DLL" );
    }

    oldname = arch->name;
    arch->ffname = arch->name;
    arch->name = MemAlloc( _MAX_FNAME + _MAX_EXT );
    _splitpath( oldname, NULL, NULL, arch->name, NULL );
    DLLname = DupStr( arch->name );
    _splitpath( oldname, NULL, NULL, NULL, arch->name + strlen( arch->name ) );

    export_sec = FindSec( file, ".exports" );
    ORLSecGetContents( export_sec, (char **)&export_table );
    export_size = (Elf32_Word) ORLSecGetSize( export_sec ) / sizeof( Elf32_Export );
    sym_sec = ORLSecGetSymbolTable( export_sec );
    ORLSecGetContents( sym_sec, (char **)&sym_table );
    sym_size = (Elf32_Word) ORLSecGetSize( sym_sec ) / sizeof( Elf32_Sym );
    string_sec = ORLSecGetStringTable( sym_sec );
    ORLSecGetContents( string_sec, (char **)&strings );

    ElfMKImport( arch, ELF, export_size, DLLname, strings,
    export_table, sym_table, processor );

    MemFree( arch->name );
    MemFree( DLLname );
    arch->name = oldname;
    CloseObjFile( file );
    return( TRUE );
}

static bool getOs2Symbol( libfile io, char *symbol, unsigned_16 *ordinal, unsigned *len )
{
    unsigned_8  name_len;

    if( LibRead( io, &name_len, sizeof( name_len ) ) != sizeof( name_len ) ) {
        return( FALSE );
    }
    if( name_len == 0 ) {
        return( FALSE );
    }
    if( LibRead( io, symbol, name_len ) != name_len ) {
        FatalError( ERR_BAD_DLL, io->name );
    }
    symbol[name_len] = 0;
    if( LibRead( io, ordinal, sizeof( unsigned_16 ) ) != sizeof( unsigned_16 ) ) {
        FatalError( ERR_BAD_DLL, io->name );
    }
    *len = 1 + name_len + 2;
    return( TRUE );
}

static void importOs2Table( libfile io, arch_header *arch, char *dll_name, bool coff_obj, importType type, unsigned length )
{
    unsigned_16 ordinal;
    char        symbol[256];
    unsigned    bytes_read;
    unsigned    total_read = 0;

    while( getOs2Symbol( io, symbol, &ordinal, &bytes_read ) == TRUE ) {
        /* Make sure we're not reading past the end of name table */
        total_read += bytes_read;
        if( total_read > length ) {
            Warning( ERR_BAD_DLL, io->name );
            return;
        }
        /* The resident/non-resident name tables contain more than just exports
           (module names, comments etc.). Everything that has ordinal of zero isn't
           an export but more exports could follow */
        if( ordinal == 0 )
            continue;
        if( coff_obj == TRUE ) {
            CoffMKImport( arch, ORDINAL, ordinal, dll_name, symbol, NULL, WL_PROC_X86 );
        } else {
            OmfMKImport( arch, ordinal, dll_name, symbol, NULL, type );
        }
        AddSym( symbol, SYM_STRONG, 0 );
    }
}

static void os2AddImport( arch_header *arch, libfile io )
{
    os2_exe_header  os2_header;
    unsigned_32     ne_offset;
    char            dll_name[_MAX_FNAME + _MAX_EXT + 1];
    char            junk[256];
    unsigned_16     ordinal;
    importType      type;
    unsigned        bytes_read;

    LibSeek( io, OS2_NE_OFFSET, SEEK_SET );
    LibRead( io, &ne_offset, sizeof( ne_offset ) );
    LibSeek( io, ne_offset, SEEK_SET );
    LibRead( io, &os2_header, sizeof( os2_header ) );
    LibSeek( io, os2_header.resident_off - sizeof( os2_header ), SEEK_CUR );
    getOs2Symbol( io, dll_name, &ordinal, &bytes_read );
    type = Options.r_ordinal ? ORDINAL : NAMED;
    importOs2Table( io, arch, dll_name, FALSE, type, UINT_MAX );
    if( os2_header.nonres_off ) {
        type = Options.nr_ordinal ? ORDINAL : NAMED;
        LibSeek( io, os2_header.nonres_off, SEEK_SET );
        // The first entry is the module description and should be ignored
        getOs2Symbol( io, junk, &ordinal, &bytes_read );
        importOs2Table( io, arch, dll_name, FALSE, type, os2_header.nonres_size - bytes_read );
    }
}

static void os2FlatAddImport( arch_header *arch, libfile io )
{
    os2_flat_header os2_header;
    unsigned_32     ne_offset;
    char            dll_name[256];
    unsigned_16     ordinal;
    bool            coff_obj;
    importType      type;
    unsigned        bytes_read;

    if( Options.coff_found || (Options.libtype == WL_TYPE_AR && !Options.omf_found) ) {
        coff_obj = TRUE;
    } else {
        coff_obj = FALSE;
    }
    LibSeek( io, OS2_NE_OFFSET, SEEK_SET );
    LibRead( io, &ne_offset, sizeof( ne_offset ) );
    LibSeek( io, ne_offset, SEEK_SET );
    LibRead( io, &os2_header, sizeof( os2_header ) );
    LibSeek( io, os2_header.resname_off - sizeof( os2_header ), SEEK_CUR );
    getOs2Symbol( io, dll_name, &ordinal, &bytes_read );
    if( coff_obj == TRUE ) {
        coffAddImportOverhead( arch, dll_name, WL_PROC_X86 );
    }
    type = Options.r_ordinal ? ORDINAL : NAMED;
    importOs2Table( io, arch, dll_name, coff_obj, type, os2_header.resname_off - os2_header.entry_off );
    if( os2_header.nonres_off ) {
        LibSeek( io, os2_header.nonres_off, SEEK_SET );
        type = Options.nr_ordinal ? ORDINAL : NAMED;
        importOs2Table( io, arch, dll_name, coff_obj, type, os2_header.nonres_size );
    }
}

static bool nlmAddImport( arch_header *arch, libfile io )
{
    nlm_header  nlm;
    unsigned_8  name_len;
    char        dll_name[_MAX_FNAME + _MAX_EXT + 1];
    char        symbol[256];
    unsigned_32 offset;

    LibSeek( io, 0x00, SEEK_SET );
    LibRead( io, &nlm, sizeof( nlm ) );
    if( memcmp( nlm.signature, NLM_SIGNATURE, sizeof( nlm.signature ) ) != 0 ) {
        return( FALSE );
    }
    LibSeek( io, offsetof( nlm_header, moduleName ) , SEEK_SET );
    if( LibRead( io, &name_len, sizeof( name_len ) ) != sizeof( name_len ) ) {
        FatalError( ERR_BAD_DLL, io->name );
    }
    if( name_len == 0 ) {
        FatalError( ERR_BAD_DLL, io->name );
    }
    if( LibRead( io, dll_name, name_len ) != name_len ) {
        FatalError( ERR_BAD_DLL, io->name );
    }
    symbol[name_len] = 0;
    LibSeek( io, nlm.publicsOffset, SEEK_SET  );
    while( nlm.numberOfPublics > 0 ) {
        nlm.numberOfPublics--;
        if( LibRead( io, &name_len, sizeof( name_len ) ) != sizeof( name_len ) ) {
            FatalError( ERR_BAD_DLL, io->name );
        }
        if( LibRead( io, symbol, name_len ) != name_len ) {
            FatalError( ERR_BAD_DLL, io->name );
        }
        symbol[name_len] = 0;
        if( LibRead( io, &offset, sizeof( offset ) ) != sizeof( offset ) ) {
            FatalError( ERR_BAD_DLL, io->name );
        }
        OmfMKImport( arch, 0, dll_name, symbol, NULL, NAMED );
        AddSym( symbol, SYM_STRONG, 0 );
    }
    return( TRUE );
}

static void peAddImport( arch_header *arch, libfile io )
{
    obj_file        *file;
    orl_sec_handle  export_sec;
    orl_sec_offset  export_base;
    char            *edata;
    char            *DLLName;
    char            *oldname;
    char            *currname;
    char            *buffer;
    Coff32_Export   *export_header;
    Coff32_EName    *name_table;
    Coff32_EOrd     *ord_table;
    int             i;
    long            ordinal_base;
    short           processor = 0;
    importType      type;
    bool            coff_obj;
    long            adjust;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?