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 + -
显示快捷键?