loadpe.c

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

C
1,456
字号
            object->flags |= PE_OBJ_CODE | PE_OBJ_EXECUTABLE;
            if( !(group->segflags & SEG_READ_ONLY) ) {
                object->flags |= PE_OBJ_READABLE;
            }
            if( group->segflags & SEG_NOPAGE) {
                object->flags |= PE_OBJ_NOT_PAGABLE;
            }
            header->code_size += object->physical_size;
            if( object->rva < header->code_base ) {
                header->code_base = object->rva;
            }
        }
        if( group->segflags & SEG_PURE ) {
            object->flags |= PE_OBJ_SHARED;
        }
        if( size_ph != 0 ) {
            object->physical_offset = NullAlign( header->file_align );
            WriteGroupLoad( group );
            PadLoad( size_ph - group->size );
        }
        ++object;
    }
    header->image_size = linear;
    if( header->code_base == 0xFFFFFFFFUL ) {
        header->code_base = 0;
    }
    if( header->data_base == 0xFFFFFFFFUL ) {
        header->data_base = 0;
    }
}

static void WalkImportsMods( void (*action)(dll_sym_info *, unsigned*),
                             void *cookie )
/****************************************************************/
{
    struct module_import *      mod;
    struct import_name *        imp;

    for( mod = PEImpList; mod != NULL; mod = mod->next ) {
        for( imp = mod->imports; imp != NULL; imp = imp->next ) {
            action( imp->dll, cookie );
        }
        action( NULL, cookie );
    }
}

static void WriteIAT( virt_mem buf, offset linear )
/*************************************************/
{
    struct module_import *      mod;
    struct import_name *        imp;
    pe_va       iat;
    offset      pos;
    offset      hint_rva ;

    pos = 0;
    hint_rva = IData.hint_off + linear;
    for( mod = PEImpList; mod != NULL; mod = mod->next ) {
        for( imp = mod->imports; imp != NULL; imp = imp->next ) {
            if( imp->imp != NULL ) {
                hint_rva += (hint_rva & 1); /* round up */
                iat = PE_IMPORT_BY_NAME | hint_rva;
                hint_rva += imp->imp->len +
                        (sizeof( unsigned_16 ) + sizeof( unsigned_8 ));
            } else {
                iat = PE_IMPORT_BY_ORDINAL | imp->dll->u.ordinal;
            }
            PutInfo( buf+pos, &iat, sizeof( iat ) ); pos += sizeof ( iat );
        }
        /* NULL entry marks end of list */
        iat = 0;
        PutInfo( buf+pos, &iat, sizeof( iat ) ); pos += sizeof ( iat );
    }
}

static void WriteImportInfo( void )
/*********************************/
{
    pe_import_directory         dir;
    unsigned_16                 hint;
    virt_mem                    buf;
    offset                      pos;
    group_entry  *              group;
    struct module_import        *mod;
    struct import_name          *imp;
    unsigned_32                 size;
    unsigned_32                 mod_name_rva;
    offset                      linear;

    if( IDataGroup == NULL ) {
        return;
    }
    group = IDataGroup;
    linear = group->linear;
    group->size = IData.total_size;
    buf = IData.sdata->data;
    pos = 0;
    dir.time_stamp = 0;
    dir.major = 0;
    dir.minor = 0;
    /* dump the directory table */
    size = 0;
    mod_name_rva = IData.mod_name_off + linear;
    for( mod = PEImpList; mod != NULL; mod = mod->next ) {
        dir.name_rva = mod_name_rva;
        dir.import_lookup_table_rva = IData.ilt_off + size + linear;
        dir.import_address_table_rva = IData.iat_off + size + linear;
        size += (mod->num_entries + 1) * sizeof( pe_va );
        mod_name_rva += mod->mod->len + 1;
        PutInfo( buf+pos, &dir, sizeof(dir) );
        pos += sizeof(dir);
    }
    PutNulls( buf+pos, sizeof(dir) );    /* NULL entry marks end of table */
    pos += sizeof(dir);
    WriteIAT(buf+IData.ilt_off, linear); // Import Lookup table
    WriteToc(buf+IData.eof_ilt_off);
    for( pos = IData.eof_ilt_off; pos < IData.iat_off; pos += sizeof(pe_va)) {
        XFerReloc( pos, group, PE_FIX_HIGHLOW );
    }
    WriteIAT(buf+IData.iat_off, linear); // Import Address table
    pos = IData.mod_name_off;            /* write the module names */
    for( mod = PEImpList; mod != NULL; mod = mod->next ) {
        int size = mod->mod->len + 1;
        PutInfo( buf+pos, mod->mod->name, size);
        pos += size;
    }
    pos = IData.hint_off;        /* write out the import names */
    for( mod = PEImpList; mod != NULL; mod = mod->next ) {
        hint = 1;
        for( imp = mod->imports; imp != NULL; imp = imp->next ) {
            if( imp->imp != NULL ) {
                PutNulls( buf+pos, pos & 1);
                pos += pos & 1;/* round up */
                PutInfo(buf+pos, &hint, sizeof(hint));
                pos += sizeof(hint);
                size = imp->imp->len;
                PutInfo(buf+pos, imp->imp->name, size);
                pos += size;
                PutNulls( buf+pos, 1);
                pos++;
                hint++;
            }
        }
    }
}

static int namecmp( const void *pn1, const void *pn2 )
/****************************************************/
{
    entry_export        *n1;
    entry_export        *n2;

    n1 = *(entry_export **)pn1;
    n2 = *(entry_export **)pn2;
    return( strcmp( n1->name, n2->name ) );
}


static void WriteExportInfo( pe_header *header, pe_object *object )
/*****************************************************************/
{
    unsigned long       size;
    pe_export_directory dir;
    char                *name;
    int                 namelen;
    entry_export        **sort;
    entry_export        *exp;
    unsigned            i;
    unsigned_16         ord;
    pe_va               eat;
    unsigned            next_ord;
    unsigned            high_ord;
    unsigned            num_entries;

    strncpy( object->name, ".edata", PE_OBJ_NAME_LEN );
    object->physical_offset = NullAlign( header->file_align );
    object->rva = header->image_size;
    object->flags = PE_OBJ_INIT_DATA | PE_OBJ_READABLE;
    dir.flags = 0;
    dir.time_stamp = 0;
    dir.major = 0;
    dir.minor = 0;
    dir.name_rva = object->rva + sizeof( dir );
    dir.ordinal_base = FmtData.u.os2.exports->ordinal;
    if( FmtData.u.os2.res_module_name != NULL ) {
        name = FmtData.u.os2.res_module_name;
    } else {
        name = RemovePath( Root->outfile->fname, &namelen );
    }
    /* RemovePath strips the extension, which we don't want */
    namelen = strlen( name ) + 1;
    dir.address_table_rva = ROUND_UP( dir.name_rva+namelen,
                                                (unsigned long)sizeof(pe_va) );
    num_entries = 0;
    for( exp = FmtData.u.os2.exports; exp != NULL; exp = exp->next ) {
        high_ord = exp->ordinal;
        ++num_entries;
        if( !exp->isprivate ) {
            if( exp->impname != NULL ) {
                AddImpLibEntry( exp->impname, exp->name, NOT_IMP_BY_ORDINAL );
            } else {
                AddImpLibEntry( exp->sym->name, exp->name, NOT_IMP_BY_ORDINAL );
            }
        }
    }
    dir.num_eat_entries = high_ord - dir.ordinal_base + 1;
    dir.num_name_ptrs = num_entries;
    dir.name_ptr_table_rva = dir.address_table_rva +
                                dir.num_eat_entries * sizeof( pe_va );
    dir.ordinal_table_rva = dir.name_ptr_table_rva +
                                num_entries * sizeof( pe_va );
    _ChkAlloc( sort, sizeof( entry_export * ) * num_entries );
    /* write the export directory table and module name */
    WriteLoad( &dir, sizeof( dir ) );
    WriteLoad( name, namelen );
    NullAlign( sizeof( pe_va ) );
    /* write the export address table */
    i = 0;
    next_ord = dir.ordinal_base;
    for( exp = FmtData.u.os2.exports; exp != NULL; exp = exp->next ) {
        sort[ i++ ] = exp;
        eat = exp->addr.off;
        if( next_ord < exp->ordinal ) {
            PadLoad( (exp->ordinal - next_ord) * sizeof( pe_va ) );
        }
        next_ord = exp->ordinal + 1;
        WriteLoad( &eat, sizeof( eat ) );
    }
    qsort( sort, num_entries, sizeof( entry_export * ), &namecmp );
    /* write out the export name ptr table */
    eat = dir.ordinal_table_rva + num_entries * sizeof( unsigned_16 );
    for( i = 0; i < num_entries; ++i ) {
        exp = sort[i];
        WriteLoad( &eat, sizeof( eat ) );
        eat += strlen( exp->name ) + 1;
    }
    /* write out the export ordinal table */
    for( i = 0; i < num_entries; ++i ) {
        ord = sort[i]->ordinal - dir.ordinal_base;
        WriteLoad( &ord, sizeof( ord ) );
    }
    /* write out the export name table */
    for( i = 0; i < num_entries; ++i ) {
        exp = sort[i];
        WriteLoad( exp->name, strlen( exp->name ) + 1 );
    }
    _LnkFree( sort );
    size = eat - object->rva;
    object->physical_size = ROUND_UP( size, header->file_align );
    header->table[PE_TBL_EXPORT].size = size;
    header->table[PE_TBL_EXPORT].rva = object->rva;
    header->image_size += ROUND_UP( size, header->object_align );
}

#define PAGE_COUNT( size )  (((size)+(0x1000-1))>>0xC)

static unsigned_32 WriteRelocList( void ** reloclist, unsigned_32 size,
                                   unsigned_32 pagerva, unsigned limit )
/**********************************************************************/
{
    unsigned_32 pagesize;
    bool        padme;

    while( limit > 0 ) {
        pagesize = RelocSize( *reloclist );
        if( pagesize != 0 ) {
            padme = FALSE;
            if( (pagesize / sizeof(pe_reloc_item)) & 0x1 ) {
                pagesize += sizeof(pe_reloc_item);
                padme = TRUE;
            }
            pagesize += 2*sizeof(unsigned_32);
            WriteLoad( &pagerva, sizeof(unsigned_32) );
            WriteLoad( &pagesize, sizeof(unsigned_32) );
            DumpRelocList( *reloclist );
            if( padme ) {
                PadLoad( sizeof(pe_reloc_item) );
            }
            size += pagesize;
        }
        pagerva += OSF_PAGE_SIZE;
        reloclist++;
        limit--;
    }
    return( size );
}

static void WriteFixupInfo( pe_header *header, pe_object *object )
/*****************************************************************/
/* dump the fixup table */
{
    unsigned_32         numpages;
    unsigned_32         highidx;
    unsigned_32         pagerva;
    group_entry *       group;
    void ***            reloclist;
    unsigned long       size;
    unsigned long       count;

    strncpy( object->name, ".reloc", PE_OBJ_NAME_LEN );
    object->physical_offset = NullAlign( header->file_align );
    object->rva = header->image_size;
    object->flags = PE_OBJ_INIT_DATA | PE_OBJ_READABLE | PE_OBJ_DISCARDABLE;
    size = 0;
    count = 0;
    for( group = Groups; group != NULL; group = group->next_group ) {
        reloclist = group->g.grp_relocs;
        if( reloclist != NULL ) {
            pagerva = group->linear;
            numpages = PAGE_COUNT( group->size );
            highidx = OSF_RLIDX_HIGH( numpages );
            while( highidx > 0 ) {
                size = WriteRelocList(*reloclist, size, pagerva, OSF_RLIDX_MAX);
                highidx--;
                reloclist++;
                pagerva += OSF_PAGE_SIZE * ((unsigned_32) OSF_RLIDX_MAX);
            }
            size = WriteRelocList( *reloclist, size, pagerva,
                                                     OSF_RLIDX_LOW(numpages) );
        }
    }
    PadLoad( sizeof(pe_fixup_header) );
    size += sizeof(pe_fixup_header);
    object->physical_size = ROUND_UP( size, header->file_align );
    header->table[PE_TBL_FIXUP].size = size - sizeof(pe_fixup_header);
    header->table[PE_TBL_FIXUP].rva = object->rva;
    header->image_size += ROUND_UP( size, header->object_align );
}

static void WriteDescription( pe_header *header, pe_object *object )
/******************************************************************/
{
    size_t      desc_len;

    desc_len = strlen( FmtData.u.os2.description );
    strncpy( object->name, ".desc", PE_OBJ_NAME_LEN );
    object->physical_offset = NullAlign( header->file_align );
    object->rva = header->image_size;
    object->flags = PE_OBJ_INIT_DATA | PE_OBJ_READABLE;
    object->physical_size = ROUND_UP( desc_len, header->file_align );
    WriteLoad( FmtData.u.os2.description, desc_len );
    header->image_size += ROUND_UP( desc_len, header->object_align );
}

void * RcMemMalloc( size_t size )
{
    void *      retval;

    _ChkAlloc( retval, size );
    return( retval );
}

void * RcMemRealloc( void * old_ptr, size_t newsize )
{
    _LnkReAlloc( old_ptr, old_ptr, newsize );
    return( old_ptr );
}

void RcMemFree( void * ptr )
{
    _LnkFree( ptr );
}

int  RcWrite( int hdl, const void *buf, size_t len )

⌨️ 快捷键说明

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