From 5f2b6bc955535ebfc280a04c22c937cfedb83916 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 16 Mar 2016 11:33:55 +0000 Subject: [PATCH] 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. --- gas/ChangeLog | 10 ++++++++++ gas/config/rx-parse.y | 11 ++++++++--- gas/read.c | 21 ++++++++++++++++++++- gas/testsuite/gas/elf/bignums.d | 14 ++++++++++++++ gas/testsuite/gas/elf/bignums.s | 23 +++++++++++++++++++++++ gas/testsuite/gas/elf/elf.exp | 9 +++++---- 6 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 gas/testsuite/gas/elf/bignums.d create mode 100644 gas/testsuite/gas/elf/bignums.s diff --git a/gas/ChangeLog b/gas/ChangeLog index d67d752..0f1c13b 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2016-03-16 Nick Clifton + + * 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. + 2016-03-15 Ulrich Drepper * doc/c-i386.texi (Register Naming): Update to details of the diff --git a/gas/config/rx-parse.y b/gas/config/rx-parse.y index 3bd37d0..c0e3217 100644 --- a/gas/config/rx-parse.y +++ b/gas/config/rx-parse.y @@ -1494,9 +1494,14 @@ rx_intop (expressionS exp, int nbits, int opbits) long v; long mask, msb; - if (exp.X_op == O_big && nbits == 32) - return 1; - if (exp.X_op != O_constant) + if (exp.X_op == O_big) + { + if (nbits == 32) + return 1; + if (exp.X_add_number == -1) + return 0; + } + else if (exp.X_op != O_constant) return 0; v = exp.X_add_number; diff --git a/gas/read.c b/gas/read.c index 8f5dfff..ea6d9f6 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; diff --git a/gas/testsuite/gas/elf/bignums.d b/gas/testsuite/gas/elf/bignums.d new file mode 100644 index 0000000..799ef3c --- /dev/null +++ b/gas/testsuite/gas/elf/bignums.d @@ -0,0 +1,14 @@ +#readelf: -x .data +#name: bignum byte values +#not-target: rx-* +# The RX target sometimes calls its data section D_1. +# +# Test that 8-bit and 16-bit constants can be specified via bignums. +# +# Note - we should really apply this test to all targets, not just +# ELF based ones, but we need a tool that can dump the data section +# in a fixed format and readelf fits the bill. + +Hex dump of section .*: + 0x00000000 9800(7698|9876) 9800(7698|9876) 9800.* +#pass diff --git a/gas/testsuite/gas/elf/bignums.s b/gas/testsuite/gas/elf/bignums.s new file mode 100644 index 0000000..91de585 --- /dev/null +++ b/gas/testsuite/gas/elf/bignums.s @@ -0,0 +1,23 @@ + .data + + # On a 64-bit host the two values below will be read into a simple + # 64-bit field in the expressionS structure and the type will be set + # to O_constant. On a 32-bit host however they will read into the + # generic_bignum array and the type set to O_bignum. Either way they + # should both evaluate without errors. + # + # Note - some targets place .hword values on a 16-bit boundary, so we + # declare a second, zero, .byte value in order to make the data + # consistent across all targets. + + .byte 0xffffffffffffff98, 0 + .hword 0xffffffffffff9876 + + # Check that on 64-bit hosts real bignum values also work. + + .byte 0xffffffffffffffffffffffffffffff98, 0 + .hword 0xffffffffffffffffffffffffffff9876 + + # Also check a ridiculously long bignum value. + + .byte 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff98, 0 diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index fb5619d..bde875b 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -226,9 +226,10 @@ if { [is_elf_format] } then { run_dump_test "strtab" -load_lib gas-dg.exp -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn-*.s]] "" "" -dg-finish + run_dump_test "bignums" + load_lib gas-dg.exp + dg-init + dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn-*.s]] "" "" + dg-finish } -- 2.7.4