[Bug rtl-optimization/89490] [9 Regression] char array constant put in string merge section

jakub at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue Feb 26 15:49:00 GMT 2019


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89490

--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I think there is a serious flaw that the section anchor infrastructure is used
at all for the SECTION_MERGE sections, one really must not use any kind of
section anchors for those sections, there is no guarantees that the layout made
by the compiler will match what the linker will do in the end (between
different objects in the section that is, within a single object it has to
stay).

If that isn't done and we for some strange reason must still go through the
block stuff, I think we should do for something like following, where we'll
account for the artificially added trailing zeros.

--- gcc/varasm.c.jj     2019-02-22 09:30:19.133180850 +0100
+++ gcc/varasm.c        2019-02-26 16:42:11.699848053 +0100
@@ -7452,7 +7452,7 @@ place_block_symbol (rtx symbol)
   struct constant_descriptor_rtx *desc;
   unsigned int alignment;
   struct object_block *block;
-  tree decl;
+  tree decl = NULL_TREE;

   gcc_assert (SYMBOL_REF_BLOCK (symbol));
   if (SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0)
@@ -7511,6 +7511,20 @@ place_block_symbol (rtx symbol)

   /* Calculate the object's offset from the start of the block.  */
   block = SYMBOL_REF_BLOCK (symbol);
+  if ((block->sect->common.flags & SECTION_MERGE)
+      && (block->sect->common.flags & SECTION_STRINGS)
+      && decl
+      && DECL_INITIAL (decl)
+      && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
+    {
+      tree str = DECL_INITIAL (decl);
+      unsigned HOST_WIDE_INT thissize = TREE_STRING_LENGTH (str);
+      if ((thissize == 0
+          || TREE_STRING_POINTER (str) [thissize - 1] != '\0')
+         && size == thissize)
+       size++;
+    }
+
   mask = alignment / BITS_PER_UNIT - 1;
   offset = (block->size + mask) & ~mask;
   SYMBOL_REF_BLOCK_OFFSET (symbol) = offset;
@@ -7639,6 +7653,8 @@ output_object_block (struct object_block

   /* Output the objects themselves.  */
   offset = 0;
+  bool merge_strings = ((block->sect->common.flags & SECTION_MERGE)
+                       && (block->sect->common.flags & SECTION_STRINGS));
   FOR_EACH_VEC_ELT (*block->objects, i, symbol)
     {
       /* Move to the object's offset, padding with zeros if necessary.  */
@@ -7657,9 +7673,18 @@ output_object_block (struct object_block
          HOST_WIDE_INT size;
          decl = SYMBOL_REF_DECL (symbol);
          assemble_constant_contents (DECL_INITIAL (decl), XSTR (symbol, 0),
-                                     DECL_ALIGN (decl), false);
+                                     DECL_ALIGN (decl), merge_strings);

          size = get_constant_size (DECL_INITIAL (decl));
+         if (merge_strings
+             && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
+           {
+             tree str = DECL_INITIAL (decl);
+             HOST_WIDE_INT thissize = TREE_STRING_LENGTH (str);
+             if (thissize == 0
+                 || TREE_STRING_POINTER (str) [thissize - 1] != '\0')
+               size = MAX (size, thissize + 1);
+           }
          offset += size;
          if ((flag_sanitize & SANITIZE_ADDRESS)
              && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
@@ -7674,8 +7699,18 @@ output_object_block (struct object_block
        {
          HOST_WIDE_INT size;
          decl = SYMBOL_REF_DECL (symbol);
-         assemble_variable_contents (decl, XSTR (symbol, 0), false, false);
+         assemble_variable_contents (decl, XSTR (symbol, 0), false,
+                                     merge_strings);
          size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
+         if (merge_strings
+             && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
+           {
+             tree str = DECL_INITIAL (decl);
+             HOST_WIDE_INT thissize = TREE_STRING_LENGTH (str);
+             if (thissize == 0
+                 || TREE_STRING_POINTER (str) [thissize - 1] != '\0')
+               size = MAX (size, thissize + 1);
+           }
          offset += size;
          if ((flag_sanitize & SANITIZE_ADDRESS)
              && asan_protect_global (decl))


More information about the Gcc-bugs mailing list