* ehopt.c (eh_frame_code_alignment): New arg `in_seg', update all
authorRichard Henderson <rth@redhat.com>
Sat, 18 Nov 2000 00:13:28 +0000 (00:13 +0000)
committerRichard Henderson <rth@redhat.com>
Sat, 18 Nov 2000 00:13:28 +0000 (00:13 +0000)
        callers.  Don't switch segments.  Expect CIE == -1 in .debug_frame.
        (check_eh_frame): Handle .eh_frame and .debug_frame concurrently.

gas/ChangeLog
gas/ehopt.c

index f82b01f664b6a4d44c369df7675b66dd1896c98b..e4682326042748f2a6ced346ff5049ed9721810a 100644 (file)
@@ -1,3 +1,9 @@
+2000-11-17  Richard Henderson  <rth@redhat.com>
+
+       * ehopt.c (eh_frame_code_alignment): New arg `in_seg', update all
+       callers.  Don't switch segments.  Expect CIE == -1 in .debug_frame.
+       (check_eh_frame): Handle .eh_frame and .debug_frame concurrently.
+
 2000-11-17  Nick Clifton  <nickc@redhat.com>
 
        * config/tc-arm.c (md_pseudo_table): Add support for .line and
index 03d7a0416098c3df47e4f3dcc46cb0d020c2159d..67518272d4018d45a856abf95b2b0363c61c7aac 100644 (file)
@@ -31,13 +31,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 /* Try to optimize gcc 2.8 exception frame information.
 
    Exception frame information is emitted for every function in the
-   .eh_frame section.  Simple information for a function with no
-   exceptions looks like this:
+   .eh_frame or .debug_frame sections.  Simple information for a function
+   with no exceptions looks like this:
 
 __FRAME_BEGIN__:
        .4byte  .LLCIE1 / Length of Common Information Entry
 .LSCIE1:
+#if .eh_frame
        .4byte  0x0     / CIE Identifier Tag
+#elif .debug_frame
+       .4byte  0xffffffff / CIE Identifier Tag
+#endif
        .byte   0x1     / CIE Version
        .byte   0x0     / CIE Augmentation (none)
        .byte   0x1     / ULEB128 0x1 (CIE Code Alignment Factor)
@@ -84,30 +88,33 @@ __FRAME_BEGIN__:
    not know this value, it always uses four bytes.  We will know the
    value at the end of assembly, so we can do better.  */
 
-static int eh_frame_code_alignment PARAMS ((void));
+static int eh_frame_code_alignment PARAMS ((int));
 
 /* Get the code alignment factor from the CIE.  */
 
 static int
-eh_frame_code_alignment ()
+eh_frame_code_alignment (in_seg)
+     int in_seg;
 {
+  /* ??? Assume .eh_frame and .debug_frame have the same alignment.  */
   static int code_alignment;
-  segT current_seg;
-  subsegT current_subseg;
+
   fragS *f;
   fixS *fix;
   int offset;
+  char CIE_id;
   char augmentation[10];
   int iaug;
 
   if (code_alignment != 0)
     return code_alignment;
 
-  /* We should find the CIE at the start of the .eh_frame section.  */
+  /* Can't find the alignment if we've changed sections.  */
+  if (! in_seg)
+    return -1;
+
+  /* We should find the CIE at the start of the section.  */
 
-  current_seg = now_seg;
-  current_subseg = now_subseg;
-  subseg_new (".eh_frame", 0);
 #if defined (BFD_ASSEMBLER) || defined (MANY_SEGMENTS)
   f = seg_info (now_seg)->frchainP->frch_root;
 #else
@@ -118,11 +125,15 @@ eh_frame_code_alignment ()
 #else
   fix = *seg_fix_rootP;
 #endif
-  subseg_set (current_seg, current_subseg);
 
   /* Look through the frags of the section to find the code alignment.  */
 
-  /* First make sure that the CIE Identifier Tag is 0.  */
+  /* First make sure that the CIE Identifier Tag is 0/-1.  */
+
+  if (strcmp (segment_name (now_seg), ".debug_frame") == 0)
+    CIE_id = (char)0xff;
+  else
+    CIE_id = 0;
 
   offset = 4;
   while (f != NULL && offset >= f->fr_fix)
@@ -132,10 +143,10 @@ eh_frame_code_alignment ()
     }
   if (f == NULL
       || f->fr_fix - offset < 4
-      || f->fr_literal[offset] != 0
-      || f->fr_literal[offset + 1] != 0
-      || f->fr_literal[offset + 2] != 0
-      || f->fr_literal[offset + 3] != 0)
+      || f->fr_literal[offset] != CIE_id
+      || f->fr_literal[offset + 1] != CIE_id
+      || f->fr_literal[offset + 2] != CIE_id
+      || f->fr_literal[offset + 3] != CIE_id)
     {
       code_alignment = -1;
       return -1;
@@ -261,33 +272,42 @@ check_eh_frame (exp, pnbytes)
      expressionS *exp;
      unsigned int *pnbytes;
 {
-  static int saw_size;
-  static symbolS *size_end_sym;
-  static int saw_advance_loc4;
-  static fragS *loc4_frag;
-  static int loc4_fix;
-
-  if (saw_size
-      && S_IS_DEFINED (size_end_sym))
+  struct frame_data
+  {
+    symbolS *size_end_sym;
+    fragS *loc4_frag;
+    int saw_size;
+    int saw_advance_loc4;
+    int loc4_fix;
+  };
+  
+  static struct frame_data eh_frame_data;
+  static struct frame_data debug_frame_data;
+  struct frame_data *d;
+
+  /* Don't optimize.  */
+  if (flag_traditional_format)
+    return 0;
+
+  /* Select the proper section data.  */
+  if (strcmp (segment_name (now_seg), ".eh_frame") == 0)
+    d = &eh_frame_data;
+  else if (strcmp (segment_name (now_seg), ".debug_frame") == 0)
+    d = &debug_frame_data;
+  else
+    return 0;
+
+  if (d->saw_size && S_IS_DEFINED (d->size_end_sym))
     {
       /* We have come to the end of the CIE or FDE.  See below where
          we set saw_size.  We must check this first because we may now
          be looking at the next size.  */
-      saw_size = 0;
-      saw_advance_loc4 = 0;
+      d->saw_size = 0;
+      d->saw_advance_loc4 = 0;
     }
 
-  if (flag_traditional_format)
-    {
-      /* Don't optimize.  */
-    }
-  else if (strcmp (segment_name (now_seg), ".eh_frame") != 0)
-    {
-      saw_size = 0;
-      saw_advance_loc4 = 0;
-    }
-  else if (! saw_size
-          && *pnbytes == 4)
+  if (! d->saw_size
+      && *pnbytes == 4)
     {
       /* This might be the size of the CIE or FDE.  We want to know
          the size so that we don't accidentally optimize across an FDE
@@ -301,23 +321,23 @@ check_eh_frame (exp, pnbytes)
       if ((exp->X_op == O_symbol || exp->X_op == O_subtract)
          && ! S_IS_DEFINED (exp->X_add_symbol))
        {
-         saw_size = 1;
-         size_end_sym = exp->X_add_symbol;
+         d->saw_size = 1;
+         d->size_end_sym = exp->X_add_symbol;
        }
     }
-  else if (saw_size
+  else if (d->saw_size
           && *pnbytes == 1
           && exp->X_op == O_constant
           && exp->X_add_number == DW_CFA_advance_loc4)
     {
       /* This might be a DW_CFA_advance_loc4.  Record the frag and the
          position within the frag, so that we can change it later.  */
-      saw_advance_loc4 = 1;
+      d->saw_advance_loc4 = 1;
       frag_grow (1);
-      loc4_frag = frag_now;
-      loc4_fix = frag_now_fix ();
+      d->loc4_frag = frag_now;
+      d->loc4_fix = frag_now_fix ();
     }
-  else if (saw_advance_loc4
+  else if (d->saw_advance_loc4
           && *pnbytes == 4
           && exp->X_op == O_constant)
     {
@@ -328,9 +348,9 @@ check_eh_frame (exp, pnbytes)
          reduced to a constant.  We can do the optimization entirely
          in this function.  */
 
-      saw_advance_loc4 = 0;
+      d->saw_advance_loc4 = 0;
 
-      ca = eh_frame_code_alignment ();
+      ca = eh_frame_code_alignment (1);
       if (ca < 0)
        {
          /* Don't optimize.  */
@@ -338,41 +358,40 @@ check_eh_frame (exp, pnbytes)
       else if (exp->X_add_number % ca == 0
               && exp->X_add_number / ca < 0x40)
        {
-         loc4_frag->fr_literal[loc4_fix]
+         d->loc4_frag->fr_literal[d->loc4_fix]
            = DW_CFA_advance_loc | (exp->X_add_number / ca);
          /* No more bytes needed.  */
          return 1;
        }
       else if (exp->X_add_number < 0x100)
        {
-         loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
+         d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1;
          *pnbytes = 1;
        }
       else if (exp->X_add_number < 0x10000)
        {
-         loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
+         d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2;
          *pnbytes = 2;
        }
     }
-  else if (saw_advance_loc4
+  else if (d->saw_advance_loc4
           && *pnbytes == 4
           && exp->X_op == O_subtract)
     {
-
       /* This is a case we can optimize.  The expression was not
          reduced, so we can not finish the optimization until the end
          of the assembly.  We set up a variant frag which we handle
          later.  */
 
-      saw_advance_loc4 = 0;
+      d->saw_advance_loc4 = 0;
 
       frag_var (rs_cfa, 4, 0, 0, make_expr_symbol (exp),
-               loc4_fix, (char *) loc4_frag);
+               d->loc4_fix, (char *) d->loc4_frag);
 
       return 1;
     }
   else
-    saw_advance_loc4 = 0;
+    d->saw_advance_loc4 = 0;
 
   return 0;
 }
@@ -389,7 +408,7 @@ eh_frame_estimate_size_before_relax (frag)
   offsetT diff;
   int ret;
 
-  ca = eh_frame_code_alignment ();
+  ca = eh_frame_code_alignment (0);
   diff = resolve_symbol_value (frag->fr_symbol, 0);
 
   if (ca < 0)
@@ -444,7 +463,7 @@ eh_frame_convert_frag (frag)
     {
       int ca;
 
-      ca = eh_frame_code_alignment ();
+      ca = eh_frame_code_alignment (0);
       assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40);
       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca);
     }