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

Reply via email to