From 45e3030774b1b61c23a5fdd21b3c6be79c5b1cfd Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Fri, 25 Mar 2005 21:36:55 +0000 Subject: [PATCH] shared library support for HP-UX 10 Our somewhat outdated HP-UX support (which was targeted at HP-UX 10, not 11) does not have support for shared library initialization and finalization functions, nor for shared library export lists. The former was causing compilation failures unless shared library support was disabled. * include/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. * config/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. ticket: new git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17153 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 7950df236..a5ccc5437 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 b1de45f49..f7c5ac739 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