From 932ecb24eb82346866eef147fec98ee86bb1ef16 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Fri, 2 Sep 2005 15:36:03 +0000
Subject: [PATCH] Output the import directory using assembly instead of C
 structures.

---
 tools/winebuild/build.h  |   3 +-
 tools/winebuild/import.c | 123 +++++++++++++++++++++++++--------------
 tools/winebuild/spec32.c |  15 +++--
 3 files changed, 87 insertions(+), 54 deletions(-)

diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 5186aad3848..2b34f3a40a6 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -192,7 +192,8 @@ extern void add_ignore_symbol( const char *name );
 extern void add_extra_ld_symbol( const char *name );
 extern void read_undef_symbols( DLLSPEC *spec, char **argv );
 extern int resolve_imports( DLLSPEC *spec );
-extern int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed );
+extern int get_imports_size(void);
+extern void output_imports( FILE *outfile, DLLSPEC *spec );
 extern void output_import_thunks( FILE *outfile, DLLSPEC *spec );
 extern int load_res32_file( const char *name, DLLSPEC *spec );
 extern void output_resources( FILE *outfile, DLLSPEC *spec );
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 16ea7fa252e..c68a3355be4 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -742,63 +742,102 @@ static void output_import_thunk( FILE *outfile, const char *name, const char *ta
     output_function_size( outfile, name );
 }
 
-/* output the import table of a Win32 module */
-static int output_immediate_imports( FILE *outfile )
+/* compute the size of the import table */
+int get_imports_size(void)
 {
-    int i, j, nb_imm = nb_imports - nb_delayed;
+    int i, total_size, nb_imm = nb_imports - nb_delayed;
 
     if (!nb_imm) return 0;
 
+    /* list of dlls */
+    total_size = 5 * 4 * (nb_imm + 1);
+
+    for (i = 0; i < nb_imports; i++)
+    {
+        if (dll_imports[i]->delay) continue;
+        total_size += (dll_imports[i]->nb_imports + 1) * 4;
+    }
+    /* Note: the strings are not counted as being part of the import directory */
+    return total_size;
+}
+
+/* output the import table of a Win32 module */
+static void output_immediate_imports( FILE *outfile )
+{
+    int i, j;
+    const char *dll_name;
+
+    if (nb_imports == nb_delayed) return;  /* no immediate imports */
+
     /* main import header */
 
-    fprintf( outfile, "\nstatic struct {\n" );
-    fprintf( outfile, "  struct {\n" );
-    fprintf( outfile, "    void        *OriginalFirstThunk;\n" );
-    fprintf( outfile, "    unsigned int TimeDateStamp;\n" );
-    fprintf( outfile, "    unsigned int ForwarderChain;\n" );
-    fprintf( outfile, "    const char  *Name;\n" );
-    fprintf( outfile, "    void        *FirstThunk;\n" );
-    fprintf( outfile, "  } imp[%d];\n", nb_imm+1 );
-    fprintf( outfile, "  const char *data[%d];\n",
-             total_imports - total_delayed + nb_imm );
-    fprintf( outfile, "} imports = {\n  {\n" );
+    fprintf( outfile, "/* import table */\n" );
+    fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(4) );
+    fprintf( outfile, "    \"%s:\\n\"\n", asm_name("__wine_spec_imports"));
 
     /* list of dlls */
 
     for (i = j = 0; i < nb_imports; i++)
     {
         if (dll_imports[i]->delay) continue;
-        fprintf( outfile, "    { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
-                 dll_imports[i]->spec->file_name, j );
+        dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
+        fprintf( outfile, "    \"\\t.long 0\\n\"\n" );     /* OriginalFirstThunk */
+        fprintf( outfile, "    \"\\t.long 0\\n\"\n" );     /* TimeDateStamp */
+        fprintf( outfile, "    \"\\t.long 0\\n\"\n" );     /* ForwarderChain */
+        fprintf( outfile, "    \"\\t.long __wine_spec_import_name_%s\\n\"\n", dll_name ); /* Name */
+        fprintf( outfile, "    \"\\t.long %s+%d\\n\"\n",     /* FirstThunk */
+                 asm_name("__wine_spec_import_data_ptrs"), j * 4 );
         j += dll_imports[i]->nb_imports + 1;
     }
+    fprintf( outfile, "    \"\\t.long 0\\n\"\n" );     /* OriginalFirstThunk */
+    fprintf( outfile, "    \"\\t.long 0\\n\"\n" );     /* TimeDateStamp */
+    fprintf( outfile, "    \"\\t.long 0\\n\"\n" );     /* ForwarderChain */
+    fprintf( outfile, "    \"\\t.long 0\\n\"\n" );     /* Name */
+    fprintf( outfile, "    \"\\t.long 0\\n\"\n" );     /* FirstThunk */
 
-    fprintf( outfile, "    { 0, 0, 0, 0, 0 },\n" );
-    fprintf( outfile, "  },\n  {\n" );
-
-    /* list of imported functions */
+    fprintf( outfile, "    \"%s:\\n\"\n", asm_name("__wine_spec_import_data_ptrs") );
+    for (i = 0; i < nb_imports; i++)
+    {
+        if (dll_imports[i]->delay) continue;
+        dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
+        for (j = 0; j < dll_imports[i]->nb_imports; j++)
+        {
+            ORDDEF *odp = dll_imports[i]->imports[j];
+            if (!(odp->flags & FLAG_NONAME))
+                fprintf( outfile, "    \"\\t.long __wine_spec_import_data_%s_%s\\n\"\n",
+                         dll_name, odp->name );
+            else
+                fprintf( outfile, "    \"\\t.long %d\\n\"\n", odp->ordinal );
+        }
+        fprintf( outfile, "    \"\\t.long 0\\n\"\n" );
+    }
 
     for (i = 0; i < nb_imports; i++)
     {
         if (dll_imports[i]->delay) continue;
-        fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
+        dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
         for (j = 0; j < dll_imports[i]->nb_imports; j++)
         {
             ORDDEF *odp = dll_imports[i]->imports[j];
             if (!(odp->flags & FLAG_NONAME))
             {
-                unsigned short ord = odp->ordinal;
-                fprintf( outfile, "    \"\\%03o\\%03o%s\",\n",
-                         *(unsigned char *)&ord, *((unsigned char *)&ord + 1), odp->name );
+                fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(2) );
+                fprintf( outfile, "    \"__wine_spec_import_data_%s_%s:\\n\"\n", dll_name, odp->name );
+                fprintf( outfile, "    \"\\t%s %d\\n\"\n", get_asm_short_keyword(), odp->ordinal );
+                fprintf( outfile, "    \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), odp->name );
             }
-            else
-                fprintf( outfile, "    (char *)%d,\n", odp->ordinal );
         }
-        fprintf( outfile, "    0,\n" );
     }
-    fprintf( outfile, "  }\n};\n\n" );
 
-    return nb_imm;
+    for (i = 0; i < nb_imports; i++)
+    {
+        if (dll_imports[i]->delay) continue;
+        dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
+        fprintf( outfile, "    \"__wine_spec_import_name_%s:\\t%s \\\"%s\\\"\\n\"\n",
+                 dll_name, get_asm_string_keyword(), dll_imports[i]->spec->file_name );
+    }
+
+    fprintf( outfile, ");\n" );
 }
 
 /* output the import thunks of a Win32 module */
@@ -810,20 +849,18 @@ static void output_immediate_import_thunks( FILE *outfile )
 
     if (!nb_imm) return;
 
-    pos = (sizeof(void *) + 2*sizeof(unsigned int) + sizeof(const char *) + sizeof(void *)) *
-            (nb_imm + 1);  /* offset of imports.data from start of imports */
     fprintf( outfile, "/* immediate import thunks */\n" );
     fprintf( outfile, "asm(\".text\\n\\t.align %d\\n\"\n", get_alignment(8) );
     fprintf( outfile, "    \"%s:\\n\"\n", asm_name(import_thunks));
 
-    for (i = 0; i < nb_imports; i++)
+    for (i = pos = 0; i < nb_imports; i++)
     {
         if (dll_imports[i]->delay) continue;
         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += sizeof(const char *))
         {
             ORDDEF *odp = dll_imports[i]->imports[j];
             output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
-                                 "imports", pos );
+                                 "__wine_spec_import_data_ptrs", pos );
         }
         pos += 4;
     }
@@ -832,11 +869,11 @@ static void output_immediate_import_thunks( FILE *outfile )
 }
 
 /* output the delayed import table of a Win32 module */
-static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
+static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
 {
     int i, j;
 
-    if (!nb_delayed) return 0;
+    if (!nb_delayed) return;
 
     fprintf( outfile, "static void *__wine_delay_imp_hmod[%d];\n", nb_delayed );
     for (i = 0; i < nb_imports; i++)
@@ -899,8 +936,6 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
         }
     }
     fprintf( outfile, "  }\n};\n\n" );
-
-    return nb_delayed;
 }
 
 /* output the delayed import thunks of a Win32 module */
@@ -1042,7 +1077,7 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
                 }
                 break;
             }
-            output_function_size( outfile, name );
+            output_function_size( outfile, buffer );
         }
         idx++;
     }
@@ -1065,18 +1100,16 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
     fprintf( outfile, ");\n" );
 }
 
-/* output the import and delayed import tables of a Win32 module
- * returns number of DLLs exported in 'immediate' mode
- */
-int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed )
+/* output the import and delayed import tables of a Win32 module */
+void output_imports( FILE *outfile, DLLSPEC *spec )
 {
-    *nb_delayed = output_delayed_imports( outfile, spec );
-    return output_immediate_imports( outfile );
+    output_delayed_imports( outfile, spec );
 }
 
 /* output the import and delayed import thunks of a Win32 module */
 void output_import_thunks( FILE *outfile, DLLSPEC *spec )
 {
-    output_delayed_import_thunks( outfile, spec );
+    output_immediate_imports( outfile );
     output_immediate_import_thunks( outfile );
+    output_delayed_import_thunks( outfile, spec );
 }
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 8a084487e10..d3c3259dbde 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -440,13 +440,12 @@ void output_dll_init( FILE *outfile, const char *constructor, const char *destru
  */
 void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
 {
-    int exports_size = 0;
-    int nr_exports, nr_imports, nr_delayed;
+    int exports_size, imports_size;
     unsigned int page_size = get_page_size();
 
-    nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
     resolve_imports( spec );
     exports_size = get_exports_size( spec );
+    imports_size = get_imports_size();
     output_standard_file_header( outfile );
 
     /* Reserve some space for the PE header */
@@ -475,13 +474,13 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
         fprintf( outfile, "extern char _end[];\n" );
 
     fprintf( outfile, "const char __wine_spec_file_name[] = \"%s\";\n", spec->file_name );
-    fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[];\n\n" );
+    fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[], __wine_spec_imports[];\n\n" );
 
     output_stub_funcs( outfile, spec );
 
     /* Output the DLL imports */
 
-    nr_imports = output_imports( outfile, spec, &nr_delayed );
+    output_imports( outfile, spec );
 
     /* Output the resources */
 
@@ -584,10 +583,10 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
     fprintf( outfile, "    0,\n" );                      /* LoaderFlags */
     fprintf( outfile, "    %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES );  /* NumberOfRvaAndSizes */
     fprintf( outfile, "    {\n" );
-    fprintf( outfile, "      { %s, %d },\n",  /* IMAGE_DIRECTORY_ENTRY_EXPORT */
+    fprintf( outfile, "      { %s, %u },\n",  /* IMAGE_DIRECTORY_ENTRY_EXPORT */
              exports_size ? "__wine_spec_exports" : "0", exports_size );
-    fprintf( outfile, "      { %s, %s },\n",  /* IMAGE_DIRECTORY_ENTRY_IMPORT */
-             nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
+    fprintf( outfile, "      { %s, %u },\n",  /* IMAGE_DIRECTORY_ENTRY_IMPORT */
+             imports_size ? "__wine_spec_imports" : "0", imports_size );
     fprintf( outfile, "      { %s, %s },\n",   /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
              spec->nb_resources ? "&__wine_spec_resources" : "0",
              spec->nb_resources ? "sizeof(__wine_spec_resources)" : "0" );
-- 
GitLab