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

            Bug ID: 114116
           Summary: [14 Regression] Broken backtraces in bootstrapped
                    x86_64 gcc
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
  Target Milestone: ---

The expected ICE on
void
foo (void)
{
  unsigned _BitInt (575) a = 3;
  __builtin_clzg (a);
}
with -fno-tree-dce -O1 (might go away soon when PR114044 is fixed) is from
stage1-gcc/cc1
~/src/gcc/obj88/stage1-gcc/cc1 -quiet pr114044-2.c -fno-tree-dce -O1
during RTL pass: expand
pr114044-2.c: In function ‘foo’:
pr114044-2.c:5:3: internal compiler error: in expand_fn_using_insn, at
internal-fn.cc:208
    5 |   __builtin_clzg (a);
      |   ^~~~~~~~~~~~~~~~~~
0x12e77f6 expand_fn_using_insn
        ../../gcc/internal-fn.cc:208
0x12f6321 expand_direct_optab_fn
        ../../gcc/internal-fn.cc:3817
0x12fce16 expand_CLZ
        ../../gcc/internal-fn.def:444
0x12fdb14 expand_internal_call(internal_fn, gcall*)
        ../../gcc/internal-fn.cc:4913
0x12fdb3f expand_internal_call(gcall*)
        ../../gcc/internal-fn.cc:4921
0xf39343 expand_call_stmt
        ../../gcc/cfgexpand.cc:2771
0xf3e2db expand_gimple_stmt_1
        ../../gcc/cfgexpand.cc:3932
0xf3e99b expand_gimple_stmt
        ../../gcc/cfgexpand.cc:4077
0xf48362 expand_gimple_basic_block
        ../../gcc/cfgexpand.cc:6133
0xf4a9d2 execute
        ../../gcc/cfgexpand.cc:6872
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

but from gcc/cc1

during RTL pass: expand
pr114044-2.c: In function ‘foo’:
pr114044-2.c:5:3: internal compiler error: in expand_fn_using_insn, at
internal-fn.cc:208
    5 |   __builtin_clzg (a);
      |   ^~~~~~~~~~~~~~~~~~
0x7d9246 expand_fn_using_insn
        ../../gcc/internal-fn.cc:208

pr114044-2.c:5:3: internal compiler error: Segmentation fault
0x1554262 crash_signal
        ../../gcc/toplev.cc:319
0x2b20320 x86_64_fallback_frame_state
        ./md-unwind-support.h:63
0x2b20320 uw_frame_state_for
        ../../../libgcc/unwind-dw2.c:1013
0x2b2165d _Unwind_Backtrace
        ../../../libgcc/unwind.inc:303
0x2acbd69 backtrace_full
        ../../libbacktrace/backtrace.c:127
0x2a32fa6 diagnostic_context::action_after_output(diagnostic_t)
        ../../gcc/diagnostic.cc:781
0x2a331bb diagnostic_action_after_output(diagnostic_context*, diagnostic_t)
        ../../gcc/diagnostic.h:1002
0x2a331bb diagnostic_context::report_diagnostic(diagnostic_info*)
        ../../gcc/diagnostic.cc:1633
0x2a33543 diagnostic_impl
        ../../gcc/diagnostic.cc:1767
0x2a33c26 internal_error(char const*, ...)
        ../../gcc/diagnostic.cc:2225
0xe232c8 fancy_abort(char const*, int, char const*)
        ../../gcc/diagnostic.cc:2336
0x7d9246 expand_fn_using_insn
        ../../gcc/internal-fn.cc:208
Segmentation fault (core dumped)

I believe this is caused by the r14-8470 change.
The problem can be also seen when running the cc1 in the debugger.
When a breakpoint as added on fancy_abort (.gdbinit normally does that), the
backtrace still looks sane:
#0  fancy_abort (file=file@entry=0x2bd70fb "../../gcc/internal-fn.cc",
line=line@entry=208, function=function@entry=0x2bd76cf "expand_fn_using_insn")
at ../../gcc/diagnostic.cc:2313
#1  0x00000000007d9247 in expand_fn_using_insn (stmt=<optimized out>,
icode=CODE_FOR_nothing, ninputs=1, noutputs=1) at ../../gcc/internal-fn.cc:208
#2  0x0000000000fcd1d0 in expand_call_stmt (stmt=0x7fffea307000) at
../../gcc/cfgexpand.cc:2771
#3  expand_gimple_stmt_1 (stmt=<gimple_call 0x7fffea307000>) at
../../gcc/cfgexpand.cc:3932
#4  expand_gimple_stmt (stmt=<gimple_call 0x7fffea307000>) at
../../gcc/cfgexpand.cc:4077
#5  0x0000000000fcdf18 in expand_gimple_basic_block (bb=<optimized out>,
disable_tail_calls=false) at ../../gcc/cfgexpand.cc:6133
#6  0x0000000000fd059f in (anonymous namespace)::pass_expand::execute
(this=<optimized out>, fun=<optimized out>) at ../../gcc/cfgexpand.cc:6872
#7  0x000000000140bff8 in execute_one_pass (pass=<opt_pass* 0x3924c60
"expand"(271)>) at ../../gcc/passes.cc:2646
#8  0x000000000140c890 in execute_pass_list_1 (pass=<opt_pass* 0x3924c60
"expand"(271)>) at ../../gcc/passes.cc:2755
#9  0x000000000140c8c9 in execute_pass_list (fn=0x7fffea302000, pass=<optimized
out>) at ../../gcc/passes.cc:2766
#10 0x0000000001011a26 in cgraph_node::expand (this=<cgraph_node * const
0x7fffea144220 "foo"/0>) at ../../gcc/context.h:48
#11 cgraph_node::expand (this=<cgraph_node * const 0x7fffea144220 "foo"/0>) at
../../gcc/cgraphunit.cc:1798
#12 0x00000000010137fb in expand_all_functions () at
../../gcc/cgraphunit.cc:2028
#13 symbol_table::compile (this=0x7fffea130000) at ../../gcc/cgraphunit.cc:2402
#14 0x0000000001015e18 in symbol_table::compile (this=0x7fffea130000) at
../../gcc/cgraphunit.cc:2315
#15 symbol_table::finalize_compilation_unit (this=0x7fffea130000) at
../../gcc/cgraphunit.cc:2587
#16 0x0000000001554742 in compile_file () at ../../gcc/toplev.cc:476
#17 0x0000000000e281cc in do_compile () at ../../gcc/toplev.cc:2154
#18 toplev::main (this=this@entry=0x7fffffffdd4e, argc=<optimized out>,
argc@entry=5, argv=<optimized out>, argv@entry=0x7fffffffde78) at
../../gcc/toplev.cc:2310
#19 0x0000000000e299de in main (argc=5, argv=0x7fffffffde78) at
../../gcc/main.cc:39
and on fancy_abort's
=> 0x0000000000e2320f <+0>:     sub    $0x18,%rsp
   0x0000000000e23213 <+4>:     mov    0x28e7fd6(%rip),%rax        # 0x370b1f0
<global_dc>
   0x0000000000e2321a <+11>:    mov    %rdi,%r12
   0x0000000000e2321d <+14>:    mov    %esi,%ebp
   0x0000000000e2321f <+16>:    mov    %rdx,%rbx
prologue single stepping through the functions shows still correct backtrace at
0x0000000000e2321d but stepping one more yields:
#0  0x0000000000e2321f in fancy_abort (file=file@entry=0x2bd70fb
"../../gcc/internal-fn.cc", line=line@entry=208,
function=function@entry=0x2bd76cf "expand_fn_using_insn")
    at ../../gcc/diagnostic.cc:2303
#1  0x00000000007d9247 in expand_fn_using_insn (stmt=<optimized out>,
icode=<error reading variable: Cannot access memory at address 0x8c>, 
    ninputs=<error reading variable: Cannot access memory at address 0x98>,
noutputs=1) at ../../gcc/internal-fn.cc:208
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

The bug is obvious.  The caller of fancy_abort, expand_fn_using_insn starts
with
   0x000000000122f2e0 <+0>:     push   %rbp
   0x000000000122f2e1 <+1>:     mov    %rsp,%rbp
   0x000000000122f2e4 <+4>:     push   %r15
   0x000000000122f2e6 <+6>:     push   %r14
   0x000000000122f2e8 <+8>:     push   %r13
   0x000000000122f2ea <+10>:    push   %r12
   0x000000000122f2ec <+12>:    push   %rbx
   0x000000000122f2ed <+13>:    sub    $0x48,%rsp
in its unwind info says that CFA is based on the %rbp register:
0008a2c4 000000000000002c 0008a2c8 FDE cie=00000000
pc=000000000122f2e0..000000000122f695
  DW_CFA_advance_loc: 1 to 000000000122f2e1
  DW_CFA_def_cfa_offset: 16
  DW_CFA_offset: r6 (rbp) at cfa-16
  DW_CFA_advance_loc: 3 to 000000000122f2e4
  DW_CFA_def_cfa_register: r6 (rbp)
  DW_CFA_advance_loc: 13 to 000000000122f2f1
  DW_CFA_offset: r15 (r15) at cfa-24
  DW_CFA_offset: r14 (r14) at cfa-32
  DW_CFA_offset: r13 (r13) at cfa-40
  DW_CFA_offset: r12 (r12) at cfa-48
  DW_CFA_offset: r3 (rbx) at cfa-56
But then fancy_abort, being a noreturn function, since it doesn't bother to
save call saved registers, doesn't save %rbp and so backtrace from it is
impossible.

So, I think for the case where the user didn't use no_callee_saved_registers
attribute we should be saving at least hard frame pointer if the noreturn
function modifies it.
Backtraces still might not work properly if some caller decides to use some
other call saved register as CFA or use it in the computation of CFA, but that
should be fairly rare.  While using %rbp for CFA happens pretty much in every
function which needs a frame pointer.  And it doesn't have to be the immediate
caller, if the immediate caller doesn't use frame pointer and doesn't use %rbp
register for anything, it can be its caller, etc.

Reply via email to