public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug other/111629] New: [14 Regression] ggc_common_finalize() corrupts global memory outsuide GTY(()) objects
@ 2023-09-28 13:26 slyfox at gcc dot gnu.org
  2023-09-28 14:14 ` [Bug other/111629] " pinskia at gcc dot gnu.org
  2023-09-28 14:17 ` pinskia at gcc dot gnu.org
  0 siblings, 2 replies; 3+ messages in thread
From: slyfox at gcc dot gnu.org @ 2023-09-28 13:26 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 111629
           Summary: [14 Regression] ggc_common_finalize() corrupts global
                    memory outsuide GTY(()) objects
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: slyfox at gcc dot gnu.org
  Target Milestone: ---

Initially I observed the bug as a gcc profiled bootstrap failure on
r14-4300-g1fab05a885a308:

$ ~/dev/git/gcc/configure --disable-multilib --enable-languages=c,c++ 'CC=gcc
-O2 -ggdb3' 'CXX=g++ -O2 -ggdb3'
$ make profiledbootstrap
configure: error: uint64_t or int64_t not found
$ touch a.c &&  /tmp/gb/./prev-gcc/xg++ -B/tmp/gb/./prev-gcc/ -c a.c
xg++: internal compiler error: Segmentation fault signal terminated program
cc1plus

While it look slike a profile-related problem I think it's just a coincidence:
it's a side-effect of gcov globals corruption exposed by
`ggc_common_finalize()`.

`ggc_common_finalize()` is supposed to memset() GTY(()) globals, but its
slightly out of bounds and corrupts gcov.

Debugging:

$ gdb --args /tmp/gb/./prev-gcc/cc1plus -quiet -v -iprefix
/tmp/gb/prev-gcc/../lib/gcc/x86_64-pc-linux-gnu/14.0.0/ -isystem
/tmp/gb/./prev-gcc/include -isystem /tmp/gb/./prev-gcc/include-fixed
-D_GNU_SOURCE a.c -quiet -dumpbase a.c -dumpbase-ext .c -mtune=generic
-march=x86-64 -version -o /run/user/1000/ccA6Gln1.s
(gdb) run
...
Program received signal SIGSEGV, Segmentation fault.
0x000000000442ab26 in gcov_do_dump (list=0x5cab0e0, run_counted=0, mode=0) at
/home/slyfox/dev/git/gcc/libgcc/libgcov-driver.c:690
690             for (unsigned i = 0; i < cinfo->num; i++)

(gdb) list
685         for (unsigned f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
f_ix++)
686           {
687             const struct gcov_ctr_info *cinfo
688               = &gi_ptr->functions[f_ix]->ctrs[GCOV_COUNTER_ARCS];

(gdb) p gi_ptr->functions[f_ix]
$1 = (const gcov_fn_info * const) 0x0

 === This is a corruption: `gi_ptr->functions[f_ix]` are gcov.* global
counters.  
 === They are never expected to be zero. Looking up place of corruption:

(gdb) p &gi_ptr->functions[f_ix]
$2 = (const gcov_fn_info * const *) 0x50c1540
(gdb) watch -l *(void**)0x50c1540
Hardware watchpoint 1: -location *(void**)0x50c1540
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Hardware watchpoint 1: -location *(void**)0x50c1540

Old value = (void *) 0x50c4080
<__gcov_._ZN10hash_tableI18subsumption_hasherLb0E11xcallocatorE26find_empty_slot_for_expandEj>
New value = (void *) 0x50c4000
__memset_avx2_unaligned_erms () at
../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:328
328     ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: No such file
or directory.
(gdb) bt
#0  __memset_avx2_unaligned_erms () at
../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:328
#1  0x0000000001933651 in ggc_common_finalize () at
/home/slyfox/dev/git/gcc/gcc/ggc-common.cc:1312
#2  0x00000000020d7cf1 in toplev::finalize (this=this@entry=0x7fffffffaece) at
/home/slyfox/dev/git/gcc/gcc/toplev.cc:2354
#3  0x0000000000c640b6 in main (argc=<optimized out>, argv=0x7fffffffaff8) at
/home/slyfox/dev/git/gcc/gcc/main.cc:42
(gdb) fr 1
#1  0x0000000001933651 in ggc_common_finalize () at
/home/slyfox/dev/git/gcc/gcc/ggc-common.cc:1312
1312          memset (rti->base, 0, rti->stride * rti->nelt);
(gdb) list
1307        for (rti = *rt; rti->base != NULL; rti++)
1308          memset (rti->base, 0, rti->stride * rti->nelt);
1309
1310      for (rt = gt_ggc_rtab; *rt; rt++)
1311        for (rti = *rt; rti->base != NULL; rti++)
1312          memset (rti->base, 0, rti->stride * rti->nelt);
1313
1314      for (rt = gt_pch_scalar_rtab; *rt; rt++)
1315        for (rti = *rt; rti->base != NULL; rti++)
1316          memset (rti->base, 0, rti->stride * rti->nelt);

 === What ggc are we destroying?

(gdb) p *rt
$3 = (const ggc_root_tab * const) 0x448e320 <gt_ggc_r_gt_cp_tree_h>
(gdb) p rti - *rt
$4 = 5

Fifth element of gt_ggc_r_gt_cp_tree_h:

From prev-gcc/gt-cp-tree.h:

/* Structures for the easy way to mark roots.
   In an array, terminated by having base == NULL.  */
struct ggc_root_tab {
  void *base;
  size_t nelt;
  size_t stride;
  gt_pointer_walker cb;
  gt_pointer_walker pchw;
};

EXPORTED_CONST struct ggc_root_tab gt_ggc_r_gt_cp_tree_h[] = {
...
  { // 4
    &ovl_op_info[0][0].identifier,
    1 * (2) * (OVL_OP_MAX),
    sizeof (ovl_op_info[0][0]),
    &gt_ggc_mx_tree_node,
    &gt_pch_nx_tree_node
  },
  { // 5
    &ovl_op_info[0][0].name,
    1 * (2) * (OVL_OP_MAX),
    sizeof (ovl_op_info[0][0]),
    (gt_pointer_walker) &gt_ggc_m_S,
    (gt_pointer_walker) &gt_pch_n_S
  },
  { //6
    &ovl_op_info[0][0].mangled_name,
    1 * (2) * (OVL_OP_MAX),
    sizeof (ovl_op_info[0][0]),
    (gt_pointer_walker) &gt_ggc_m_S,
    (gt_pointer_walker) &gt_pch_n_S
  },

  === Note how 'base' points not at the beginning of the whole
'ovl_op_info[0][0])' but at the GTY()) field itself within the struct:

struct GTY(()) ovl_op_info_t {
  /* The IDENTIFIER_NODE for the operator.  */
  tree identifier;
  /* The name of the operator.  */
  const char *name;
  /* The mangled name of the operator.  */
  const char *mangled_name;
  /* The (regular) tree code.  */
  enum tree_code tree_code : 16;
  /* The (compressed) operator code.  */
  enum ovl_op_code ovl_op_code : 8;
  /* The ovl_op_flags of the operator */
  unsigned flags : 8;
};

/* Overloaded operator info indexed by ass_op_p & ovl_op_code.  */
extern GTY(()) ovl_op_info_t ovl_op_info[2][OVL_OP_MAX];

 === Done.

I think `ggc_common_finalize()`'s intent is to memset() the whole struct, but
it has no pointer to that struct. Sounds about right? What would be the best
fix here? Just zero out pointers? Sounds a bit risky, but might be fine?

Compiler version:

$ /tmp/gb/./prev-gcc/xg++ -B/tmp/gb/./prev-gcc/ -v
Reading specs from /tmp/gb/./prev-gcc/specs
COLLECT_GCC=/tmp/gb/./prev-gcc/xg++
COLLECT_LTO_WRAPPER=/tmp/gb/./prev-gcc/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /home/slyfox/dev/git/gcc/configure --disable-multilib
--enable-languages=c,c++ CC='gcc -O2 -ggdb3' CXX='g++ -O2 -ggdb3'
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 14.0.0 20230926 (experimental) (GCC)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug other/111629] [14 Regression] ggc_common_finalize() corrupts global memory outsuide GTY(()) objects
  2023-09-28 13:26 [Bug other/111629] New: [14 Regression] ggc_common_finalize() corrupts global memory outsuide GTY(()) objects slyfox at gcc dot gnu.org
@ 2023-09-28 14:14 ` pinskia at gcc dot gnu.org
  2023-09-28 14:17 ` pinskia at gcc dot gnu.org
  1 sibling, 0 replies; 3+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-09-28 14:14 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
There is a dup of this where valgrind complains.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug other/111629] [14 Regression] ggc_common_finalize() corrupts global memory outsuide GTY(()) objects
  2023-09-28 13:26 [Bug other/111629] New: [14 Regression] ggc_common_finalize() corrupts global memory outsuide GTY(()) objects slyfox at gcc dot gnu.org
  2023-09-28 14:14 ` [Bug other/111629] " pinskia at gcc dot gnu.org
@ 2023-09-28 14:17 ` pinskia at gcc dot gnu.org
  1 sibling, 0 replies; 3+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-09-28 14:17 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |DUPLICATE
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Dup of bug 111505.

*** This bug has been marked as a duplicate of bug 111505 ***

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-09-28 14:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-28 13:26 [Bug other/111629] New: [14 Regression] ggc_common_finalize() corrupts global memory outsuide GTY(()) objects slyfox at gcc dot gnu.org
2023-09-28 14:14 ` [Bug other/111629] " pinskia at gcc dot gnu.org
2023-09-28 14:17 ` pinskia at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).