This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] Fix dw2gencfi.c .eh_frame alignment
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: binutils at sources dot redhat dot com
- Date: Wed, 18 Jun 2003 14:10:22 +0200
- Subject: [PATCH] Fix dw2gencfi.c .eh_frame alignment
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Mixing GCC generated .eh_frame with GAS generated one through .cfi*
directives does not work at all on 64-bit arches.
GCC aligns .eh_frame to PTR_SIZE while GAS aligns .eh_frame to 4,
which means if GAS generated .eh_frame is not multiple of 8 bytes
and it is followed by GCC generated .eh_frame, there will be a premature
terminating CIE in the padding which will end .eh_frame section.
Fixed thusly, provided GAS generated .eh_frame CIEs and FDEs don't need
any alignment (they don't use DW_EH_PE_aligned, so I think they don't).
If for some reason CIEs/FDEs need to be aligned to 4 bytes, frag_align
in output_cie should be kept and in output_fde it should be
frag_align (align ? align : 2, 0, 0); instead of the if.
2003-06-18 Jakub Jelinek <jakub@redhat.com>
* dw2gencfi.c (EH_FRAME_ALIGNMENT): Define if not defined.
(output_cie): Don't pad.
(output_fde): Add align argument. Pad to align if not 0.
(cfi_finish): Set .eh_frame alignment to EH_FRAME_ALIGNMENT.
Pad just last FDE to EH_FRAME_ALIGNMENT.
--- gas/dw2gencfi.c.jj 2003-06-17 03:59:16.000000000 -0400
+++ gas/dw2gencfi.c 2003-06-18 07:25:06.000000000 -0400
@@ -41,6 +41,14 @@
# endif
#endif
+#ifndef EH_FRAME_ALIGNMENT
+# ifdef BFD_ASSEMBLER
+# define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
+# else
+# define EH_FRAME_ALIGNMENT 2
+# endif
+#endif
+
#ifndef tc_cfi_frame_initial_instructions
# define tc_cfi_frame_initial_instructions() ((void)0)
#endif
@@ -836,13 +844,12 @@ output_cie (struct cie_entry *cie)
for (i = cie->first; i != cie->last; i = i->next)
output_cfi_insn (i);
- frag_align (2, 0, 0);
symbol_set_value_now (end_address);
}
static void
output_fde (struct fde_entry *fde, struct cie_entry *cie,
- struct cfi_insn_data *first)
+ struct cfi_insn_data *first, int align)
{
symbolS *after_size_address, *end_address;
expressionS exp;
@@ -874,7 +881,8 @@ output_fde (struct fde_entry *fde, struc
for (; first; first = first->next)
output_cfi_insn (first);
- frag_align (2, 0, 0);
+ if (align)
+ frag_align (align, 0, 0);
symbol_set_value_now (end_address);
}
@@ -990,7 +998,7 @@ cfi_finish (void)
SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY);
#endif
subseg_set (cfi_seg, 0);
- record_alignment (cfi_seg, 2);
+ record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
/* Make sure check_eh_frame doesn't do anything with our output. */
save_flag_traditional_format = flag_traditional_format;
@@ -1002,7 +1010,7 @@ cfi_finish (void)
struct cie_entry *cie;
cie = select_cie_for_fde (fde, &first);
- output_fde (fde, cie, first);
+ output_fde (fde, cie, first, fde->next == NULL ? EH_FRAME_ALIGNMENT : 0);
}
flag_traditional_format = save_flag_traditional_format;
Jakub