diff options
author | Nick Clifton <nickc@redhat.com> | 2005-08-18 09:26:16 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2005-08-18 09:26:16 +0000 |
commit | 4111faa5792ba8a46e62b64f44ecda09a1e9c9a1 (patch) | |
tree | 41a19876c63627dc5b5db1c5a622dfffcab4dca6 /gas/write.c | |
parent | 48733062ff1b494f5a6a40dbb318abe587eb5444 (diff) | |
download | gdb-4111faa5792ba8a46e62b64f44ecda09a1e9c9a1.zip gdb-4111faa5792ba8a46e62b64f44ecda09a1e9c9a1.tar.gz 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.c | 35 |
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) |