Print this page
10346 ld(1) should not reduce symbol visibility of COMDAT symbols when producing relocatable objects

@@ -989,10 +989,13 @@
                 sdflags |= FLG_SY_EXPORT;
                 break;
         case STV_SINGLETON:
                 sdflags |= FLG_SY_SINGLE;
                 break;
+        case STV_HIDDEN:
+                sdflags |= FLG_SY_HIDDEN;
+                break;
         }
 
         /*
          * Determine whether a symbol definition already exists, and if so
          * obtain the visibility.

@@ -1514,11 +1517,11 @@
                  *
                  * Also refer to make_mvsections() in sunwmove.c
                  */
                 if ((sym->st_shndx == SHN_COMMON) &&
                     (((oflags & FLG_OF_RELOBJ) == 0) ||
-                    (SYM_IS_HIDDEN(sdp) && (oflags & FLG_OF_PROCRED)))) {
+                    ld_sym_reducable(ofl, sdp))) {
                         if ((sdp->sd_move == NULL) ||
                             ((sdp->sd_flags & FLG_SY_PAREXPN) == 0)) {
                                 if (type != STT_TLS) {
                                         need_bss = TRUE;
                                         bsssize = (Xword)S_ROUND(bsssize,

@@ -1566,11 +1569,11 @@
                  * Note, a capabilities symbol must remain as visible as a
                  * global symbol.  However, the runtime linker recognizes the
                  * hidden requirement and ensures the symbol isn't made globally
                  * available at runtime.
                  */
-                if (SYM_IS_HIDDEN(sdp) && (oflags & FLG_OF_PROCRED)) {
+                if (ld_sym_reducable(ofl, sdp)) {
                         /*
                          * If any reductions are being processed, keep a count
                          * of eliminated symbols, and if the symbol is being
                          * reduced to local, count it's size for the .symtab.
                          */

@@ -3131,5 +3134,28 @@
                 isp->is_sym_name = str;
         }
 
         return (isp->is_sym_name);
 }
+
+/*
+ * If we're producing a relocatable object and the symbol is eligible for
+ * COMDAT section, it shouldn't be reduced in scope as that will break the
+ * COMDAT matching when the output object is later consumed.  Leave it alone,
+ * and any reduction (and COMDAT) processing will occur then.
+ *
+ * Otherwise, any hidden symbol is reduced when reductions are being processed.
+ */
+Boolean
+ld_sym_reducable(Ofl_desc *ofl, Sym_desc *sdp)
+{
+        Is_desc *isc = sdp->sd_isc;
+
+        if (((ofl->ofl_flags & FLG_OF_RELOBJ) != 0) &&
+            (isc != NULL) &&
+            ((isc->is_flags & FLG_IS_COMDAT) != 0)) {
+                return (FALSE);
+        } else {
+                return (SYM_IS_HIDDEN(sdp) &&
+                    (ofl->ofl_flags & FLG_OF_PROCRED));
+        }
+}