OSDN Git Service

(relax_segment): Count the number of frags being processed and use this to
authorNick Clifton <nickc@redhat.com>
Thu, 18 Aug 2005 09:26:16 +0000 (09:26 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 18 Aug 2005 09:26:16 +0000 (09:26 +0000)
compute a maximum limit on the number of iterations that will be allowed when
attempting to relax the segment.

gas/ChangeLog
gas/write.c

index 985e15e..5b07657 100644 (file)
@@ -1,3 +1,10 @@
+2005-08-18  Nick Clifton  <nickc@redhat.com>
+
+       * write.c (relax_segment): Count the number of frags being
+       processed and use this to compute a maximum limit on the number of
+       iterations that will be allowed when attempting to relax the
+       segment.
+
 2005-08-17  Danny Smith  <dannysmith@users.sourceforge.net>
 
        * config/obj-coff.c (obj_coff_weak): Set auxiliary record
index ee80050..aca53b6 100644 (file)
@@ -1721,8 +1721,9 @@ relax_align (register relax_addressT address,     /* Address now.  */
 int
 relax_segment (struct frag *segment_frag_root, segT segment)
 {
-  register struct frag *fragP;
-  register relax_addressT address;
+  unsigned long frag_count;
+  struct frag *fragP;
+  relax_addressT address;
   int ret;
 
   /* In case md_estimate_size_before_relax() wants to make fixSs.  */
@@ -1731,7 +1732,9 @@ relax_segment (struct frag *segment_frag_root, segT segment)
   /* For each frag in segment: count and store  (a 1st guess of)
      fr_address.  */
   address = 0;
-  for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
+  for (frag_count = 0, fragP = segment_frag_root;
+       fragP;
+       fragP = fragP->fr_next, frag_count ++)
     {
       fragP->relax_marker = 0;
       fragP->fr_address = address;
@@ -1807,6 +1810,7 @@ relax_segment (struct frag *segment_frag_root, segT segment)
 
   /* Do relax().  */
   {
+    unsigned long max_iterations;
     offsetT stretch;   /* May be any size, 0 or negative.  */
     /* Cumulative number of addresses we have relaxed this pass.
        We may have relaxed more than one address.  */
@@ -1815,6 +1819,20 @@ relax_segment (struct frag *segment_frag_root, segT segment)
        grew, and another shrank.  If a branch instruction doesn't fit anymore,
        we could be scrod.  */
 
+    /* We want to prevent going into an infinite loop where one frag grows
+       depending upon the location of a symbol which is in turn moved by
+       the growing frag.  eg:
+
+         foo = .
+         .org foo+16
+         foo = .
+
+       So we dictate that this algorithm can be at most O2.  */
+    max_iterations = frag_count * frag_count;
+    /* Check for overflow.  */
+    if (max_iterations < frag_count)
+      max_iterations = frag_count;
+
     do
       {
        stretch = 0;
@@ -2033,10 +2051,15 @@ relax_segment (struct frag *segment_frag_root, segT segment)
                stretch += growth;
                stretched = 1;
              }
-         }                     /* For each frag in the segment.  */
+         }
       }
-    while (stretched);         /* Until nothing further to relax.  */
-  }                            /* do_relax  */
+    /* Until nothing further to relax.  */
+    while (stretched && -- max_iterations);
+
+    if (stretched)
+      as_fatal (_("Infinite loop encountered whilst attempting to compute the addresses of symbols in section %s"),
+               segment_name (segment));
+  }
 
   ret = 0;
   for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)