From 2abc2bec4d8c241c1cd3972b64162407128b4daf Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 13 Nov 2017 12:19:34 +0100 Subject: [PATCH] x86-64/Intel: issue diagnostic for out of range displacement ... rather than silently dropping it altogether. i386_finalize_displacement() expects baseindex to already be set, so the respective statement needs to be moved up. This then also allows a subsequent conditional to be simplified. For this to not regress on 32-bit addressing, break out address size guessing from i386_index_check(), invoking the new function earlier so that i386_finalize_displacement() has i.prefix[ADDR_PREFIX] available. i386_addressing_mode () in turn needs i.base_reg / i.index_reg set earlier. --- gas/ChangeLog | 11 ++++++ gas/config/tc-i386-intel.c | 49 ++++++++++++++------------- gas/config/tc-i386.c | 22 +++++++++--- gas/testsuite/gas/i386/x86-64-inval.l | 2 ++ gas/testsuite/gas/i386/x86-64-inval.s | 1 + 5 files changed, 56 insertions(+), 29 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 7a5808d51bb..2c63aaa31f7 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +2017-11-13 Jan Beulich + + * config/tc-i386.c (i386_index_check): Break out ... + (i386_addressing_mode): ... this new function. + * config/tc-i386-intel.c (i386_intel_operand): Do base/index + swapping and the setting of .baseindex earlier. Call + i386_addressing_mode. + * testsuite/gas/i386/x86-64-inval.s: Add out of range + displacement case. + * testsuite/gas/i386/x86-64-inval.l: Adjust expectations. + 2017-11-09 Jim Wilson * testsuite/gas/elf/dwarf2-10.l: Accept optional line number in error. diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c index 9e8135e3bac..36ae8189edd 100644 --- a/gas/config/tc-i386-intel.c +++ b/gas/config/tc-i386-intel.c @@ -876,18 +876,41 @@ i386_intel_operand (char *operand_string, int got_a_float) return 0; } + /* Swap base and index in 16-bit memory operands like + [si+bx]. Since i386_index_check is also used in AT&T + mode we have to do this here. */ + if (intel_state.base + && intel_state.index + && intel_state.base->reg_type.bitfield.reg16 + && intel_state.index->reg_type.bitfield.reg16 + && intel_state.base->reg_num >= 6 + && intel_state.index->reg_num < 6) + { + i.base_reg = intel_state.index; + i.index_reg = intel_state.base; + } + else + { + i.base_reg = intel_state.base; + i.index_reg = intel_state.index; + } + + if (i.base_reg || i.index_reg) + i.types[this_operand].bitfield.baseindex = 1; + expP = &disp_expressions[i.disp_operands]; memcpy (expP, &exp, sizeof(exp)); resolve_expression (expP); if (expP->X_op != O_constant || expP->X_add_number - || (!intel_state.base - && !intel_state.index)) + || !i.types[this_operand].bitfield.baseindex) { i.op[this_operand].disps = expP; i.disp_operands++; + i386_addressing_mode (); + if (flag_code == CODE_64BIT) { i.types[this_operand].bitfield.disp32 = 1; @@ -927,9 +950,6 @@ i386_intel_operand (char *operand_string, int got_a_float) return 0; } - if (intel_state.base || intel_state.index) - i.types[this_operand].bitfield.baseindex = 1; - if (intel_state.seg) { expP = symbol_get_value_expression (intel_state.seg); @@ -956,25 +976,6 @@ i386_intel_operand (char *operand_string, int got_a_float) } } - /* Swap base and index in 16-bit memory operands like - [si+bx]. Since i386_index_check is also used in AT&T - mode we have to do that here. */ - if (intel_state.base - && intel_state.index - && intel_state.base->reg_type.bitfield.reg16 - && intel_state.index->reg_type.bitfield.reg16 - && intel_state.base->reg_num >= 6 - && intel_state.index->reg_num < 6) - { - i.base_reg = intel_state.index; - i.index_reg = intel_state.base; - } - else - { - i.base_reg = intel_state.base; - i.index_reg = intel_state.index; - } - if (!i386_index_check (operand_string)) return 0; diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index dcc70c80455..4161c8c0de5 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -8633,13 +8633,13 @@ i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp, return ret; } -/* Make sure the memory operand we've been dealt is valid. - Return 1 on success, 0 on a failure. */ +/* Return the active addressing mode, taking address override and + registers forming the address into consideration. Update the + address override prefix if necessary. */ -static int -i386_index_check (const char *operand_string) +static enum flag_code +i386_addressing_mode (void) { - const char *kind = "base/index"; enum flag_code addr_mode; if (i.prefix[ADDR_PREFIX]) @@ -8688,6 +8688,18 @@ i386_index_check (const char *operand_string) #endif } + return addr_mode; +} + +/* Make sure the memory operand we've been dealt is valid. + Return 1 on success, 0 on a failure. */ + +static int +i386_index_check (const char *operand_string) +{ + const char *kind = "base/index"; + enum flag_code addr_mode = i386_addressing_mode (); + if (current_templates->start->opcode_modifier.isstring && !current_templates->start->opcode_modifier.immext && (current_templates->end[-1].opcode_modifier.isstring diff --git a/gas/testsuite/gas/i386/x86-64-inval.l b/gas/testsuite/gas/i386/x86-64-inval.l index ad460c2f888..099cc62e48d 100644 --- a/gas/testsuite/gas/i386/x86-64-inval.l +++ b/gas/testsuite/gas/i386/x86-64-inval.l @@ -109,6 +109,7 @@ .*:115: Error: .* .*:116: Error: .* .*:117: Error: .* +.*:118: Error: .* GAS LISTING .* @@ -235,3 +236,4 @@ GAS LISTING .* [ ]*115[ ]+jmpd \[r8\] \# 32-bit data size not allowed [ ]*116[ ]+jmpd \[rax\] \# 32-bit data size not allowed [ ]*117[ ]+jmpq \[ax\] \# no 16-bit addressing +[ ]*[1-9][0-9]*[ ]+mov eax,\[rax\+0x876543210\] \# out of range displacement diff --git a/gas/testsuite/gas/i386/x86-64-inval.s b/gas/testsuite/gas/i386/x86-64-inval.s index 2c2f5db48cf..1ce832099be 100644 --- a/gas/testsuite/gas/i386/x86-64-inval.s +++ b/gas/testsuite/gas/i386/x86-64-inval.s @@ -115,3 +115,4 @@ movnti word ptr [rax], ax jmpd [r8] # 32-bit data size not allowed jmpd [rax] # 32-bit data size not allowed jmpq [ax] # no 16-bit addressing + mov eax,[rax+0x876543210] # out of range displacement -- 2.30.2