From dde69528047035a9bef216a11b2bb695907214a8 Mon Sep 17 00:00:00 2001
From: David Edelsohn <dje.gcc@gmail.com>
Date: Wed, 23 Sep 2020 16:52:15 -0400
Subject: [PATCH] aix: collect2 visibility

The code that collect2 generates, compiles and links into applications
and shared libraries to initialize constructors and register DWARF tables
is built with the compiler options used to invoke the linker.  If the
compiler options change the visibility from default, the library
initialization routines will not be visible and this can prevent
initialization.

This patch checks if the command line sets visibiliity and then adds
GCC pragmas to the initialization code generated by collect2 if
necessary to define the visibility on global, exported functions as default.

gcc/ChangeLog:

2020-09-26  David Edelsohn  <dje.gcc@gmail.com>
	    Clement Chigot  <clement.chigot@atos.com>

	* collect2.c (visibility_flag): New.
	(main): Detect -fvisibility.
	(write_c_file_stat): Push and pop default visibility.
---
 gcc/collect2.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/gcc/collect2.c b/gcc/collect2.c
index f8a5ce45994..6d074a79e91 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -184,7 +184,8 @@ static int strip_flag;			/* true if -s */
 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 */
+static int aixlazy_flag;		/* true if -blazy */
+static int visibility_flag;		/* true if -fvisibility */
 #endif
 
 enum lto_mode_d {
@@ -1239,6 +1240,11 @@ main (int argc, char **argv)
 	      *c_ptr++ = xstrdup (q);
 	    }
 	}
+#ifdef COLLECT_EXPORT_LIST
+      /* Detect any invocation with -fvisibility.  */
+      if (strncmp (q, "-fvisibility", 12) == 0)
+	visibility_flag = 1;
+#endif
     }
   obstack_free (&temporary_obstack, temporary_firstobj);
   *c_ptr++ = "-fno-profile-arcs";
@@ -2131,6 +2137,11 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
       fprintf (stream, "\t}\n");
     }
 
+#ifdef COLLECT_EXPORT_LIST
+  /* Set visibility of initializers to default.  */
+  if (visibility_flag)
+    fprintf (stream, "#pragma GCC visibility push(default)\n");
+#endif
   fprintf (stream, "void %s() {\n", initname);
   if (constructors.number > 0 || frames)
     {
@@ -2163,11 +2174,24 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
 	       destructors.number + frames);
     }
   fprintf (stream, "}\n");
+#ifdef COLLECT_EXPORT_LIST
+  if (visibility_flag)
+    fprintf (stream, "#pragma GCC visibility pop\n");
+#endif
 
   if (shared_obj)
     {
+#ifdef COLLECT_EXPORT_LIST
+      /* Set visibility of initializers to default.  */
+      if (visibility_flag)
+	fprintf (stream, "#pragma GCC visibility push(default)\n");
+#endif
       COLLECT_SHARED_INIT_FUNC (stream, initname);
       COLLECT_SHARED_FINI_FUNC (stream, fininame);
+#ifdef COLLECT_EXPORT_LIST
+      if (visibility_flag)
+	fprintf (stream, "#pragma GCC visibility pop\n");
+#endif
     }
 }
 
-- 
2.20.1

