Subject: Can't Reference Stderr from a DLL
From: [email-masked] (John Cerney)

12 Mar 1997 09:06:02 -0800
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
Reply-To: John Cerney <[email-masked]>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7Bit
X-Mailer: BeyondMail for Windows/Professional 2.3
Original-To: [email-masked]
X-BeyondMail-Priority: 1
Conversation-ID: <[email-masked]>
X-Receipt-From-Agent: true
Original-Sender: [email-masked]

I've run into problem trying to build a dynamic lib version of perl5.003_25.
I believe I have narrowed it down to a referencing stderr or stdout in a dll. A
simple test case which duplicates the problem is included at the end of this
message.

Specifically, if I build a dll that references stderr inside of it (like a
fputs("test out",stderr) call inside the DLL) the linker complains about
unresolved references:
libcmain.cc:29: undefined reference to `GetModuleHandleA@4'
libcmain.cc:30: undefined reference to `GetCommandLineA@0'
libcmain.cc:30: undefined reference to `WinMain@16'

When I remove the reference to stderr by replacing the fputs call with a simple
printf, the dll builds and runs fine.

Looking at the cygwin.dll source code, it appears that stderr is translated to
_impure_ptr->stderr by the defines inside of the <stdio.h> include. _impure_ptr
is defined in libccrt0.cc inside of cygwin.dll, which also references main().
Does the linker try to resolve all references in an object file, even if you
just refer to one variable that is defined in it?

I have tried building the DLL using the --noinhibit-exec linker option. The dll
is built in this case, but the main.exe executable crashes with a seg fault.

Has anyone here seen this problem before? Does anyone know what is going on?

-John

*********** Simple Test Case *******
*** file foo.c ***
// Test file to check out building DLLs with gnuwin32
//  This uses printf from the std lib

#include <stdio.h>

int
doit (int i)
{

     //printf("In foo.c inside of doit\n");  
     fputs("In foo.c inside of doit\n",stderr);
     return( 4 );
}
*** File init.cc ***
// DLL entry point module
#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;
}
*** File fixup.c ***

/* This is needed to terminate the list of import stuff */
/* Copied from winsup/dcrt0.cc in the cygwin32 source distribution. */
        asm(".section .idata$3\n" ".long 0,0,0,0, 0,0,0,0");
*** File Main.c ***
// Main file to try linking with a DLL under gnuwin32
int
main()
{
        printf("doit(5) returns %d\n", doit(5));
       
}

*** File buildLib ****
#! /bin/sh
# script to build the simple test case DLL and a the main executable that runs
it
#   jc 3/12/97

LIBPATH=/gnuwin32/H-i386-cygwin32/i386-cygwin32/lib

gcc -c foo.c
gcc -c init.cc
gcc -c fixup.c
echo EXPORTS > foo.def
nm foo.o init.o fixup.o | grep '^........ [T] _' | sed 's/[^_]*_//' >> foo.def

# Link DLL.
ld --base-file foo.base --dll -o foo.dll foo.o init.o fixup.o \
 $LIBPATH/libcygwin.a -e _dll_entry@12 --noinhibit-exec
dlltool --as=as --dllname foo.dll --def foo.def --base-file foo.base
--output-exp foo.exp
ld --base-file foo.base foo.exp --dll -o foo.dll foo.o init.o fixup.o \
  $LIBPATH/libcygwin.a -e _dll_entry@12 --noinhibit-exec
dlltool --as=as --dllname foo.dll --def foo.def --base-file foo.base
--output-exp foo.exp
ld foo.exp --dll -o foo.dll foo.o init.o fixup.o\
 $LIBPATH/libcygwin.a -e _dll_entry@12 --noinhibit-exec

# Build the foo.a lib to link to:
dlltool --as=as --dllname foo.dll --def foo.def --output-lib foo.a

# Linking with main
gcc main.c foo.a -o main.exe

-
For help on using this list, send a message to
"[email-masked]" with one line of text: "help".