From 6d6c219ea14c2ec673e841fb4fb0ef99ae57caeb Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Thu, 7 Apr 2005 21:38:55 +0000 Subject: [PATCH] pullup from trunk ticket: 2981 version_fixed: 1.4.1 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-4@17169 dc483132-0cff-0310-8789-dd5450dbe970 --- src/config/ChangeLog | 10 +++++ src/config/lib.in | 12 ++++++ src/config/shlib.conf | 29 +++++++++---- src/include/ChangeLog | 7 ++++ src/include/k5-platform.h | 87 +++++++++++++++++++++++++++++++++++---- 5 files changed, 131 insertions(+), 14 deletions(-) diff --git a/src/config/ChangeLog b/src/config/ChangeLog index ba2c712af..b8221ff92 100644 --- a/src/config/ChangeLog +++ b/src/config/ChangeLog @@ -1,3 +1,13 @@ +2005-03-25 Ken Raeburn + + * lib.in (hpux10.exports): New target, constructed similar to + osf1.exports but with HP-UX 10.x linker options, no initializers, + and "errno" explicitly added to the export list. + * shlib.conf (*-*-hpux*): Combine PICFLAGS setting with + SHLIB_EXPFLAGS and LDCOMBINE setting. Add linker option "-c + hpux10.exports" to LDCOMBINE. Set SHLIB_EXPORT_FILE_DEP to + hpux10.exports. Set use_linker_fini_option. + 2005-02-08 Ken Raeburn * lib.in (config.status): Change target to be in $thisconfigdir diff --git a/src/config/lib.in b/src/config/lib.in index eea4601d5..ef159f528 100644 --- a/src/config/lib.in +++ b/src/config/lib.in @@ -72,6 +72,18 @@ osf1.exports: $(SHLIB_EXPORT_FILE) Makefile done; echo " $$a" >> osf1.tmp; \ mv -f osf1.tmp osf1.exports +hpux10.exports: $(SHLIB_EXPORT_FILE) Makefile + $(RM) hpux10.tmp hpux10.exports + sed "s/^/+e /" < $(SHLIB_EXPORT_FILE) > hpux10.tmp + a=""; \ + for f in . $(LIBFINIFUNC); do \ + if test "$$f" != .; then \ + a="+I $${f}__auxfini $$a"; \ + else :; fi; \ + done; echo "$$a" >> hpux10.tmp + echo "+e errno" >> hpux10.tmp + mv -f hpux10.tmp hpux10.exports + lib$(LIBBASE)$(PFLIBEXT): $(PFOBJLISTS) $(RM) $@ @echo "building profiled $(LIBBASE) library" diff --git a/src/config/shlib.conf b/src/config/shlib.conf index 4d09e84e4..3261b672c 100644 --- a/src/config/shlib.conf +++ b/src/config/shlib.conf @@ -75,27 +75,42 @@ alpha*-dec-osf*) # on the commandline of the linker will determine which path # (compiled-in or SHLIB_PATH) will be searched first. # +# +I initproc routine gets called at load and unload time for +# shl_load calls, but appears to never be called for link-time +# specified libraries. +# +e sym exports symbol and supposedly prevents other symbols +# from being exported, according to the man page, but the +# latter bit doesn't actually seem to work +# -O +dpv should display any routines eliminated as unused, but -b +# apparently turns that off *-*-hpux*) - if test "$krb5_cv_prog_gcc" = yes; then - PICFLAGS=-fPIC - else - PICFLAGS=+z - fi INSTALL_SHLIB='$(INSTALL)' SHLIBEXT=.sl SHLIBVEXT='.$(LIBMAJOR).$(LIBMINOR)' SHLIBSEXT='.$(LIBMAJOR)' RPATH_FLAG='-Wl,+b,' if test "$krb5_cv_prog_gcc" = yes; then + PICFLAGS=-fPIC SHLIB_EXPFLAGS='-Wl,+s -Wl,+b,$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' - LDCOMBINE='gcc -fPIC -shared -Wl,+h,lib$(LIBBASE)$(SHLIBSEXT)' + LDCOMBINE='gcc -fPIC -shared -Wl,+h,lib$(LIBBASE)$(SHLIBSEXT) -Wl,-c,hpux10.exports' else + PICFLAGS=+z SHLIB_EXPFLAGS='+s +b $(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' - LDCOMBINE='ld -b +h lib$(LIBBASE)$(SHLIBSEXT)' + LDCOMBINE='ld -b +h lib$(LIBBASE)$(SHLIBSEXT) -c hpux10.exports' fi CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -Wl,+s $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)' CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' RUN_ENV='SHLIB_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export SHLIB_PATH;' + SHLIB_EXPORT_FILE_DEP=hpux10.exports + # Do *not* set use_linker_init_option=yes here, because in the + # case where the library is specified at program link time, the + # initialization function appears not to get called, only for + # shl_load. But for finalization functions, the shl_load case + # is the one we care about. + # + # Not setting use_linker_init_option here should cause compilation + # failures if the user tries to disable delayed initialization. + use_linker_fini_option=yes ;; mips-sgi-irix6.3) # This is a Kludge; see below diff --git a/src/include/ChangeLog b/src/include/ChangeLog index 29358cafd..7ecb536b7 100644 --- a/src/include/ChangeLog +++ b/src/include/ChangeLog @@ -1,3 +1,10 @@ +2005-03-25 Ken Raeburn + + * k5-platform.h: Expand on init/fini comments some more. + (MAKE_FINI_FUNCTION): Add an HP-UX specific variant that defines + an auxiliary function fitting the signature of HP-UX 10 library + combined initializer/finalizer functions. + 2005-03-04 Ken Raeburn * configure.in: Check return type of gmtime_r, and define diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h index 5c634bfc4..b178622d8 100644 --- a/src/include/k5-platform.h +++ b/src/include/k5-platform.h @@ -44,14 +44,23 @@ At top level, before the functions are defined or even declared: MAKE_INIT_FUNCTION(init_fn); MAKE_FINI_FUNCTION(fini_fn); + Then: int init_fn(void) { ... } void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... } - In code, in the same file: err = CALL_INIT_FUNCTION(init_fn); To trigger or verify the initializer invocation from another file, - an additional function must be created. + a helper function must be created. + + This model handles both the load-time execution (Windows) and + delayed execution (pthread_once) approaches, and should be able to + guarantee in both cases that the init function is run once, in one + thread, before other stuff in the library is done; furthermore, the + finalization code should only run if the initialization code did. + (Maybe I could've made the "if INITIALIZER_RAN" test implicit, via + another function hidden in macros, but this is hairy enough + already.) The init_fn and fini_fn names should be chosen such that any exported names staring with those names, and optionally followed by @@ -59,6 +68,21 @@ the library in question. + There's also PROGRAM_EXITING() currently always defined as zero. + If there's some trivial way to find out if the fini function is + being called because the program that the library is linked into is + exiting, we can just skip all the work because the resources are + about to be freed up anyways. Generally this is likely to be the + same as distinguishing whether the library was loaded dynamically + while the program was running, or loaded as part of program + startup. On most platforms, I don't think we can distinguish these + cases easily, and it's probably not worth expending any significant + effort. (Note in particular that atexit() won't do, because if the + library is explicitly loaded and unloaded, it would have to be able + to deregister the atexit callback function. Also, the system limit + on atexit callbacks may be small.) + + Implementation outline: Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that @@ -78,6 +102,11 @@ just check the flag) and returns the stored error code (or the pthread_once error). + (That's the basic idea. With some debugging assert() calls and + such, it's a bit more complicated. And we also need to handle + doing the pthread test at run time on systems where that works, so + we use the k5_once_t stuff instead.) + UNIX, with compiler support: MAKE_FINI_FUNCTION declares the function as a destructor, and the run time linker support or whatever will cause it to be invoked when the library is unloaded, @@ -91,12 +120,20 @@ UNIX, no library finalization support: The finalization function never runs, and we leak memory. Tough. + DELAY_INITIALIZER will be defined by the configure script if we + want to use k5_once instead of load-time initialization. That'll + be the preferred method on most systems except Windows, where we + have to initialize some mutexes. + + For maximum flexibility in defining the macros, the function name parameter should be a simple name, not even a macro defined as another name. The function should have a unique name, and should conform to whatever namespace is used by the library in question. + (We do have export lists, but (1) they're not used for all + platforms, and (2) they're not used for static libraries.) If the macro expansion needs the function to have been declared, it must include a declaration. If it is not necessary for the symbol @@ -110,7 +147,8 @@ This is going to be compiler- and environment-specific, and may require some support at library build time, and/or "asm" - statements. + statements. But through macro expansion and auxiliary functions, + we should be able to handle most things except #pragma. It's okay for this code to require that the library be built with the same compiler and compiler options throughout, but @@ -129,7 +167,12 @@ work, we'll only have memory leaks in a load/use/unload cycle. If anyone (like, say, the OS vendor) complains about this, they can tell us how to get a shared library finalization function invoked - automatically. */ + automatically. + + Currently there's --disable-delayed-initialization for preventing + the initialization from being delayed on UNIX, but that's mainly + just for testing the linker options for initialization, and will + probably be removed at some point. */ /* Helper macros. */ @@ -194,8 +237,11 @@ static inline int k5_call_init_function(k5_init_t *i) multiple active threads mucking around in our library at this point. So ignore the once_t object and just look at the flag. - XXX Could we have problems with memory coherence between - processors if we don't invoke mutex/once routines? */ + XXX Could we have problems with memory coherence between processors + if we don't invoke mutex/once routines? Probably not, the + application code should already be coordinating things such that + the library code is not in use by this point, and memory + synchronization will be needed there. */ # define INITIALIZER_RAN(NAME) \ (JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0) @@ -206,6 +252,7 @@ static inline int k5_call_init_function(k5_init_t *i) /* Run initializer at load time, via GCC/C++ hook magic. */ # ifdef USE_LINKER_INIT_OPTION + /* Both gcc and linker option?? Favor gcc. */ # define MAYBE_DUMMY_INIT(NAME) \ void JOIN__2(NAME, auxinit) () { } # else @@ -273,9 +320,35 @@ typedef struct { int error; unsigned char did_run; } k5_init_t; matter what compiler we're using. Do it the same way regardless. */ -# define MAKE_FINI_FUNCTION(NAME) \ +# ifdef __hpux + + /* On HP-UX, we need this auxiliary function. At dynamic load or + unload time (but *not* program startup and termination for + link-time specified libraries), the linker-indicated function + is called with a handle on the library and a flag indicating + whether it's being loaded or unloaded. + + The "real" fini function doesn't need to be exported, so + declare it static. + + As usual, the final declaration is just for syntactic + convenience, so the top-level invocation of this macro can be + followed by a semicolon. */ + +# include +# define MAKE_FINI_FUNCTION(NAME) \ + static void NAME(void); \ + void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \ + void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); } \ + static void NAME(void) + +# else /* not hpux */ + +# define MAKE_FINI_FUNCTION(NAME) \ void NAME(void) +# endif + #elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS) /* If we're using gcc, if the C++ support works, the compiler should build executables and shared libraries that support the use of -- 2.26.2