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]

gas fix for ia64 target


The patch below fixes a bug in gas which causes it to generate bad
unwind info on ia64.  The problem is that the .label_state and
.copy_state directives failed to preserve the prologue count.  This
bug usually has the effect that gas ends up generating epilogue unwind
descriptors with an epilogue count of 65535.  The patch also adds a
sanity check so that such problems can be found more easily.
Unrelated but trivial: the patch adds documentation for the
-mconstant-gp and -mauto-pic command-line options.

If this looks OK, could someone check it in?

Thanks,

	--david

2002-02-20  David Mosberger  <davidm@hpl.hp.com>

	* config/tc-ia64.c (dot_restore): Issue error message of epilogue
	count exceeds prologue count.
	(md_show_usage): Describe -mconstant-gp and -mauto-pic.
	(unwind.label_prologue_count): New member.

	Based on a patch by Hans Boehm <hboehm@hpl.hp.com>:

	(get_saved_prologue_count): New function.
	(save_prologue_count): New function.
	(free_saved_prologue_count): New function.
	(dot_label_state): Record state label by calling save_prologue_count().
	(dot_copy_state): Restore prologue count by calling
	get_saved_prologue_count().
	(generate_unwind_image): Free up list of saved prologue
	counts by calling free_saved_prologue_counts().

Index: config/tc-ia64.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ia64.c,v
retrieving revision 1.64
diff -u -r1.64 tc-ia64.c
--- config/tc-ia64.c	2002/01/11 09:27:38	1.64
+++ config/tc-ia64.c	2002/02/21 05:09:14
@@ -649,8 +649,19 @@
   int prologue;
   int prologue_mask;
   unsigned int prologue_count;	/* number of .prologues seen so far */
+  struct label_prologue_count * saved_prologue_counts;
+  				/* Prologue counts at previous .label_state	*/
+  				/* directives.					*/
 } unwind;
 
+/* Linked list of saved prologue counts.  A very poor implementation of 	*/
+/* a map from label numbers to prologue counts.					*/
+typedef struct label_prologue_count {
+  struct label_prologue_count *next;
+  unsigned long label_number;
+  unsigned int prologue_count;
+} label_prologue_count;
+
 typedef void (*vbyte_func) PARAMS ((int, char *, char *));
 
 /* Forward delarations:  */
@@ -779,6 +790,9 @@
 				      unsigned long));
 static void output_X4_format PARAMS ((vbyte_func, int, int, int, int, int, int, unsigned long));
 static void free_list_records PARAMS ((unw_rec_list *));
+static unsigned int get_saved_prologue_count PARAMS ((unsigned long lbl));
+static void save_prologue_count PARAMS ((unsigned long lbl, unsigned int count));
+static void free_saved_prologue_counts PARAMS ((void));
 static unw_rec_list *output_prologue PARAMS ((void));
 static unw_rec_list *output_prologue_gr PARAMS ((unsigned int, unsigned int));
 static unw_rec_list *output_body PARAMS ((void));
@@ -3156,6 +3170,14 @@
     }
   else
     ecount = unwind.prologue_count - 1;
+
+  if (ecount >= unwind.prologue_count)
+    {
+      as_bad ("Epilogue count of %lu exceeds number of nested prologues (%u)",
+	      ecount + 1, unwind.prologue_count);
+      return;
+    }
+
   add_unwind_entry (output_epilogue (ecount));
 
   if (ecount < unwind.prologue_count)
@@ -3228,7 +3250,7 @@
   size = output_unw_records (unwind.list, (void **) &unw_rec);
   if (size % md.pointer_size != 0)
     as_bad ("Unwind record is not a multiple of %d bytes.", md.pointer_size);
-                      
+
   /* If there are unwind records, switch sections, and output the info.  */
   if (size != 0)
     {
@@ -3288,6 +3310,7 @@
     }
 
   free_list_records (unwind.list);
+  free_saved_prologue_counts ();
   unwind.list = unwind.tail = unwind.current_entry = NULL;
 
   return size;
@@ -3714,6 +3737,57 @@
     add_unwind_entry (output_spill_sprel_p (ab, reg, e3.X_add_number, qp));
 }
 
+static unsigned int
+get_saved_prologue_count (lbl)
+     unsigned long lbl;
+{
+  label_prologue_count *lpc = unwind.saved_prologue_counts;
+  while (lpc != 0 && lpc->label_number != lbl)
+    lpc = lpc->next;
+  if (lpc == 0)
+    {
+      as_bad ("Missing .label_state %ld", lbl);
+      return 1;
+    }
+  else
+    return lpc->prologue_count;
+}
+
+static void
+save_prologue_count (lbl, count)
+     unsigned long lbl;
+     unsigned int count;
+{
+  label_prologue_count *lpc = unwind.saved_prologue_counts;
+  while (lpc != 0 && lpc->label_number != lbl)
+    lpc = lpc->next;
+  if (lpc != 0)
+    lpc->prologue_count = count;
+  else
+    {
+      label_prologue_count * new_lpc = xmalloc (sizeof (label_prologue_count));
+      new_lpc->next = lpc;
+      new_lpc->label_number = lbl;
+      new_lpc->prologue_count = count;
+      unwind.saved_prologue_counts = new_lpc;
+    }
+}
+
+static void
+free_saved_prologue_counts ()
+{
+  label_prologue_count * lpc = unwind.saved_prologue_counts;
+  label_prologue_count * next;
+
+  while (lpc != 0)
+    {
+      next = lpc->next;
+      free (lpc);
+      lpc = next;
+    }
+  unwind.saved_prologue_counts = 0;
+}
+
 static void
 dot_label_state (dummy)
      int dummy ATTRIBUTE_UNUSED;
@@ -3727,6 +3801,7 @@
       return;
     }
   add_unwind_entry (output_label_state (e.X_add_number));
+  save_prologue_count (e.X_add_number, unwind.prologue_count);
 }
 
 static void
@@ -3742,6 +3817,7 @@
       return;
     }
   add_unwind_entry (output_copy_state (e.X_add_number));
+  unwind.prologue_count = get_saved_prologue_count (e.X_add_number);
 }
 
 static void
@@ -6336,6 +6412,11 @@
 {
   fputs (_("\
 IA-64 options:\n\
+  -mconstant-gp		  mark output file as using the constant-GP model\n\
+			  (sets ELF header flag EF_IA_64_CONS_GP)\n\
+  -mauto-pic		  mark output file as using the constant-GP model\n\
+			  without function descriptors (sets ELF header flag\n\
+			  EF_IA_64_NOFUNCDESC_CONS_GP)\n\
   -milp32|-milp64|-mlp64|-mp64	select data model (default -mlp64)\n\
   -mle | -mbe		  select little- or big-endian byte order (default -mle)\n\
   -x | -xexplicit	  turn on dependency violation checking (default)\n\


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