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]), >_ggc_mx_tree_node, >_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) >_ggc_m_S, (gt_pointer_walker) >_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) >_ggc_m_S, (gt_pointer_walker) >_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)
There is a dup of this where valgrind complains.
Dup of bug 111505. *** This bug has been marked as a duplicate of bug 111505 ***