Subject: Re: export data from a b18 DLL? (stdout bug?)
From: [email-masked] (Gunther Ebert)

30 Jul 1997 08:30:56 -0700
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
References: <Pine.SOL.3.91.970728164421.7112A-100000@supersun>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: Mozilla 2.01Gold (WinNT; I)
Original-To: Ron Kulper <[email-masked]>
Original-Cc: [email-masked]
Original-Sender: [email-masked]

Ron Kulper wrote:
> 
> Is it possible to export data (as opposed to a function) from a dll?

Yes, in general it is but it is somewhat difficult. If you link a dll with
exported data to a program you will not get a pointer to the actual data
but to a jump instruction (the linker assumes that the pointer is to a function).
An example:

/* dll code fragment */
char *some_data = "string from dll";

/* exe code fragment */
extern char *some_data;

void foo() { printf(some_data); } /* fails because some_data isn't valid */

This will run into a SIGSEGV because the some_data pointer is not valid, meaning
it doesn't point to the "string from dll" data but to some jump instructions.
However, ld generates another symbol for every item which is exported by
a dll. The name of the new symbol is the name itself with a preceding "__imp__".
This symbol contains the address of the actual data, use this instead.
The code fragments will change to

/* dll code fragment */
char *some_data = "string from a dll";

/* exe code fragment */
extern char *__imp__some_data;

void foo()  { printf(__imp__some_data); }   /* Ok */

This works for gcc, but this isn't portable at all because it depends on the
naming conventions which are used by the linker to generate the extra symbol.
I know for sure that this doesn't work with MSVC.
Anyway, I would suggest not exporting data directly. Write data access functions
and export them instead of the actual data.

> For instance, can I access a malloc'ed structure located in one dll
> from a different dll by exporting a structure pointer to the allocated
> space? I know this can be done in MSVC++, but when I try it using
> cygwin32, I receive a SIGSEGV when attempting to reference the pointer.
> Does this issue have anything to do with the bug described below?
> 
> I recieve a SIGSEGV when attempting to set a FILE * = stdout within a dll.
> Platform is NT4.0SP3 on a pentium with cygwin32 beta 18.

No, this is a completely different problem. The stdout pointer isn't valid
because it isn't initialized when your dll has been loaded. You cannot
build a dll which uses cygwin functions which need initializing. This is 
because there isn't any dllcrt0.o module which contains the correct startup code
for a dll (i.e. the appropriate dll_entry function) which uses cygwin.dll.

> 
> The problem can be recreated with the 5 small files below.
> "dbpcc8.sh stdout" will create stdout.dll
> gcc -g main2.c creates a.exe which tries to load C:\tmp\stdout.dll and
>  call stdout_dll().
> init.cc and fixup.c are the standard files included for completeness.
> The SIGSEGV occurs at line 7 of stdout.c "fp=stdout".
> 
> Any help resolving this problem is appreciated.
> 
> Thanks,
> Ron Kulper
> [email-masked]
> 
> stdout.c
> --------------------------------------------------------------------------------
> #include <stdio.h>
> 
> void
> stdout_dll()
> {
>         FILE *fp;
>         fp=stdout;
>         fprintf(fp,"hello\n");
> }
> main()
> {
>         stdout_dll();
> }
> --------------------------------------------------------------------------------
> 
> main2.c
> --------------------------------------------------------------------------------
> #include <stdio.h>
> #include "windows.h"
> 
> typedef void (*vfp)();
> 
> main()
> {
>         vfp dbp_init_func;
>         HINSTANCE lib_handle = LoadLibrary("c:\\tmp\\stdout.dll");
>         if(lib_handle == NULL)
>         {
>                 perror("Error loading DLL");
>                 exit(0);
>         }
> 
>         dbp_init_func = (vfp) GetProcAddress(lib_handle, "stdout_dll");
>         if(dbp_init_func == NULL)
>         {
>                 perror("Error loading func dbp_init_report");
>                 exit(0);
>         }
> 
>         dbp_init_func();
> 
>         FreeLibrary(lib_handle);
> }
> --------------------------------------------------------------------------------
> 
> dbpcc8.sh
> --------------------------------------------------------------------------------
> export LIBPATH="C:/gnuwin32/b18/H-i386-cygwin32/i386-cygwin32/lib"
> echo EXPORTS > $1.def
> gcc -DCYGWIN32 -g -c  $1.c
> nm $1.o | grep '^........ [T] _'|sed 's/[^_]*_//' >> $1.def
> ld --base-file $1.base --dll -o $1.dll $1.o  init.o fixup.o $LIBPATH/libcygwin.a $LIBPATH/libkernel32.a -e _dll_entry@12
> dlltool --as=as --dllname $1.dll --def $1.def --base-file $1.base --output-exp $1.exp
> ld --base-file $1.base $1.exp --dll -o $1.dll $1.o  init.o fixup.o $LIBPATH/libcygwin.a $LIBPATH/libkernel32.a -e _dll_entry@12
> dlltool --as=as --dllname $1.dll --def $1.def --base-file $1.base --output-exp $1.exp
> ld $1.exp --dll -o $1.dll $1.o  init.o fixup.o $LIBPATH/libcygwin.a $LIBPATH/libkernel32.a -e _dll_entry@12
> dlltool --as=as --dllname $1.dll --def $1.def --output-lib $1.a
> --------------------------------------------------------------------------------
> 
> init.cc
> --------------------------------------------------------------------------------
> /* #include GNU version 2 copyright */
> #include <windows.h>
> extern "C"
> {
>         int WINAPI dll_entry (HANDLE h, DWORD reason, void *ptr);
> };
> 
> int WINAPI dll_entry (HANDLE, DWORD reason, void *)
> {
>         switch(reason)
>         {
>                 case DLL_PROCESS_ATTACH:
>                         break;
>                 case DLL_PROCESS_DETACH:
>                         break;
>                 case DLL_THREAD_ATTACH:
>                         break;
>                 case DLL_THREAD_DETACH:
>                         break;
>         }
>         return 1;
> }
> --------------------------------------------------------------------------------
> 
> fixup.c
> --------------------------------------------------------------------------------
> asm(".section .idata$3\n" ".long 0,0,0,0, 0,0,0,0");
> --------------------------------------------------------------------------------
> 
> -
> For help on using this list (especially unsubscribing), send a message to
> "[email-masked]" with one line of text: "help".

-- 

Gunther Ebert
iXOS Anwendungs-Software GmbH
Angerstrasse 40-42
D-04177 Leipzig

Phone : +49 341 48503-0
Fax   : +49 341 48503-99
E-mail: mailto:[email-masked]
www   : http://www.ixos-leipzig.de
-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".