This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix dw2gencfi.c .eh_frame alignment


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]