On targets where -funwind-tables is not enabled by default doing gcc -c -flto -funwind-tables t.c -g gcc t.o -g ends up without unwind tables even if the flags state is recorded in per-function settings. dwarf2out.c suggests the state is accumulated from all functions in the TU /* Unlike the debug version, the EH version of frame unwind info is a per- function setting so we need to record whether we need it for the unit. */ do_eh_frame |= dwarf2out_do_eh_frame (); but that doesn't work since dwarf2out_do_eh_frame looks at the global flag_unwind_tables (and global flag_exceptions and passes global opts to the target hook). We probably can switch between EH-frame and debug-frame per function but a way out would be to handle flag_{,asynchronous_}unwind_tables in lto-wrapper. Eric was here fixing the similar PR81351. One target where this shows is riscv.
Eric - was the intent of the PR81351 fix that the dwarf2out_do_eh_frame () works per function? We could also fix this similar to how we do lto_init_eh which forces the global flag_exceptions to 1, force flag_unwind_tables to 1 in case any function had it enabled (that's still finer-grained than enabling it for all LTRANS units via lto-wrapper). Similar on targets where EH unwind is the default disabling it via -fno-unwind-tables would have no effect with LTO even if all functions have it disabled.
So one possible fix would be Index: gcc/dwarf2cfi.c =================================================================== --- gcc/dwarf2cfi.c (revision 275639) +++ gcc/dwarf2cfi.c (working copy) @@ -3489,7 +3489,7 @@ bool dwarf2out_do_eh_frame (void) { return - (flag_unwind_tables || flag_exceptions) + (opt_for_fn (cfun->decl, flag_unwind_tables) || flag_exceptions) && targetm_common.except_unwind_info (&global_options) == UI_DWARF2; } note this predicate also controls the 'dwarf2' RTL pass so you'd get per function CFI notes(?).
Created attachment 46890 [details] patch for lto-wrapper This instead makes lto-wrapper append -funwind-tables when one CU had that enabled.
Created attachment 46891 [details] fixed patch
> Eric - was the intent of the PR81351 fix that the dwarf2out_do_eh_frame () > works per function? No, dwarf2out_do_eh_frame is global but whether the CFI for EH is emitted is decided on a per-function basis in the end, see my explanation in: https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00771.html
(In reply to Eric Botcazou from comment #5) > > Eric - was the intent of the PR81351 fix that the dwarf2out_do_eh_frame () > > works per function? > > No, dwarf2out_do_eh_frame is global but whether the CFI for EH is emitted is > decided on a per-function basis in the end, see my explanation in: > https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00771.html Hmm, that doesn't give a lot of detail. Clearly it doesn't yet work. I see dwarf2out_do_eh_frame is also used as gate for the "dwarf2" pass. That probably should use per-function settings then, thus an alternate predicate? Because the global setting simply tells the assembler to either emit everything into eh_frame or debug_frame (seems the assembler cannot have different settings on a per function basis?). So I guess an appropriate cleanup would be to pass a struct function to dwarf2out_do_eh_frame but also deal with it being NULL?
> So I guess an appropriate cleanup would be to pass a struct function > to dwarf2out_do_eh_frame but also deal with it being NULL? You need to ask Jan, my fix for 81351 was minimal and based on his insight.