Added support for importing by ordinal.

This commit is contained in:
Alexandre Julliard 2002-07-28 17:54:31 +00:00
parent 112c665f83
commit 15a75259bd
5 changed files with 95 additions and 27 deletions

View File

@ -166,6 +166,22 @@ static inline void fixup_rva_ptrs( void *array, void *base, int count )
}
/* fixup RVAs in the import directory */
static void fixup_imports( IMAGE_IMPORT_DESCRIPTOR *dir, DWORD size, void *base )
{
int count = size / sizeof(void *);
void **ptr = (void **)dir;
/* everything is either a pointer or a ordinal value below 0x10000 */
while (count--)
{
if (*ptr >= (void *)0x10000) *ptr = (void *)((char *)*ptr - (char *)base);
else if (*ptr) *ptr = (void *)(0x80000000 | (unsigned int)*ptr);
ptr++;
}
}
/* fixup RVAs in the resource directory */
static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *base )
{
@ -268,8 +284,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
{
IMAGE_IMPORT_DESCRIPTOR *imports = (void *)dir->VirtualAddress;
fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
/* we can fixup everything at once since we only have pointers and 0 values */
fixup_rva_ptrs( imports, addr, dir->Size / sizeof(void*) );
fixup_imports( imports, dir->Size, addr );
}
/* Build the resource directory */

View File

@ -91,8 +91,9 @@ typedef struct
int offset;
int lineno;
int flags;
char *name;
char *link_name;
char *name; /* public name of this function */
char *link_name; /* name of the C symbol to link to */
char *export_name; /* name exported under for noname exports */
union
{
ORD_VARIABLE var;
@ -104,10 +105,11 @@ typedef struct
/* entry point flags */
#define FLAG_NOIMPORT 0x01 /* don't make function available for importing */
#define FLAG_NORELAY 0x02 /* don't use relay debugging for this function */
#define FLAG_RET64 0x04 /* function returns a 64-bit value */
#define FLAG_I386 0x08 /* function is i386 only */
#define FLAG_REGISTER 0x10 /* use register calling convention */
#define FLAG_INTERRUPT 0x20 /* function is an interrupt handler */
#define FLAG_NONAME 0x04 /* don't import function by name */
#define FLAG_RET64 0x08 /* function returns a 64-bit value */
#define FLAG_I386 0x10 /* function is i386 only */
#define FLAG_REGISTER 0x20 /* use register calling convention */
#define FLAG_INTERRUPT 0x40 /* function is an interrupt handler */
/* Offset of a structure field relative to the start of the struct */
#define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)

View File

@ -33,6 +33,7 @@ struct func
{
const char *name; /* function name */
int ordinal; /* function ordinal */
int ord_only; /* non-zero if function is imported by ordinal */
};
struct import
@ -140,7 +141,7 @@ static char *open_library( const char *name )
static void read_exported_symbols( const char *name, struct import *imp )
{
FILE *f;
char buffer[1024], prefix[80];
char buffer[1024], prefix[80], ord_prefix[80];
char *fullname, *cmdline;
int size, err;
@ -156,20 +157,27 @@ static void read_exported_symbols( const char *name, struct import *imp )
fatal_error( "Cannot execute '%s'\n", cmdline );
sprintf( prefix, "__wine_dllexport_%s_", make_c_identifier(name) );
sprintf( ord_prefix, "__wine_ordexport_%s_", make_c_identifier(name) );
while (fgets( buffer, sizeof(buffer), f ))
{
int ordinal = 0;
int ordinal = 0, ord_only = 0;
char *p = buffer + strlen(buffer) - 1;
if (p < buffer) continue;
if (*p == '\n') *p-- = 0;
if (!(p = strstr( buffer, prefix ))) continue;
if (!(p = strstr( buffer, prefix )))
{
if (!(p = strstr( buffer, ord_prefix ))) continue;
ord_only = 1;
}
p += strlen(prefix);
if (isdigit(*p))
{
ordinal = strtol( p, &p, 10 );
if (*p++ != '_') continue;
if (ordinal >= MAX_ORDINALS) continue;
}
if (ord_only && !ordinal) continue;
if (imp->nb_exports == size)
{
@ -178,6 +186,7 @@ static void read_exported_symbols( const char *name, struct import *imp )
}
imp->exports[imp->nb_exports].name = xstrdup( p );
imp->exports[imp->nb_exports].ordinal = ordinal;
imp->exports[imp->nb_exports].ord_only = ord_only;
imp->nb_exports++;
}
if ((err = pclose( f ))) fatal_error( "%s error %d\n", cmdline, err );
@ -239,6 +248,7 @@ static void add_import_func( struct import *imp, const struct func *func )
imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
imp->imports[imp->nb_imports].name = xstrdup( func->name );
imp->imports[imp->nb_imports].ordinal = func->ordinal;
imp->imports[imp->nb_imports].ord_only = func->ord_only;
imp->nb_imports++;
total_imports++;
if (imp->delay) total_delayed++;
@ -284,7 +294,7 @@ static int add_extra_symbol( const char **extras, int *count, const char *name )
odp->type == TYPE_VARARGS ||
odp->type == TYPE_EXTERN)
{
if (!strcmp( odp->name, name )) return 0;
if (odp->name && !strcmp( odp->name, name )) return 0;
}
}
extras[*count] = name;
@ -489,9 +499,14 @@ static int output_immediate_imports( FILE *outfile )
for (j = 0; j < dll_imports[i]->nb_imports; j++)
{
struct func *import = &dll_imports[i]->imports[j];
unsigned short ord = import->ordinal;
fprintf( outfile, " \"\\%03o\\%03o%s\",\n",
*(unsigned char *)&ord, *((unsigned char *)&ord + 1), import->name );
if (!import->ord_only)
{
unsigned short ord = import->ordinal;
fprintf( outfile, " \"\\%03o\\%03o%s\",\n",
*(unsigned char *)&ord, *((unsigned char *)&ord + 1), import->name );
}
else
fprintf( outfile, " (char *)%d,\n", import->ordinal );
}
fprintf( outfile, " 0,\n" );
}
@ -626,7 +641,11 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
for (j = 0; j < dll_imports[i]->nb_imports; j++)
{
fprintf( outfile, " \"\\0\\0%s\",\n", dll_imports[i]->imports[j].name );
struct func *import = &dll_imports[i]->imports[j];
if (import->ord_only)
fprintf( outfile, " (char *)%d,\n", import->ordinal );
else
fprintf( outfile, " \"%s\",\n", import->name );
}
}
fprintf( outfile, " }\n};\n\n" );
@ -659,7 +678,7 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, " void *fn;\n\n" );
fprintf( outfile, " if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
fprintf( outfile, " if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT + 2)))\n");
fprintf( outfile, " if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
fprintf( outfile, " /* patch IAT with final value */\n" );
fprintf( outfile, " return *pIAT = fn;\n" );
fprintf( outfile, " else {\n");

View File

@ -61,6 +61,7 @@ static const char * const FlagNames[] =
{
"noimport", /* FLAG_NOIMPORT */
"norelay", /* FLAG_NORELAY */
"noname", /* FLAG_NONAME */
"ret64", /* FLAG_RET64 */
"i386", /* FLAG_I386 */
"register", /* FLAG_REGISTER */
@ -431,6 +432,7 @@ static void ParseOrdinal(int ordinal)
if (ordinal != -1)
{
if (!ordinal) fatal_error( "Ordinal 0 is not valid\n" );
if (ordinal >= MAX_ORDINALS) fatal_error( "Ordinal number %d too large\n", ordinal );
if (ordinal > Limit) Limit = ordinal;
if (ordinal < Base) Base = ordinal;
@ -438,13 +440,15 @@ static void ParseOrdinal(int ordinal)
Ordinals[ordinal] = odp;
}
if (!strcmp( odp->name, "@" ))
if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME)
{
if (ordinal == -1)
fatal_error( "Nameless function needs an explicit ordinal number\n" );
if (SpecType != SPEC_WIN32)
fatal_error( "Nameless functions not supported for Win16\n" );
odp->name[0] = 0;
if (!strcmp( odp->name, "@" )) free( odp->name );
else odp->export_name = odp->name;
odp->name = NULL;
}
else Names[nb_names++] = odp;
}

View File

@ -50,10 +50,11 @@ static int string_compare( const void *ptr1, const void *ptr2 )
static const char *make_internal_name( const ORDDEF *odp, const char *prefix )
{
static char buffer[256];
if (odp->name[0])
if (odp->name || odp->export_name)
{
char *p;
sprintf( buffer, "__wine_%s_%s_%s", prefix, DLLFileName, odp->name );
sprintf( buffer, "__wine_%s_%s_%s", prefix, DLLFileName,
odp->name ? odp->name : odp->export_name );
/* make sure name is a legal C identifier */
for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
if (!*p) return buffer;
@ -314,6 +315,24 @@ static int output_exports( FILE *outfile, int nr_exports )
fprintf( outfile, " \"" __ASM_NAME("__wine_dllexport_%s_%d_%s") ":\\n\"\n",
make_c_identifier(DLLFileName), i, Names[i]->name );
}
/* output ordinal exports */
for (i = 0; i < nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
if (odp->flags & FLAG_NOIMPORT) continue;
if (odp->name || !odp->export_name) continue;
/* check for invalid characters in the name */
for (p = odp->export_name; *p; p++)
if (!isalnum(*p) && *p != '_' && *p != '.') break;
if (*p) continue;
fprintf( outfile, " \"\\t.globl " __ASM_NAME("__wine_ordexport_%s_%d_%s") "\\n\"\n",
make_c_identifier(DLLFileName), odp->ordinal, odp->export_name );
fprintf( outfile, " \"" __ASM_NAME("__wine_ordexport_%s_%d_%s") ":\\n\"\n",
make_c_identifier(DLLFileName), odp->ordinal, odp->export_name );
}
fprintf( outfile, " \"\\t.long 0xffffffff\\n\"\n" );
/* output variables */
@ -388,8 +407,10 @@ static void output_stub_funcs( FILE *outfile )
ORDDEF *odp = EntryPoints[i];
if (odp->type != TYPE_STUB) continue;
fprintf( outfile, "void %s(void) ", make_internal_name( odp, "stub" ) );
if (odp->name[0])
if (odp->name)
fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
else if (odp->export_name)
fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->export_name );
else
fprintf( outfile, "{ __wine_unimplemented(\"%d\"); }\n", odp->ordinal );
}
@ -803,6 +824,7 @@ void BuildSpec32File( FILE *outfile )
*/
void BuildDef32File(FILE *outfile)
{
const char *name;
int i;
AssignOrdinals();
@ -819,10 +841,16 @@ void BuildDef32File(FILE *outfile)
for(i = 0; i < nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
if(!odp || !*odp->name || (odp->flags & FLAG_NOIMPORT)) continue;
if (!odp) continue;
if (odp->flags & FLAG_NOIMPORT) continue;
if (odp->type == TYPE_STUB) continue;
fprintf(outfile, " %s", odp->name);
if (odp->name) name = odp->name;
else if (odp->export_name) name = odp->export_name;
else continue;
fprintf(outfile, " %s", name);
switch(odp->type)
{
@ -831,7 +859,7 @@ void BuildDef32File(FILE *outfile)
case TYPE_CDECL:
case TYPE_VARIABLE:
/* try to reduce output */
if(strcmp(odp->name, odp->link_name))
if(strcmp(name, odp->link_name))
fprintf(outfile, "=%s", odp->link_name);
break;
case TYPE_STDCALL:
@ -841,7 +869,7 @@ void BuildDef32File(FILE *outfile)
fprintf(outfile, "@%d", at_param);
#endif /* NEED_STDCALL_DECORATION */
/* try to reduce output */
if(strcmp(odp->name, odp->link_name))
if(strcmp(name, odp->link_name))
{
fprintf(outfile, "=%s", odp->link_name);
#ifdef NEED_STDCALL_DECORATION
@ -856,7 +884,7 @@ void BuildDef32File(FILE *outfile)
default:
assert(0);
}
fprintf(outfile, " @%d\n", odp->ordinal);
fprintf(outfile, " @%d%s\n", odp->ordinal, odp->name ? "" : " NONAME" );
}
}