https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80848
Alexey Neyman <stilor at att dot net> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |stilor at att dot net --- Comment #1 from Alexey Neyman <stilor at att dot net> --- I have looked at this issue when the problem was reported in crosstool-NG tracker [1]. The issue started with the commit 66035fd [2]; the link at [3] explains in more detail the problem that commit tried to solve. After that change, BFD trips over this check [4]: 724 if (hdr_length == 0) 725 { 726 /* A zero-length CIE should only be found at the end of 727 the section. */ 728 REQUIRE ((bfd_size_type) (buf - ehbuf) == sec->size); 729 ENSURE_NO_RELOCS (buf); 730 sec_info->count++; 731 break; 732 } The crtend.o generated by the build has the following in .eh_frame: [[[[ alphaev4-unknown-linux-gnu-readelf -wf .build/alphaev4-unknown-linux-gnu/buildtools/lib/gcc/alphaev4-unknown-linux-gnu/4.8.4/crtend.o Contents of the .eh_frame section: 00000000 ZERO terminator 00000004 0000000000000010 00000000 CIE Version: 1 Augmentation: "zR" Code alignment factor: 4 Data alignment factor: -8 Return address column: 26 Augmentation data: 1b DW_CFA_def_cfa_register: r30 DW_CFA_nop 00000018 0000000000000024 00000018 FDE cie=00000004 pc=0000000000000000..0000000000000070 DW_CFA_advance_loc: 20 to 0000000000000014 DW_CFA_def_cfa_offset: 32 DW_CFA_advance_loc: 12 to 0000000000000020 DW_CFA_offset: r9 at cfa-24 DW_CFA_advance_loc: 8 to 0000000000000028 DW_CFA_offset: r10 at cfa-16 DW_CFA_advance_loc: 8 to 0000000000000030 DW_CFA_offset: r26 at cfa-32 DW_CFA_advance_loc: 60 to 000000000000006c DW_CFA_restore: r10 DW_CFA_restore: r9 DW_CFA_restore: r26 DW_CFA_def_cfa_offset: 0 DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop ]]]] I.e., the zero terminator is indeed not the last record. GCC produces the following assembly when compiling crtstuff.c into crtend.o (skipping irrelevant parts): [[[[ .section .eh_frame,"a",@progbits .align 2 .type __FRAME_END__, @object __FRAME_END__: .zero 4 ... __do_global_ctors_aux: $LFB9: .cfi_startproc ldah $29,0($27) !gpdisp!1 lda $29,0($29) !gpdisp!1 ]]]] That is, GCC generates both the explicit zero terminator as well as the CFI instructions that make the assembler generate additional CIE/FDE records. Adding -fno-asynchronous-unwind-tables and/or -fno-exceptions has no effect. Adding -fno-dwarf2-cfi-insns makes GCC emit a second .eh_section fragment with explicitly generated DWARF2 bytecode. In both cases, the result is an invalid .eh_frame section with zero terminator record not being the last. In other words, there is no way to prevent GCC from emitting any additional content into the .eh_frame section, aside from the terminator. - So, the question is, how should this be fixed? - Was [2] a correct change to begin with? - Should alpha (in addition to [2], or instead of [2]) implement a custom "alpha_except_unwind_info" that will return UI_NONE if exceptions are disabled (and then use that while compiling crtend.o)? - Or if CFI is desired for __do_global_ctors_aux, perhaps compile this routine separately into, say, crtend1.o; then compile the data-only section terminators into crtend2.o; and then do a `ld -r` of both crtend[12].o into crtend.o? [1] https://github.com/crosstool-ng/crosstool-ng/issues/719 [2] https://github.com/gcc-mirror/gcc/commit/66035fd81f6fb8dff84e0c64d52ed041450fdebc [3] https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01680.html [4] https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=bfd/elf-eh-frame.c;h=52ba9c62138bb7d2c8901d961ba322dbfe23e220;hb=HEAD#l724