* read.c (TC_IMPLICIT_LCOMM_ALIGNMENT): New default-definition.
[deliverable/binutils-gdb.git] / gas / ehopt.c
index efc9337a3435086d9559bd1bd5b1d07e94b9ee5a..a0a5f62f4d7abe18b070764bc911a75e05a1ccd5 100644 (file)
@@ -97,7 +97,8 @@ eh_frame_code_alignment ()
   fragS *f;
   fixS *fix;
   int offset;
-  int eh_state;
+  char augmentation[10];
+  int iaug;
 
   if (code_alignment != 0)
     return code_alignment;
@@ -107,8 +108,16 @@ eh_frame_code_alignment ()
   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
+  f = frchain_now->frch_root;
+#endif
+#ifdef BFD_ASSEMBLER
   fix = seg_info (now_seg)->frchainP->fix_root;
+#else
+  fix = *seg_fix_rootP;
+#endif
   subseg_set (current_seg, current_subseg);
 
   /* Look through the frags of the section to find the code alignment.  */
@@ -150,8 +159,8 @@ eh_frame_code_alignment ()
 
   /* Skip the augmentation (a null terminated string).  */
 
+  iaug = 0;
   ++offset;
-  eh_state = 0;
   while (1)
     {
       while (f != NULL && offset >= f->fr_fix)
@@ -166,19 +175,10 @@ eh_frame_code_alignment ()
        }
       while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
        {
-         switch (eh_state)
+         if ((size_t) iaug < (sizeof augmentation) - 1)
            {
-           case 0:
-             if (f->fr_literal[offset] == 'e')
-               eh_state = 1;
-             break;
-           case 1:
-             if (f->fr_literal[offset] == 'h')
-               eh_state = 2;
-             break;
-           default:
-             eh_state = 3;
-             break;
+             augmentation[iaug] = f->fr_literal[offset];
+             ++iaug;
            }
          ++offset;
        }
@@ -197,11 +197,15 @@ eh_frame_code_alignment ()
       return -1;
     }
 
-  /* If the augmentation field is "eh", then we have to skip a
-     pointer.  Unfortunately, we don't know how large it is.  We find
-     out by looking for a matching fixup.  */
-  if (eh_state == 2)
+  augmentation[iaug] = '\0';
+  if (augmentation[0] == '\0')
     {
+      /* No augmentation.  */
+    }
+  else if (strcmp (augmentation, "eh") == 0)
+    {
+      /* We have to skip a pointer.  Unfortunately, we don't know how
+        large it is.  We find out by looking for a matching fixup.  */
       while (fix != NULL
             && (fix->fx_frag != f || fix->fx_where != offset))
        fix = fix->fx_next;
@@ -220,6 +224,11 @@ eh_frame_code_alignment ()
          return -1;
        }
     }
+  else
+    {
+      code_alignment = -1;
+      return -1;
+    }
 
   /* We're now at the code alignment factor, which is a ULEB128.  If
      it isn't a single byte, forget it.  */
@@ -252,17 +261,52 @@ 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))
+    {
+      /* 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;
+    }
+
   if (flag_traditional_format)
     {
       /* Don't optimize.  */
     }
   else if (strcmp (segment_name (now_seg), ".eh_frame") != 0)
-    saw_advance_loc4 = 0;
-  else if (*pnbytes == 1
+    {
+      saw_size = 0;
+      saw_advance_loc4 = 0;
+    }
+  else if (! 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
+         boundary.  We recognize the size in one of two forms: a
+         symbol which will later be defined as a difference, or a
+         subtraction of two symbols.  Either way, we can tell when we
+         are at the end of the FDE because the symbol becomes defined
+         (in the case of a subtraction, the end symbol, from which the
+         start symbol is being subtracted).  Other ways of describing
+         the size will not be optimized.  */
+      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;
+       }
+    }
+  else if (saw_size
+          && *pnbytes == 1
           && exp->X_op == O_constant
           && exp->X_add_number == DW_CFA_advance_loc4)
     {
This page took 0.023978 seconds and 4 git commands to generate.