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 */ /* fixup RVAs in the resource directory */
static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *base ) 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; IMAGE_IMPORT_DESCRIPTOR *imports = (void *)dir->VirtualAddress;
fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 ); fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
/* we can fixup everything at once since we only have pointers and 0 values */ fixup_imports( imports, dir->Size, addr );
fixup_rva_ptrs( imports, addr, dir->Size / sizeof(void*) );
} }
/* Build the resource directory */ /* Build the resource directory */

View File

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

View File

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

View File

@ -61,6 +61,7 @@ static const char * const FlagNames[] =
{ {
"noimport", /* FLAG_NOIMPORT */ "noimport", /* FLAG_NOIMPORT */
"norelay", /* FLAG_NORELAY */ "norelay", /* FLAG_NORELAY */
"noname", /* FLAG_NONAME */
"ret64", /* FLAG_RET64 */ "ret64", /* FLAG_RET64 */
"i386", /* FLAG_I386 */ "i386", /* FLAG_I386 */
"register", /* FLAG_REGISTER */ "register", /* FLAG_REGISTER */
@ -431,6 +432,7 @@ static void ParseOrdinal(int ordinal)
if (ordinal != -1) 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 >= MAX_ORDINALS) fatal_error( "Ordinal number %d too large\n", ordinal );
if (ordinal > Limit) Limit = ordinal; if (ordinal > Limit) Limit = ordinal;
if (ordinal < Base) Base = ordinal; if (ordinal < Base) Base = ordinal;
@ -438,13 +440,15 @@ static void ParseOrdinal(int ordinal)
Ordinals[ordinal] = odp; Ordinals[ordinal] = odp;
} }
if (!strcmp( odp->name, "@" )) if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME)
{ {
if (ordinal == -1) if (ordinal == -1)
fatal_error( "Nameless function needs an explicit ordinal number\n" ); fatal_error( "Nameless function needs an explicit ordinal number\n" );
if (SpecType != SPEC_WIN32) if (SpecType != SPEC_WIN32)
fatal_error( "Nameless functions not supported for Win16\n" ); 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; 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 const char *make_internal_name( const ORDDEF *odp, const char *prefix )
{ {
static char buffer[256]; static char buffer[256];
if (odp->name[0]) if (odp->name || odp->export_name)
{ {
char *p; 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 */ /* make sure name is a legal C identifier */
for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break; for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
if (!*p) return buffer; 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", fprintf( outfile, " \"" __ASM_NAME("__wine_dllexport_%s_%d_%s") ":\\n\"\n",
make_c_identifier(DLLFileName), i, Names[i]->name ); 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" ); fprintf( outfile, " \"\\t.long 0xffffffff\\n\"\n" );
/* output variables */ /* output variables */
@ -388,8 +407,10 @@ static void output_stub_funcs( FILE *outfile )
ORDDEF *odp = EntryPoints[i]; ORDDEF *odp = EntryPoints[i];
if (odp->type != TYPE_STUB) continue; if (odp->type != TYPE_STUB) continue;
fprintf( outfile, "void %s(void) ", make_internal_name( odp, "stub" ) ); 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 ); fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
else if (odp->export_name)
fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->export_name );
else else
fprintf( outfile, "{ __wine_unimplemented(\"%d\"); }\n", odp->ordinal ); fprintf( outfile, "{ __wine_unimplemented(\"%d\"); }\n", odp->ordinal );
} }
@ -803,6 +824,7 @@ void BuildSpec32File( FILE *outfile )
*/ */
void BuildDef32File(FILE *outfile) void BuildDef32File(FILE *outfile)
{ {
const char *name;
int i; int i;
AssignOrdinals(); AssignOrdinals();
@ -819,10 +841,16 @@ void BuildDef32File(FILE *outfile)
for(i = 0; i < nb_entry_points; i++) for(i = 0; i < nb_entry_points; i++)
{ {
ORDDEF *odp = EntryPoints[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; 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) switch(odp->type)
{ {
@ -831,7 +859,7 @@ void BuildDef32File(FILE *outfile)
case TYPE_CDECL: case TYPE_CDECL:
case TYPE_VARIABLE: case TYPE_VARIABLE:
/* try to reduce output */ /* try to reduce output */
if(strcmp(odp->name, odp->link_name)) if(strcmp(name, odp->link_name))
fprintf(outfile, "=%s", odp->link_name); fprintf(outfile, "=%s", odp->link_name);
break; break;
case TYPE_STDCALL: case TYPE_STDCALL:
@ -841,7 +869,7 @@ void BuildDef32File(FILE *outfile)
fprintf(outfile, "@%d", at_param); fprintf(outfile, "@%d", at_param);
#endif /* NEED_STDCALL_DECORATION */ #endif /* NEED_STDCALL_DECORATION */
/* try to reduce output */ /* try to reduce output */
if(strcmp(odp->name, odp->link_name)) if(strcmp(name, odp->link_name))
{ {
fprintf(outfile, "=%s", odp->link_name); fprintf(outfile, "=%s", odp->link_name);
#ifdef NEED_STDCALL_DECORATION #ifdef NEED_STDCALL_DECORATION
@ -856,7 +884,7 @@ void BuildDef32File(FILE *outfile)
default: default:
assert(0); assert(0);
} }
fprintf(outfile, " @%d\n", odp->ordinal); fprintf(outfile, " @%d%s\n", odp->ordinal, odp->name ? "" : " NONAME" );
} }
} }