From 163e294eb7ccd49292df436d7b0abdded441fe05 Mon Sep 17 00:00:00 2001 From: janwas Date: Thu, 7 Jun 2007 19:15:45 +0000 Subject: [PATCH] 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. --- source/lib/sysdep/win/winit.cpp | 13 ++++--- source/lib/sysdep/win/winit.h | 50 ++++++++++++------------- source/lib/sysdep/win/wposix/wposix.cpp | 6 +-- source/lib/sysdep/win/wstartup.cpp | 10 +++-- source/lib/sysdep/win/wstartup.h | 29 ++++++++------ 5 files changed, 60 insertions(+), 48 deletions(-) diff --git a/source/lib/sysdep/win/winit.cpp b/source/lib/sysdep/win/winit.cpp index eb4454af1c..5904a4fcfa 100644 --- a/source/lib/sysdep/win/winit.cpp +++ b/source/lib/sysdep/win/winit.cpp @@ -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. diff --git a/source/lib/sysdep/win/winit.h b/source/lib/sysdep/win/winit.h index ec637d07e9..535768bd90 100644 --- a/source/lib/sysdep/win/winit.h +++ b/source/lib/sysdep/win/winit.h @@ -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)) //----------------------------------------------------------------------------- diff --git a/source/lib/sysdep/win/wposix/wposix.cpp b/source/lib/sysdep/win/wposix/wposix.cpp index da4f1c4cd3..85e28ec6ce 100644 --- a/source/lib/sysdep/win/wposix/wposix.cpp +++ b/source/lib/sysdep/win/wposix/wposix.cpp @@ -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) { diff --git a/source/lib/sysdep/win/wstartup.cpp b/source/lib/sysdep/win/wstartup.cpp index 71112a2e7a..5ccb1a338f 100644 --- a/source/lib/sysdep/win/wstartup.cpp +++ b/source/lib/sysdep/win/wstartup.cpp @@ -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") diff --git a/source/lib/sysdep/win/wstartup.h b/source/lib/sysdep/win/wstartup.h index 7dccec6571..57e8ac8494 100644 --- a/source/lib/sysdep/win/wstartup.h +++ b/source/lib/sysdep/win/wstartup.h @@ -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.)