Index: libgcc/config/rs6000/aixinitfini.c
===================================================================
--- libgcc/config/rs6000/aixinitfini.c	(revision 0)
+++ libgcc/config/rs6000/aixinitfini.c	(revision 0)
@@ -0,0 +1,33 @@
+/* FIXME: rename this file */
+
+/*
+   Artificially create _GLOBAL_AIX[ID]_shr_o symbols in libgcc.a.
+
+   This means that libstdc++.a can invoke these symbols and they are resolved
+   regardless of whether libstdc++.a is linked against libgcc_s.a or libgcc.a.
+
+   The symbols are created in libgcc_s.a by collect2 as there are exception
+   frames to register for LIB2_DIVMOD_FUNCS.
+
+   The symbols are NOT created by collect2 for libgcc.a, because libgcc.a is
+   a 'real' archive containing objects and collect2 is not invoked.
+
+   libstdc++.a is linked against libgcc.a when handling the command line
+   options '-static-libgcc -static-libstdc++'.
+*/
+
+void _GLOBAL__AIXI_shr_o (void);
+void _GLOBAL__AIXD_shr_o (void);
+
+void
+_GLOBAL__AIXI_shr_o (void)
+{
+  return;
+}
+
+void
+_GLOBAL__AIXD_shr_o (void)
+{
+  return;
+}
+
Index: libgcc/config/rs6000/t-aix-cxa
===================================================================
--- libgcc/config/rs6000/t-aix-cxa	(revision 205145)
+++ libgcc/config/rs6000/t-aix-cxa	(working copy)
@@ -1,6 +1,8 @@
 LIB2ADDEH += $(srcdir)/config/rs6000/cxa_atexit.c \
 	$(srcdir)/config/rs6000/cxa_finalize.c
 
+LIB2ADD_ST += $(srcdir)/config/rs6000/aixinitfini.c
+
 SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-aix-cxa.ver
 
 crtcxa.o: $(srcdir)/config/rs6000/crtcxa.c
Index: libgcc/config/rs6000/libgcc-aix-cxa.ver
===================================================================
--- libgcc/config/rs6000/libgcc-aix-cxa.ver	(revision 205145)
+++ libgcc/config/rs6000/libgcc-aix-cxa.ver	(working copy)
@@ -2,3 +2,8 @@
   __cxa_atexit
   __cxa_finalize
 }
+
+GCC_4.9 {
+  _GLOBAL__AIXI_shr_o
+  _GLOBAL__AIXD_shr_o
+}
Index: gcc/config/rs6000/aix.h
===================================================================
--- gcc/config/rs6000/aix.h	(revision 205145)
+++ gcc/config/rs6000/aix.h	(working copy)
@@ -47,6 +47,35 @@
    collect has a chance to see them, so scan the object files directly.  */
 #define COLLECT_EXPORT_LIST
 
+/* On AIX, initialisers specified with -binitfini are called in breadth-first
+   order.
+   e.g. if a.out depends on lib1.so, the init function for a.out is called before
+   the init function for lib1.so.
+
+   To ensure global C++ constructors in linked libraries are run before global
+   C++ constructors from the current module, there is additional symbol scanning
+   logic in collect2.
+
+   The global initialiser/finaliser functions are named __GLOBAL_AIXI_{libname}
+   and __GLOBAL_AIXD_{libname} and are exported from each shared library.
+
+   collect2 will detect these symbols when they exist in shared libraries that
+   the current program is being linked against.  All such initiliser functions
+   will be called prior to the constructors of the current program, and
+   finaliser functions called after destructors.
+
+   Reference counting generated by collect2 will ensure that constructors are
+   only invoked once in the case of multiple dependencies on a library.
+
+   -binitfini is still used in parallel to this solution.
+   This handles the case where a library is loaded through dlopen(), and also
+   handles the option -blazy.
+*/
+#define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
+	  fprintf ((STREAM), "void %s() {\n\t%s();\n}\n", aix_shared_initname, (FUNC))
+#define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
+	  fprintf ((STREAM), "void %s() {\n\t%s();\n}\n", aix_shared_fininame, (FUNC))
+
 #if HAVE_AS_REF
 /* Issue assembly directives that create a reference to the given DWARF table
    identifier label from the current function section.  This is defined to
Index: gcc/collect2.c
===================================================================
--- gcc/collect2.c	(revision 205145)
+++ gcc/collect2.c	(working copy)
@@ -182,6 +182,7 @@
 static int export_flag;                 /* true if -bE */
 static int aix64_flag;			/* true if -b64 */
 static int aixrtl_flag;			/* true if -brtl */
+static int aixlazy_flag;               /* true if -blazy */
 #endif
 
 enum lto_mode_d {
@@ -215,6 +216,13 @@
 const char *c_file_name;		/* pathname of gcc */
 static char *initname, *fininame;	/* names of init and fini funcs */
 
+
+#ifdef TARGET_AIX_VERSION
+static char *aix_shared_initname;
+static char *aix_shared_fininame;       /* init/fini names as per the scheme
+					   described in config/rs6000/aix.h */
+#endif
+
 static struct head constructors;	/* list of constructors found */
 static struct head destructors;		/* list of destructors found */
 #ifdef COLLECT_EXPORT_LIST
@@ -279,7 +287,9 @@
   SYM_DTOR = 2,  /* destructor  */
   SYM_INIT = 3,  /* shared object routine that calls all the ctors  */
   SYM_FINI = 4,  /* shared object routine that calls all the dtors  */
-  SYM_DWEH = 5   /* DWARF exception handling table  */
+  SYM_DWEH = 5,  /* DWARF exception handling table  */
+  SYM_AIXI = 6,
+  SYM_AIXD = 7
 } symkind;
 
 static symkind is_ctor_dtor (const char *);
@@ -340,6 +350,8 @@
   SCAN_INIT = 1 << SYM_INIT,
   SCAN_FINI = 1 << SYM_FINI,
   SCAN_DWEH = 1 << SYM_DWEH,
+  SCAN_AIXI = 1 << SYM_AIXI,
+  SCAN_AIXD = 1 << SYM_AIXD,
   SCAN_ALL  = ~0
 };
 
@@ -589,6 +601,10 @@
     { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, SYM_DWEH, 0 },
     { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, SYM_INIT, 0 },
     { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, SYM_FINI, 0 },
+#ifdef TARGET_AIX_VERSION
+    { "GLOBAL__AIXI_", sizeof ("GLOBAL__AIXI_")-1, SYM_AIXI, 0 },
+    { "GLOBAL__AIXD_", sizeof ("GLOBAL__AIXD_")-1, SYM_AIXD, 0 },
+#endif
     { NULL, 0, SYM_REGULAR, 0 }
   };
 
@@ -1034,6 +1050,8 @@
 	    aixrtl_flag = 1;
 	else if (strcmp (argv[i], "-bnortl") == 0)
 	    aixrtl_flag = 0;
+	else if (strcmp (argv[i], "-blazy") == 0)
+	    aixlazy_flag = 1;
 #endif
       }
     vflag = debug;
@@ -1728,6 +1746,9 @@
       if (! exports.first)
 	*ld2++ = concat ("-bE:", export_file, NULL);
 
+      add_to_list (&exports, aix_shared_initname);
+      add_to_list (&exports, aix_shared_fininame);
+
 #ifndef LD_INIT_SWITCH
       add_to_list (&exports, initname);
       add_to_list (&exports, fininame);
@@ -2020,6 +2041,19 @@
 {
   int pos = 0, pri;
 
+#ifdef TARGET_AIX_VERSION
+  /* Run dependent module initializers before any constructors in this
+     module.  */
+  switch (is_ctor_dtor (name))
+    {
+    case SYM_AIXI:
+    case SYM_AIXD:
+      return INT_MIN;
+    default:
+      break;
+    }
+#endif
+
   while (name[pos] == '_')
     ++pos;
   pos += 10; /* strlen ("GLOBAL__X_") */
@@ -2180,11 +2214,22 @@
 
   initname = concat ("_GLOBAL__FI_", prefix, NULL);
   fininame = concat ("_GLOBAL__FD_", prefix, NULL);
+#ifdef TARGET_AIX_VERSION
+  aix_shared_initname = concat ("_GLOBAL__AIXI_", prefix, NULL);
+  aix_shared_fininame = concat ("_GLOBAL__AIXD_", prefix, NULL);
+#endif
 
   free (prefix);
 
   /* Write the tables as C code.  */
 
+  /* This count variable is used to prevent multiple calls to the
+     constructors/destructors.
+     This guard against multiple calls is important on AIX as the initfini
+     functions are deliberately invoked multiple times as part of the
+     mechanisms GCC uses to order constructors across different dependent
+     shared libraries (see config/rs6000/aix.h).
+   */
   fprintf (stream, "static int count;\n");
   fprintf (stream, "typedef void entry_pt();\n");
   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
@@ -2531,6 +2576,7 @@
 
 
       *end = '\0';
+
       switch (is_ctor_dtor (name))
 	{
 	case SYM_CTOR:
@@ -2892,6 +2938,25 @@
 
 		      switch (is_ctor_dtor (name))
 			{
+#if TARGET_AIX_VERSION
+		      /* Add AIX shared library initalisers/finalisers
+			 to the constructors/destructors list of the
+			 current module.  */
+			case SYM_AIXI:
+			  if (! (filter & SCAN_CTOR))
+			    break;
+			  if (is_shared && !aixlazy_flag)
+			    add_to_list (&constructors, name);
+			  break;
+
+			case SYM_AIXD:
+			  if (! (filter & SCAN_DTOR))
+			    break;
+			  if (is_shared && !aixlazy_flag)
+			    add_to_list (&destructors, name);
+			  break;
+#endif
+
 			case SYM_CTOR:
 			  if (! (filter & SCAN_CTOR))
 			    break;
