winebuild: Store delayed imports in a separate list.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2016-03-22 16:05:14 +09:00
parent 9b70b6bd13
commit 68614d5db2
1 changed files with 54 additions and 61 deletions

View File

@ -46,7 +46,6 @@ struct import
char *full_name; /* full name of the input file */
dev_t dev; /* device/inode of the input file */
ino_t ino;
int delay; /* delay or not dll loading ? */
ORDDEF **exports; /* functions exported from this dll */
int nb_exports; /* number of exported functions */
ORDDEF **imports; /* functions we want to import from this dll */
@ -59,8 +58,7 @@ static struct strarray delayed_imports; /* list of delayed import dlls */
static struct strarray ext_link_imports; /* list of external symbols to link to */
static struct list dll_imports = LIST_INIT( dll_imports );
static int nb_imports = 0; /* number of imported dlls (delayed or not) */
static int nb_delayed = 0; /* number of delayed dlls */
static struct list dll_delayed = LIST_INIT( dll_delayed );
static inline const char *ppc_reg( int reg )
@ -155,6 +153,8 @@ static struct import *is_already_imported( const char *name )
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
if (!strcmp( import->dll_name, name )) return import;
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
if (!strcmp( import->dll_name, name )) return import;
return NULL;
}
@ -272,12 +272,9 @@ void add_import_dll( const char *name, const char *filename )
imp->c_name = make_c_identifier( imp->dll_name );
if (is_delayed_import( dll_name ))
{
imp->delay = 1;
nb_delayed++;
}
list_add_tail( &dll_delayed, &imp->entry );
else
list_add_tail( &dll_imports, &imp->entry );
nb_imports++;
}
/* add a library to the list of delayed imports */
@ -287,20 +284,11 @@ void add_delayed_import( const char *name )
char *fullname = get_dll_name( name, NULL );
strarray_add( &delayed_imports, fullname, NULL );
if ((imp = is_already_imported( fullname )) && !imp->delay)
{
imp->delay = 1;
nb_delayed++;
}
}
/* remove an imported dll */
static void remove_import_dll( struct import *imp )
if ((imp = is_already_imported( fullname )))
{
list_remove( &imp->entry );
nb_imports--;
if (imp->delay) nb_delayed--;
free_imports( imp );
list_add_tail( &dll_delayed, &imp->entry );
}
}
/* add a symbol to the list of extra symbols that ld must resolve */
@ -343,7 +331,7 @@ static void add_extra_undef_symbols( DLLSPEC *spec )
if (!spec->init_func) spec->init_func = xstrdup( get_default_entry_point(spec) );
add_extra_ld_symbol( spec->init_func );
if (has_stubs( spec )) add_extra_ld_symbol( "__wine_spec_unimplemented_stub" );
if (nb_delayed) add_extra_ld_symbol( "__wine_spec_delay_load" );
if (!list_empty( &dll_delayed )) add_extra_ld_symbol( "__wine_spec_delay_load" );
}
/* check if a given imported dll is not needed, taking forwards into account */
@ -391,11 +379,19 @@ static void check_undefined_forwards( DLLSPEC *spec )
if (!find_export( api_name, imp->exports, imp->nb_exports ))
warning( "%s:%d: forward '%s' not found in %s\n",
spec->src_name, odp->lineno, odp->link_name, imp->dll_name );
break;
goto done;
}
LIST_FOR_EACH_ENTRY( imp, &dll_delayed, struct import, entry )
{
if (strcasecmp( imp->dll_name, dll_name )) continue;
if (!find_export( api_name, imp->exports, imp->nb_exports ))
warning( "%s:%d: forward '%s' not found in %s\n",
spec->src_name, odp->lineno, odp->link_name, imp->dll_name );
goto done;
}
if (&imp->entry == &dll_imports)
warning( "%s:%d: forward '%s' not found in the imported dll list\n",
spec->src_name, odp->lineno, odp->link_name );
done:
free( link_name );
free( dll_name );
}
@ -519,16 +515,13 @@ void read_undef_symbols( DLLSPEC *spec, char **argv )
free( cmd );
}
/* resolve the imports for a Win32 module */
void resolve_imports( DLLSPEC *spec )
void resolve_dll_imports( DLLSPEC *spec, struct list *list )
{
unsigned int j, removed;
struct import *imp, *next;
ORDDEF *odp;
check_undefined_forwards( spec );
LIST_FOR_EACH_ENTRY_SAFE( imp, next, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY_SAFE( imp, next, list, struct import, entry )
{
for (j = removed = 0; j < undef_symbols.count; j++)
{
@ -552,10 +545,18 @@ void resolve_imports( DLLSPEC *spec )
/* the dll is not used, get rid of it */
if (check_unused( imp, spec ))
warning( "winebuild: %s imported but no symbols used\n", imp->dll_name );
remove_import_dll( imp );
list_remove( &imp->entry );
free_imports( imp );
}
}
}
/* resolve the imports for a Win32 module */
void resolve_imports( DLLSPEC *spec )
{
check_undefined_forwards( spec );
resolve_dll_imports( spec, &dll_imports );
resolve_dll_imports( spec, &dll_delayed );
sort_names( &undef_symbols );
check_undefined_exports( spec );
}
@ -647,7 +648,7 @@ static void output_import_thunk( const char *name, const char *table, int pos )
/* check if we need an import directory */
int has_imports(void)
{
return (nb_imports - nb_delayed) > 0;
return !list_empty( &dll_imports );
}
/* output the import table of a Win32 module */
@ -656,7 +657,7 @@ static void output_immediate_imports(void)
int j;
struct import *import;
if (nb_imports == nb_delayed) return; /* no immediate imports */
if (list_empty( &dll_imports )) return; /* no immediate imports */
/* main import header */
@ -670,7 +671,6 @@ static void output_immediate_imports(void)
j = 0;
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
{
if (import->delay) continue;
output( "\t.long .L__wine_spec_import_data_names+%d-.L__wine_spec_rva_base\n", /* OriginalFirstThunk */
j * get_ptr_size() );
output( "\t.long 0\n" ); /* TimeDateStamp */
@ -691,7 +691,6 @@ static void output_immediate_imports(void)
output( ".L__wine_spec_import_data_names:\n" );
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
{
if (import->delay) continue;
for (j = 0; j < import->nb_imports; j++)
{
ORDDEF *odp = import->imports[j];
@ -711,7 +710,6 @@ static void output_immediate_imports(void)
output( ".L__wine_spec_import_data_ptrs:\n" );
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
{
if (import->delay) continue;
for (j = 0; j < import->nb_imports; j++) output( "\t%s 0\n", get_asm_ptr_keyword() );
output( "\t%s 0\n", get_asm_ptr_keyword() );
}
@ -719,7 +717,6 @@ static void output_immediate_imports(void)
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
{
if (import->delay) continue;
for (j = 0; j < import->nb_imports; j++)
{
ORDDEF *odp = import->imports[j];
@ -735,7 +732,6 @@ static void output_immediate_imports(void)
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
{
if (import->delay) continue;
output( ".L__wine_spec_import_name_%s:\n\t%s \"%s\"\n",
import->c_name, get_asm_string_keyword(), import->dll_name );
}
@ -745,11 +741,10 @@ static void output_immediate_imports(void)
static void output_immediate_import_thunks(void)
{
int j, pos;
int nb_imm = nb_imports - nb_delayed;
struct import *import;
static const char import_thunks[] = "__wine_spec_import_thunks";
if (!nb_imm) return;
if (list_empty( &dll_imports )) return;
output( "\n/* immediate import thunks */\n\n" );
output( "\t.text\n" );
@ -759,7 +754,6 @@ static void output_immediate_import_thunks(void)
pos = 0;
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
{
if (import->delay) continue;
for (j = 0; j < import->nb_imports; j++, pos += get_ptr_size())
{
ORDDEF *odp = import->imports[j];
@ -777,7 +771,7 @@ static void output_delayed_imports( const DLLSPEC *spec )
int j, mod;
struct import *import;
if (!nb_delayed) return;
if (list_empty( &dll_delayed )) return;
output( "\n/* delayed imports */\n\n" );
output( "\t.data\n" );
@ -787,9 +781,8 @@ static void output_delayed_imports( const DLLSPEC *spec )
/* list of dlls */
j = mod = 0;
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
{
if (!import->delay) continue;
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
output( "\t%s .L__wine_delay_name_%s\n", /* szName */
get_asm_ptr_keyword(), import->c_name );
@ -815,9 +808,8 @@ static void output_delayed_imports( const DLLSPEC *spec )
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
output( "\n.L__wine_delay_IAT:\n" );
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
{
if (!import->delay) continue;
for (j = 0; j < import->nb_imports; j++)
{
ORDDEF *odp = import->imports[j];
@ -828,9 +820,8 @@ static void output_delayed_imports( const DLLSPEC *spec )
}
output( "\n.L__wine_delay_INT:\n" );
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
{
if (!import->delay) continue;
for (j = 0; j < import->nb_imports; j++)
{
ORDDEF *odp = import->imports[j];
@ -843,21 +834,19 @@ static void output_delayed_imports( const DLLSPEC *spec )
}
output( "\n.L__wine_delay_modules:\n" );
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
{
if (import->delay) output( "\t%s 0\n", get_asm_ptr_keyword() );
output( "\t%s 0\n", get_asm_ptr_keyword() );
}
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
{
if (!import->delay) continue;
output( ".L__wine_delay_name_%s:\n", import->c_name );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), import->dll_name );
}
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
{
if (!import->delay) continue;
for (j = 0; j < import->nb_imports; j++)
{
ORDDEF *odp = import->imports[j];
@ -877,7 +866,7 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
if (!nb_delayed) return;
if (list_empty( &dll_delayed )) return;
output( "\n/* delayed import thunks */\n\n" );
output( "\t.text\n" );
@ -1005,9 +994,8 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
output( "\n" );
idx = 0;
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
{
if (!import->delay) continue;
for (j = 0; j < import->nb_imports; j++)
{
ORDDEF *odp = import->imports[j];
@ -1090,9 +1078,8 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
output( "%s:\n", asm_name(delayed_import_thunks));
pos = 0;
LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
{
if (!import->delay) continue;
for (j = 0; j < import->nb_imports; j++, pos += get_ptr_size())
{
ORDDEF *odp = import->imports[j];
@ -1289,9 +1276,15 @@ void output_imports( DLLSPEC *spec )
output_immediate_import_thunks();
output_delayed_import_thunks( spec );
output_external_link_imports( spec );
if (nb_imports || ext_link_imports.count || has_stubs(spec) || has_relays(spec))
if (!list_empty( &dll_imports ) ||
!list_empty( &dll_delayed ) ||
ext_link_imports.count ||
has_stubs(spec) ||
has_relays(spec))
{
output_get_pc_thunk();
}
}
/* output an import library for a Win32 module and additional object files */
void output_import_lib( DLLSPEC *spec, char **argv )