http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55395



Jakub Jelinek <jakub at gcc dot gnu.org> changed:



           What    |Removed                     |Added

----------------------------------------------------------------------------

             Status|UNCONFIRMED                 |NEW

   Last reconfirmed|                            |2012-12-04

                 CC|                            |hubicka at gcc dot gnu.org,

                   |                            |jakub at gcc dot gnu.org

     Ever Confirmed|0                           |1



--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-12-04 
10:13:06 UTC ---

Reduced testcase:

/* { dg-do compile } */

/* { dg-options "-fdata-sections -g -O2" } */

/* { dg-additional-options "-fstack-protector" { target fstack_protector } } */



extern inline __attribute__ ((__always_inline__))

void *

memcpy (void *__restrict d, const void *__restrict s, __SIZE_TYPE__ l)

{

  return __builtin___memcpy_chk (d, s, l, __builtin_object_size (d, 0));

}



void

foo (char *p)

{

  static const char q[] = "\n";

  memcpy (p, &q, 1);

}



The reason why this fails is IMHO bogus change from

http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=187631



void

varpool_remove_node (struct varpool_node *node)

{

  symtab_unregister_node ((symtab_node)node);

  if (DECL_INITIAL (node->symbol.decl)

      && !DECL_IN_CONSTANT_POOL (node->symbol.decl)

      /* Keep vtables for BINFO folding.  */

      && !DECL_VIRTUAL_P (node->symbol.decl)

      /* dbxout output constant initializers for readonly vars.  */

      && (!host_integerp (DECL_INITIAL (node->symbol.decl), 0)

          || !TREE_READONLY (node->symbol.decl)))

    DECL_INITIAL (node->symbol.decl) = error_mark_node;

  ggc_free (node);

}



(the DECL_INITIAL setting to error_mark_node).  I can understand the aim at

saving compile time memory, but this is a wrong thing to do.  dwarf2out.c uses

DECL_INITIAL heavily to emit debug info even for optimized away variables.



The exact reason for the error is that we have get_named_section called twice,

once before the varpool_remove_node call, once after it.

The first one is:

#1  0x0000000000cc64dc in get_named_section (decl=0x7ffff19a5850,

name=0x7ffff17fdbf4 ".rodata.q.4121", reloc=0) at ../../gcc/varasm.c:411

#2  0x0000000000cc7d6c in get_variable_section (decl=0x7ffff19a5850,

prefer_noswitch_p=true) at ../../gcc/varasm.c:1030

#3  0x0000000000cc7f88 in get_block_for_decl (decl=0x7ffff19a5850) at

../../gcc/varasm.c:1076

#4  0x0000000000cc8a88 in make_decl_rtl (decl=0x7ffff19a5850) at

../../gcc/varasm.c:1295

#5  0x0000000000cc8e4f in make_decl_rtl_for_debug (decl=0x7ffff19a5850) at

../../gcc/varasm.c:1350

#6  0x0000000000654bea in expand_debug_expr (exp=0x7ffff19a5850) at

../../gcc/cfgexpand.c:2777

#7  0x0000000000657357 in expand_debug_expr (exp=0x7ffff17ed460) at

../../gcc/cfgexpand.c:3358

#8  0x0000000000658b37 in expand_debug_locations () at

../../gcc/cfgexpand.c:3739

#9  0x000000000065b3c5 in gimple_expand_cfg () at ../../gcc/cfgexpand.c:4606

when creating DEBUG_IMPLICIT_PTR for the parameter s.  Then varpool_remove_node

is called:

#0  varpool_remove_node (node=0x7ffff19a6410) at ../../gcc/varpool.c:61

#1  0x0000000000cdb98a in varpool_remove_unreferenced_decls () at

../../gcc/varpool.c:406

#2  0x0000000000cdbb07 in varpool_output_variables () at

../../gcc/varpool.c:440

#3  0x0000000000686a00 in compile () at ../../gcc/cgraphunit.c:2044

#4  0x0000000000686b7a in finalize_compilation_unit () at

../../gcc/cgraphunit.c:2120

and finally get_named_section again:

#1  0x0000000000cc64dc in get_named_section (decl=0x7ffff19a5850,

name=0x7ffff17fdbf4 ".rodata.q.4121", reloc=0) at ../../gcc/varasm.c:411

#2  0x0000000000cc7d6c in get_variable_section (decl=0x7ffff19a5850,

prefer_noswitch_p=true) at ../../gcc/varasm.c:1030

#3  0x0000000000cc7f88 in get_block_for_decl (decl=0x7ffff19a5850) at

../../gcc/varasm.c:1076

#4  0x0000000000cc8a88 in make_decl_rtl (decl=0x7ffff19a5850) at

../../gcc/varasm.c:1295

#5  0x0000000000cc8e4f in make_decl_rtl_for_debug (decl=0x7ffff19a5850) at

../../gcc/varasm.c:1350

#6  0x00000000006f4d33 in rtl_for_decl_location (decl=0x7ffff19a5850) at

../../gcc/dwarf2out.c:15150

#7  0x00000000006f503f in add_location_or_const_value_attribute

(die=0x7ffff1805be0, decl=0x7ffff19a5850, cache_p=false, attr=DW_AT_location)

    at ../../gcc/dwarf2out.c:15244

#8  0x0000000000709d9b in dwarf2out_finish (filename=0x7fffffffe58b

"pr55395.i") at ../../gcc/dwarf2out.c:23218

#9  0x0000000000a3e2ce in compile_file () at ../../gcc/toplev.c:600



In the first case, DECL_INITIAL is not NULL, nor error_mark_node, nor zero

initializer, so rodata.q.4121 is assumed to be a read-only section, in the

second case DECL_INITIAL of q is already error_mark_node and thus rodata.q.4121

is assumed to be a bss section, therefore a section flags conflict.  In the

case of array initialized with a constant string right now the initializer

won't be useful, but I guess we could emit DW_OP_GNU_implicit_pointer in that

case, pointing to a DW_OP_implicit_value initialized artificial object.  But

there are tons of cases where DECL_INITIAL is even successfully used at

dwarf2out_finish time, e.g. during the deferred location processing.  So, if

you want to save memory, please do that solely if not emitting debug info.

So, I'd suggest replacing the

      /* dbxout output constant initializers for readonly vars.  */

      && (!host_integerp (DECL_INITIAL (node->symbol.decl), 0)

          || !TREE_READONLY (node->symbol.decl)))

part with

      && write_symbols == NO_DEBUG)

or ammending it with

      /* dwarf2out.c uses DECL_INITIAL even on optimized away decls,

         very late during compilation.  */

      && (write_symbols != DWARF2_DEBUG && write_symbols !=

VMS_AND_DWARF2_DEBUG)

Reply via email to