Output the resource data in assembly too.

This commit is contained in:
Alexandre Julliard 2005-09-15 09:42:22 +00:00
parent d7f6424199
commit 41177ca0bd
3 changed files with 74 additions and 119 deletions

View File

@ -199,7 +199,7 @@ extern int resolve_imports( DLLSPEC *spec );
extern int has_imports(void);
extern void output_imports( FILE *outfile, DLLSPEC *spec );
extern int load_res32_file( const char *name, DLLSPEC *spec );
extern int output_resources( FILE *outfile, DLLSPEC *spec );
extern void output_resources( FILE *outfile, DLLSPEC *spec );
extern void load_res16_file( const char *name, DLLSPEC *spec );
extern unsigned int get_res16_data_size( DLLSPEC *spec, unsigned int res_offset,
unsigned int alignment );

View File

@ -90,7 +90,7 @@ static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */
/* size of a resource directory with n entries */
#define RESDIR_SIZE(n) ((4 + 2 * (n)) * sizeof(int))
#define RESDIR_SIZE(n) (sizeof(IMAGE_RESOURCE_DIRECTORY) + (n) * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))
inline static struct resource *add_resource( DLLSPEC *spec )
@ -319,75 +319,55 @@ static void free_resource_tree( struct res_tree *tree )
static void output_string( FILE *outfile, const WCHAR *name )
{
int i, len = strlenW(name);
fprintf( outfile, "0x%04x", len );
for (i = 0; i < len; i++) fprintf( outfile, ", 0x%04x", name[i] );
fprintf( outfile, " /* " );
fprintf( outfile, " \"\\t%s 0x%04x", get_asm_short_keyword(), len );
for (i = 0; i < len; i++) fprintf( outfile, ",0x%04x", name[i] );
fprintf( outfile, "\\n\" /* " );
for (i = 0; i < len; i++) fprintf( outfile, "%c", isprint((char)name[i]) ? (char)name[i] : '?' );
fprintf( outfile, " */" );
fprintf( outfile, " */\n" );
}
/* output a resource directory */
static inline void output_res_dir( FILE *outfile, unsigned int nb_names, unsigned int nb_ids )
{
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* Characteristics */
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* TimeDateStamp */
fprintf( outfile, " \"\\t%s 0,0\\n\"\n", /* Major/MinorVersion */
get_asm_short_keyword() );
fprintf( outfile, " \"\\t%s %u,%u\\n\"\n", /* NumberOfNamed/IdEntries */
get_asm_short_keyword(), nb_names, nb_ids );
}
/* output the resource definitions */
int output_resources( FILE *outfile, DLLSPEC *spec )
void output_resources( FILE *outfile, DLLSPEC *spec )
{
int j, k, nb_id_types, total_size;
int j, k, nb_id_types;
unsigned int i, n, offset, data_offset;
struct res_tree *tree;
struct res_type *type;
struct res_name *name;
const struct resource *res;
if (!spec->nb_resources) return 0;
if (!spec->nb_resources) return;
tree = build_resource_tree( spec );
/* directory structures */
/* compute the offsets */
fprintf( outfile, "struct res_dir {\n" );
fprintf( outfile, " unsigned int Characteristics;\n" );
fprintf( outfile, " unsigned int TimeDateStamp;\n" );
fprintf( outfile, " unsigned short MajorVersion, MinorVersion;\n" );
fprintf( outfile, " unsigned short NumerOfNamedEntries, NumberOfIdEntries;\n};\n\n" );
fprintf( outfile, "struct res_dir_entry {\n" );
fprintf( outfile, " unsigned int Name;\n" );
fprintf( outfile, " unsigned int OffsetToData;\n};\n\n" );
fprintf( outfile, "struct res_data_entry {\n" );
fprintf( outfile, " const unsigned int *OffsetToData;\n" );
fprintf( outfile, " unsigned int Size;\n" );
fprintf( outfile, " unsigned int CodePage;\n" );
fprintf( outfile, " unsigned int ResourceHandle;\n};\n\n" );
/* resource directory definition */
fprintf( outfile, "static struct res_struct{\n" );
fprintf( outfile, " struct res_dir type_dir;\n" );
fprintf( outfile, " struct res_dir_entry type_entries[%d];\n", tree->nb_types );
offset = RESDIR_SIZE( tree->nb_types );
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
offset += RESDIR_SIZE( type->nb_names );
fprintf( outfile, " struct res_dir name_%d_dir;\n", i );
fprintf( outfile, " struct res_dir_entry name_%d_entries[%d];\n", i, type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
offset += RESDIR_SIZE( name->nb_languages );
fprintf( outfile, " struct res_dir lang_%d_%d_dir;\n", i, n );
fprintf( outfile, " struct res_dir_entry lang_%d_%d_entries[%d];\n",
i, n, name->nb_languages );
}
}
fprintf( outfile, " struct res_data_entry data_entries[%d];\n", spec->nb_resources );
offset += spec->nb_resources * 4 * sizeof(int);
offset += spec->nb_resources * sizeof(IMAGE_RESOURCE_DATA_ENTRY);
for (i = nb_id_types = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
type->name_offset = offset | 0x80000000;
offset += (strlenW(type->type->str)+1) * sizeof(unsigned short);
fprintf( outfile, " unsigned short type_%d_name[%d];\n",
i, strlenW(type->type->str)+1 );
offset += (strlenW(type->type->str)+1) * sizeof(WCHAR);
}
else
{
@ -400,110 +380,94 @@ int output_resources( FILE *outfile, DLLSPEC *spec )
if (name->name->str)
{
name->name_offset = offset | 0x80000000;
offset += (strlenW(name->name->str)+1) * sizeof(unsigned short);
fprintf( outfile, " unsigned short name_%d_%d_name[%d];\n",
i, n, strlenW(name->name->str)+1 );
offset += (strlenW(name->name->str)+1) * sizeof(WCHAR);
}
else name->name_offset = name->name->id;
}
}
total_size = offset;
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
fprintf( outfile, " unsigned int res_%d[%d];\n", i, res->data_size / 4 );
total_size += (res->data_size + 3) & ~3;
}
/* resource directory contents */
/* output the resource directories */
fprintf( outfile, "} __wine_spec_resources = {\n" );
fprintf( outfile, " { 0, 0, 0, 0, %d, %d },\n", tree->nb_types - nb_id_types, nb_id_types );
fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(get_ptr_size()) );
fprintf( outfile, " \".L__wine_spec_resources:\\n\"\n" );
output_res_dir( outfile, tree->nb_types - nb_id_types, nb_id_types );
/* dump the type directory */
offset = RESDIR_SIZE( tree->nb_types );
fprintf( outfile, " {\n" );
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
fprintf( outfile, " { 0x%08x, 0x%08x },\n", type->name_offset, offset | 0x80000000 );
fprintf( outfile, " \"\\t.long 0x%08x,0x%08x\\n\"\n",
type->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
offset += RESDIR_SIZE( name->nb_languages );
}
fprintf( outfile, " },\n" );
data_offset = offset;
offset = RESDIR_SIZE( tree->nb_types );
/* dump the names and languages directories */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
fprintf( outfile, " { 0, 0, 0, 0, %d, %d }, /* name_%d_dir */\n {\n",
type->nb_names - type->nb_id_names, type->nb_id_names, i );
output_res_dir( outfile, type->nb_names - type->nb_id_names, type->nb_id_names );
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
fprintf( outfile, " { 0x%08x, 0x%08x },\n", name->name_offset, offset | 0x80000000 );
fprintf( outfile, " \"\\t.long 0x%08x,0x%08x\\n\"\n",
name->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( name->nb_languages );
}
fprintf( outfile, " },\n" );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
fprintf( outfile, " { 0, 0, 0, 0, 0, %d }, /* lang_%d_%d_dir */\n {\n",
name->nb_languages, i, n );
output_res_dir( outfile, 0, name->nb_languages );
for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
{
fprintf( outfile, " { 0x%04x, 0x%08x },\n",
res->lang, data_offset + (res - spec->resources) * 4 * sizeof(int) );
fprintf( outfile, " \"\\t.long 0x%08x,0x%08x\\n\"\n", res->lang,
data_offset + (res - spec->resources) * sizeof(IMAGE_RESOURCE_DATA_ENTRY) );
}
fprintf( outfile, " },\n" );
}
}
/* dump the resource data entries */
fprintf( outfile, " {\n" );
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
fprintf( outfile, " { __wine_spec_resources.res_%d, sizeof(__wine_spec_resources.res_%d), 0, 0 }, /* %08x */\n", i, i,
data_offset + i * 4 * sizeof(int) );
}
fprintf( outfile, " \"\\t.long .L__wine_spec_res_%d,%u,0,0\\n\"\n",
i, res->data_size );
/* dump the name strings */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
fprintf( outfile, " },\n { " );
output_string( outfile, type->type->str );
}
if (type->type->str) output_string( outfile, type->type->str );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
if (name->name->str)
{
fprintf( outfile, " },\n { " );
output_string( outfile, name->name->str );
}
}
if (name->name->str) output_string( outfile, name->name->str );
}
fprintf( outfile, " },\n" );
fprintf( outfile, ");\n" );
/* resource data */
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
const unsigned int *p = res->data;
int size = res->data_size / 4;
/* dump data as ints to ensure correct alignment */
fprintf( outfile, " { /* res_%d */\n ", i );
for (j = 0; j < size - 1; j++, p++)
const unsigned char *p = res->data;
fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(get_ptr_size()) );
fprintf( outfile, " \".L__wine_spec_res_%d:\\n\"\n", i );
fprintf( outfile, " \"\\t.byte " );
for (j = 0; j < res->data_size - 1; j++, p++)
{
fprintf( outfile, "0x%08x,", *p );
if ((j % 8) == 7) fprintf( outfile, "\n " );
if ((j % 16) == 15) fprintf( outfile, "0x%02x\\n\"\n \"\\t.byte ", *p );
else fprintf( outfile, "0x%02x,", *p );
}
fprintf( outfile, "0x%08x\n },\n", *p );
fprintf( outfile, "0x%02x\\n\"\n", *p );
fprintf( outfile, ");\n" );
}
fprintf( outfile, "};\n\n" );
fprintf( outfile, "asm(\".data\\n\"\n" );
fprintf( outfile, " \".L__wine_spec_resources_end:\\n\"\n" );
fprintf( outfile, " \"\\t.byte 0\\n\"\n" );
fprintf( outfile, ");\n" );
free_resource_tree( tree );
return total_size;
}

View File

@ -427,7 +427,7 @@ void output_dll_init( FILE *outfile, const char *constructor, const char *destru
*/
void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
{
int resources_size, machine = 0;
int machine = 0;
unsigned int page_size = get_page_size();
resolve_imports( spec );
@ -436,8 +436,9 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
/* Reserve some space for the PE header */
fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "static void __asm__dummy_header(void) {\n" );
fprintf( outfile, "static void __asm__dummy(void) {\n" );
fprintf( outfile, "#endif\n" );
fprintf( outfile, "asm(\".text\\n\\t\"\n" );
fprintf( outfile, " \".align %d\\n\"\n", get_alignment(page_size) );
fprintf( outfile, " \"__wine_spec_pe_header:\\t\"\n" );
@ -445,28 +446,11 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
fprintf( outfile, " \".space 65536\\n\\t\"\n" );
else
fprintf( outfile, " \".skip 65536\\n\\t\"\n" );
fprintf( outfile, " \".data\\n\\t\"\n" );
fprintf( outfile, " \".align %d\\n\"\n", get_alignment(4) );
fprintf( outfile, " \".L__wine_spec_data_start:\\t.long 1\");\n" );
fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "}\n" );
fprintf( outfile, "#endif\n" );
if (target_platform == PLATFORM_APPLE)
fprintf( outfile, "static char _end[4];\n" );
/* Output the resources */
resources_size = output_resources( outfile, spec );
/* Output the NT header */
fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "static void __asm__dummy(void) {\n" );
fprintf( outfile, "#endif\n" );
fprintf( outfile, "/* NT header */\n" );
fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(4) );
fprintf( outfile, " \"\\t.data\\n\\t\"\n" );
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(get_ptr_size()) );
fprintf( outfile, " \"\\t.globl %s\\n\"\n", asm_name("__wine_spec_nt_header") );
fprintf( outfile, " \"%s:\\n\"\n", asm_name("__wine_spec_nt_header"));
@ -502,7 +486,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
fprintf( outfile, " \"\\t.long %s\\n\"\n", /* AddressOfEntryPoint */
asm_name(spec->init_func) );
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* BaseOfCode */
fprintf( outfile, " \"\\t.long .L__wine_spec_data_start\\n\"\n" ); /* BaseOfData */
if (get_ptr_size() == 4)
fprintf( outfile, " \"\\t.long %s\\n\"\n", asm_name("__wine_spec_nt_header") ); /* BaseOfData */
fprintf( outfile, " \"\\t%s __wine_spec_pe_header\\n\"\n", /* ImageBase */
get_asm_ptr_keyword() );
fprintf( outfile, " \"\\t.long %u\\n\"\n", page_size ); /* SectionAlignment */
@ -539,8 +524,10 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
else
fprintf( outfile, " \"\\t.long 0,0\\n\"\n" );
fprintf( outfile, " \"\\t.long %s,%u\\n\"\n", /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
resources_size ? asm_name("__wine_spec_resources") : "0", resources_size );
if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
fprintf( outfile, " \"\\t.long .L__wine_spec_resources, .L__wine_spec_resources_end-.L__wine_spec_resources\\n\"\n" );
else
fprintf( outfile, " \"\\t.long 0,0\\n\"\n" );
fprintf( outfile, " \"\\t.long 0,0\\n\"\n" ); /* DataDirectory[3] */
fprintf( outfile, " \"\\t.long 0,0\\n\"\n" ); /* DataDirectory[4] */
@ -561,11 +548,15 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
fprintf( outfile, " \"\\t.globl %s\\n\"\n", asm_name("__wine_spec_file_name") );
fprintf( outfile, " \"%s:\\n\"\n", asm_name("__wine_spec_file_name"));
fprintf( outfile, " \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), spec->file_name );
if (target_platform == PLATFORM_APPLE)
fprintf( outfile, " \"\\t.comm %s,4\\n\"\n", asm_name("_end") );
fprintf( outfile, ");\n" );
output_stubs( outfile, spec );
output_exports( outfile, spec );
output_imports( outfile, spec );
output_resources( outfile, spec );
output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
fprintf( outfile, "#ifndef __GNUC__\n" );