[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    Re: debugger fix
From:       Ulrich Weigand <weigand () immd1 ! informatik ! uni-erlangen ! de>
Date:       2001-01-31 4:39:58
[Download RAW message or body]


I wrote:

> Hmmm.  Maybe it would be even better to completely strip the import
> stub symbols from Wine DLLs.  This removes the possibility of someone
> accidentally using ELF linking to resolve against those symbols.
> (As I recall, this was one of the reasons why we now need to build
> all Winelib apps as .so files ...)

Argh.  Of course to fix *that* problem requires that the *dynamic*
symbols are removed as well as the regular symbols ...

Unfortunately, there is currently no way to remove dynamic symbols
from a shared object.  However, one can prevent the dynamic symbol
being created in the first place, if the symbol is not present or
local in the object the shared object is created from.

The symbol can't be not present, because there are still relocations
pointing to it.  However, it can be made local using objcopy -L ...
Then, the shared object doesn't have the dynamic symbol, however it
still has the regular symbol, as a local one.  To fix the debugger
problem, this has then to be removed.

The complete sequence of events to link a Wine DLL is then:
  1. combine all DLL objects to a temp object
  2. create the .spec.c file from this temp object
  3. link all objects + the .spec.o object to another temp object
  4. localize all import stub symbols in the temp object
  5. create a shared object from the temp object
  6. strip all import stub symbols from the shared object

The appended patch implements this sequence ...  (This is starting
to get ugly.  Maybe we should write a libtool-like script that
combines everything necessary to build a Wine DLL?)

Note that this now means a dependency on GNU objcopy at least 
version 2.9.1 ...


ChangeLog:

	* dlls/Makedll.rules.in tools/strip_imports tools/localize_imports
 	Strip import stub symbols from Wine DLLs.
 
 	* tools/winebuild/Makefile.in tools/winebuild/build.h tools/winebuild/import.c
 	  tools/winebuild/spec16.c tools/winebuild/spec32.c tools/winebuild/sysdeps.c
 	Move architecture dependent routines to sysdeps.c
 	Emit __wine_dllimport_... symbols to mark import stubs.
 

diff -urN wine-cvs/dlls/Makedll.rules.in wine-uw/dlls/Makedll.rules.in
--- wine-cvs/dlls/Makedll.rules.in	Wed Jan  3 22:51:24 2001
+++ wine-uw/dlls/Makedll.rules.in	Wed Jan 31 05:18:58 2001
@@ -25,7 +25,10 @@
 # Rules for .so files
 
 lib$(MODULE).so: $(ALL_OBJS) Makefile.in
-	$(LDSHARED) $(LDDLLFLAGS) $(ALL_OBJS) -o $@ -L$(DLLDIR) $(IMPORTS:%=-l%) $(ALL_LIBS)
+	$(LDCOMBINE) $(ALL_OBJS) -o lib$(MODULE).tmp.o
+	$(TOPSRCDIR)/tools/localize_imports lib$(MODULE).tmp.o 
+	$(LDSHARED) $(LDDLLFLAGS) lib$(MODULE).tmp.o -o $@ -L$(DLLDIR) $(IMPORTS:%=-l%) $(ALL_LIBS)
+	$(TOPSRCDIR)/tools/strip_imports $@
 
 $(ALTNAMES:%=lib%.$(LIBEXT)): lib$(MODULE).$(LIBEXT)
 	$(RM) $@ && $(LN_S) lib$(MODULE).$(LIBEXT) $@
diff -urN wine-cvs/tools/localize_imports wine-uw/tools/localize_imports
--- wine-cvs/tools/localize_imports	Thu Jan  1 01:00:00 1970
+++ wine-uw/tools/localize_imports	Wed Jan 31 05:19:31 2001
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Localize import stub symbols from Wine DLLs
+#
+ 
+while [ $# -gt 0 ]
+do
+  if [ ! -e $1 ]
+  then
+    echo "localize_imports: $1: file not found"
+    exit 1
+  fi
+
+  IMPLIST=`nm $1 | grep __wine_dllimport | sed -e 's/^.*__wine_dllimport_[^_]*_/-L /'`
+  if [ "$IMPLIST" != "" ]
+  then
+    echo $IMPLIST | xargs objcopy $1
+  fi
+
+  shift
+done
+
+exit 0
+
diff -urN wine-cvs/tools/strip_imports wine-uw/tools/strip_imports
--- wine-cvs/tools/strip_imports	Thu Jan  1 01:00:00 1970
+++ wine-uw/tools/strip_imports	Wed Jan 31 05:24:42 2001
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Strip import stub symbols from Wine DLLs
+#
+ 
+while [ $# -gt 0 ]
+do
+  if [ ! -e $1 ]
+  then
+    echo "strip_imports: $1: file not found"
+    exit 1
+  fi
+
+  IMPLIST=`nm $1 | grep __wine_dllimport | sed -e 's/^.*__wine_dllimport_[^_]*_/-N /'`
+  if [ "$IMPLIST" != "" ]
+  then
+    echo $IMPLIST | xargs objcopy $1
+  fi
+
+  shift
+done
+
+exit 0
+
diff -urN wine-cvs/tools/winebuild/Makefile.in wine-uw/tools/winebuild/Makefile.in
--- wine-cvs/tools/winebuild/Makefile.in	Wed Jan  3 22:51:34 2001
+++ wine-uw/tools/winebuild/Makefile.in	Wed Jan 31 01:52:09 2001
@@ -16,6 +16,7 @@
 	res32.c \
 	spec16.c \
 	spec32.c \
+	sysdeps.c \
 	utils.c
 
 all: $(PROGRAMS)
diff -urN wine-cvs/tools/winebuild/build.h wine-uw/tools/winebuild/build.h
--- wine-cvs/tools/winebuild/build.h	Wed Jan  3 22:51:34 2001
+++ wine-uw/tools/winebuild/build.h	Wed Jan 31 01:52:09 2001
@@ -143,6 +143,15 @@
 extern int output_res16_data( FILE *outfile );
 extern int output_res16_directory( unsigned char *buffer );
 
+extern void output_asm_constructor( FILE *outfile, char *func );
+extern void output_asm_destructor( FILE *outfile, char *func );
+extern void output_asm_import_thunk_prolog( FILE *outfile );
+extern void output_asm_import_thunk( FILE *outfile, char *func, char *base, int pos );
+extern void output_asm_import_thunk_epilog( FILE *outfile );
+extern void output_asm_delayed_import_thunk_prolog( FILE *outfile, char *glue );
+extern void output_asm_delayed_import_thunk( FILE *outfile, char *func, int token );
+extern void output_asm_delayed_import_thunk_epilog( FILE *outfile );
+
 extern void BuildGlue( FILE *outfile, FILE *infile );
 extern void BuildRelays( FILE *outfile );
 extern void BuildSpec16File( FILE *outfile );
diff -urN wine-cvs/tools/winebuild/import.c wine-uw/tools/winebuild/import.c
--- wine-cvs/tools/winebuild/import.c	Sun Jan 28 18:58:09 2001
+++ wine-uw/tools/winebuild/import.c	Wed Jan 31 01:53:03 2001
@@ -395,55 +395,17 @@
 
     /* thunks for imported functions */
 
-    fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
+    output_asm_import_thunk_prolog( outfile );
     pos = 20 * (nb_imm + 1);  /* offset of imports.data from start of imports */
-    fprintf( outfile, "asm(\".data\\n\\t.align 8\\n\"\n" );
     for (i = 0; i < nb_imports; i++)
     {
         if (dll_imports[i]->delay) continue;
         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
-        {
-            fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n",
-                     dll_imports[i]->imports[j] );
-            fprintf( outfile, "    \"\\t.globl " PREFIX "%s\\n\"\n",
-                     dll_imports[i]->imports[j] );
-
-
-
-
-            fprintf( outfile, "    \"" PREFIX "%s:\\n\\t", dll_imports[i]->imports[j] );
-
-#if defined(__i386__)
-            if (strstr( dll_imports[i]->imports[j], "__wine_call_from_16" ))
-                fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
-            else
-                fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
-#elif defined(__sparc__)
-            if ( !UsePIC )
-            {
-                fprintf( outfile, "sethi %%hi(imports+%d), %%g1\\n\\t", pos );
-                fprintf( outfile, "ld [%%g1+%%lo(imports+%d)], %%g1\\n\\t", pos );
-                fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
-            }
-            else
-            {
-                /* Hmpf.  Stupid sparc assembler always interprets global variable
-                   names as GOT offsets, so we have to do it the long way ... */
-                fprintf( outfile, "save %%sp, -96, %%sp\\n" );
-                fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
-                fprintf( outfile, "1:\\tsethi %%hi(imports+%d-0b), %%g1\\n\\t", pos );
-                fprintf( outfile, "or %%g1, %%lo(imports+%d-0b), %%g1\\n\\t", pos );
-                fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
-                fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
-            }
-#else
-#error You need to define import thunks for your architecture!
-#endif
-            fprintf( outfile, "\"\n" );
-        }
+            output_asm_import_thunk( outfile, dll_imports[i]->imports[j], 
+                                              "imports", pos );
         pos += 4;
     }
-    fprintf( outfile, "\".previous\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
+    output_asm_import_thunk_epilog( outfile );
 
  done:
     return nb_imm;
@@ -559,26 +521,7 @@
     fprintf( outfile, "    return 0; /* shouldn't go here */\n" );
     fprintf( outfile, "  }\n}\n\n" );
 
-    fprintf( outfile, "#ifndef __GNUC__\n" );
-    fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
-    fprintf( outfile, "#endif\n" );
-
-    fprintf( outfile, "asm(\".align 8\\n\"\n" );
-    fprintf( outfile, "    \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
-    fprintf( outfile, "    \"" PREFIX "__wine_delay_load_asm:\\n\"\n" );
-#if defined(__i386__)
-    fprintf( outfile, "    \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
-    fprintf( outfile, "    \"\\tcall __wine_delay_load\\n\"\n" );
-    fprintf( outfile, "    \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
-#elif defined(__sparc__)
-    fprintf( outfile, "    \"\\tsave %%sp, -96, %%sp\\n\"\n" );
-    fprintf( outfile, "    \"\\tcall __wine_delay_load\\n\"\n" );
-    fprintf( outfile, "    \"\\tmov %%g1, %%o0\\n\"\n" );
-    fprintf( outfile, "    \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
-#else
-#error You need to defined delayed import thunks for your architecture!
-#endif
-
+    output_asm_delayed_import_thunk_prolog( outfile, "__wine_delay_load" );
     for (i = idx = 0; i < nb_imports; i++)
     {
         if (!dll_imports[i]->delay) continue;
@@ -586,67 +529,22 @@
         {
             char buffer[128];
             sprintf( buffer, "__wine_delay_imp_%d_%s", i, dll_imports[i]->imports[j]);
-            fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
-            fprintf( outfile, "    \"" PREFIX "%s:\\n\"\n", buffer );
-#if defined(__i386__)
-            fprintf( outfile, "    \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
-            fprintf( outfile, "    \"\\tjmp __wine_delay_load_asm\\n\"\n" );
-#elif defined(__sparc__)
-            fprintf( outfile, "    \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
-            fprintf( outfile, "    \"\\tb,a __wine_delay_load_asm\\n\"\n" );
-#else
-#error You need to defined delayed import thunks for your architecture!
-#endif
+            output_asm_delayed_import_thunk( outfile, buffer, (idx << 16) | j );
         }
         idx++;
     }
+    output_asm_delayed_import_thunk_epilog( outfile );
 
-    fprintf( outfile, "\n    \".data\\n\\t.align 8\\n\"\n" );
+    output_asm_import_thunk_prolog( outfile );
     pos = nb_delayed * 32;
     for (i = 0; i < nb_imports; i++)
     {
         if (!dll_imports[i]->delay) continue;
         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
-        {
-            fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n",
-                     dll_imports[i]->imports[j] );
-            fprintf( outfile, "    \"\\t.globl " PREFIX "%s\\n\"\n",
-                     dll_imports[i]->imports[j] );
-            fprintf( outfile, "    \"" PREFIX "%s:\\n\\t", dll_imports[i]->imports[j] );
-#if defined(__i386__)
-            if (strstr( dll_imports[i]->imports[j], "__wine_call_from_16" ))
-                fprintf( outfile, ".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n", pos );
-            else
-                fprintf( outfile, "jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
-#elif defined(__sparc__)
-            if ( !UsePIC )
-            {
-                fprintf( outfile, "sethi %%hi(delay_imports+%d), %%g1\\n\\t", pos );
-                fprintf( outfile, "ld [%%g1+%%lo(delay_imports+%d)], %%g1\\n\\t", pos );
-                fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
-            }
-            else
-            {
-                /* Hmpf.  Stupid sparc assembler always interprets global variable
-                   names as GOT offsets, so we have to do it the long way ... */
-                fprintf( outfile, "save %%sp, -96, %%sp\\n" );
-                fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
-                fprintf( outfile, "1:\\tsethi %%hi(delay_imports+%d-0b), %%g1\\n\\t", pos );
-                fprintf( outfile, "or %%g1, %%lo(delay_imports+%d-0b), %%g1\\n\\t", pos );
-                fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
-                fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
-            }
-#else
-#error You need to define import thunks for your architecture!
-#endif
-            fprintf( outfile, "\"\n" );
-        }
+            output_asm_import_thunk( outfile, dll_imports[i]->imports[j], 
+                                              "delay_imports", pos );
     }
-    fprintf( outfile, "\".previous\");\n" );
-    fprintf( outfile, "#ifndef __GNUC__\n" );
-    fprintf( outfile, "}\n" );
-    fprintf( outfile, "#endif\n" );
-    fprintf( outfile, "\n" );
+    output_asm_import_thunk_epilog( outfile );
 
  done:
     return nb_delayed;
diff -urN wine-cvs/tools/winebuild/spec16.c wine-uw/tools/winebuild/spec16.c
--- wine-cvs/tools/winebuild/spec16.c	Wed Jan  3 22:51:34 2001
+++ wine-uw/tools/winebuild/spec16.c	Wed Jan 31 01:52:09 2001
@@ -560,6 +560,7 @@
     int i, nFuncs, nTypes;
     int code_offset, data_offset, module_size, res_size;
     unsigned char *data;
+    char buffer[256];
 #ifdef __i386__
     unsigned short code_selector = __get_cs();
 #endif
@@ -787,26 +788,8 @@
 
     /* Output the DLL constructor */
 
-    fprintf( outfile, "#ifndef __GNUC__\n" );
-    fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
-    fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
-
-#if defined(__i386__)
-    fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
-    fprintf( outfile, "    \"\\tcall " PREFIX "__wine_spec_%s_init\\n\"\n", DLLName );
-    fprintf( outfile, "    \"\\t.previous\\n\");\n" );
-#elif defined(__sparc__)
-    fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
-    fprintf( outfile, "    \"\\tcall " PREFIX "__wine_spec_%s_init\\n\"\n", DLLName );
-    fprintf( outfile, "    \"\\tnop\\n\"\n" );
-    fprintf( outfile, "    \"\\t.previous\\n\");\n" );
-#else
-#error You need to define the DLL constructor for your architecture
-#endif
-
-    fprintf( outfile, "#ifndef __GNUC__\n" );
-    fprintf( outfile, "}\n" );
-    fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
+    sprintf( buffer, "__wine_spec_%s_init", DLLName );
+    output_asm_constructor( outfile, buffer );
 
     fprintf( outfile,
              "void __wine_spec_%s_init(void)\n"
diff -urN wine-cvs/tools/winebuild/spec32.c wine-uw/tools/winebuild/spec32.c
--- wine-cvs/tools/winebuild/spec32.c	Wed Jan  3 22:51:34 2001
+++ wine-uw/tools/winebuild/spec32.c	Wed Jan 31 01:52:09 2001
@@ -425,6 +425,7 @@
     int nr_exports, nr_imports, nr_resources, nr_debug;
     int characteristics, subsystem;
     DWORD page_size;
+    char buffer[256];
 
 #ifdef HAVE_GETPAGESIZE
     page_size = getpagesize();
@@ -667,39 +668,14 @@
 
     /* Output the DLL constructor */
 
-    fprintf( outfile, "#ifndef __GNUC__\n" );
-    fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
-    fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
-
-#if defined(__i386__)
-    fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
-    fprintf( outfile, "    \"\\tcall " PREFIX "__wine_spec_%s_init\\n\"\n", DLLName );
-    fprintf( outfile, "    \"\\t.previous\\n\");\n" );
-    if (nr_debug)
-    {
-        fprintf( outfile, "asm(\"\\t.section\t.fini ,\\\"ax\\\"\\n\"\n" );
-        fprintf( outfile, "    \"\\tcall " PREFIX "__wine_spec_%s_fini\\n\"\n", DLLName );
-        fprintf( outfile, "    \"\\t.previous\\n\");\n" );
-    }
-#elif defined(__sparc__)
-    fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
-    fprintf( outfile, "    \"\\tcall " PREFIX "__wine_spec_%s_init\\n\"\n", DLLName );
-    fprintf( outfile, "    \"\\tnop\\n\"\n" );
-    fprintf( outfile, "    \"\\t.previous\\n\");\n" );
-    if (nr_debug)
+    sprintf( buffer, "__wine_spec_%s_init", DLLName );
+    output_asm_constructor( outfile, buffer );
+
+    if ( nr_debug )
     {
-        fprintf( outfile, "asm(\"\\t.section\t.fini ,\\\"ax\\\"\\n\"\n" );
-        fprintf( outfile, "    \"\\tcall " PREFIX "__wine_spec_%s_fini\\n\"\n", DLLName );
-        fprintf( outfile, "    \"\\tnop\\n\"\n" );
-        fprintf( outfile, "    \"\\t.previous\\n\");\n" );
+        sprintf( buffer, "__wine_spec_%s_fini", DLLName );
+        output_asm_destructor( outfile, buffer );
     }
-#else
-#error You need to define the DLL constructor for your architecture
-#endif
-
-    fprintf( outfile, "#ifndef __GNUC__\n" );
-    fprintf( outfile, "}\n" );
-    fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
 
     fprintf( outfile,
              "void __wine_spec_%s_init(void)\n"
diff -urN wine-cvs/tools/winebuild/sysdeps.c wine-uw/tools/winebuild/sysdeps.c
--- wine-cvs/tools/winebuild/sysdeps.c	Thu Jan  1 01:00:00 1970
+++ wine-uw/tools/winebuild/sysdeps.c	Wed Jan 31 01:59:17 2001
@@ -0,0 +1,188 @@
+/*
+ * Architecture specific assembly code generation
+ *
+ * Copyright 2001 Ulrich Weigand
+ */
+
+#include <string.h>
+#include "build.h"
+#include "winnt.h"
+
+static int dummy_count = 0;
+
+
+/*
+ * DLL constructor
+ */
+
+void output_asm_constructor( FILE *outfile, char *func )
+{
+    fprintf( outfile, "#ifndef __GNUC__\n" );
+    fprintf( outfile, "static void __asm__dummy_%d(void) {\n", dummy_count++ );
+    fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
+
+#if defined(__i386__)
+    fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
+    fprintf( outfile, "    \"\\tcall " PREFIX "%s\\n\"\n", func );
+    fprintf( outfile, "    \"\\t.previous\\n\");\n" );
+#elif defined(__sparc__)
+    fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
+    fprintf( outfile, "    \"\\tcall " PREFIX "%s\\n\"\n", func );
+    fprintf( outfile, "    \"\\tnop\\n\"\n" );
+    fprintf( outfile, "    \"\\t.previous\\n\");\n" );
+#else
+#error You need to define the DLL constructor for your architecture
+#endif
+
+    fprintf( outfile, "#ifndef __GNUC__\n" );
+    fprintf( outfile, "}\n" );
+    fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
+}
+
+
+/*
+ * DLL destructor
+ */
+
+void output_asm_destructor( FILE *outfile, char *func )
+{
+    fprintf( outfile, "#ifndef __GNUC__\n" );
+    fprintf( outfile, "static void __asm__dummy_%d(void) {\n", dummy_count++ );
+    fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
+
+#if defined(__i386__)
+    fprintf( outfile, "asm(\"\\t.section\t.fini ,\\\"ax\\\"\\n\"\n" );
+    fprintf( outfile, "    \"\\tcall " PREFIX "%s\\n\"\n", func );
+    fprintf( outfile, "    \"\\t.previous\\n\");\n" );
+#elif defined(__sparc__)
+    fprintf( outfile, "asm(\"\\t.section\t.fini ,\\\"ax\\\"\\n\"\n" );
+    fprintf( outfile, "    \"\\tcall " PREFIX "%s\\n\"\n", func );
+    fprintf( outfile, "    \"\\tnop\\n\"\n" );
+    fprintf( outfile, "    \"\\t.previous\\n\");\n" );
+#else
+#error You need to define the DLL destructor for your architecture
+#endif
+
+    fprintf( outfile, "#ifndef __GNUC__\n" );
+    fprintf( outfile, "}\n" );
+    fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
+}
+
+
+/*
+ * Import thunks
+ */
+
+void output_asm_import_thunk_prolog( FILE *outfile )
+{
+    fprintf( outfile, "#ifndef __GNUC__\n" );
+    fprintf( outfile, "static void __asm__dummy_%d(void) {\n", dummy_count++ );
+    fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
+
+    fprintf( outfile, "asm(\".data\\n\\t.align 8\\n\"\n" );
+}
+
+void output_asm_import_thunk( FILE *outfile, char *func, char *base, int pos )
+{
+    fprintf( outfile, "    \"\\t" __ASM_FUNC("__wine_dllimport_%s_%s") "\\n\"\n", DLLName, func );
+    fprintf( outfile, "    \"" PREFIX "__wine_dllimport_%s_%s:\\n\"\n", DLLName, func );
+    fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", func );
+    fprintf( outfile, "    \"\\t.globl " PREFIX "%s\\n\"\n", func );
+    fprintf( outfile, "    \"" PREFIX "%s:\\n\\t", func );
+ 
+#if defined(__i386__)
+    if (strstr( func, "__wine_call_from_16" ))
+        fprintf( outfile, ".byte 0x2e\\n\\tjmp *(%s+%d)\\n\\tnop\\n", base, pos );
+    else
+        fprintf( outfile, "jmp *(%s+%d)\\n\\tmovl %%esi,%%esi\\n", base, pos );
+#elif defined(__sparc__)
+    if ( !UsePIC )
+    {
+        fprintf( outfile, "sethi %%hi(%s+%d), %%g1\\n\\t", base, pos );
+        fprintf( outfile, "ld [%%g1+%%lo(%s+%d)], %%g1\\n\\t", base, pos );
+        fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
+    }
+    else
+    {
+        /* Hmpf.  Stupid sparc assembler always interprets global variable
+           names as GOT offsets, so we have to do it the long way ... */
+        fprintf( outfile, "save %%sp, -96, %%sp\\n" );
+        fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
+        fprintf( outfile, "1:\\tsethi %%hi(%s+%d-0b), %%g1\\n\\t", base, pos );
+        fprintf( outfile, "or %%g1, %%lo(%s+%d-0b), %%g1\\n\\t", base, pos );
+        fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
+        fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
+    }
+#else
+#error You need to define import thunks for your architecture!
+#endif
+    fprintf( outfile, "\"\n" );
+}
+
+void output_asm_import_thunk_epilog( FILE *outfile )
+{
+    fprintf( outfile, "\".previous\");\n" );
+
+    fprintf( outfile, "#ifndef __GNUC__\n" );
+    fprintf( outfile, "}\n" );
+    fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
+}
+
+
+/*
+ * Delayed import thunks
+ */
+
+static char *delayed_import_glue = NULL;
+
+void output_asm_delayed_import_thunk_prolog( FILE *outfile, char *glue )
+{
+    fprintf( outfile, "#ifndef __GNUC__\n" );
+    fprintf( outfile, "static void __asm__dummy_%d(void) {\n", dummy_count++ );
+    fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
+
+    fprintf( outfile, "asm(\".align 8\\n\"\n" );
+
+    fprintf( outfile, "    \"\\t" __ASM_FUNC("%s_asm") "\\n\"\n", glue );
+    fprintf( outfile, "    \"" PREFIX "%s_asm:\\n\"\n", glue );
+#if defined(__i386__)
+    fprintf( outfile, "    \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
+    fprintf( outfile, "    \"\\tcall %s\\n\"\n", glue );
+    fprintf( outfile, "    \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
+#elif defined(__sparc__)
+    fprintf( outfile, "    \"\\tsave %%sp, -96, %%sp\\n\"\n" );
+    fprintf( outfile, "    \"\\tcall %s\\n\"\n", glue );
+    fprintf( outfile, "    \"\\tmov %%g1, %%o0\\n\"\n" );
+    fprintf( outfile, "    \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
+#else
+#error You need to defined delayed import thunks for your architecture!
+#endif
+
+    delayed_import_glue = glue;
+}
+
+void output_asm_delayed_import_thunk( FILE *outfile, char *func, int token )
+{
+    fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", func );
+    fprintf( outfile, "    \"" PREFIX "%s:\\n\"\n", func );
+#if defined(__i386__)
+    fprintf( outfile, "    \"\\tmovl $%d, %%eax\\n\"\n", token );
+    fprintf( outfile, "    \"\\tjmp %s_asm\\n\"\n", delayed_import_glue );
+#elif defined(__sparc__)
+    fprintf( outfile, "    \"\\tset %d, %%g1\\n\"\n", token );
+    fprintf( outfile, "    \"\\tb,a %s_asm\\n\"\n", delayed_import_glue );
+#else
+#error You need to defined delayed import thunks for your architecture!
+#endif
+}
+
+void output_asm_delayed_import_thunk_epilog( FILE *outfile )
+{
+    delayed_import_glue = NULL;
+    fprintf( outfile, "\".previous\");\n" );
+
+    fprintf( outfile, "#ifndef __GNUC__\n" );
+    fprintf( outfile, "}\n" );
+    fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
+}
+
-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic