mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-30 12:44:10 +08:00
gas: fix overflow diagnostics
While the logic in fixup_segment() so far was off by 1 for fixups
dealing with quantities without known signedness, thus failing to report
an overflow when e.g. a byte-sized resulting value is -0x100, the logic
in emit_expr_with_reloc() reported an overflow even on large negative
values when the respective positive ones would not be warned
about, and when fixup_segment() wouldn't do so either. Such diagnostics
all ought to follow a similar pattern of what value range is acceptable.
(If expressions' X_unsigned was reliably set, emit_expr_with_reloc()'s
checking might make sense to tighten based on that flag.)
Note that with commit 80aab57939
("Changes to let cons handle bignums
like general expressions") having added handling of nbytes >
sizeof(valueT) in the O_constant case, converting to O_big, the setting
to zero of "hibit" had become dead. With "hibit" no longer used, this
code now gets dropped altogether. But additionally a respective know()
gets inserted.
This commit is contained in:
parent
b80d447580
commit
4504a63467
@ -1,3 +1,13 @@
|
||||
2021-06-16 Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
* read.c (emit_expr_with_reloc): Adjust overflow check. Drop
|
||||
hibit local variable.
|
||||
* write.c (fixup_segment): Differentiate signed and non-signed
|
||||
relocs in overflow check.
|
||||
* testsuite/gas/all/overflow.s,
|
||||
testsuite/gas/all/overflow.l: New.
|
||||
* testsuite/gas/all/gas.exp: Run new test.
|
||||
|
||||
2021-06-15 Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
* config/tc-i386.c (md_show_usage): Split ELF and PE/COFF parts
|
||||
|
11
gas/read.c
11
gas/read.c
@ -4505,24 +4505,19 @@ emit_expr_with_reloc (expressionS *exp,
|
||||
valueT get;
|
||||
valueT use;
|
||||
valueT mask;
|
||||
valueT hibit;
|
||||
valueT unmask;
|
||||
|
||||
/* JF << of >= number of bits in the object is undefined. In
|
||||
particular SPARC (Sun 4) has problems. */
|
||||
if (nbytes >= sizeof (valueT))
|
||||
{
|
||||
know (nbytes == sizeof (valueT));
|
||||
mask = 0;
|
||||
if (nbytes > sizeof (valueT))
|
||||
hibit = 0;
|
||||
else
|
||||
hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't store these bits. */
|
||||
mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
|
||||
hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
|
||||
}
|
||||
|
||||
unmask = ~mask; /* Do store these bits. */
|
||||
@ -4534,9 +4529,7 @@ emit_expr_with_reloc (expressionS *exp,
|
||||
|
||||
get = exp->X_add_number;
|
||||
use = get & unmask;
|
||||
if ((get & mask) != 0
|
||||
&& ((get & mask) != mask
|
||||
|| (get & hibit) == 0))
|
||||
if ((get & mask) != 0 && (-get & mask) != 0)
|
||||
{
|
||||
/* Leading bits contain both 0s & 1s. */
|
||||
as_warn (_("value 0x%" BFD_VMA_FMT "x truncated to 0x%" BFD_VMA_FMT "x"),
|
||||
|
@ -372,6 +372,27 @@ switch -glob $target_triplet {
|
||||
}
|
||||
}
|
||||
|
||||
# Various targets use too custom handling to be able to sensibly create
|
||||
# common expecations for this test. Also .equ works differently on some
|
||||
# targets.
|
||||
if { ![istarget avr-*-*]
|
||||
&& ![istarget bfin-*-*]
|
||||
&& ![istarget cris*-*-*]
|
||||
&& ![istarget dlx-*-*]
|
||||
&& ![istarget hppa*-*-*]
|
||||
&& ![istarget m68k-*-*]
|
||||
&& ![istarget nios2-*-*]
|
||||
&& ![istarget pj-*-*]
|
||||
&& ![istarget sh*-*-*]
|
||||
&& ![istarget *c4x-*-*]
|
||||
&& ![istarget *c54x-*-*]
|
||||
&& ![istarget *c6x-*-*]
|
||||
&& ![istarget z80-*-*] } then {
|
||||
# Some further targets' custom handling fails to recognize the overflows.
|
||||
setup_xfail "crx-*-*" "h8300-*-*" "mcore-*-*" "mn10200-*-*" "mn10300-*-*" "msp430-*-*" "ns32k-*-*"
|
||||
run_list_test "overflow"
|
||||
}
|
||||
|
||||
if { ([istarget "i*86-*-*pe*"] && ![istarget "i*86-*-openbsd*"]) \
|
||||
|| [istarget "i*86-*-cygwin*"] \
|
||||
|| [istarget "i*86-*-mingw32*"] } {
|
||||
|
9
gas/testsuite/gas/all/overflow.l
Normal file
9
gas/testsuite/gas/all/overflow.l
Normal file
@ -0,0 +1,9 @@
|
||||
.*: Assembler messages:
|
||||
.*:5: Warning: .* (0x)?100 truncated to (0x)?0
|
||||
.*:6: Warning: .* (0x)?101 truncated to (0x)?1
|
||||
.*:11: Warning: .* (0x)?f+00 truncated to (0x)?0
|
||||
.*:12: Warning: .* (0x)?f+eff truncated to (0x)?ff
|
||||
.*:17: Error: .* (256|(0x)?100) too large .*
|
||||
.*:18: Error: .* (257|(0x)?101) too large .*
|
||||
.*:23: Error: .* (0x)?f+00 too large .*
|
||||
.*:24: Error: .* (0x)?f+eff too large .*
|
26
gas/testsuite/gas/all/overflow.s
Normal file
26
gas/testsuite/gas/all/overflow.s
Normal file
@ -0,0 +1,26 @@
|
||||
.data
|
||||
.dc.b +0x80
|
||||
.dc.b +0x81
|
||||
.dc.b +0xff
|
||||
.dc.b +0x100
|
||||
.dc.b +0x101
|
||||
|
||||
.dc.b -0x80
|
||||
.dc.b -0x81
|
||||
.dc.b -0xff
|
||||
.dc.b -0x100
|
||||
.dc.b -0x101
|
||||
|
||||
.dc.b zero+0x80
|
||||
.dc.b zero+0x81
|
||||
.dc.b zero+0xff
|
||||
.dc.b zero+0x100
|
||||
.dc.b zero+0x101
|
||||
|
||||
.dc.b zero-0x80
|
||||
.dc.b zero-0x81
|
||||
.dc.b zero-0xff
|
||||
.dc.b zero-0x100
|
||||
.dc.b zero-0x101
|
||||
|
||||
.equ zero, 0
|
@ -1107,7 +1107,10 @@ fixup_segment (fixS *fixP, segT this_segment)
|
||||
mask = 0;
|
||||
mask--; /* Set all bits to one. */
|
||||
mask <<= fixP->fx_size * 8 - (fixP->fx_signed ? 1 : 0);
|
||||
if ((add_number & mask) != 0 && (add_number & mask) != mask)
|
||||
if ((add_number & mask) != 0
|
||||
&& (fixP->fx_signed
|
||||
? (add_number & mask) != mask
|
||||
: (-add_number & mask) != 0))
|
||||
{
|
||||
char buf[50], buf2[50];
|
||||
bfd_sprintf_vma (stdoutput, buf, fragP->fr_address + fixP->fx_where);
|
||||
|
Loading…
Reference in New Issue
Block a user