+2021-04-28 Jan Beulich <jbeulich@suse.com>
+ H.J. Lu <hjl.tools@gmail.com>
+
+ PR gas/27763
+ * config/tc-i386.c (output_jump): Also mark 2-byte relocs as
+ signed for XBEGIN. Also mark 4-byte relocs as signed for 64-bit.
+ (output_disp): Also mark 4-byte relocs as signed for 64-bit.
+ (md_estimate_size_before_relax): Move local variable fixP. Set
+ it from fix_new() return values. Mark 4-byte relocs as signed
+ for 64-bit.
+ * testsuite/gas/i386/pcrel64.s, testsuite/gas/i386/pcrel64.l,
+ * testsuite/gas/i386/x86-64-rip-2.s,
+ * testsuite/gas/i386/x86-64-rip-2.d,
+ * testsuite/gas/i386/x86-64-rip-inval-1.s,
+ * testsuite/gas/i386/x86-64-rip-inval-1.l,
+ * testsuite/gas/i386/x86-64-rip-inval-2.s,
+ * testsuite/gas/i386/x86-64-rip-inval-2.l: New.
+ * testsuite/gas/i386/i386.exp: Run new tests.
+
2021-04-27 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-i386.c (optimize_encoding): Add () to silence GCC 5.
fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.op[0].disps, 1, jump_reloc);
- /* All jumps handled here are signed, but don't use a signed limit
- check for 32 and 16 bit jumps as we want to allow wrap around at
- 4G and 64k respectively. */
- if (size == 1)
- fixP->fx_signed = 1;
+ /* All jumps handled here are signed, but don't unconditionally use a
+ signed limit check for 32 and 16 bit jumps as we want to allow wrap
+ around at 4G (outside of 64-bit mode) and 64k (except for XBEGIN)
+ respectively. */
+ switch (size)
+ {
+ case 1:
+ fixP->fx_signed = 1;
+ break;
+
+ case 2:
+ if (i.tm.base_opcode == 0xc7f8)
+ fixP->fx_signed = 1;
+ break;
+
+ case 4:
+ if (flag_code == CODE_64BIT)
+ fixP->fx_signed = 1;
+ break;
+ }
}
static void
fixP = fix_new_exp (frag_now, p - frag_now->fr_literal,
size, i.op[n].disps, pcrel,
reloc_type);
+
+ if (flag_code == CODE_64BIT && size == 4 && pcrel
+ && !i.prefix[ADDR_PREFIX])
+ fixP->fx_signed = 1;
+
/* Check for "call/jmp *mem", "mov mem, %reg",
"test %reg, mem" and "binop mem, %reg" where binop
is one of adc, add, and, cmp, or, sbb, sub, xor
enum bfd_reloc_code_real reloc_type;
unsigned char *opcode;
int old_fr_fix;
+ fixS *fixP = NULL;
if (fragP->fr_var != NO_RELOC)
reloc_type = (enum bfd_reloc_code_real) fragP->fr_var;
/* Make jmp (0xeb) a (d)word displacement jump. */
opcode[0] = 0xe9;
fragP->fr_fix += size;
- fix_new (fragP, old_fr_fix, size,
- fragP->fr_symbol,
- fragP->fr_offset, 1,
- reloc_type);
+ fixP = fix_new (fragP, old_fr_fix, size,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ reloc_type);
break;
case COND_JUMP86:
case COND_JUMP:
if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC)
{
- fixS *fixP;
-
fragP->fr_fix += 1;
fixP = fix_new (fragP, old_fr_fix, 1,
fragP->fr_symbol,
opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
/* We've added an opcode byte. */
fragP->fr_fix += 1 + size;
- fix_new (fragP, old_fr_fix + 1, size,
- fragP->fr_symbol,
- fragP->fr_offset, 1,
- reloc_type);
+ fixP = fix_new (fragP, old_fr_fix + 1, size,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ reloc_type);
break;
default:
BAD_CASE (fragP->fr_subtype);
break;
}
+
+ /* All jumps handled here are signed, but don't unconditionally use a
+ signed limit check for 32 and 16 bit jumps as we want to allow wrap
+ around at 4G (outside of 64-bit mode) and 64k. */
+ if (size == 4 && flag_code == CODE_64BIT)
+ fixP->fx_signed = 1;
+
frag_wane (fragP);
return fragP->fr_fix - old_fr_fix;
}
# if defined (TE_PE) || defined (TE_PEP)
case bfd_target_coff_flavour:
if (flag_code == CODE_64BIT)
- return use_big_obj ? "pe-bigobj-x86-64" : "pe-x86-64";
- else
- return use_big_obj ? "pe-bigobj-i386" : "pe-i386";
+ {
+ object_64bit = 1;
+ return use_big_obj ? "pe-bigobj-x86-64" : "pe-x86-64";
+ }
+ return use_big_obj ? "pe-bigobj-i386" : "pe-i386";
# elif defined (TE_GO32)
case bfd_target_coff_flavour:
return "coff-go32";
} else {
run_dump_test "x86-64-w64-pcrel"
}
+ run_list_test "pcrel64" "-al"
run_dump_test "x86-64-rip"
run_dump_test "x86-64-rip-intel"
+ run_dump_test "x86-64-rip-2"
+ run_list_test "x86-64-rip-inval-1" "-al"
+ run_list_test "x86-64-rip-inval-2" "-al"
run_dump_test "x86-64-stack"
run_dump_test "x86-64-stack-intel"
run_dump_test "x86-64-stack-suffix"
--- /dev/null
+.*: Assembler messages:
+.*:16: Error: .*
+.*:17: Error: .*
+.*:13: Error: .*
+.*:15: Error: .*
+.*:18: Error: .*
+.*:19: Error: .*
+.*:20: Error: .*
+GAS LISTING .*
+
+
+[ ]*[0-9]+[ ]+\.text
+[ ]*[0-9]+[ ]+\.code64
+[ ]*[0-9]+[ ]+pcrel:
+[ ]*[0-9]+ \?\?\?\? E8..8000[ ]+call target
+[ ]*[0-9]+[ ]+00
+[ ]*[0-9]+ \?\?\?\? E9..8000[ ]+jmp target
+[ ]*[0-9]+[ ]+00
+[ ]*[0-9]+ \?\?\?\? 0F84..80[ ]+jz target
+[ ]*[0-9]+[ ]+0000
+[ ]*[0-9]+ \?\?\?\? C7F8..80[ ]+xbegin target
+[ ]*[0-9]+[ ]+0000
+[ ]*[0-9]+ \?\?\?\? 8B05..80[ ]+mov target\(%rip\), %eax
+[ ]*[0-9]+[ ]+0000
+[ ]*[0-9]+ \?\?\?\? 678B05..[ ]+mov target\(%eip\), %eax
+[ ]*[0-9]+[ ]+800000
+[ ]*[0-9]+ \?\?\?\? 48C7C0..[ ]+mov \$target-., %rax
+[ ]*[0-9]+[ ]+800000
+[ ]*[0-9]+ \?\?\?\? B8..8000[ ]+mov \$target-., %eax
+[ ]*[0-9]+[ ]+00
+[ ]*[0-9]+[ ]*
+[ ]*[0-9]+ \?\?\?\? 66C7F8..[ ]+data16 xbegin target
+[ ]*[0-9]+[ ]+80
+[ ]*[0-9]+[ ]*
+[ ]*[0-9]+ \?\?\?\? E8...000[ ]+call target\+0x7ffff000
+[ ]*[0-9]+[ ]+80
+[ ]*[0-9]+ \?\?\?\? E9000000[ ]+jmp target\+0x7ffff000
+[ ]*[0-9]+[ ]+00
+[ ]*[0-9]+ \?\?\?\? 0F840000[ ]+jz target\+0x7ffff000
+[ ]*[0-9]+[ ]+0000
+[ ]*[0-9]+ \?\?\?\? C7F8...0[ ]+xbegin target\+0x7ffff000
+[ ]*[0-9]+[ ]+0080
+[ ]*[0-9]+ \?\?\?\? 8B05...0[ ]+mov target\+0x7ffff000\(%rip\), %eax
+[ ]*[0-9]+[ ]+0080
+[ ]*[0-9]+ \?\?\?\? 48C7C0..[ ]+mov \$target\+0x7ffff000-., %rax
+[ ]*[0-9]+[ ]+.00080
+[ ]*[0-9]+[ ]*
+[ ]*[0-9]+ \?\?\?\? 678B05..[ ]+mov target\+0x7ffff000\(%eip\), %eax
+[ ]*[0-9]+[ ]+.00080
+[ ]*[0-9]+ \?\?\?\? B8...000[ ]+mov \$target\+0x7ffff000-., %eax
+[ ]*[0-9]+[ ]+80
+[ ]*[0-9]+[ ]*
+[ ]*[0-9]+ \?\?\?\? CCCCCCCC[ ]+\.fill 0x8000, 1, 0xcc
+#pass
--- /dev/null
+ .text
+ .code64
+pcrel:
+ call target
+ jmp target
+ jz target
+ xbegin target
+ mov target(%rip), %eax
+ mov target(%eip), %eax
+ mov $target-., %rax
+ mov $target-., %eax
+
+ data16 xbegin target
+
+ call target+0x7ffff000
+ jmp target+0x7ffff000
+ jz target+0x7ffff000
+ xbegin target+0x7ffff000
+ mov target+0x7ffff000(%rip), %eax
+ mov $target+0x7ffff000-., %rax
+
+ mov target+0x7ffff000(%eip), %eax
+ mov $target+0x7ffff000-., %eax
+
+ .fill 0x8000, 1, 0xcc
+target:
+ ret
--- /dev/null
+#as: -J
+#objdump: -drw --syms
+#name: x86-64 rip addressing 2
+
+.*: +file format .*
+
+SYMBOL TABLE:
+0000000000000000 l .text 0000000000000000 _start
+0000000080000006 l .text 0000000000000000 test1
+ffffffff8000000e l .text 0000000000000000 test2
+00000000f000000e l .text 0000000000000000 test3
+ffffffff1000000e l .text 0000000000000000 test4
+
+
+
+Disassembly of section .text:
+
+0000000000000000 <_start>:
+ +0: 48 8b 05 ff ff ff 7f mov 0x7fffffff\(%rip\),%rax # 80000006 <test1>
+ +7: 48 8b 05 00 00 00 80 mov -0x80000000\(%rip\),%rax # ffffffff8000000e <test2>
+#pass
--- /dev/null
+ .text
+_start:
+ movq test1(%rip), %rax
+ .set test1, . + 0x7fffffff
+
+ movq test2(%rip), %rax
+ .set test2, . - 0x80000000
+
+ .set test3, . + 0xf0000000
+ .set test4, . - 0xf0000000
--- /dev/null
+.*: Assembler messages:
+.*:3: Error:.* (0x)?ffffffff7fffffff .*
+GAS LISTING .*
+
+
+[ ]*1[ ]+\.text
+[ ]*2[ ]+_start:
+[ ]*3[ ]+\?\?\?\? 488B05FF movq test1\(%rip\), %rax
+[ ]*3[ ]+FFFF7F
+[ ]*4[ ]+\.set test1, \. - 0x80000001
+#pass
--- /dev/null
+ .text
+_start:
+ movq test1(%rip), %rax
+ .set test1, . - 0x80000001
--- /dev/null
+.*: Assembler messages:
+.*:3: Error:.* (0x)?0*80000000 .*
+GAS LISTING .*
+
+
+[ ]*1[ ]+\.text
+[ ]*2[ ]+_start:
+[ ]*3[ ]+\?\?\?\? 488B0500 movq test1\(%rip\), %rax
+[ ]*3[ ]+000080
+[ ]*4[ ]+\.set test1, \. \+ 0x80000000
+#pass
--- /dev/null
+ .text
+_start:
+ movq test1(%rip), %rax
+ .set test1, . + 0x80000000