diff options
author | Maciej W. Rozycki <macro@imgtec.com> | 2017-03-02 01:24:15 +0000 |
---|---|---|
committer | Maciej W. Rozycki <macro@imgtec.com> | 2017-03-02 01:44:07 +0000 |
commit | 9875b36538d35f2292ddc3bb5e7c60e1582aa087 (patch) | |
tree | 9de303f12626d4b6f99406f109f1f73e6072f04e /gas/write.c | |
parent | 673cff9b8b3105f74ce97c202a0727f9e83e56e6 (diff) | |
download | gdb-9875b36538d35f2292ddc3bb5e7c60e1582aa087.zip gdb-9875b36538d35f2292ddc3bb5e7c60e1582aa087.tar.gz gdb-9875b36538d35f2292ddc3bb5e7c60e1582aa087.tar.bz2 |
GAS: Fix bogus "attempt to move .org backwards" relaxation errors
Fix a commit 6afe8e98a664 ("internal error for backwards .org"),
<https://www.sourceware.org/ml/binutils/2008-06/msg00212.html>,
GAS regression that caused legitimate code to fail assembly with an
"attempt to move .org backwards" error.
For example with the `mips-linux' target we get:
$ cat org.s
.set mips16
la $2, foo
.org 0x1000
.align 2
foo:
.half 0
$ as -o org.o org.s
org.s: Assembler messages:
org.s:3: Error: attempt to move .org backwards
$
where the location pointer is obviously not moved backwards with `.org'.
The cause is positive `stretch' in relaxation due to a PC-relative ADDIU
instruction (produced from the LA macro used) getting expanded from 2 to
4 bytes as `foo' is noticed to be out of range for the short encoding.
This in turn triggers logic in `relax_segment' which concludes in the
processing of an `rs_org' frag produced that the location pointer is
moved backwards while in fact only the amount to space forward to the
location requested has shrunk, resulting in a negative growth of the
frag.
Correct the bad logic then and instead verify that the fixed part of an
`rs_org' frag has not overrun the location requested, as per the comment
already included with the error message:
/* Growth may be negative, but variable part of frag
cannot have fewer than 0 chars. That is, we can't
.org backwards. */
which accurately describes the regression scenario. Move the comment
ahead the conditional noted, for clarity.
Add generic and MIPS test cases for the `.org' pseudo-op, including the
test case discussed though not integrated with the offending commit in
particular, adjusted to work across all targets.
gas/
* write.c (relax_segment) <rs_org>: Only bail out if the fixed
part of the frag has overrun the location requested.
* testsuite/gas/all/org-1.d: New test.
* testsuite/gas/all/org-2.d: New test.
* testsuite/gas/all/org-3.d: New test.
* testsuite/gas/all/org-4.d: New test.
* testsuite/gas/all/org-5.d: New test.
* testsuite/gas/all/org-6.d: New test.
* testsuite/gas/all/org-1.l: New stderr output.
* testsuite/gas/all/org-2.l: New stderr output.
* testsuite/gas/all/org-3.l: New stderr output.
* testsuite/gas/all/org-1.s: New test source.
* testsuite/gas/all/org-2.s: New test source.
* testsuite/gas/all/org-3.s: New test source.
* testsuite/gas/all/org-4.s: New test source.
* testsuite/gas/all/org-5.s: New test source.
* testsuite/gas/all/org-6.s: New test source.
* testsuite/gas/all/gas.exp: Run the new tests.
* testsuite/gas/mips/org-1.d: New test.
* testsuite/gas/mips/org-2.d: New test.
* testsuite/gas/mips/org-3.d: New test.
* testsuite/gas/mips/org-4.d: New test.
* testsuite/gas/mips/org-5.d: New test.
* testsuite/gas/mips/org-6.d: New test.
* testsuite/gas/mips/org-7.d: New test.
* testsuite/gas/mips/org-8.d: New test.
* testsuite/gas/mips/org-9.d: New test.
* testsuite/gas/mips/org-10.d: New test.
* testsuite/gas/mips/org-11.d: New test.
* testsuite/gas/mips/org-12.d: New test.
* testsuite/gas/mips/org-1.l: New stderr output.
* testsuite/gas/mips/org-4.l: New stderr output.
* testsuite/gas/mips/org-5.l: New stderr output.
* testsuite/gas/mips/org-6.l: New stderr output.
* testsuite/gas/mips/org-10.l: New stderr output.
* testsuite/gas/mips/org-1.s: New test source.
* testsuite/gas/mips/org-2.s: New test source.
* testsuite/gas/mips/org-3.s: New test source.
* testsuite/gas/mips/org-4.s: New test source.
* testsuite/gas/mips/org-5.s: New test source.
* testsuite/gas/mips/org-6.s: New test source.
* testsuite/gas/mips/org-7.s: New test source.
* testsuite/gas/mips/org-8.s: New test source.
* testsuite/gas/mips/org-9.s: New test source.
* testsuite/gas/mips/org-10.s: New test source.
* testsuite/gas/mips/org-11.s: New test source.
* testsuite/gas/mips/org-12.s: New test source.
* testsuite/gas/mips/mips.exp: Run the new tests.
Diffstat (limited to 'gas/write.c')
-rw-r--r-- | gas/write.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/gas/write.c b/gas/write.c index 9a99a0f..d570b6f 100644 --- a/gas/write.c +++ b/gas/write.c @@ -2692,7 +2692,11 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass) know (fragP->fr_next); after = fragP->fr_next->fr_address + stretch; growth = target - after; - if (growth < 0) + + /* Growth may be negative, but variable part of frag + cannot have fewer than 0 chars. That is, we can't + .org backwards. */ + if (address + fragP->fr_fix > target) { growth = 0; @@ -2714,9 +2718,6 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass) break; } - /* Growth may be negative, but variable part of frag - cannot have fewer than 0 chars. That is, we can't - .org backwards. */ as_bad_where (fragP->fr_file, fragP->fr_line, _("attempt to move .org backwards")); |