From octave-maintainers-request at bevo dot che dot wisc dot edu Thu Jun 28 18:09:37 2001 Subject: [patch] dynamic linking for GCC v2/3 and Sun C++ ABI From: Mumit Khan To: octave-maintainers at bevo dot che dot wisc dot edu cc: Mumit Khan Date: Thu, 28 Jun 2001 18:09:28 -0500 (CDT) [ I'm not subscribed to this list, so please copy me if appropriate ] The following patch adds support for dynamic linking when using GNU v3 and Sun ABI. JWE's suggestion to use C linkage for dynamically loadable functions is definitely worth investigating, provided we understand the caveat -- loaded modules will mysteriously crash if there's a compiler version mismatch. One solution is to encode the abi version (eg., gxx_v2, gxx_v3, sun, compaq, etc) in the function name via the DEFUN_DLD macro. I'll send a patch along if it works. Note to testers -- you must re-create the autogenerated files after applying this patch as it changes acconfig.h and aclocal.m4. If you use the CVS version: $ cd $ ./autogen.sh or, if you're using snapshots that lack autogen.sh, $ autoconf $ autoheader should do the job. A few odds and ends to note: - I've added a new macro -- CXX_ABI_VERSION -- that is used only for GNU C++. If the other C++ vendors start using the new ABI, supposedly a standard now, it will of course get used for other compilers as well. - I've stuck to using deprecated strstream instead of stringstream to avoid the whole library issue. This will get "fixed" once the all of Octave moves to using strstream instead. - The Sun mangling is based on a somewhat educated guess. My tree is somewhat modified, so please try and manually work out any patch conflicts. Tested on GNU/Linux with gcc-2.95.2 and gcc-3.0, SPARC/Solaris 8 with Sun Workshop 6 update 1. ChangeLog/toplevel: 2001-04-28 Mumit Khan * aclocal.m4 (OCTAVE_CXX_ABI_VERSION): New macro. (OCTAVE_CXX_PREPENDS_UNDERSCORE): Add missing return value. * configure.in: Use. * acconfig.h (CXX_ABI_VERSION): New macro. ChangeLog/src: 2001-04-28 Mumit Khan * dynamic-ld.cc ({algorithm,cctype,strstream}): Include. (octave_dynamic_loader::mangle_name): Support dynamic linking for GNU v3 and Sun C++ ABI. Index: aclocal.m4 =================================================================== RCS file: /cvs/octave/aclocal.m4,v retrieving revision 1.55 diff -u -3 -p -r1.55 aclocal.m4 --- aclocal.m4 2001/05/23 06:41:58 1.55 +++ aclocal.m4 2001/06/28 19:10:12 at @ -913,7 +913,7 @@ AC_DEFUN(OCTAVE_CXX_PREPENDS_UNDERSCORE, AC_LANG_SAVE AC_LANG_CPLUSPLUS cat > conftest.$ac_ext <= 3.0). +dnl +dnl OCTAVE_CXX_ABI_VERSION +AC_DEFUN(OCTAVE_CXX_ABI_VERSION, +[AC_MSG_CHECKING([C++ ABI version used by ${CXX-g++}]) + AC_CACHE_VAL(octave_cv_cxx_abi_version, + [octave_cv_cxx_abi_version='0' + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + cat > conftest.$ac_ext <&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC + fi + AC_LANG_RESTORE + ]) + AC_MSG_RESULT($octave_cv_cxx_abi_version) + AC_DEFINE_UNQUOTED(CXX_ABI_VERSION, $octave_cv_cxx_abi_version) +]) + Index: configure.in =================================================================== RCS file: /cvs/octave/configure.in,v retrieving revision 1.348 diff -u -3 -p -r1.348 configure.in --- configure.in 2001/05/23 06:41:58 1.348 +++ configure.in 2001/06/28 19:10:12 at @ -185,6 +185,14 @@ changequote([,])dnl ;; esac + +# The GNU C++ compiler uses either ABI version 2, default for GCC versions +# <= 2.95.x, or version 3, default for GCC versions >= 3.0. However, we +# can't just assume one or the other since gcc-2.9[6-7] snapshots could +# be built to use either ABI. + +OCTAVE_CXX_ABI_VERSION + CXX_VERSION= if test -n "$gxx_version"; then CXX_VERSION="$gxx_version" Index: acconfig.h =================================================================== RCS file: /cvs/octave/acconfig.h,v retrieving revision 1.47 diff -u -3 -p -r1.47 acconfig.h --- acconfig.h 2001/05/02 06:15:07 1.47 +++ acconfig.h 2001/06/28 19:10:12 at @ -14,6 +14,9 @@ internal array and matrix classes. */ #undef BOUNDS_CHECKING +/* Define to the C++ ABI version your compiler uses. */ +#undef CXX_ABI_VERSION + /* Define if your C++ runtime library is ISO compliant. */ #undef CXX_ISO_COMPLIANT_LIBRARY Index: src/dynamic-ld.cc =================================================================== RCS file: /cvs/octave/src/dynamic-ld.cc,v retrieving revision 1.64 diff -u -3 -p -r1.64 dynamic-ld.cc --- src/dynamic-ld.cc 2000/04/04 06:16:23 1.64 +++ src/dynamic-ld.cc 2001/06/28 22:51:11 at @ -24,6 +24,10 @@ Software Foundation, 59 Temple Place - S #include #endif +#include +#include +#include + #include "oct-time.h" #include "file-stat.h" at @ -311,13 +315,69 @@ octave_dynamic_loader::remove (const std std::string octave_dynamic_loader::mangle_name (const std::string& name) { -#if defined (CXX_PREPENDS_UNDERSCORE) - std::string retval ("_FS"); -#else - std::string retval ("FS"); -#endif + std::string retval; + +#if defined(__GNUC__) + +# if CXX_ABI_VERSION < 2 +# error Unsupported GNU C++ ABI version. Must be >= 2. +# elif CXX_ABI_VERSION == 2 + +# if defined (CXX_PREPENDS_UNDERSCORE) + retval = ("_FS"); +# else + retval = ("FS"); +# endif retval.append (name); retval.append ("__FRC12octave_shlib"); + +# elif CXX_ABI_VERSION == 3 + + /* GNU C++ ABI v3 uses _Z followed by the length of the symbol. We + add 2 to account for "FS". */ + std::ostrstream mangled_name; + mangled_name << "_Z" << (name.length () + 2) << "FS"; + mangled_name << name << "RK12octave_shlib" << std::ends; + retval = mangled_name.str (); + mangled_name.freeze (0); + +# else /* CXX_ABI_VERSION */ +# warning Unsupported GNU C++ ABI version. Supported versions are <= 3. +# endif /* CXX_ABI_VERSION */ + +#elif defined(__SUNPRO_CC) + + /* Sun Workshop uses __1c followed by the length of the symbol, encoded + in the most bizarre way, almost base-26, but not quite: the least + significant digit goes from 'B' to 'Z', and the rest from 'b' to 'z'. + Go figure. We add 2 to account for "FS". */ + + std::string::size_type len = name.length () + 2; + std::ostrstream ostr; + while (len > 25) + { + int digit = len % 26; + len /= 26; + ostr << static_cast ('a' + digit); + } + ostr << static_cast ('a' + len); + + ostr << std::ends; + std::string mangled_len = ostr.str (); + ostr.freeze (0); + mangled_len[0] = std::toupper (mangled_len[0]); + std::reverse (mangled_len.begin (), mangled_len.end ()); + + std::ostrstream mangled_name; + mangled_name << "__1c" << mangled_len << "FS" << + name << "6FrknMoctave_shlib__b_" << std::ends; + retval = mangled_name.str (); + mangled_name.freeze (0); + +#else +# warning Unsupported C++ ABI version. +#endif /* __GNUC__ */ + return retval; }