[binutils-gdb] i386: Allow non-absolute segment values for lcall/ljmp

H.J. Lu hjl@sourceware.org
Mon Oct 5 13:02:54 GMT 2020


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6d96a5946d1ec76fea79bc36aa95d7d3dd304200

commit 6d96a5946d1ec76fea79bc36aa95d7d3dd304200
Author: T.K. Chia <u1049321969@caramail.com>
Date:   Mon Oct 5 05:46:23 2020 -0700

    i386: Allow non-absolute segment values for lcall/ljmp
    
    Allow an unresolved or non-absolute symbol as the segment operand of an
    immediate far jump (`ljmp SEG, OFF') or far call (`lcall SEG, OFF').
    
    gas/
    
    2020-10-05  T.K. Chia  <u1049321969@caramail.com>
    
            PR gas/26694
            * NEWS: Updated for i386 lcall and ljmp change.
            * config/tc-i386.c (output_interseg_jump): Allow non-absolute
            segment operand for immediate lcall and ljmp.
            * testsuite/gas/i386/jump.d,
            * testsuite/gas/i386/jump.s,
            * testsuite/gas/i386/jump16.d,
            * testsuite/gas/i386/jump16.e,
            * testsuite/gas/i386/jump16.s: Add tests for non-absolute
            segment operand for immediate ljmp.
    
    ld/
    
    2020-10-05  T.K. Chia  <u1049321969@caramail.com>
    
            PR gas/26694
            * testsuite/ld-i386/ljmp.s,
            * testsuite/ld-i386/ljmp1.d,
            * testsuite/ld-i386/ljmp1.s,
            * testsuite/ld-i386/ljmp2.d,
            * testsuite/ld-i386/ljmp2.s,
            * testsuite/ld-x86-64/ljmp1.d,
            * testsuite/ld-x86-64/ljmp2.d: New testcases.
            * testsuite/ld-i386/i386.exp,
            * testsuite/ld-x86-64/x86-64.exp: Run them.

Diff:
---
 gas/ChangeLog                     | 13 +++++++++++++
 gas/NEWS                          |  3 +++
 gas/config/tc-i386.c              | 11 +++++++----
 gas/testsuite/gas/i386/jump.d     | 12 ++++++++++++
 gas/testsuite/gas/i386/jump.s     |  9 +++++++++
 gas/testsuite/gas/i386/jump16.d   | 12 ++++++++++++
 gas/testsuite/gas/i386/jump16.e   |  4 ++--
 gas/testsuite/gas/i386/jump16.s   |  9 +++++++++
 ld/ChangeLog                      | 13 +++++++++++++
 ld/testsuite/ld-i386/i386.exp     |  2 ++
 ld/testsuite/ld-i386/ljmp.s       | 10 ++++++++++
 ld/testsuite/ld-i386/ljmp1.d      | 18 ++++++++++++++++++
 ld/testsuite/ld-i386/ljmp1.s      |  9 +++++++++
 ld/testsuite/ld-i386/ljmp2.d      |  7 +++++++
 ld/testsuite/ld-i386/ljmp2.s      |  9 +++++++++
 ld/testsuite/ld-x86-64/ljmp1.d    | 17 +++++++++++++++++
 ld/testsuite/ld-x86-64/ljmp2.d    |  6 ++++++
 ld/testsuite/ld-x86-64/x86-64.exp |  2 ++
 18 files changed, 160 insertions(+), 6 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index bd0834016b9..b27e08bccb0 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2020-10-05  T.K. Chia  <u1049321969@caramail.com>
+
+	PR gas/26694
+	* NEWS: Updated for i386 lcall and ljmp change.
+	* config/tc-i386.c (output_interseg_jump): Allow non-absolute
+	segment operand for immediate lcall and ljmp.
+	* testsuite/gas/i386/jump.d,
+	* testsuite/gas/i386/jump.s,
+	* testsuite/gas/i386/jump16.d,
+	* testsuite/gas/i386/jump16.e,
+	* testsuite/gas/i386/jump16.s: Add tests for non-absolute
+	segment operand for immediate ljmp.
+
 2020-10-05  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR binutils/26704
diff --git a/gas/NEWS b/gas/NEWS
index 8f83beb15b2..1107725ea66 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,4 +1,7 @@
 -*- text -*-
+
+* Support non-absolute segment values for i386 lcall and ljmp.
+
 * When setting the link order attribute of ELF sections, it is now possible to
   use a numeric section index instead of symbol name.
 
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 8f798479baa..f3eaba6231e 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -8776,10 +8776,13 @@ output_interseg_jump (void)
   else
     fix_new_exp (frag_now, p - frag_now->fr_literal, size,
 		 i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1]));
-  if (i.op[0].imms->X_op != O_constant)
-    as_bad (_("can't handle non absolute segment in `%s'"),
-	    i.tm.name);
-  md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2);
+
+  p += size;
+  if (i.op[0].imms->X_op == O_constant)
+    md_number_to_chars (p, (valueT) i.op[0].imms->X_add_number, 2);
+  else
+    fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
+		 i.op[0].imms, 0, reloc (2, 0, 0, i.reloc[0]));
 }
 
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
diff --git a/gas/testsuite/gas/i386/jump.d b/gas/testsuite/gas/i386/jump.d
index 6dcececc1f2..72e399599c7 100644
--- a/gas/testsuite/gas/i386/jump.d
+++ b/gas/testsuite/gas/i386/jump.d
@@ -54,4 +54,16 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	ea 90 90 90 90 90 90 	ljmp   \$0x9090,\$0x90909090
 [ 	]*[a-f0-9]+:	ea 00 00 00 00 90 90 	ljmp   \$0x9090,\$0x0[ 	]+[a-f0-9]+: (R_386_)?(dir)?32	xxx
 [ 	]*[a-f0-9]+:	ea 00 00 00 00 90 90 	ljmp   \$0x9090,\$0x0[ 	]+[a-f0-9]+: (R_386_)?(dir)?32	xxx
+[ 	]*[a-f0-9]+:	ea 90 90 90 90 00 00 	ljmp   \$0x0,\$0x90909090[ 	]+[a-f0-9]+: (R_386_)?(dir)?16	yyy
+[ 	]*[a-f0-9]+:	ea 90 90 90 90 00 00 	ljmp   \$0x0,\$0x90909090[ 	]+[a-f0-9]+: (R_386_)?(dir)?16	yyy
+[ 	]*[a-f0-9]+:	ea 00 00 00 00 00 00 	ljmp   \$0x0,\$0x0[ 	]+[a-f0-9]+: (R_386_)?(dir)?32	xxx
+[	]+[a-f0-9]+: (R_386_)?(dir)?16	yyy
+[ 	]*[a-f0-9]+:	ea 00 00 00 00 00 00 	ljmp   \$0x0,\$0x0[ 	]+[a-f0-9]+: (R_386_)?(dir)?32	xxx
+[	]+[a-f0-9]+: (R_386_)?(dir)?16	yyy
+[ 	]*[a-f0-9]+:	ea 90 90 90 90 00 00 	ljmp   \$0x0,\$0x90909090[ 	]+[a-f0-9]+: (R_386_)?(dir)?16	yyy
+[ 	]*[a-f0-9]+:	ea 90 90 90 90 00 00 	ljmp   \$0x0,\$0x90909090[ 	]+[a-f0-9]+: (R_386_)?(dir)?16	yyy
+[ 	]*[a-f0-9]+:	ea 00 00 00 00 00 00 	ljmp   \$0x0,\$0x0[ 	]+[a-f0-9]+: (R_386_)?(dir)?32	xxx
+[	]+[a-f0-9]+: (R_386_)?(dir)?16	yyy
+[ 	]*[a-f0-9]+:	ea 00 00 00 00 00 00 	ljmp   \$0x0,\$0x0[ 	]+[a-f0-9]+: (R_386_)?(dir)?32	xxx
+[	]+[a-f0-9]+: (R_386_)?(dir)?16	yyy
 #pass
diff --git a/gas/testsuite/gas/i386/jump.s b/gas/testsuite/gas/i386/jump.s
index eec3f0ab639..5efe43882a8 100644
--- a/gas/testsuite/gas/i386/jump.s
+++ b/gas/testsuite/gas/i386/jump.s
@@ -1,6 +1,7 @@
 .psize 0
 .text
 .extern xxx
+.extern yyy
 
 1:	jmp	1b
 	jmp	xxx
@@ -54,3 +55,11 @@
 	jmp	0x9090:0x90909090
 	jmp	0x9090,xxx
 	jmp	0x9090:xxx
+	ljmp	yyy,0x90909090
+	ljmp	yyy:0x90909090
+	ljmp	yyy,xxx
+	ljmp	yyy:xxx
+	jmp	yyy,0x90909090
+	jmp	yyy:0x90909090
+	jmp	yyy,xxx
+	jmp	yyy:xxx
diff --git a/gas/testsuite/gas/i386/jump16.d b/gas/testsuite/gas/i386/jump16.d
index afb1c377e73..df4facc10c0 100644
--- a/gas/testsuite/gas/i386/jump16.d
+++ b/gas/testsuite/gas/i386/jump16.d
@@ -68,6 +68,18 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	ea 10 10 90 90       	ljmp   \$0x9090,\$0x1010
 [ 	]*[a-f0-9]+:	ea 00 00 90 90       	ljmp   \$0x9090,\$0x0	ed: (R_386_)?16	xxx
 [ 	]*[a-f0-9]+:	ea 00 00 90 90       	ljmp   \$0x9090,\$0x0	f2: (R_386_)?16	xxx
+[ 	]*[a-f0-9]+:	ea 10 10 00 00       	ljmp   \$0x0,\$0x1010	f9: (R_386_)?16	yyy
+[ 	]*[a-f0-9]+:	ea 10 10 00 00       	ljmp   \$0x0,\$0x1010	fe: (R_386_)?16	yyy
+[ 	]*[a-f0-9]+:	ea 00 00 00 00       	ljmp   \$0x0,\$0x0	101: (R_386_)?16	xxx
+[	]+103: (R_386_)?16	yyy
+[ 	]*[a-f0-9]+:	ea 00 00 00 00       	ljmp   \$0x0,\$0x0	106: (R_386_)?16	xxx
+[	]+108: (R_386_)?16	yyy
+[ 	]*[a-f0-9]+:	ea 10 10 00 00       	ljmp   \$0x0,\$0x1010	10d: (R_386_)?16	yyy
+[ 	]*[a-f0-9]+:	ea 10 10 00 00       	ljmp   \$0x0,\$0x1010	112: (R_386_)?16	yyy
+[ 	]*[a-f0-9]+:	ea 00 00 00 00       	ljmp   \$0x0,\$0x0	115: (R_386_)?16	xxx
+[	]+117: (R_386_)?16	yyy
+[ 	]*[a-f0-9]+:	ea 00 00 00 00       	ljmp   \$0x0,\$0x0	11a: (R_386_)?16	xxx
+[	]+11c: (R_386_)?16	yyy
 [ 	]*[a-f0-9]+:	cf                   	iret   
 [ 	]*[a-f0-9]+:	cf                   	iret   
 [ 	]*[a-f0-9]+:	66 cf                	iretl  
diff --git a/gas/testsuite/gas/i386/jump16.e b/gas/testsuite/gas/i386/jump16.e
index 2ad7ea056b6..aa5c5aad653 100644
--- a/gas/testsuite/gas/i386/jump16.e
+++ b/gas/testsuite/gas/i386/jump16.e
@@ -1,3 +1,3 @@
 .*: Assembler messages:
-.*:77: Warning: generating 16-bit `iret' for .code16gcc directive
-.*:88: Warning: generating 16-bit `iret' for .code16gcc directive
+.*:86: Warning: generating 16-bit `iret' for .code16gcc directive
+.*:97: Warning: generating 16-bit `iret' for .code16gcc directive
diff --git a/gas/testsuite/gas/i386/jump16.s b/gas/testsuite/gas/i386/jump16.s
index fb9e830c52b..42d150ff978 100644
--- a/gas/testsuite/gas/i386/jump16.s
+++ b/gas/testsuite/gas/i386/jump16.s
@@ -1,6 +1,7 @@
 .psize 0
 .text
 .extern xxx
+.extern yyy
 
 .code16gcc
 1:	jmp	1b
@@ -71,6 +72,14 @@
 	jmp	0x9090:0x1010
 	jmp	0x9090,xxx
 	jmp	0x9090:xxx
+	ljmp	yyy,0x1010
+	ljmp	yyy:0x1010
+	ljmp	yyy,xxx
+	ljmp	yyy:xxx
+	jmp	yyy,0x1010
+	jmp	yyy:0x1010
+	jmp	yyy,xxx
+	jmp	yyy:xxx
 
 	.att_syntax
 .code16gcc
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 0d5953a11b7..c259b09c74a 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,16 @@
+2020-10-05  T.K. Chia  <u1049321969@caramail.com>
+
+	PR gas/26694
+	* testsuite/ld-i386/ljmp.s,
+	* testsuite/ld-i386/ljmp1.d,
+	* testsuite/ld-i386/ljmp1.s,
+	* testsuite/ld-i386/ljmp2.d,
+	* testsuite/ld-i386/ljmp2.s,
+	* testsuite/ld-x86-64/ljmp1.d,
+	* testsuite/ld-x86-64/ljmp2.d: New testcases.
+	* testsuite/ld-i386/i386.exp,
+	* testsuite/ld-x86-64/x86-64.exp: Run them.
+
 2020-10-05  Nick Clifton  <nickc@redhat.com>
 
 	* lexsup.c (parse_args): Generate an error or warning message when
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 164c099cbbb..d0b8ed77bd1 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -342,6 +342,8 @@ run_dump_test "call3g"
 run_dump_test "call3h"
 run_dump_test "jmp1"
 run_dump_test "jmp2"
+run_dump_test "ljmp1"
+run_dump_test "ljmp2"
 run_dump_test "load1"
 run_dump_test "load2"
 run_dump_test "load3"
diff --git a/ld/testsuite/ld-i386/ljmp.s b/ld/testsuite/ld-i386/ljmp.s
new file mode 100644
index 00000000000..4b27a25a18e
--- /dev/null
+++ b/ld/testsuite/ld-i386/ljmp.s
@@ -0,0 +1,10 @@
+ .global seg1
+ .equiv seg1, 8
+ .global seg2
+ .equiv seg2, 0x18
+	/* Bad IA-16 segment values --- will overflow R_386_16 (and
+	   R_X86_64_16). */
+ .global seg3
+ .equiv seg3, 0x10000
+ .global seg4
+ .equiv seg4, -0x10001
diff --git a/ld/testsuite/ld-i386/ljmp1.d b/ld/testsuite/ld-i386/ljmp1.d
new file mode 100644
index 00000000000..9708ad0e002
--- /dev/null
+++ b/ld/testsuite/ld-i386/ljmp1.d
@@ -0,0 +1,18 @@
+#name: Absolute non-overflowing relocs in ljmp segments
+#as: --32
+#source: ljmp1.s
+#source: ljmp.s
+#ld: -melf_i386 -z noseparate-code
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	0f 22 c0             	mov    %eax,%cr0
+ +[a-f0-9]+:	ea ([0-9a-f]{2} ){4}08 00 	ljmp   \$0x8,\$0x[a-f0-9]+
+
+0+[a-f0-9]+ <foo>:
+ +[a-f0-9]+:	66 ea 00 00 18 00    	ljmpw  \$0x18,\$0x0
diff --git a/ld/testsuite/ld-i386/ljmp1.s b/ld/testsuite/ld-i386/ljmp1.s
new file mode 100644
index 00000000000..3ae6882de52
--- /dev/null
+++ b/ld/testsuite/ld-i386/ljmp1.s
@@ -0,0 +1,9 @@
+ .text
+.code32
+ .global _start
+_start:
+	movl	%eax, %cr0
+	ljmp	$seg1, $foo
+foo:
+	ljmpw	$seg2, $0
+ .p2align 4,0x90
diff --git a/ld/testsuite/ld-i386/ljmp2.d b/ld/testsuite/ld-i386/ljmp2.d
new file mode 100644
index 00000000000..b599cf9868a
--- /dev/null
+++ b/ld/testsuite/ld-i386/ljmp2.d
@@ -0,0 +1,7 @@
+#name: ljmp segment value overflow
+#as: --32
+#source: ljmp2.s
+#source: ljmp.s
+#ld: -melf_i386 -z noseparate-code
+#error: .*relocation truncated to fit: R_386_16 .*
+#error: .*relocation truncated to fit: R_386_16 .*
diff --git a/ld/testsuite/ld-i386/ljmp2.s b/ld/testsuite/ld-i386/ljmp2.s
new file mode 100644
index 00000000000..f6a4227a225
--- /dev/null
+++ b/ld/testsuite/ld-i386/ljmp2.s
@@ -0,0 +1,9 @@
+ .text
+.code32
+ .global _start
+_start:
+	movl	%eax, %cr0
+	ljmp	$seg3, $foo
+foo:
+	ljmpw	$seg4, $0
+ .p2align 4,0x90
diff --git a/ld/testsuite/ld-x86-64/ljmp1.d b/ld/testsuite/ld-x86-64/ljmp1.d
new file mode 100644
index 00000000000..eb378fb6079
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/ljmp1.d
@@ -0,0 +1,17 @@
+#name: Absolute non-overflowing relocs in ljmp segments
+#source: ../ld-i386/ljmp1.s
+#source: ../ld-i386/ljmp.s
+#ld: -z noseparate-code
+#objdump: -Mi386 -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:	0f 22 c0             	mov    %eax,%cr0
+ +[a-f0-9]+:	ea ([0-9a-f]{2} ){4}08 00 	ljmp   \$0x8,\$0x[a-f0-9]+
+
+0+[a-f0-9]+ <foo>:
+ +[a-f0-9]+:	66 ea 00 00 18 00    	ljmpw  \$0x18,\$0x0
diff --git a/ld/testsuite/ld-x86-64/ljmp2.d b/ld/testsuite/ld-x86-64/ljmp2.d
new file mode 100644
index 00000000000..b3581822ce6
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/ljmp2.d
@@ -0,0 +1,6 @@
+#name: ljmp segment value overflow
+#source: ../ld-i386/ljmp2.s
+#source: ../ld-i386/ljmp.s
+#ld: -z noseparate-code
+#error: .*relocation truncated to fit: R_X86_64_16 .*
+#error: .*relocation truncated to fit: R_X86_64_16 .*
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 3c0b4347d02..2c2551fd62e 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -519,6 +519,8 @@ run_dump_test "mov2a"
 run_dump_test "mov2b"
 run_dump_test "mov2c"
 run_dump_test "mov2d"
+run_dump_test "ljmp1"
+run_dump_test "ljmp2"
 run_dump_test "load1a"
 run_dump_test "load1b"
 run_dump_test "load1c"


More information about the Binutils-cvs mailing list