diff options
author | Alan Modra <amodra@gmail.com> | 2020-09-01 11:35:37 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2020-09-01 16:02:48 +0930 |
commit | 7af677524e205f3c343707d61bccd4dfd74089da (patch) | |
tree | 425997c5fd06bf60e615e75aa96dfde87be8e793 | |
parent | f911bb2201c5642151d06622e6ad3d20d5d8cc7b (diff) | |
download | binutils-gdb-7af677524e205f3c343707d61bccd4dfd74089da.tar.gz |
PR26420, PR26421, PR26425, PR26427 UBSAN: tc-arm.c left shifts
PR 26420
PR 26421
PR 26425
PR 26427
* config/tc-arm.c (struct arm_it): Make size, size_req, cond and
uncond_value unsigned.
(parse_vfp_reg_list): Make setmask unsigned, vpr_str_len size_t.
(parse_big_immediate): Cast generic_bignum elements to unsigned.
(encode_thumb32_immediate): Shift left 0xffU.
(double_to_single): Make sign unsigned. Tidy.
(move_or_literal_pool): Cast LITTLE_NUM elements to uint64_t or
valueT.
(vfp_or_neon_is_neon): Adjust inst.uncond_value expression.
(md_assemble): Likewise.
(handle_pred_state): Make cond unsigned.
(thumb32_negate_data_op): Make variables unsigned.
(md_apply_fix): Make value and newval unsigned, adjust uses.
-rw-r--r-- | gas/ChangeLog | 20 | ||||
-rw-r--r-- | gas/config/tc-arm.c | 156 |
2 files changed, 98 insertions, 78 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 80df2b32ca4..add6fd89eed 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,23 @@ +2020-09-01 Alan Modra <amodra@gmail.com> + + PR 26420 + PR 26421 + PR 26425 + PR 26427 + * config/tc-arm.c (struct arm_it): Make size, size_req, cond and + uncond_value unsigned. + (parse_vfp_reg_list): Make setmask unsigned, vpr_str_len size_t. + (parse_big_immediate): Cast generic_bignum elements to unsigned. + (encode_thumb32_immediate): Shift left 0xffU. + (double_to_single): Make sign unsigned. Tidy. + (move_or_literal_pool): Cast LITTLE_NUM elements to uint64_t or + valueT. + (vfp_or_neon_is_neon): Adjust inst.uncond_value expression. + (md_assemble): Likewise. + (handle_pred_state): Make cond unsigned. + (thumb32_negate_data_op): Make variables unsigned. + (md_apply_fix): Make value and newval unsigned, adjust uses. + 2020-08-31 Alan Modra <amodra@gmail.com> PR 26510 diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 830cbda6182..a645ffec901 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -517,13 +517,13 @@ struct arm_it { const char * error; unsigned long instruction; - int size; - int size_req; - int cond; + unsigned int size; + unsigned int size_req; + unsigned int cond; /* "uncond_value" is set to the value in place of the conditional field in - unconditional versions of the instruction, or -1 if nothing is + unconditional versions of the instruction, or -1u if nothing is appropriate. */ - int uncond_value; + unsigned int uncond_value; struct neon_type vectype; /* This does not indicate an actual NEON instruction, only that the mnemonic accepts neon-style type suffixes. */ @@ -2175,9 +2175,9 @@ parse_vfp_reg_list (char **ccp, unsigned int *pbase, enum reg_list_els etype, do { - int setmask = 1, addregs = 1; + unsigned int setmask = 1, addregs = 1; const char vpr_str[] = "vpr"; - int vpr_str_len = strlen (vpr_str); + size_t vpr_str_len = strlen (vpr_str); new_base = arm_typed_reg_parse (&str, regtype, ®type, NULL); @@ -5263,12 +5263,12 @@ parse_big_immediate (char **str, int i, expressionS *in_exp, inst.operands[i].imm = 0; for (j = 0; j < parts; j++, idx++) - inst.operands[i].imm |= generic_bignum[idx] - << (LITTLENUM_NUMBER_OF_BITS * j); + inst.operands[i].imm |= ((unsigned) generic_bignum[idx] + << (LITTLENUM_NUMBER_OF_BITS * j)); inst.operands[i].reg = 0; for (j = 0; j < parts; j++, idx++) - inst.operands[i].reg |= generic_bignum[idx] - << (LITTLENUM_NUMBER_OF_BITS * j); + inst.operands[i].reg |= ((unsigned) generic_bignum[idx] + << (LITTLENUM_NUMBER_OF_BITS * j)); inst.operands[i].regisimm = 1; } else if (!(exp_p->X_op == O_symbol && allow_symbol_p)) @@ -8289,7 +8289,7 @@ encode_thumb32_immediate (unsigned int val) for (i = 1; i <= 24; i++) { a = val >> i; - if ((val & ~(0xff << i)) == 0) + if ((val & ~(0xffU << i)) == 0) return ((val >> i) & 0x7f) | ((32 - i) << 7); } @@ -8773,9 +8773,9 @@ is_double_a_single (bfd_int64_t v) static int double_to_single (bfd_int64_t v) { - int sign = (int) ((v >> 63) & 1l); - int exp = (int) ((v >> 52) & 0x7FF); - bfd_int64_t mantissa = (v & (bfd_int64_t)0xFFFFFFFFFFFFFULL); + unsigned int sign = (v >> 63) & 1; + int exp = (v >> 52) & 0x7FF; + bfd_int64_t mantissa = (v & (bfd_int64_t) 0xFFFFFFFFFFFFFULL); if (exp == 0x7FF) exp = 0xFF; @@ -8867,17 +8867,16 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3) l = generic_bignum; #if defined BFD_HOST_64_BIT - v = - ((((((((bfd_int64_t) l[3] & LITTLENUM_MASK) - << LITTLENUM_NUMBER_OF_BITS) - | ((bfd_int64_t) l[2] & LITTLENUM_MASK)) + v = ((((bfd_uint64_t) l[3] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) - | ((bfd_int64_t) l[1] & LITTLENUM_MASK)) - << LITTLENUM_NUMBER_OF_BITS) - | ((bfd_int64_t) l[0] & LITTLENUM_MASK)); + | (((bfd_int64_t) l[2] & LITTLENUM_MASK) + << LITTLENUM_NUMBER_OF_BITS) + | (((bfd_uint64_t) l[1] & LITTLENUM_MASK) + << LITTLENUM_NUMBER_OF_BITS) + | (l[0] & LITTLENUM_MASK)); #else - v = ((l[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) - | (l[0] & LITTLENUM_MASK); + v = ((((valueT) l[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) + | (l[0] & LITTLENUM_MASK)); #endif } else @@ -16834,7 +16833,7 @@ if (!thumb_mode && (check & NEON_CHECK_CC)) first_error (_(BAD_COND)); return FAIL; } - if (inst.uncond_value != -1) + if (inst.uncond_value != -1u) inst.instruction |= inst.uncond_value << 28; } @@ -23065,7 +23064,8 @@ handle_pred_state (void) case MANUAL_PRED_BLOCK: { - int cond, is_last; + unsigned int cond; + int is_last; if (now_pred.type == SCALAR_PRED) { /* Check conditional suffixes. */ @@ -23461,7 +23461,7 @@ md_assemble (char *str) /* The value which unconditional instructions should have in place of the condition field. */ - inst.uncond_value = (opcode->tag == OT_csuffixF) ? 0xf : -1; + inst.uncond_value = (opcode->tag == OT_csuffixF) ? 0xf : -1u; if (thumb_mode) { @@ -28178,10 +28178,10 @@ negate_data_op (unsigned long * instruction, /* Like negate_data_op, but for Thumb-2. */ static unsigned int -thumb32_negate_data_op (offsetT *instruction, unsigned int value) +thumb32_negate_data_op (valueT *instruction, unsigned int value) { - int op, new_inst; - int rd; + unsigned int op, new_inst; + unsigned int rd; unsigned int negated, inverted; negated = encode_thumb32_immediate (-value); @@ -28317,8 +28317,8 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) { - offsetT value = * valP; - offsetT newval; + valueT value = * valP; + valueT newval; unsigned int newimm; unsigned long temp; int sign; @@ -28381,7 +28381,7 @@ md_apply_fix (fixS * fixP, temp = md_chars_to_number (buf, INSN_SIZE); /* If the offset is negative, we should use encoding A2 for ADR. */ - if ((temp & 0xfff0000) == 0x28f0000 && value < 0) + if ((temp & 0xfff0000) == 0x28f0000 && (offsetT) value < 0) newimm = negate_data_op (&temp, value); else { @@ -28399,7 +28399,7 @@ md_apply_fix (fixS * fixP, && ((temp >> DATA_OP_SHIFT) & 0xf) == OPCODE_MOV && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2) && !((temp >> SBIT_SHIFT) & 0x1) - && value >= 0 && value <= 0xffff) + && value <= 0xffff) { /* Clear bits[23:20] to change encoding from A1 to A2. */ temp &= 0xff0fffff; @@ -28496,9 +28496,9 @@ md_apply_fix (fixS * fixP, /* Fall through. */ case BFD_RELOC_ARM_LITERAL: - sign = value > 0; + sign = (offsetT) value > 0; - if (value < 0) + if ((offsetT) value < 0) value = - value; if (validate_offset_imm (value, 0) == FAIL) @@ -28526,9 +28526,9 @@ md_apply_fix (fixS * fixP, case BFD_RELOC_ARM_OFFSET_IMM8: case BFD_RELOC_ARM_HWLITERAL: - sign = value > 0; + sign = (offsetT) value > 0; - if (value < 0) + if ((offsetT) value < 0) value = - value; if (validate_offset_imm (value, 1) == FAIL) @@ -28555,7 +28555,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_ARM_T32_OFFSET_U8: - if (value < 0 || value > 1020 || value % 4 != 0) + if (value > 1020 || value % 4 != 0) as_bad_where (fixP->fx_file, fixP->fx_line, _("bad immediate value for offset (%ld)"), (long) value); value /= 4; @@ -28591,7 +28591,7 @@ md_apply_fix (fixS * fixP, if ((newval & 0xf0000000) == 0xe0000000) { /* Doubleword load/store: 8-bit offset, scaled by 4. */ - if (value >= 0) + if ((offsetT) value >= 0) newval |= (1 << 23); else value = -value; @@ -28613,7 +28613,7 @@ md_apply_fix (fixS * fixP, else if ((newval & 0x000f0000) == 0x000f0000) { /* PC-relative, 12-bit offset. */ - if (value >= 0) + if ((offsetT) value >= 0) newval |= (1 << 23); else value = -value; @@ -28628,7 +28628,7 @@ md_apply_fix (fixS * fixP, else if ((newval & 0x00000100) == 0x00000100) { /* Writeback: 8-bit, +/- offset. */ - if (value >= 0) + if ((offsetT) value >= 0) newval |= (1 << 9); else value = -value; @@ -28643,7 +28643,7 @@ md_apply_fix (fixS * fixP, else if ((newval & 0x00000f00) == 0x00000e00) { /* T-instruction: positive 8-bit offset. */ - if (value < 0 || value > 0xff) + if (value > 0xff) { as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range")); @@ -28655,8 +28655,8 @@ md_apply_fix (fixS * fixP, else { /* Positive 12-bit or negative 8-bit offset. */ - int limit; - if (value >= 0) + unsigned int limit; + if ((offsetT) value >= 0) { newval |= (1 << 23); limit = 0xfff; @@ -28682,7 +28682,7 @@ md_apply_fix (fixS * fixP, case BFD_RELOC_ARM_SHIFT_IMM: newval = md_chars_to_number (buf, INSN_SIZE); - if (((unsigned long) value) > 32 + if (value > 32 || (value == 32 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60))) { @@ -28745,7 +28745,7 @@ md_apply_fix (fixS * fixP, if ((newval & 0x00100000) == 0) { /* 12 bit immediate for addw/subw. */ - if (value < 0) + if ((offsetT) value < 0) { value = -value; newval ^= 0x00a00000; @@ -28768,7 +28768,7 @@ md_apply_fix (fixS * fixP, && (((newval >> 16) & 0xf) == 0xf) && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2_v8m) && !((newval >> T2_SBIT_SHIFT) & 0x1) - && value >= 0 && value <= 0xffff) + && value <= 0xffff) { /* Toggle bit[25] to change encoding from T2 to T3. */ newval ^= 1 << 25; @@ -28799,7 +28799,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_ARM_SMC: - if (((unsigned long) value) > 0xf) + if (value > 0xf) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid smc expression")); @@ -28809,7 +28809,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_ARM_HVC: - if (((unsigned long) value) > 0xffff) + if (value > 0xffff) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid hvc expression")); newval = md_chars_to_number (buf, INSN_SIZE); @@ -28820,7 +28820,7 @@ md_apply_fix (fixS * fixP, case BFD_RELOC_ARM_SWI: if (fixP->tc_fix_data != 0) { - if (((unsigned long) value) > 0xff) + if (value > 0xff) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid swi expression")); newval = md_chars_to_number (buf, THUMB_SIZE); @@ -28829,7 +28829,7 @@ md_apply_fix (fixS * fixP, } else { - if (((unsigned long) value) > 0x00ffffff) + if (value > 0x00ffffff) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid swi expression")); newval = md_chars_to_number (buf, INSN_SIZE); @@ -28839,7 +28839,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_ARM_MULTI: - if (((unsigned long) value) > 0xffff) + if (value > 0xffff) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid expression in load/store multiple")); newval = value | md_chars_to_number (buf, INSN_SIZE); @@ -28923,8 +28923,8 @@ md_apply_fix (fixS * fixP, if (value & temp) as_bad_where (fixP->fx_file, fixP->fx_line, _("misaligned branch destination")); - if ((value & (offsetT)0xfe000000) != (offsetT)0 - && (value & (offsetT)0xfe000000) != (offsetT)0xfe000000) + if ((value & 0xfe000000) != 0 + && (value & 0xfe000000) != 0xfe000000) as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE); if (fixP->fx_done || !seg->use_rela_p) @@ -28952,7 +28952,7 @@ md_apply_fix (fixS * fixP, FIXME: It may be better to remove the instruction completely and perform relaxation. */ - if (value == -2) + if ((offsetT) value == -2) { newval = md_chars_to_number (buf, THUMB_SIZE); newval = 0xbf00; /* NOP encoding T1 */ @@ -29225,24 +29225,24 @@ md_apply_fix (fixS * fixP, if ((newval & 0x0f200f00) == 0x0d000900) { /* This is a fp16 vstr/vldr. The immediate offset in the mnemonic - has permitted values that are multiples of 2, in the range 0 + has permitted values that are multiples of 2, in the range -510 to 510. */ - if (value < -510 || value > 510 || (value & 1)) + if (value + 510 > 510 + 510 || (value & 1)) as_bad_where (fixP->fx_file, fixP->fx_line, _("co-processor offset out of range")); } else if ((newval & 0xfe001f80) == 0xec000f80) { - if (value < -511 || value > 512 || (value & 3)) + if (value + 511 > 512 + 511 || (value & 3)) as_bad_where (fixP->fx_file, fixP->fx_line, _("co-processor offset out of range")); } - else if (value < -1023 || value > 1023 || (value & 3)) + else if (value + 1023 > 1023 + 1023 || (value & 3)) as_bad_where (fixP->fx_file, fixP->fx_line, _("co-processor offset out of range")); cp_off_common: - sign = value > 0; - if (value < 0) + sign = (offsetT) value > 0; + if ((offsetT) value < 0) value = -value; if (fixP->fx_r_type == BFD_RELOC_ARM_CP_OFF_IMM || fixP->fx_r_type == BFD_RELOC_ARM_CP_OFF_IMM_S2) @@ -29284,7 +29284,7 @@ md_apply_fix (fixS * fixP, case BFD_RELOC_ARM_CP_OFF_IMM_S2: case BFD_RELOC_ARM_T32_CP_OFF_IMM_S2: - if (value < -255 || value > 255) + if (value + 255 > 255 + 255) as_bad_where (fixP->fx_file, fixP->fx_line, _("co-processor offset out of range")); value *= 4; @@ -29390,11 +29390,11 @@ md_apply_fix (fixS * fixP, _("invalid Hi register with immediate")); /* If value is negative, choose the opposite instruction. */ - if (value < 0) + if ((offsetT) value < 0) { value = -value; subtract = !subtract; - if (value < 0) + if ((offsetT) value < 0) as_bad_where (fixP->fx_file, fixP->fx_line, _("immediate value out of range")); } @@ -29478,7 +29478,7 @@ md_apply_fix (fixS * fixP, case BFD_RELOC_ARM_THUMB_IMM: newval = md_chars_to_number (buf, THUMB_SIZE); - if (value < 0 || value > 255) + if (value > 255) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid immediate: %ld is out of range"), (long) value); @@ -29490,7 +29490,7 @@ md_apply_fix (fixS * fixP, /* 5bit shift value (0..32). LSL cannot take 32. */ newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf83f; temp = newval & 0xf800; - if (value < 0 || value > 32 || (value == 32 && temp == T_OPCODE_LSL_I)) + if (value > 32 || (value == 32 && temp == T_OPCODE_LSL_I)) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid shift value: %ld"), (long) value); /* Shifts of zero must be encoded as LSL. */ @@ -29517,7 +29517,7 @@ md_apply_fix (fixS * fixP, /* REL format relocations are limited to a 16-bit addend. */ if (!fixP->fx_done) { - if (value < -0x8000 || value > 0x7fff) + if (value + 0x8000 > 0x7fff + 0x8000) as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range")); } @@ -29560,7 +29560,7 @@ md_apply_fix (fixS * fixP, bfd_vma encoded_addend = value; /* Check that addend can be encoded in instruction. */ - if (!seg->use_rela_p && (value < 0 || value > 255)) + if (!seg->use_rela_p && value > 255) as_bad_where (fixP->fx_file, fixP->fx_line, _("the offset 0x%08lX is not representable"), (unsigned long) encoded_addend); @@ -29626,7 +29626,7 @@ md_apply_fix (fixS * fixP, { bfd_vma insn; bfd_vma encoded_addend; - bfd_vma addend_abs = llabs (value); + bfd_vma addend_abs = llabs ((offsetT) value); /* Check that the absolute value of the addend can be expressed as an 8-bit constant plus a rotation. */ @@ -29642,7 +29642,7 @@ md_apply_fix (fixS * fixP, /* If the addend is positive, use an ADD instruction. Otherwise use a SUB. Take care not to destroy the S bit. */ insn &= 0xff1fffff; - if (value < 0) + if ((offsetT) value < 0) insn |= 1 << 22; else insn |= 1 << 23; @@ -29667,7 +29667,7 @@ md_apply_fix (fixS * fixP, if (!seg->use_rela_p) { bfd_vma insn; - bfd_vma addend_abs = llabs (value); + bfd_vma addend_abs = llabs ((offsetT) value); /* Check that the absolute value of the addend can be encoded in 12 bits. */ @@ -29681,7 +29681,7 @@ md_apply_fix (fixS * fixP, /* If the addend is negative, clear bit 23 of the instruction. Otherwise set it. */ - if (value < 0) + if ((offsetT) value < 0) insn &= ~(1 << 23); else insn |= 1 << 23; @@ -29706,7 +29706,7 @@ md_apply_fix (fixS * fixP, if (!seg->use_rela_p) { bfd_vma insn; - bfd_vma addend_abs = llabs (value); + bfd_vma addend_abs = llabs ((offsetT) value); /* Check that the absolute value of the addend can be encoded in 8 bits. */ @@ -29720,7 +29720,7 @@ md_apply_fix (fixS * fixP, /* If the addend is negative, clear bit 23 of the instruction. Otherwise set it. */ - if (value < 0) + if ((offsetT) value < 0) insn &= ~(1 << 23); else insn |= 1 << 23; @@ -29746,7 +29746,7 @@ md_apply_fix (fixS * fixP, if (!seg->use_rela_p) { bfd_vma insn; - bfd_vma addend_abs = llabs (value); + bfd_vma addend_abs = llabs ((offsetT) value); /* Check that the absolute value of the addend is a multiple of four and, when divided by four, fits in 8 bits. */ @@ -29765,7 +29765,7 @@ md_apply_fix (fixS * fixP, /* If the addend is negative, clear bit 23 of the instruction. Otherwise set it. */ - if (value < 0) + if ((offsetT) value < 0) insn &= ~(1 << 23); else insn |= 1 << 23; @@ -29813,7 +29813,7 @@ md_apply_fix (fixS * fixP, { fixP->fx_done = 0; } - if ((value & ~0x7f) && ((value & ~0x3f) != ~0x3f)) + if ((value & ~0x7f) && ((value & ~0x3f) != (valueT) ~0x3f)) as_bad_where (fixP->fx_file, fixP->fx_line, _("branch out of range")); |