Jakub Jelinek 7be905
2009-10-02  Jakub Jelinek  <jakub@redhat.com>
Jakub Jelinek 7be905
Jakub Jelinek 7be905
	* dw2gencfi.c: Include dwarf2dbg.h.
Jakub Jelinek 7be905
	(DWARF2_FORMAT): Define if not defined.
Jakub Jelinek 7be905
	(dot_cfi_sections): New function.
Jakub Jelinek 7be905
	(cfi_pseudo_table): Handle .cfi_sections.
Jakub Jelinek 7be905
	(CFI_EMIT_eh_frame, CFI_EMIT_debug_frame): Define.
Jakub Jelinek 7be905
	(cfi_sections): New variable.
Jakub Jelinek 7be905
	(output_cie, output_fde, select_cie_for_fde): Add eh_frame
Jakub Jelinek 7be905
	argument, add supporting for outputting .debug_frame
Jakub Jelinek 7be905
	section.
Jakub Jelinek 7be905
	(cfi_change_reg_numbers): New function or macro.
Jakub Jelinek 7be905
	(cfi_finish): Only emit .eh_frame if
Jakub Jelinek 7be905
	cfi_sections & CFI_EMIT_eh_frame.  Emit .debug_frame if
Jakub Jelinek 7be905
	cfi_sections & CFI_EMIT_debug_frame.
Jakub Jelinek 7be905
	* config/tc-ppc.h (md_reg_eh_frame_to_debug_frame): Define.
Jakub Jelinek 7be905
	* doc/as.texinfo (CFI directives): Document .cfi_sections.
Jakub Jelinek 7be905
Jakub Jelinek 7be905
--- gas/dw2gencfi.c	11 Sep 2009 15:27:33 -0000	1.43
Jakub Jelinek 7be905
+++ gas/dw2gencfi.c	2 Oct 2009 11:33:49 -0000	1.44
Jakub Jelinek 7be905
@@ -23,6 +23,7 @@
Jakub Jelinek 7be905
 #include "as.h"
Jakub Jelinek 7be905
 #include "dw2gencfi.h"
Jakub Jelinek 7be905
 #include "subsegs.h"
Jakub Jelinek 7be905
+#include "dwarf2dbg.h"
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 #ifdef TARGET_USE_CFIPOP
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
@@ -59,6 +60,10 @@
Jakub Jelinek 7be905
 # define tc_cfi_frame_initial_instructions() ((void)0)
Jakub Jelinek 7be905
 #endif
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
+#ifndef DWARF2_FORMAT
Jakub Jelinek 7be905
+# define DWARF2_FORMAT(SEC) dwarf2_format_32bit
Jakub Jelinek 7be905
+#endif
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
 #ifndef DWARF2_ADDR_SIZE
Jakub Jelinek 7be905
 # define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8)
Jakub Jelinek 7be905
 #endif
Jakub Jelinek 7be905
@@ -386,6 +391,7 @@ cfi_add_CFA_restore_state (void)
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 static void dot_cfi (int);
Jakub Jelinek 7be905
 static void dot_cfi_escape (int);
Jakub Jelinek 7be905
+static void dot_cfi_sections (int);
Jakub Jelinek 7be905
 static void dot_cfi_startproc (int);
Jakub Jelinek 7be905
 static void dot_cfi_endproc (int);
Jakub Jelinek 7be905
 static void dot_cfi_personality (int);
Jakub Jelinek 7be905
@@ -402,6 +408,7 @@ static void dot_cfi_val_encoded_addr (in
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 const pseudo_typeS cfi_pseudo_table[] =
Jakub Jelinek 7be905
   {
Jakub Jelinek 7be905
+    { "cfi_sections", dot_cfi_sections, 0 },
Jakub Jelinek 7be905
     { "cfi_startproc", dot_cfi_startproc, 0 },
Jakub Jelinek 7be905
     { "cfi_endproc", dot_cfi_endproc, 0 },
Jakub Jelinek 7be905
     { "cfi_def_cfa", dot_cfi, DW_CFA_def_cfa },
Jakub Jelinek 7be905
@@ -864,6 +871,56 @@ dot_cfi_val_encoded_addr (int ignored AT
Jakub Jelinek 7be905
   demand_empty_rest_of_line ();
Jakub Jelinek 7be905
 }
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
+/* By default emit .eh_frame only, not .debug_frame.  */
Jakub Jelinek 7be905
+#define CFI_EMIT_eh_frame	(1 << 0)
Jakub Jelinek 7be905
+#define CFI_EMIT_debug_frame	(1 << 1)
Jakub Jelinek 7be905
+static int cfi_sections = CFI_EMIT_eh_frame;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+static void
Jakub Jelinek 7be905
+dot_cfi_sections (int ignored ATTRIBUTE_UNUSED)
Jakub Jelinek 7be905
+{
Jakub Jelinek 7be905
+  int sections = 0;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+  SKIP_WHITESPACE ();
Jakub Jelinek 7be905
+  if (is_name_beginner (*input_line_pointer))
Jakub Jelinek 7be905
+    while (1)
Jakub Jelinek 7be905
+      {
Jakub Jelinek 7be905
+	char *name, c;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+	name = input_line_pointer;
Jakub Jelinek 7be905
+	c = get_symbol_end ();
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+	if (strcmp (name, ".eh_frame") == 0)
Jakub Jelinek 7be905
+	  sections |= CFI_EMIT_eh_frame;
Jakub Jelinek 7be905
+	else if (strcmp (name, ".debug_frame") == 0)
Jakub Jelinek 7be905
+	  sections |= CFI_EMIT_debug_frame;
Jakub Jelinek 7be905
+	else
Jakub Jelinek 7be905
+	  {
Jakub Jelinek 7be905
+	    *input_line_pointer = c;
Jakub Jelinek 7be905
+	    input_line_pointer = name;
Jakub Jelinek 7be905
+	    break;
Jakub Jelinek 7be905
+	  }
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+	*input_line_pointer = c;
Jakub Jelinek 7be905
+	SKIP_WHITESPACE ();
Jakub Jelinek 7be905
+	if (*input_line_pointer == ',')
Jakub Jelinek 7be905
+	  {
Jakub Jelinek 7be905
+	    name = input_line_pointer++;
Jakub Jelinek 7be905
+	    SKIP_WHITESPACE ();
Jakub Jelinek 7be905
+	    if (!is_name_beginner (*input_line_pointer))
Jakub Jelinek 7be905
+	      {
Jakub Jelinek 7be905
+		input_line_pointer = name;
Jakub Jelinek 7be905
+		break;
Jakub Jelinek 7be905
+	      }
Jakub Jelinek 7be905
+	  }
Jakub Jelinek 7be905
+	else if (is_name_beginner (*input_line_pointer))
Jakub Jelinek 7be905
+	  break;
Jakub Jelinek 7be905
+      }
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+  demand_empty_rest_of_line ();
Jakub Jelinek 7be905
+  cfi_sections = sections;
Jakub Jelinek 7be905
+}
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
 static void
Jakub Jelinek 7be905
 dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
Jakub Jelinek 7be905
 {
Jakub Jelinek 7be905
@@ -1194,13 +1251,14 @@ encoding_size (unsigned char encoding)
Jakub Jelinek 7be905
 }
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 static void
Jakub Jelinek 7be905
-output_cie (struct cie_entry *cie)
Jakub Jelinek 7be905
+output_cie (struct cie_entry *cie, bfd_boolean eh_frame, int align)
Jakub Jelinek 7be905
 {
Jakub Jelinek 7be905
   symbolS *after_size_address, *end_address;
Jakub Jelinek 7be905
   expressionS exp;
Jakub Jelinek 7be905
   struct cfi_insn_data *i;
Jakub Jelinek 7be905
   offsetT augmentation_size;
Jakub Jelinek 7be905
   int enc;
Jakub Jelinek 7be905
+  enum dwarf2_format fmt = DWARF2_FORMAT (now_seg);
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
   cie->start_address = symbol_temp_new_now ();
Jakub Jelinek 7be905
   after_size_address = symbol_temp_make ();
Jakub Jelinek 7be905
@@ -1211,18 +1269,35 @@ output_cie (struct cie_entry *cie)
Jakub Jelinek 7be905
   exp.X_op_symbol = after_size_address;
Jakub Jelinek 7be905
   exp.X_add_number = 0;
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-  emit_expr (&exp, 4);				/* Length.  */
Jakub Jelinek 7be905
+  if (eh_frame || fmt == dwarf2_format_32bit)
Jakub Jelinek 7be905
+    emit_expr (&exp, 4);			/* Length.  */
Jakub Jelinek 7be905
+  else
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      if (fmt == dwarf2_format_64bit)
Jakub Jelinek 7be905
+	out_four (-1);
Jakub Jelinek 7be905
+      emit_expr (&exp, 8);			/* Length.  */
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
   symbol_set_value_now (after_size_address);
Jakub Jelinek 7be905
-  out_four (0);					/* CIE id.  */
Jakub Jelinek 7be905
+  if (eh_frame)
Jakub Jelinek 7be905
+    out_four (0);				/* CIE id.  */
Jakub Jelinek 7be905
+  else
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      out_four (-1);				/* CIE id.  */
Jakub Jelinek 7be905
+      if (fmt != dwarf2_format_32bit)
Jakub Jelinek 7be905
+	out_four (-1);
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
   out_one (DW_CIE_VERSION);			/* Version.  */
Jakub Jelinek 7be905
-  out_one ('z');				/* Augmentation.  */
Jakub Jelinek 7be905
-  if (cie->per_encoding != DW_EH_PE_omit)
Jakub Jelinek 7be905
-    out_one ('P');
Jakub Jelinek 7be905
-  if (cie->lsda_encoding != DW_EH_PE_omit)
Jakub Jelinek 7be905
-    out_one ('L');
Jakub Jelinek 7be905
-  out_one ('R');
Jakub Jelinek 7be905
-  if (cie->signal_frame)
Jakub Jelinek 7be905
-    out_one ('S');
Jakub Jelinek 7be905
+  if (eh_frame)
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      out_one ('z');				/* Augmentation.  */
Jakub Jelinek 7be905
+      if (cie->per_encoding != DW_EH_PE_omit)
Jakub Jelinek 7be905
+	out_one ('P');
Jakub Jelinek 7be905
+      if (cie->lsda_encoding != DW_EH_PE_omit)
Jakub Jelinek 7be905
+	out_one ('L');
Jakub Jelinek 7be905
+      out_one ('R');
Jakub Jelinek 7be905
+      if (cie->signal_frame)
Jakub Jelinek 7be905
+	out_one ('S');
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
   out_one (0);
Jakub Jelinek 7be905
   out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH);	/* Code alignment.  */
Jakub Jelinek 7be905
   out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);	/* Data alignment.  */
Jakub Jelinek 7be905
@@ -1230,10 +1305,13 @@ output_cie (struct cie_entry *cie)
Jakub Jelinek 7be905
     out_one (cie->return_column);
Jakub Jelinek 7be905
   else
Jakub Jelinek 7be905
     out_uleb128 (cie->return_column);
Jakub Jelinek 7be905
-  augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit);
Jakub Jelinek 7be905
-  if (cie->per_encoding != DW_EH_PE_omit)
Jakub Jelinek 7be905
-    augmentation_size += 1 + encoding_size (cie->per_encoding);
Jakub Jelinek 7be905
-  out_uleb128 (augmentation_size);		/* Augmentation size.  */
Jakub Jelinek 7be905
+  if (eh_frame)
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit);
Jakub Jelinek 7be905
+      if (cie->per_encoding != DW_EH_PE_omit)
Jakub Jelinek 7be905
+	augmentation_size += 1 + encoding_size (cie->per_encoding);
Jakub Jelinek 7be905
+      out_uleb128 (augmentation_size);		/* Augmentation size.  */
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
   if (cie->per_encoding != DW_EH_PE_omit)
Jakub Jelinek 7be905
     {
Jakub Jelinek 7be905
       offsetT size = encoding_size (cie->per_encoding);
Jakub Jelinek 7be905
@@ -1274,23 +1352,28 @@ output_cie (struct cie_entry *cie)
Jakub Jelinek 7be905
 #if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
Jakub Jelinek 7be905
   enc |= DW_EH_PE_pcrel;
Jakub Jelinek 7be905
 #endif
Jakub Jelinek 7be905
-  out_one (enc);
Jakub Jelinek 7be905
+  if (eh_frame)
Jakub Jelinek 7be905
+    out_one (enc);
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
   if (cie->first)
Jakub Jelinek 7be905
     for (i = cie->first; i != cie->last; i = i->next)
Jakub Jelinek 7be905
       output_cfi_insn (i);
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-  frag_align (2, DW_CFA_nop, 0);
Jakub Jelinek 7be905
+  frag_align (align, DW_CFA_nop, 0);
Jakub Jelinek 7be905
   symbol_set_value_now (end_address);
Jakub Jelinek 7be905
 }
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 static void
Jakub Jelinek 7be905
 output_fde (struct fde_entry *fde, struct cie_entry *cie,
Jakub Jelinek 7be905
-	    struct cfi_insn_data *first, int align)
Jakub Jelinek 7be905
+	    bfd_boolean eh_frame, struct cfi_insn_data *first,
Jakub Jelinek 7be905
+	    int align)
Jakub Jelinek 7be905
 {
Jakub Jelinek 7be905
   symbolS *after_size_address, *end_address;
Jakub Jelinek 7be905
   expressionS exp;
Jakub Jelinek 7be905
   offsetT augmentation_size;
Jakub Jelinek 7be905
+  enum dwarf2_format fmt = DWARF2_FORMAT (now_seg);
Jakub Jelinek 7be905
+  int offset_size;
Jakub Jelinek 7be905
+  int addr_size;
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
   after_size_address = symbol_temp_make ();
Jakub Jelinek 7be905
   end_address = symbol_temp_make ();
Jakub Jelinek 7be905
@@ -1299,35 +1382,63 @@ output_fde (struct fde_entry *fde, struc
Jakub Jelinek 7be905
   exp.X_add_symbol = end_address;
Jakub Jelinek 7be905
   exp.X_op_symbol = after_size_address;
Jakub Jelinek 7be905
   exp.X_add_number = 0;
Jakub Jelinek 7be905
-  emit_expr (&exp, 4);				/* Length.  */
Jakub Jelinek 7be905
+  if (eh_frame || fmt == dwarf2_format_32bit)
Jakub Jelinek 7be905
+    offset_size = 4;
Jakub Jelinek 7be905
+  else
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      if (fmt == dwarf2_format_64bit)
Jakub Jelinek 7be905
+	out_four (-1);
Jakub Jelinek 7be905
+      offset_size = 8;
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
+  emit_expr (&exp, offset_size);		/* Length.  */
Jakub Jelinek 7be905
   symbol_set_value_now (after_size_address);
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-  exp.X_add_symbol = after_size_address;
Jakub Jelinek 7be905
-  exp.X_op_symbol = cie->start_address;
Jakub Jelinek 7be905
-  emit_expr (&exp, 4);				/* CIE offset.  */
Jakub Jelinek 7be905
+  if (eh_frame)
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      exp.X_add_symbol = after_size_address;
Jakub Jelinek 7be905
+      exp.X_op_symbol = cie->start_address;
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
+  else
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      exp.X_op = O_symbol;
Jakub Jelinek 7be905
+      exp.X_add_symbol = cie->start_address;
Jakub Jelinek 7be905
+      exp.X_op_symbol = NULL;
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
+  emit_expr (&exp, offset_size);		/* CIE offset.  */
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
+  if (eh_frame)
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
 #if CFI_DIFF_EXPR_OK
Jakub Jelinek 7be905
-  exp.X_add_symbol = fde->start_address;
Jakub Jelinek 7be905
-  exp.X_op_symbol = symbol_temp_new_now ();
Jakub Jelinek 7be905
-  emit_expr (&exp, DWARF2_FDE_RELOC_SIZE);	/* Code offset.  */
Jakub Jelinek 7be905
+      exp.X_add_symbol = fde->start_address;
Jakub Jelinek 7be905
+      exp.X_op_symbol = symbol_temp_new_now ();
Jakub Jelinek 7be905
+      emit_expr (&exp, DWARF2_FDE_RELOC_SIZE);	/* Code offset.  */
Jakub Jelinek 7be905
 #else
Jakub Jelinek 7be905
-  exp.X_op = O_symbol;
Jakub Jelinek 7be905
-  exp.X_add_symbol = fde->start_address;
Jakub Jelinek 7be905
-  exp.X_op_symbol = NULL;
Jakub Jelinek 7be905
+      exp.X_op = O_symbol;
Jakub Jelinek 7be905
+      exp.X_add_symbol = fde->start_address;
Jakub Jelinek 7be905
+      exp.X_op_symbol = NULL;
Jakub Jelinek 7be905
 #ifdef tc_cfi_emit_pcrel_expr
Jakub Jelinek 7be905
-  tc_cfi_emit_pcrel_expr (&exp, DWARF2_FDE_RELOC_SIZE);	 /* Code offset.  */
Jakub Jelinek 7be905
+      tc_cfi_emit_pcrel_expr (&exp, DWARF2_FDE_RELOC_SIZE);	 /* Code offset.  */
Jakub Jelinek 7be905
 #else
Jakub Jelinek 7be905
-  emit_expr (&exp, DWARF2_FDE_RELOC_SIZE);	/* Code offset.  */
Jakub Jelinek 7be905
+      emit_expr (&exp, DWARF2_FDE_RELOC_SIZE);	/* Code offset.  */
Jakub Jelinek 7be905
 #endif
Jakub Jelinek 7be905
-  exp.X_op = O_subtract;
Jakub Jelinek 7be905
 #endif
Jakub Jelinek 7be905
+      addr_size = DWARF2_FDE_RELOC_SIZE;
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
+  else
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      exp.X_add_symbol = fde->start_address;
Jakub Jelinek 7be905
+      addr_size = DWARF2_ADDR_SIZE (stdoutput);
Jakub Jelinek 7be905
+      emit_expr (&exp, addr_size);
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
+  exp.X_op = O_subtract;
Jakub Jelinek 7be905
   exp.X_add_symbol = fde->end_address;
Jakub Jelinek 7be905
   exp.X_op_symbol = fde->start_address;		/* Code length.  */
Jakub Jelinek 7be905
-  emit_expr (&exp, DWARF2_FDE_RELOC_SIZE);
Jakub Jelinek 7be905
+  emit_expr (&exp, addr_size);
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
   augmentation_size = encoding_size (fde->lsda_encoding);
Jakub Jelinek 7be905
-  out_uleb128 (augmentation_size);		/* Augmentation size.  */
Jakub Jelinek 7be905
+  if (eh_frame)
Jakub Jelinek 7be905
+    out_uleb128 (augmentation_size);		/* Augmentation size.  */
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
   if (fde->lsda_encoding != DW_EH_PE_omit)
Jakub Jelinek 7be905
     {
Jakub Jelinek 7be905
@@ -1356,7 +1467,8 @@ output_fde (struct fde_entry *fde, struc
Jakub Jelinek 7be905
 }
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 static struct cie_entry *
Jakub Jelinek 7be905
-select_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
Jakub Jelinek 7be905
+select_cie_for_fde (struct fde_entry *fde, bfd_boolean eh_frame,
Jakub Jelinek 7be905
+		    struct cfi_insn_data **pfirst, int align)
Jakub Jelinek 7be905
 {
Jakub Jelinek 7be905
   struct cfi_insn_data *i, *j;
Jakub Jelinek 7be905
   struct cie_entry *cie;
Jakub Jelinek 7be905
@@ -1477,12 +1589,56 @@ select_cie_for_fde (struct fde_entry *fd
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
   cie->last = i;
Jakub Jelinek 7be905
   *pfirst = i;
Jakub Jelinek 7be905
-   
Jakub Jelinek 7be905
-  output_cie (cie);
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+  output_cie (cie, eh_frame, align);
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
   return cie;
Jakub Jelinek 7be905
 }
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
+#ifdef md_reg_eh_frame_to_debug_frame
Jakub Jelinek 7be905
+static void
Jakub Jelinek 7be905
+cfi_change_reg_numbers (struct cfi_insn_data *insn)
Jakub Jelinek 7be905
+{
Jakub Jelinek 7be905
+  for (; insn; insn = insn->next)
Jakub Jelinek 7be905
+    switch (insn->insn)
Jakub Jelinek 7be905
+      {
Jakub Jelinek 7be905
+      case DW_CFA_advance_loc:
Jakub Jelinek 7be905
+      case DW_CFA_def_cfa_offset:
Jakub Jelinek 7be905
+      case DW_CFA_remember_state:
Jakub Jelinek 7be905
+      case DW_CFA_restore_state:
Jakub Jelinek 7be905
+      case DW_CFA_GNU_window_save:
Jakub Jelinek 7be905
+      case CFI_escape:
Jakub Jelinek 7be905
+	break;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+      case DW_CFA_def_cfa:
Jakub Jelinek 7be905
+      case DW_CFA_offset:
Jakub Jelinek 7be905
+	insn->u.ri.reg = md_reg_eh_frame_to_debug_frame (insn->u.ri.reg);
Jakub Jelinek 7be905
+	break;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+      case DW_CFA_def_cfa_register:
Jakub Jelinek 7be905
+      case DW_CFA_undefined:
Jakub Jelinek 7be905
+      case DW_CFA_same_value:
Jakub Jelinek 7be905
+      case DW_CFA_restore:
Jakub Jelinek 7be905
+	insn->u.r = md_reg_eh_frame_to_debug_frame (insn->u.r);
Jakub Jelinek 7be905
+	break;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+      case DW_CFA_register:
Jakub Jelinek 7be905
+	insn->u.rr.reg1 = md_reg_eh_frame_to_debug_frame (insn->u.rr.reg1);
Jakub Jelinek 7be905
+	insn->u.rr.reg2 = md_reg_eh_frame_to_debug_frame (insn->u.rr.reg2);
Jakub Jelinek 7be905
+	break;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+      case CFI_val_encoded_addr:
Jakub Jelinek 7be905
+	insn->u.ea.reg = md_reg_eh_frame_to_debug_frame (insn->u.ea.reg);
Jakub Jelinek 7be905
+	break;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+      default:
Jakub Jelinek 7be905
+	abort ();
Jakub Jelinek 7be905
+      }
Jakub Jelinek 7be905
+}
Jakub Jelinek 7be905
+#else
Jakub Jelinek 7be905
+#define cfi_change_reg_numbers(insn) do { } while (0)
Jakub Jelinek 7be905
+#endif
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
 void
Jakub Jelinek 7be905
 cfi_finish (void)
Jakub Jelinek 7be905
 {
Jakub Jelinek 7be905
@@ -1493,38 +1649,80 @@ cfi_finish (void)
Jakub Jelinek 7be905
   if (all_fde_data == 0)
Jakub Jelinek 7be905
     return;
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-  /* Open .eh_frame section.  */
Jakub Jelinek 7be905
-  cfi_seg = subseg_new (".eh_frame", 0);
Jakub Jelinek 7be905
-  bfd_set_section_flags (stdoutput, cfi_seg,
Jakub Jelinek 7be905
-			 SEC_ALLOC | SEC_LOAD | SEC_DATA
Jakub Jelinek 7be905
-			 | DWARF2_EH_FRAME_READ_ONLY);
Jakub Jelinek 7be905
-  subseg_set (cfi_seg, 0);
Jakub Jelinek 7be905
-  record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
Jakub Jelinek 7be905
+  if ((cfi_sections & CFI_EMIT_eh_frame) != 0)
Jakub Jelinek 7be905
+    {
Jakub Jelinek 7be905
+      /* Open .eh_frame section.  */
Jakub Jelinek 7be905
+      cfi_seg = subseg_new (".eh_frame", 0);
Jakub Jelinek 7be905
+      bfd_set_section_flags (stdoutput, cfi_seg,
Jakub Jelinek 7be905
+			     SEC_ALLOC | SEC_LOAD | SEC_DATA
Jakub Jelinek 7be905
+			     | DWARF2_EH_FRAME_READ_ONLY);
Jakub Jelinek 7be905
+      subseg_set (cfi_seg, 0);
Jakub Jelinek 7be905
+      record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 #ifdef md_fix_up_eh_frame
Jakub Jelinek 7be905
-  md_fix_up_eh_frame (cfi_seg);
Jakub Jelinek 7be905
+      md_fix_up_eh_frame (cfi_seg);
Jakub Jelinek 7be905
 #endif
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-  /* Make sure check_eh_frame doesn't do anything with our output.  */
Jakub Jelinek 7be905
-  save_flag_traditional_format = flag_traditional_format;
Jakub Jelinek 7be905
-  flag_traditional_format = 1;
Jakub Jelinek 7be905
+      /* Make sure check_eh_frame doesn't do anything with our output.  */
Jakub Jelinek 7be905
+      save_flag_traditional_format = flag_traditional_format;
Jakub Jelinek 7be905
+      flag_traditional_format = 1;
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-  for (fde = all_fde_data; fde ; fde = fde->next)
Jakub Jelinek 7be905
+      for (fde = all_fde_data; fde ; fde = fde->next)
Jakub Jelinek 7be905
+	{
Jakub Jelinek 7be905
+	  struct cfi_insn_data *first;
Jakub Jelinek 7be905
+	  struct cie_entry *cie;
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+	  if (fde->end_address == NULL)
Jakub Jelinek 7be905
+	    {
Jakub Jelinek 7be905
+	      as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
Jakub Jelinek 7be905
+	      fde->end_address = fde->start_address;
Jakub Jelinek 7be905
+	    }
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+	  cie = select_cie_for_fde (fde, TRUE, &first, 2);
Jakub Jelinek 7be905
+	  output_fde (fde, cie, TRUE, first,
Jakub Jelinek 7be905
+		      fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
Jakub Jelinek 7be905
+	}
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+      flag_traditional_format = save_flag_traditional_format;
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+  if ((cfi_sections & CFI_EMIT_debug_frame) != 0)
Jakub Jelinek 7be905
     {
Jakub Jelinek 7be905
-      struct cfi_insn_data *first;
Jakub Jelinek 7be905
-      struct cie_entry *cie;
Jakub Jelinek 7be905
+      struct cie_entry *cie, *cie_next;
Jakub Jelinek 7be905
+      int alignment = ffs (DWARF2_ADDR_SIZE (stdoutput)) - 1;
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-      if (fde->end_address == NULL)
Jakub Jelinek 7be905
+      for (cie = cie_root; cie; cie = cie_next)
Jakub Jelinek 7be905
 	{
Jakub Jelinek 7be905
-	  as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
Jakub Jelinek 7be905
-	  fde->end_address = fde->start_address;
Jakub Jelinek 7be905
+	  cie_next = cie->next;
Jakub Jelinek 7be905
+	  free ((void *) cie);
Jakub Jelinek 7be905
 	}
Jakub Jelinek 7be905
+      cie_root = NULL;
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-      cie = select_cie_for_fde (fde, &first);
Jakub Jelinek 7be905
-      output_fde (fde, cie, first, fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
Jakub Jelinek 7be905
-    }
Jakub Jelinek 7be905
+      /* Open .debug_frame section.  */
Jakub Jelinek 7be905
+      cfi_seg = subseg_new (".debug_frame", 0);
Jakub Jelinek 7be905
+      bfd_set_section_flags (stdoutput, cfi_seg,
Jakub Jelinek 7be905
+			     SEC_READONLY | SEC_DEBUGGING);
Jakub Jelinek 7be905
+      subseg_set (cfi_seg, 0);
Jakub Jelinek 7be905
+      record_alignment (cfi_seg, alignment);
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+      for (fde = all_fde_data; fde ; fde = fde->next)
Jakub Jelinek 7be905
+	{
Jakub Jelinek 7be905
+	  struct cfi_insn_data *first;
Jakub Jelinek 7be905
+	  struct cie_entry *cie;
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
-  flag_traditional_format = save_flag_traditional_format;
Jakub Jelinek 7be905
+	  if (fde->end_address == NULL)
Jakub Jelinek 7be905
+	    {
Jakub Jelinek 7be905
+	      as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
Jakub Jelinek 7be905
+	      fde->end_address = fde->start_address;
Jakub Jelinek 7be905
+	    }
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
+	  fde->per_encoding = DW_EH_PE_omit;
Jakub Jelinek 7be905
+	  fde->lsda_encoding = DW_EH_PE_omit;
Jakub Jelinek 7be905
+	  cfi_change_reg_numbers (fde->data);
Jakub Jelinek 7be905
+	  cie = select_cie_for_fde (fde, FALSE, &first, alignment);
Jakub Jelinek 7be905
+	  output_fde (fde, cie, FALSE, first, alignment);
Jakub Jelinek 7be905
+	}
Jakub Jelinek 7be905
+    }
Jakub Jelinek 7be905
 }
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 #else /* TARGET_USE_CFIPOP */
Jakub Jelinek 7be905
--- gas/config/tc-ppc.h	5 Sep 2009 07:56:24 -0000	1.40
Jakub Jelinek 7be905
+++ gas/config/tc-ppc.h	2 Oct 2009 11:33:50 -0000	1.41
Jakub Jelinek 7be905
@@ -249,6 +249,12 @@ extern int ppc_parse_name (const char *,
Jakub Jelinek 7be905
 #define md_cleanup() ppc_cleanup ()
Jakub Jelinek 7be905
 extern void ppc_cleanup (void);
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
+/* ppc uses different register numbers between .eh_frame and .debug_frame.
Jakub Jelinek 7be905
+   This macro translates the .eh_frame register numbers to .debug_frame
Jakub Jelinek 7be905
+   register numbers.  */
Jakub Jelinek 7be905
+#define md_reg_eh_frame_to_debug_frame(regno) \
Jakub Jelinek 7be905
+  ((regno) == 70 ? 64 /* cr2 */ : (regno))
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
 #define TARGET_USE_CFIPOP 1
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 #define tc_cfi_frame_initial_instructions ppc_cfi_frame_initial_instructions
Jakub Jelinek 7be905
--- gas/doc/as.texinfo	29 Sep 2009 14:17:09 -0000	1.210
Jakub Jelinek 7be905
+++ gas/doc/as.texinfo	2 Oct 2009 11:33:50 -0000	1.211
Jakub Jelinek 7be905
@@ -4197,6 +4197,15 @@ undefined.
Jakub Jelinek 7be905
 Each expression is assembled into the next byte.
Jakub Jelinek 7be905
 
Jakub Jelinek 7be905
 @node CFI directives
Jakub Jelinek 7be905
+@section @code{.cfi_sections @var{section_list}}
Jakub Jelinek 7be905
+@cindex @code{cfi_sections} directive
Jakub Jelinek 7be905
+@code{.cfi_sections} may be used to specify whether CFI directives
Jakub Jelinek 7be905
+should emit @code{.eh_frame} section and/or @code{.debug_frame} section.
Jakub Jelinek 7be905
+If @var{section_list} is @code{.eh_frame}, @code{.eh_frame} is emitted,
Jakub Jelinek 7be905
+if @var{section_list} is @code{.debug_frame}, @code{.debug_frame} is emitted.
Jakub Jelinek 7be905
+To emit both use @code{.eh_frame, .debug_frame}.  The default if this
Jakub Jelinek 7be905
+directive is not used is @code{.cfi_sections .eh_frame}.
Jakub Jelinek 7be905
+
Jakub Jelinek 7be905
 @section @code{.cfi_startproc [simple]}
Jakub Jelinek 7be905
 @cindex @code{cfi_startproc} directive
Jakub Jelinek 7be905
 @code{.cfi_startproc} is used at the beginning of each function that