From 4111faa5792ba8a46e62b64f44ecda09a1e9c9a1 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 18 Aug 2005 09:26:16 +0000 Subject: [PATCH] (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. --- gas/ChangeLog | 7 +++++++ gas/write.c | 35 +++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 985e15eced7..5b0765769af 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2005-08-18 Nick Clifton + + * 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 * config/obj-coff.c (obj_coff_weak): Set auxiliary record diff --git a/gas/write.c b/gas/write.c index ee80050e5c3..aca53b670d6 100644 --- a/gas/write.c +++ b/gas/write.c @@ -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) -- 2.30.2