1
0
forked from 0ad/0ad

winit: section names should start with .

wposix: raise exception instead of quietly exiting
wstartup: add note on what needs to be done on vc7

This was SVN commit r5148.
This commit is contained in:
janwas 2007-06-07 19:15:45 +00:00
parent 914e5f7c2f
commit 163e294eb7
5 changed files with 60 additions and 48 deletions

View File

@ -15,7 +15,10 @@
// see http://blogs.msdn.com/larryosterman/archive/2004/09/27/234840.aspx
// for discussion of a similar mechanism.
//
// note: this module is kept distinct from the CRT's init/shutdown mechanism
// to insulate against changes there. another advantage is that callbacks
// can return LibError instead of int.
typedef LibError (*PfnLibErrorVoid)(void);
@ -25,10 +28,10 @@ typedef LibError (*PfnLibErrorVoid)(void);
// (zero, because CallFunctionPointers has to ignore entries =0 anyway).
// - ASCII '$' and 'Z' come before resp. after '0'..'9', so use that to
// bound the section names.
__declspec(allocate("WINIT$I$")) PfnLibErrorVoid initBegin = 0;
__declspec(allocate("WINIT$IZ")) PfnLibErrorVoid initEnd = 0;
__declspec(allocate("WINIT$S$")) PfnLibErrorVoid shutdownBegin = 0;
__declspec(allocate("WINIT$SZ")) PfnLibErrorVoid shutdownEnd = 0;
__declspec(allocate(".WINIT$I$")) PfnLibErrorVoid initBegin = 0;
__declspec(allocate(".WINIT$IZ")) PfnLibErrorVoid initEnd = 0;
__declspec(allocate(".WINIT$S$")) PfnLibErrorVoid shutdownBegin = 0;
__declspec(allocate(".WINIT$SZ")) PfnLibErrorVoid shutdownEnd = 0;
// note: #pragma comment(linker, "/include") is not necessary since
// these are referenced below.

View File

@ -69,25 +69,25 @@ Several methods of module init are possible: (see Large Scale C++ Design)
//-----------------------------------------------------------------------------
// section declarations
// section names are of the format "WINIT${type}{group}".
// section names are of the format ".WINIT${type}{group}".
// {type} is I for initialization- or S for shutdown functions.
// {group} is [0, 9] - see below.
// note: __declspec(allocate) requires declaring segments in advance via
// #pragma section.
#pragma section("WINIT$I$", read)
#pragma section("WINIT$I0", read)
#pragma section("WINIT$I1", read)
#pragma section("WINIT$I2", read)
#pragma section("WINIT$I6", read)
#pragma section("WINIT$I7", read)
#pragma section("WINIT$IZ", read)
#pragma section("WINIT$S$", read)
#pragma section("WINIT$S0", read)
#pragma section("WINIT$S1", read)
#pragma section("WINIT$S6", read)
#pragma section("WINIT$S7", read)
#pragma section("WINIT$S8", read)
#pragma section("WINIT$SZ", read)
#pragma section(".WINIT$I$", read)
#pragma section(".WINIT$I0", read)
#pragma section(".WINIT$I1", read)
#pragma section(".WINIT$I2", read)
#pragma section(".WINIT$I6", read)
#pragma section(".WINIT$I7", read)
#pragma section(".WINIT$IZ", read)
#pragma section(".WINIT$S$", read)
#pragma section(".WINIT$S0", read)
#pragma section(".WINIT$S1", read)
#pragma section(".WINIT$S6", read)
#pragma section(".WINIT$S7", read)
#pragma section(".WINIT$S8", read)
#pragma section(".WINIT$SZ", read)
#pragma comment(linker, "/merge:WINIT=.rdata")
@ -117,29 +117,29 @@ Several methods of module init are possible: (see Large Scale C++ Design)
// very early init; must not fail, since error handling code *crashes*
// if called before these have completed.
#define WINIT_REGISTER_CRITICAL_INIT(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$I0")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_CRITICAL_INIT(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$I0")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
// meant for modules with dependents but whose init is complicated and may
// raise error/warning messages (=> can't go in WINIT_REGISTER_CRITICAL_INIT)
#define WINIT_REGISTER_EARLY_INIT(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$I1")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_EARLY_INIT(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$I1")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
// available for dependents of WINIT_REGISTER_EARLY_INIT-modules that
// must still come before WINIT_REGISTER_MAIN_INIT.
#define WINIT_REGISTER_EARLY_INIT2(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$I2")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_EARLY_INIT2(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$I2")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
// most modules will go here unless they are often used or
// have many dependents.
#define WINIT_REGISTER_MAIN_INIT(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$I6")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_MAIN_INIT(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$I6")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
// available for any modules that may need to come after
// WINIT_REGISTER_MAIN_INIT (unlikely)
#define WINIT_REGISTER_LATE_INIT(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$I7")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_LATE_INIT(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$I7")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_EARLY_SHUTDOWN(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$S0")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_EARLY_SHUTDOWN2(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$S1")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_MAIN_SHUTDOWN(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$S6")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_LATE_SHUTDOWN(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$S7")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_LATE_SHUTDOWN2(func) static LibError func(void); EXTERN_C __declspec(allocate("WINIT$S8")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_EARLY_SHUTDOWN(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$S0")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_EARLY_SHUTDOWN2(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$S1")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_MAIN_SHUTDOWN(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$S6")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_LATE_SHUTDOWN(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$S7")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
#define WINIT_REGISTER_LATE_SHUTDOWN2(func) static LibError func(void); EXTERN_C __declspec(allocate(".WINIT$S8")) LibError (*p##func)(void) = func; __pragma(comment(linker, "/include:_p"#func))
//-----------------------------------------------------------------------------

View File

@ -43,10 +43,10 @@ long sysconf(int name)
{
// called before InitSysconf => winit/wstartup are broken. this is
// going to cause a hard crash because debug.cpp's error reporting
// code requires the page size to be known. we'll exit with a unique
// value to hopefully help track down the problem.
// code requires the page size to be known. we'll raise an exception
// with a unique value so that this issue is immediately noticed.
if(!pageSize)
exit(239786); // 0x3A8AA
RaiseException(0xFA57FA57, 0, 0, 0);
switch(name)
{

View File

@ -85,13 +85,15 @@ application, not the CRT DLL.)
*/
EXTERN_C void InitAndRegisterShutdown()
// reference: see http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945__1
EXTERN_C void wstartup_InitAndRegisterShutdown()
{
winit_CallInitFunctions();
atexit(winit_CallShutdownFunctions);
}
#pragma data_seg(".CRT$XCB")
EXTERN_C void(*pInitAndRegisterShutdown)() = InitAndRegisterShutdown;
#pragma comment(linker, "/include:_pInitAndRegisterShutdown")
#pragma data_seg(".CRT$XIV") // after C init, after XIU ("User") block
EXTERN_C void(*wstartup_pInitAndRegisterShutdown)() = wstartup_InitAndRegisterShutdown;
#pragma data_seg()
#pragma comment(linker, "/include:_wstartup_pInitAndRegisterShutdown")

View File

@ -8,15 +8,22 @@
// license: GPL; see lib/license.txt
// linking with this component automatically causes winit's functions to
// be called at the appropriate times.
// linking with this component should automatically arrange for winit's
// functions to be called at the appropriate times.
//
// the current implementation manages to trigger winit initialization
// in-between calls to CRT init and the static C++ ctors. that means
// wpthread etc. APIs are safe to use from ctors, and winit initializers
// are allowed to use non-stateless CRT functions such as atexit.
#ifndef INCLUDED_WSTARTUP
#define INCLUDED_WSTARTUP
#endif // #ifndef INCLUDED_WSTARTUP
// the current implementation manages to trigger initialization in-between
// calls to CRT init and the static C++ ctors. that means wpthread etc.
// APIs are safe to use from ctors, and winit initializers are allowed
// to use non-stateless CRT functions such as atexit.
//
// IMPORTANT NOTE: if compiling this into a static lib and not using VC8's
// "use library dependency inputs" linking mode, the object file will be
// discarded because it does not contain any symbols that resolve another
// module's undefined external(s). for a discussion of this topic, see:
// http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=144087
// workaround: in the main EXE project, reference a symbol from this module,
// thus forcing it to be linked in. example:
// #pragma comment(linker, "/include:_wstartup_InitAndRegisterShutdown")
// (doing that in this module isn't sufficient, because it would only
// affect the librarian and its generation of the static lib that holds
// this file. instead, the process of linking the main EXE must be fixed.)