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

--- Comment #18 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
It is a fundamental assumption that the FDE/CIE chain is zero terminated, after
all, all the registration APIs (__register_frame_table,
__register_frame_info_table, __register_frame_info_table_bases) take just a
begin pointer, not a begin and end pointer nor begin + count or something
similar, nor assume there is just one FDE (after all, a FDE needs some CIE, so
there would need to be a routine that expects exactly two or something
similar).

When not using .eh_frame_hdr (which is used most of the time on glibc since end
of 2001 when I've added it and somewhat later on Solaris etc.),
crtbegin.o/crtend.o ensures this, crtbegin.o provides a label at the start of
.eh_frame and is linked first among the objects:
/* Stick a label at the beginning of the frame unwind info so we can register
   and deregister it with the exception handling library code.  */
STATIC EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
     __attribute__((section(__LIBGCC_EH_FRAME_SECTION_NAME__), aligned(4)))
     = { };
while crtend.o provides the zero termination:
/* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
   this would be the 'length' field in a real FDE.  */
# if __INT_MAX__ == 2147483647
typedef int int32;
# elif __LONG_MAX__ == 2147483647
typedef long int32;
# elif __SHRT_MAX__ == 2147483647
typedef short int32;
# else
#  error "Missing a 4 byte integer"
# endif
STATIC EH_FRAME_SECTION_CONST int32 __FRAME_END__[]
     __attribute__ ((used, section(__LIBGCC_EH_FRAME_SECTION_NAME__),
                     aligned(__alignof__(int32))))
     = { 0 };
and is linked last.
I believe LLVM does the same thing in compiler-rt/lib/crt/crtbegin.c and
compiler-rt/lib/crt/crtend.c .
If you readelf -wf any_binary_or_library
it should show
00330010 ZERO terminator
line (with whatever address) at the end.

Reply via email to