* pseudo-reloc.c (do_pseudo_reloc): Make static. * pseudo-reloc-list.c: New file. * crt1.c (_pei386_runtime_relocator): Declare. (__mingw_CRTStartup): Call it. * dllcrt1.c (_pei386_runtime_relocator): Declare. (DllMainCRTStartup): Call it. * Makefile.in: Add pseudo-reloc.o pseude-reloc-list.o to libmingw32.a. 2003-01-01 Egor Duda <deo@logos-m.ru> * pseudo-reloc.c: New file.
		
			
				
	
	
		
			202 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * dllcrt1.c
 | 
						|
 *
 | 
						|
 * Initialization code for DLLs.
 | 
						|
 *
 | 
						|
 * This file is part of the Mingw32 package.
 | 
						|
 *
 | 
						|
 * Contributors:
 | 
						|
 *  Created by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
 | 
						|
 *  DLL support adapted from Gunther Ebert <gunther.ebert@ixos-leipzig.de>
 | 
						|
 *  Maintained by Mumit Khan <khan@xraylith.wisc.EDU>
 | 
						|
 *
 | 
						|
 *  THIS SOFTWARE IS NOT COPYRIGHTED
 | 
						|
 *
 | 
						|
 *  This source code is offered for use in the public domain. You may
 | 
						|
 *  use, modify or distribute it freely.
 | 
						|
 *
 | 
						|
 *  This code is distributed in the hope that it will be useful but
 | 
						|
 *  WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
 | 
						|
 *  DISCLAMED. This includes but is not limited to warrenties of
 | 
						|
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | 
						|
 *
 | 
						|
 * $Revision$
 | 
						|
 * $Author$
 | 
						|
 * $Date$
 | 
						|
 * 
 | 
						|
 */
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <io.h>
 | 
						|
#include <process.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <windows.h>
 | 
						|
 | 
						|
/* Unlike normal crt1, I don't initialize the FPU, because the process
 | 
						|
 * should have done that already. I also don't set the file handle modes,
 | 
						|
 * because that would be rude. */
 | 
						|
 | 
						|
#ifdef	__GNUC__
 | 
						|
extern void __main ();
 | 
						|
extern void __do_global_dtors ();
 | 
						|
#endif
 | 
						|
 | 
						|
typedef void (* p_atexit_fn )(void);
 | 
						|
static p_atexit_fn* first_atexit;
 | 
						|
static p_atexit_fn* next_atexit;
 | 
						|
 | 
						|
static void
 | 
						|
__dll_exit (void);
 | 
						|
 | 
						|
/* This  is based on the function in the Wine project's exit.c */
 | 
						|
p_atexit_fn __dllonexit (p_atexit_fn, p_atexit_fn**, p_atexit_fn**);
 | 
						|
 | 
						|
 | 
						|
extern BOOL WINAPI DllMain (HANDLE, DWORD, LPVOID);
 | 
						|
 | 
						|
extern void _pei386_runtime_relocator (void);
 | 
						|
 | 
						|
BOOL WINAPI
 | 
						|
DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
 | 
						|
{
 | 
						|
  BOOL bRet;
 | 
						|
 | 
						|
  if (dwReason == DLL_PROCESS_ATTACH)
 | 
						|
    {
 | 
						|
 | 
						|
#ifdef DEBUG
 | 
						|
      printf ("%s: DLL_PROCESS_ATTACH (%d)\n", __FUNCTION__);
 | 
						|
#endif
 | 
						|
 | 
						|
      /* Initialize private atexit table for this dll.
 | 
						|
	 32 is min size required by ANSI */
 | 
						|
 | 
						|
      first_atexit = (p_atexit_fn*) malloc (32 * sizeof (p_atexit_fn));
 | 
						|
      if (first_atexit == NULL ) /* can't allocate memory */
 | 
						|
	{
 | 
						|
	  errno=ENOMEM;
 | 
						|
	  return FALSE;
 | 
						|
	}
 | 
						|
      *first_atexit =  NULL;
 | 
						|
      next_atexit = first_atexit;
 | 
						|
 | 
						|
      /* Adust references to dllimported data (from other DLL's)
 | 
						|
	 that have non-zero offsets.  */ 
 | 
						|
      _pei386_runtime_relocator ();
 | 
						|
 | 
						|
#ifdef	__GNUC__
 | 
						|
      /* From libgcc.a, __main calls global class constructors,
 | 
						|
	 __do_global_ctors, which registers __do_global_dtors
 | 
						|
	 as the first entry of the private atexit table we
 | 
						|
	 have just initialised  */
 | 
						|
      __main ();
 | 
						|
      	
 | 
						|
#endif
 | 
						|
   }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Call the user-supplied DllMain subroutine.
 | 
						|
   * This has to come after initialization of atexit table and
 | 
						|
   * registration of global constructors.
 | 
						|
   * NOTE: DllMain is optional, so libmingw32.a includes a stub
 | 
						|
   *       which will be used if the user does not supply one.
 | 
						|
   */
 | 
						|
 | 
						|
  bRet = DllMain (hDll, dwReason, lpReserved);
 | 
						|
  /* Handle case where DllMain returns FALSE on attachment attempt.  */ 
 | 
						|
 | 
						|
  if ( (dwReason == DLL_PROCESS_ATTACH) && !bRet)
 | 
						|
    {
 | 
						|
#ifdef DEBUG
 | 
						|
      printf ("%s: DLL_PROCESS_ATTACH failed, cleaning up\n", __FUNCTION__);
 | 
						|
#endif
 | 
						|
 | 
						|
      __dll_exit ();     /* Cleanup now. This will set first_atexit to NULL so we
 | 
						|
			    know we've cleaned up	*/
 | 
						|
    }
 | 
						|
 | 
						|
  if (dwReason == DLL_PROCESS_DETACH)
 | 
						|
    {
 | 
						|
#ifdef DEBUG
 | 
						|
      printf ("%s: DLL_PROCESS_DETACH (%d)\n", __FUNCTION__);
 | 
						|
#endif
 | 
						|
      /* If not attached, return FALSE. Cleanup already done above
 | 
						|
	 if failed attachment attempt. */
 | 
						|
      if  (! first_atexit )
 | 
						|
        bRet = FALSE;
 | 
						|
      else
 | 
						|
	/*
 | 
						|
	 * We used to call __do_global_dtors () here. This is
 | 
						|
	 * no longer necessary since  __do_global_dtors is now
 | 
						|
	 * registered at start (last out) of private atexit table.
 | 
						|
	 */
 | 
						|
	__dll_exit ();
 | 
						|
    }
 | 
						|
  return bRet;
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
void
 | 
						|
__dll_exit(void)
 | 
						|
/* Run LIFO terminators registered in private atexit table */
 | 
						|
{
 | 
						|
  if ( first_atexit )
 | 
						|
    {
 | 
						|
      p_atexit_fn* __last = next_atexit - 1;
 | 
						|
      while ( __last >= first_atexit )
 | 
						|
	{	
 | 
						|
          if ( *__last != NULL )
 | 
						|
	    {
 | 
						|
#ifdef DEBUG
 | 
						|
	      printf ("%s: Calling exit function  0x%x from 0x%x\n",
 | 
						|
		      __FUNCTION__, (unsigned)(*__last),(unsigned)__last);
 | 
						|
#endif
 | 
						|
              (**__last) ();
 | 
						|
	    }
 | 
						|
	  __last--;
 | 
						|
	}
 | 
						|
      free ( first_atexit ) ;
 | 
						|
      first_atexit = NULL ;
 | 
						|
    }
 | 
						|
    /*
 | 
						|
       Make sure output buffers opened by DllMain or 
 | 
						|
       atexit-registered functions are flushed before detaching,
 | 
						|
       otherwise we can have problems with redirected output.
 | 
						|
     */
 | 
						|
    fflush (NULL);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * The atexit exported from msvcrt.dll causes problems in DLLs.
 | 
						|
 * Here, we override the exported version of atexit with one that passes the
 | 
						|
 * private table initialised in DllMainCRTStartup to __dllonexit.
 | 
						|
 * That means we have to hide the mscvrt.dll atexit because the
 | 
						|
 * atexit defined here gets __dllonexit from the same lib. 
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
atexit (p_atexit_fn pfn )
 | 
						|
{
 | 
						|
#ifdef DEBUG
 | 
						|
  printf ("%s: registering exit function  0x%x at 0x%x\n",
 | 
						|
	  __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
 | 
						|
#endif
 | 
						|
  return (__dllonexit (pfn,  &first_atexit, &next_atexit)
 | 
						|
	  == NULL ? -1  : 0 );
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Likewise for non-ANSI function _onexit that may be called by
 | 
						|
 * code in the dll. 
 | 
						|
 */
 | 
						|
 | 
						|
_onexit_t
 | 
						|
_onexit (_onexit_t pfn )
 | 
						|
{
 | 
						|
#ifdef DEBUG
 | 
						|
  printf ("%s: registering exit function  0x%x at 0x%x\n",
 | 
						|
	  __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
 | 
						|
#endif
 | 
						|
  return ((_onexit_t) __dllonexit ((p_atexit_fn)pfn,  &first_atexit, &next_atexit));
 | 
						|
}
 |