aboutsummaryrefslogtreecommitdiff
path: root/gas/write.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2005-08-18 09:26:16 +0000
committerNick Clifton <nickc@redhat.com>2005-08-18 09:26:16 +0000
commit4111faa5792ba8a46e62b64f44ecda09a1e9c9a1 (patch)
tree41a19876c63627dc5b5db1c5a622dfffcab4dca6 /gas/write.c
parent48733062ff1b494f5a6a40dbb318abe587eb5444 (diff)
downloadfsf-binutils-gdb-4111faa5792ba8a46e62b64f44ecda09a1e9c9a1.zip
fsf-binutils-gdb-4111faa5792ba8a46e62b64f44ecda09a1e9c9a1.tar.gz
fsf-binutils-gdb-4111faa5792ba8a46e62b64f44ecda09a1e9c9a1.tar.bz2
(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.
Diffstat (limited to 'gas/write.c')
-rw-r--r--gas/write.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/gas/write.c b/gas/write.c
index ee80050..aca53b6 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)