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 */
|
||||
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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,10 +499,15 @@ 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];
|
||||
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" );
|
||||
}
|
||||
fprintf( outfile, " }\n};\n\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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue