Skip to content

Instantly share code, notes, and snippets.

@NattyNarwhal
Last active April 5, 2019 18:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NattyNarwhal/b2d8ad27d40a7aef5be4b321493792ef to your computer and use it in GitHub Desktop.
Save NattyNarwhal/b2d8ad27d40a7aef5be4b321493792ef to your computer and use it in GitHub Desktop.
svr4 soname patch (WIP)

Static mono binary:

CONFIG_SHELL=`which bash` ./autogen.sh  --with-aix-soname=svr4 --enable-shared  --with-static_mono=yes --prefix=/opt/mono

Non-static mono binary:

OBJECT_MODE=64 CONFIG_SHELL=`which bash` LDFLAGS="-Wl,-bnoquiet" ./autogen.sh  --with-aix-soname=svr4 --enable-shared  --with-static_mono=no --disable-static --prefix=/opt/mono

maix64-ness is set automatically.

(You need OBJECT_MODE=64 for the shared lib to work properly regardless. Very hideous.)

(2019/04/05: Huh? You need --enable-shared --disable-static now?)

diff --git a/configure.ac b/configure.ac
index c2c68bb..2d95c34 100644
--- a/configure.ac
+++ b/configure.ac
@@ -413,15 +413,55 @@ case "$host" in
mono_cv_clang=no
;;
*-*-aix*|*-*-os400*)
- dnl Set up a 64-bit build
+ dnl IMPORTANT: For svr4 sonames on AIX, you should set
+ dnl `OBJECT_MODE=64` when configuring.
+ dnl libtool cannot generate functioning svr4 sonames on
+ dnl 64-bit without it.
+ dnl Unfortunately, everything is complicated by the fact that
+ dnl gcc doesn't respect this variable. (otherwise we could set
+ dnl it for build time for configure and make)
+ dnl On IBM i PASE using IBM's packages, GCC *does* respect this
+ dnl variable, and builds are 64-bit by default. svr4 sonames
+ dnl must still be specified when configuring on i, however.
+ dnl As such, because Mono doesn't support 32-bit AIX or PASE,
+ dnl set up a 64-bit build (assming GCC; XLC not supported)
+ dnl regardless of what variable is used.
+ case $host_os in
+ aix*)
+ if test "x$OBJECT_MODE" = "x64" && test "x$CC" = "x" && test "x$CXX" = "x"; then
+ dnl HACK: Set -maix64 at the GCC invocation
+ dnl level explicitly to work around the fact
+ dnl GCC in default maix32 mode explodes when
+ dnl binutils respects OBJECT_MODE.
+ dnl When that check occurs, flags are not
+ dnl passed to to the compiler, so GCC has no
+ dnl chance to change its mode.
+ dnl Otherwise, it may enter a state where it
+ dnl runs, but uses the libtool "compile"
+ dnl wrapper, which subtly breaks other things.
+ dnl This should propagate to all uses of CC.
+ dnl This is only set if not manually set.
+ CC="gcc -maix64"
+ CXX="g++ -maix64"
+ echo
+ fi
+ ;;
+ dnl Not needed on i because it defaults to 64-bit and
+ dnl has a GCC smart enough to respect OBJECT_MODE.
+ esac
+ dnl We still set this for *FLAGS, however, because we may not
+ dnl be setting OBJECT_MODE.
+ LDFLAGS="$LDFLAGS -maix64"
CPPFLAGS="$CPPFLAGS -maix64 -DGC_AIX_THREADS -D_ALL_SOURCE -D_THREAD_SAFE -D_LARGE_FILES -D_REENTRANT"
- LDFLAGS="-maix64"
libmono_cflags="-D_THREAD_SAFE -D_REENTRANT"
dnl Would you believe GNU nm doesn't know how to process AIX libraries?
dnl Hardcode IBM binutils in case GNU ones end up on our path. Also
- dnl specifiy 64-bit mode for tools.
+ dnl specifiy 64-bit mode for tools. (OBJECT_MODE is finicky with cmake.)
+ dnl XXX: We should stop the hardcoding madness
AR="/usr/bin/ar -X64"
NM="/usr/bin/nm -X64"
+ STRIP="/usr/bin/strip -X64"
+ RANLIB="/usr/bin/ranlib -X64"
dnl SGen is the future (changes to Boehm support code would be
dnl required if you wish to re-enable Boehm)
support_boehm=no
@@ -4217,11 +4257,6 @@ case "$host" in
aix*|os400*)
BTLS_SUPPORTED=yes
BTLS_PLATFORM=powerpc
- dnl on AIX/PASE, shared libraries can be inside archives
- dnl if they are, we specify them by lib.a(lib.so)
- dnl we may hardcode 64-bit names at times, but we don't do 32-bit AIX, so
- LIBC="libc.a(shr_64.o)"
- INTL="libintl.a(libintl.so.8)"
;;
linux*)
BTLS_SUPPORTED=yes
@@ -4686,6 +4721,27 @@ jit_status="Building and using the JIT"
libsuffix=".so"
case "$host" in
+ *-*-aix*)
+ dnl on AIX/PASE, shared libraries can be and usually are inside archives
+ dnl so, we specify them by libfoo.a(libfoo.so.0) for libtool's conventions,
+ dnl or libfoo.a(shr[_64].o) for the AIX system convention,
+ dnl or lib.so[.0](shr[_64].o) for libtool's hybrid convention
+ dnl we may hardcode 64-bit names at times, but we don't do 32-bit AIX
+ LIBC="libc.a(shr_64.o)"
+ # This is particularily nasty because we need to refer to libintl by version, which may not necessarily match what a system has.
+ INTL="libintl.a(libintl.so.8)"
+ SQLITE3="libsqlite3.a(libsqlite3.so.0)"
+ # it's very tempting to set a libsuffix, but it depends on the soname value
+ ;;
+ *-*-os400*)
+ dnl However, IBM's packages for i try to be more "normal" than the AIX world, naming wise.
+ dnl The library archives has "normal" .so names, but they're members with predictable "shr" names for fat libraries.
+ LIBC="libc.a(shr_64.o)"
+ INTL="libintl.so(shr_64.o)"
+ SQLITE3="libsqlite3.so(shr_64.o)"
+ # likewise, it's safer to assume ".so(shr_64.o)" due to official IBM packages being built this way, but as with AIX, others may not be guaranteed
+ # it may be worth revisiting this in the future
+ ;;
*-*-darwin*)
libsuffix=".dylib"
LIBC="libc.dylib"
@@ -5592,7 +5648,7 @@ if test "x$enable_btls" = "xyes"; then
case $host_os in
aix*|os400*)
btls_cflags="$btls_cflags -maix64 -mminimal-toc -pthread -D_ALL_SOURCE -D_THREAD_SAFE -D_REENTRANT"
- BTLS_CMAKE_ARGS="-DCMAKE_AR=/usr/bin/ar -DCMAKE_C_ARCHIVE_CREATE=\"<CMAKE_AR> -X64 cr <TARGET> <LINK_FLAGS> <OBJECTS>\""
+ BTLS_CMAKE_ARGS="$BTLS_CMAKE_ARGS -DCMAKE_AR=/usr/bin/ar -DCMAKE_C_ARCHIVE_CREATE=\"<CMAKE_AR> -X64 cr <TARGET> <LINK_FLAGS> <OBJECTS>\""
esac
;;
android-armv5)
@@ -6165,6 +6221,15 @@ elif case $host_os in aix*|os400*) true;; *) false;; esac; then
MONO_NATIVE_CPPFLAGS=$CPPFLAGS
MONO_NATIVE_CXXFLAGS=$CXXFLAGS
MONO_NATIVE_CFLAGS=$CFLAGS
+ dnl nosymbolic- is a hack in case -G for linking is used, as -G seems
+ dnl to change the way unresolved symbols work on library load in an
+ dnl incompatible manner. (as references to runtime functions are
+ dnl resolved later) Default params otherwise are that, so seems OK.
+ dnl Likewise, we don't seem to need to cover the entire runtime with
+ dnl it either, on both AIX and PASE. -brtl from -G does seem to spew
+ dnl Big Scary TOC Warnings (tm) from the linker, but it doesn't seem
+ dnl problematic with gcc's -mminimal-toc.
+ dnl ----
dnl flock in AIX exists in libbsd (not the same as freedesktop.org
dnl libbsd) which Mono.Native needs.
dnl Because of the way that the library is built by default, unresolved
@@ -6173,7 +6238,7 @@ elif case $host_os in aix*|os400*) true;; *) false;; esac; then
dnl better to explicitly link it, even though it has it shadows libc's
dnl ioctl with its own. (As for the other unresolved imports, those
dnl should be provided by the Mono runtime loaded.)
- MONO_NATIVE_LDFLAGS="$LDFLAGS -lbsd"
+ MONO_NATIVE_LDFLAGS="$LDFLAGS -lbsd -Wl,-bnosymbolic-"
mono_native=yes
mono_native_compat=no
diff --git a/mono/utils/mono-dl-posix.c b/mono/utils/mono-dl-posix.c
index 08c8dbb..3568828 100644
--- a/mono/utils/mono-dl-posix.c
+++ b/mono/utils/mono-dl-posix.c
@@ -39,6 +39,27 @@ mono_dl_get_so_suffixes (void)
{
static const char *suffixes[] = {
".so",
+#if defined (_AIX)
+/*
+ * libtool generating sysv style names (.so) still results in an .a archive,
+ * (AIX prefers to put shared objects inside the same ar archive used for
+ * static members, likely as a fat library system) so try common member names
+ * when no suffix is given. The same path with member names can be tried, then
+ * .a and .so extensions with member names. (The suffixless member names are
+ * for when .so names are specified, but the archive is a member - the runtime
+ * should just keep trying with one of these suffixes then.)
+ *
+ * Unfortunately, this strategy won't work for "aix" style libtool sonames -
+ * it tries something awful like like "libfoo.a(libfoo.so.9)" which requires
+ * you to hardcode a version in the member name.
+ */
+ "(shr.o)",
+ "(shr_64.o)",
+ ".a(shr.o)",
+ ".a(shr_64.o)",
+ ".so(shr.o)",
+ ".so(shr_64.o)",
+#endif
"",
};
return suffixes;
diff --git a/mono/utils/mono-dl.c b/mono/utils/mono-dl.c
index 043f0ab..d43a1ec 100644
--- a/mono/utils/mono-dl.c
+++ b/mono/utils/mono-dl.c
@@ -31,6 +31,40 @@ struct MonoDlFallbackHandler {
static GSList *fallback_handlers;
+#if defined (_AIX)
+#include <ar.h>
+#include <fcntl.h>
+
+/**
+ * On AIX/PASE, a shared library can be contained inside of an ar format
+ * archive. Determine if the file is an ar archive or not.
+ */
+static gboolean
+is_library_ar_archive (char *path)
+{
+ int lfd, readret;
+ char magic[SAIAMAG + 1];
+ lfd = open (path, O_RDONLY);
+
+ /* don't assume it's an archive on error */
+ if (lfd == -1)
+ return FALSE;
+
+ readret = read (lfd, magic, SAIAMAG);
+ close (lfd);
+ if (readret != SAIAMAG)
+ return FALSE;
+
+ magic [SAIAMAG] = '\0';
+
+ /* check for equality with either version of header */
+ if (strncmp(magic, AIAMAG, SAIAMAG) == 0 ||
+ strncmp(magic, AIAMAGBIG, SAIAMAG) == 0)
+ return TRUE;
+ return FALSE;
+}
+#endif
+
/*
* read a value string from line with any of the following formats:
* \s*=\s*'string'
@@ -189,6 +223,23 @@ mono_dl_open (const char *name, int flags, char **error_msg)
g_free (lname);
if (llname) {
lib = mono_dl_open_file (llname, lflags);
+#if defined (_AIX)
+ /*
+ * HACK: deal with AIX archive members because libtool
+ * underspecifies when using --with-aix-soname=svr4 -
+ * without this check, Mono can't find System.Native
+ * at build time.
+ * XXX: Does this also need to be in other places?
+ */
+ if (!lib && is_library_ar_archive (llname)) {
+ /* try common suffix */
+ char *llaixname;
+ llaixname = g_strconcat (llname, "(shr_64.o)", NULL);
+ lib = mono_dl_open_file (llaixname, lflags);
+ /* XXX: try another suffix like (shr.o)? */
+ g_free (llaixname);
+ }
+#endif
g_free (llname);
}
if (!lib) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment