summaryrefslogtreecommitdiff
path: root/gas/read.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2016-03-16 11:33:55 +0000
committerNick Clifton <nickc@redhat.com>2016-03-16 11:33:55 +0000
commit5f2b6bc955535ebfc280a04c22c937cfedb83916 (patch)
tree1e3ab4d035b80a0ea3f91f113d4bf7ce070e00e2 /gas/read.c
parent9bff188f0da2859bd5efa8d0def8c0f93d0be410 (diff)
downloadbinutils-gdb-5f2b6bc955535ebfc280a04c22c937cfedb83916.tar.gz
Fix checking bignum values that are being inserted into byte sized containers.
* read.c (emit_expr_with_reloc): Add code check a bignum with nbytes == 1. * config/rx/rx-parse.y (rx_intop): Accept bignum values for sizes other than 32-bits. * testsuite/gas/elf/bignum.s: New test source file. * testsuite/gas/elf/bignum.d: New test driver file. * testsuite/gas/elf/elf.exp: Run the new test.
Diffstat (limited to 'gas/read.c')
-rw-r--r--gas/read.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/gas/read.c b/gas/read.c
index 8f5dfff6c7f..ea6d9f61df1 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -4411,7 +4411,8 @@ emit_expr_with_reloc (expressionS *exp,
if ((get & mask) != 0
&& ((get & mask) != mask
|| (get & hibit) == 0))
- { /* Leading bits contain both 0s & 1s. */
+ {
+ /* Leading bits contain both 0s & 1s. */
#if defined (BFD64) && BFD_HOST_64BIT_LONG_LONG
#ifndef __MSVCRT__
as_warn (_("value 0x%llx truncated to 0x%llx"),
@@ -4437,16 +4438,34 @@ emit_expr_with_reloc (expressionS *exp,
if (nbytes < size)
{
int i = nbytes / CHARS_PER_LITTLENUM;
+
if (i != 0)
{
LITTLENUM_TYPE sign = 0;
if ((generic_bignum[--i]
& (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) != 0)
sign = ~(LITTLENUM_TYPE) 0;
+
while (++i < exp->X_add_number)
if (generic_bignum[i] != sign)
break;
}
+ else if (nbytes == 1)
+ {
+ /* We have nbytes == 1 and CHARS_PER_LITTLENUM == 2 (probably).
+ Check that bits 8.. of generic_bignum[0] match bit 7
+ and that they match all of generic_bignum[1..exp->X_add_number]. */
+ LITTLENUM_TYPE sign = (generic_bignum[0] & (1 << 7)) ? -1 : 0;
+ LITTLENUM_TYPE himask = LITTLENUM_MASK & ~ 0xFF;
+
+ if ((generic_bignum[0] & himask) == (sign & himask))
+ {
+ while (++i < exp->X_add_number)
+ if (generic_bignum[i] != sign)
+ break;
+ }
+ }
+
if (i < exp->X_add_number)
as_warn (_("bignum truncated to %d bytes"), nbytes);
size = nbytes;