Added support for importing by ordinal.
This commit is contained in:
parent
112c665f83
commit
15a75259bd
|
@ -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 */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue