aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-10-22 04:46:51 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-10-22 04:47:07 -0700
commit02a866936de7e63ad4962ccba56c8cd05c231275 (patch)
tree057157847f8f10880700c0fd6e006bee27034697 /ld
parent99ba51255402201c6e193d803ee1f1fc3f2de0e6 (diff)
downloadfsf-binutils-gdb-02a866936de7e63ad4962ccba56c8cd05c231275.zip
fsf-binutils-gdb-02a866936de7e63ad4962ccba56c8cd05c231275.tar.gz
fsf-binutils-gdb-02a866936de7e63ad4962ccba56c8cd05c231275.tar.bz2
Add R_386_GOT32X support to gas and ld
This patch adds support for the R_386_GOT32X relocation proposed in https://groups.google.com/forum/#!topic/ia32-abi/GbJJskkid4I to gas and ld. It updates gas to generate R_386_GOT32X relocation for memory operand, foo@GOT[(%reg)]. We must encode "mov foo@GOT, %eax" with the 0x8b opcode, instead of the 0xb8 opcode, so that it can be transformed to "lea foo, %eax". With the locally defined symbol, foo, we convert mov foo@GOT[(%reg1)], %reg2 to lea foo[@GOTOFF(%reg1)], %reg2 and convert call/jmp *foo@GOT[(%reg)] to nop call foo/jmp foo nop When PIC is false, convert test %reg1, foo@GOT[(%reg2)] to test $foo, %reg1 and convert binop foo@GOT[(%reg1)], %reg2 to binop $foo, %reg2 where binop is one of adc, add, and, cmp, or, sbb, sub, xor instructions. bfd/ * elf32-i386.c: Include opcode/i386.h. (elf_howto_table): Add R_386_GOT32X. (R_386_ext2): Replace R_386_IRELATIVE with R_386_GOT32X. (elf_i386_reloc_type_lookup): Handle BFD_RELOC_386_GOT32X. (need_convert_mov_to_lea): Renamed to ... (need_convert_load): This. (elf_i386_check_relocs): Handle R_386_GOT32X. Replace need_convert_mov_to_lea with need_convert_load. (elf_i386_gc_sweep_hook): Handle R_386_GOT32X. (elf_i386_size_dynamic_sections): Likewise. (elf_i386_relocate_section): Likewise. (elf_i386_convert_mov_to_lea): Renamed to ... (elf_i386_convert_load): This. Replace need_convert_mov_to_lea with need_convert_load. Support R_386_GOT32X transformations. * reloc.c (BFD_RELOC_386_GOT32X): New. * bfd-in2.h: Regenerated. * libbfd.h: Likewise. gas/ * config/tc-i386.c (tc_i386_fix_adjustable): Handle BFD_RELOC_386_GOT32X. (tc_gen_reloc): Likewise. (match_template): Force 0x8b encoding for "mov foo@GOT, %eax". (output_disp): 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 instructions. Set fx_tcbit if the REX prefix is generated. Set fx_tcbit2 if BFD_RELOC_386_GOT32X should be generated. (i386_validate_fix): Generate BFD_RELOC_386_GOT32X if fx_tcbit2 is set. gas/testsuite/ * gas/i386/got.d: New file. * gas/i386/got.s: Likewise. * gas/i386/i386.exp: Run got. * gas/i386/localpic.d: Replace R_386_GOT32 with R_386_GOT32X. * gas/i386/mixed-mode-reloc32.d: Likewise. * gas/i386/reloc32.d: Likewise. include/elf/ * i386.h (R_386_GOT32X): New relocation. ld/testsuite/ * ld-i386/branch1.d: New file. * ld-i386/branch1.s: Likewise. * ld-i386/call1.d: Likewise. * ld-i386/call1.s: Likewise. * ld-i386/call2.d: Likewise. * ld-i386/call2.s: Likewise. * ld-i386/got1.dd: Likewise. * ld-i386/got1.out: Likewise. * ld-i386/got1a.S: Likewise. * ld-i386/got1b.c: Likewise. * ld-i386/got1c.c: Likewise. * ld-i386/got1d.S: Likewise. * ld-i386/jmp1.d: Likewise. * ld-i386/jmp1.s: Likewise. * ld-i386/jmp2.d: Likewise. * ld-i386/jmp2.s: Likewise. * ld-i386/load1.d: Likewise. * ld-i386/load1.s: Likewise. * ld-i386/load2.d: Likewise. * ld-i386/load2.s: Likewise. * ld-i386/load3.d: Likewise. * ld-i386/load3.s: Likewise. * ld-i386/load4.s: Likewise. * ld-i386/load4a.d: Likewise. * ld-i386/load4b.d: Likewise. * ld-i386/load5.s: Likewise. * ld-i386/load5a.d: Likewise. * ld-i386/load5b.d: Likewise. * ld-i386/load6.d: Likewise. * ld-i386/load6.s: Likewise. * ld-i386/i386.exp: Run branch1, call1, call2, jmp1, jmp2, load1, load2, load3, load4a, load4b, load5a, load5b and load6 tests. Run got1 test.
Diffstat (limited to 'ld')
-rw-r--r--ld/testsuite/ChangeLog36
-rw-r--r--ld/testsuite/ld-i386/branch1.d17
-rw-r--r--ld/testsuite/ld-i386/branch1.s15
-rw-r--r--ld/testsuite/ld-i386/call1.d3
-rw-r--r--ld/testsuite/ld-i386/call1.s9
-rw-r--r--ld/testsuite/ld-i386/call2.d3
-rw-r--r--ld/testsuite/ld-i386/call2.s8
-rw-r--r--ld/testsuite/ld-i386/got1.dd20
-rw-r--r--ld/testsuite/ld-i386/got1.out7
-rw-r--r--ld/testsuite/ld-i386/got1a.S21
-rw-r--r--ld/testsuite/ld-i386/got1b.c7
-rw-r--r--ld/testsuite/ld-i386/got1c.c7
-rw-r--r--ld/testsuite/ld-i386/got1d.S54
-rw-r--r--ld/testsuite/ld-i386/i386.exp37
-rw-r--r--ld/testsuite/ld-i386/jmp1.d3
-rw-r--r--ld/testsuite/ld-i386/jmp1.s9
-rw-r--r--ld/testsuite/ld-i386/jmp2.d3
-rw-r--r--ld/testsuite/ld-i386/jmp2.s8
-rw-r--r--ld/testsuite/ld-i386/lea1c.d4
-rw-r--r--ld/testsuite/ld-i386/load1.d57
-rw-r--r--ld/testsuite/ld-i386/load1.s55
-rw-r--r--ld/testsuite/ld-i386/load2.d3
-rw-r--r--ld/testsuite/ld-i386/load2.s8
-rw-r--r--ld/testsuite/ld-i386/load3.d3
-rw-r--r--ld/testsuite/ld-i386/load3.s9
-rw-r--r--ld/testsuite/ld-i386/load4.s9
-rw-r--r--ld/testsuite/ld-i386/load4a.d4
-rw-r--r--ld/testsuite/ld-i386/load4b.d13
-rw-r--r--ld/testsuite/ld-i386/load5.s8
-rw-r--r--ld/testsuite/ld-i386/load5a.d4
-rw-r--r--ld/testsuite/ld-i386/load5b.d13
-rw-r--r--ld/testsuite/ld-i386/load6.d28
-rw-r--r--ld/testsuite/ld-i386/load6.s33
-rw-r--r--ld/testsuite/ld-i386/plt-main1.rd2
-rw-r--r--ld/testsuite/ld-i386/plt-main3.rd2
-rw-r--r--ld/testsuite/ld-i386/plt-main4.rd2
36 files changed, 519 insertions, 5 deletions
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 46587a7..becfd53 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,39 @@
+2015-10-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-i386/branch1.d: New file.
+ * ld-i386/branch1.s: Likewise.
+ * ld-i386/call1.d: Likewise.
+ * ld-i386/call1.s: Likewise.
+ * ld-i386/call2.d: Likewise.
+ * ld-i386/call2.s: Likewise.
+ * ld-i386/got1.dd: Likewise.
+ * ld-i386/got1.out: Likewise.
+ * ld-i386/got1a.S: Likewise.
+ * ld-i386/got1b.c: Likewise.
+ * ld-i386/got1c.c: Likewise.
+ * ld-i386/got1d.S: Likewise.
+ * ld-i386/jmp1.d: Likewise.
+ * ld-i386/jmp1.s: Likewise.
+ * ld-i386/jmp2.d: Likewise.
+ * ld-i386/jmp2.s: Likewise.
+ * ld-i386/load1.d: Likewise.
+ * ld-i386/load1.s: Likewise.
+ * ld-i386/load2.d: Likewise.
+ * ld-i386/load2.s: Likewise.
+ * ld-i386/load3.d: Likewise.
+ * ld-i386/load3.s: Likewise.
+ * ld-i386/load4.s: Likewise.
+ * ld-i386/load4a.d: Likewise.
+ * ld-i386/load4b.d: Likewise.
+ * ld-i386/load5.s: Likewise.
+ * ld-i386/load5a.d: Likewise.
+ * ld-i386/load5b.d: Likewise.
+ * ld-i386/load6.d: Likewise.
+ * ld-i386/load6.s: Likewise.
+ * ld-i386/i386.exp: Run branch1, call1, call2, jmp1, jmp2,
+ load1, load2, load3, load4a, load4b, load5a, load5b and load6
+ tests. Run got1 test.
+
2015-10-22 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* ld-ifunc/ifunc.exp: Run ifunc tests on s390* targets.
diff --git a/ld/testsuite/ld-i386/branch1.d b/ld/testsuite/ld-i386/branch1.d
new file mode 100644
index 0000000..a078f1d
--- /dev/null
+++ b/ld/testsuite/ld-i386/branch1.d
@@ -0,0 +1,17 @@
+#as: --32
+#ld: -melf_i386
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+#...
+[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <foo>
+[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <bar>
+[ ]*[a-f0-9]+: e9 ([0-9a-f]{2} ){4} * jmp +[a-f0-9]+ <foo>
+[ ]*[a-f0-9]+: 90 nop
+[ ]*[a-f0-9]+: e9 ([0-9a-f]{2} ){4} * jmp +[a-f0-9]+ <bar>
+[ ]*[a-f0-9]+: 90 nop
+#pass
diff --git a/ld/testsuite/ld-i386/branch1.s b/ld/testsuite/ld-i386/branch1.s
new file mode 100644
index 0000000..0ccf5cf
--- /dev/null
+++ b/ld/testsuite/ld-i386/branch1.s
@@ -0,0 +1,15 @@
+ .text
+ .type bar, @function
+bar:
+ ret
+ .globl foo
+ .type foo, @function
+foo:
+ ret
+ .globl _start
+ .type _start, @function
+_start:
+ call *foo@GOT
+ call *bar@GOT
+ jmp *foo@GOT
+ jmp *bar@GOT
diff --git a/ld/testsuite/ld-i386/call1.d b/ld/testsuite/ld-i386/call1.d
new file mode 100644
index 0000000..69383b2
--- /dev/null
+++ b/ld/testsuite/ld-i386/call1.d
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -shared -melf_i386
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/call1.s b/ld/testsuite/ld-i386/call1.s
new file mode 100644
index 0000000..ce003c8
--- /dev/null
+++ b/ld/testsuite/ld-i386/call1.s
@@ -0,0 +1,9 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ ret
+ .globl _start
+ .type _start, @function
+_start:
+ call *foo@GOT
diff --git a/ld/testsuite/ld-i386/call2.d b/ld/testsuite/ld-i386/call2.d
new file mode 100644
index 0000000..69383b2
--- /dev/null
+++ b/ld/testsuite/ld-i386/call2.d
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -shared -melf_i386
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/call2.s b/ld/testsuite/ld-i386/call2.s
new file mode 100644
index 0000000..57cd88f
--- /dev/null
+++ b/ld/testsuite/ld-i386/call2.s
@@ -0,0 +1,8 @@
+ .text
+ .type foo, @function
+foo:
+ ret
+ .globl _start
+ .type _start, @function
+_start:
+ call *foo@GOT
diff --git a/ld/testsuite/ld-i386/got1.dd b/ld/testsuite/ld-i386/got1.dd
new file mode 100644
index 0000000..e46153d
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1.dd
@@ -0,0 +1,20 @@
+#...
+[a-f0-9]+ <main>:
+[ ]*[a-f0-9]+: 83 ec 0c sub \$0xc,%esp
+[ ]*[a-f0-9]+: [ a-f0-9]+ addr16 call [a-f0-9]+ <foo>
+[ ]*[a-f0-9]+: [ a-f0-9]+ call \*0x[a-f0-9]+
+[ ]*[a-f0-9]+: [ a-f0-9]+ call \*0x[a-f0-9]+
+[ ]*[a-f0-9]+: [ a-f0-9]+ lea *0x[a-f0-9]+,%eax
+[ ]*[a-f0-9]+: ff d0 call \*%eax
+[ ]*[a-f0-9]+: [ a-f0-9]+ mov *0x[a-f0-9]+,%eax
+[ ]*[a-f0-9]+: ff d0 call \*%eax
+[ ]*[a-f0-9]+: [ a-f0-9]+ mov *0x[a-f0-9]+,%eax
+[ ]*[a-f0-9]+: ff d0 call \*%eax
+[ ]*[a-f0-9]+: [ a-f0-9]+ lea *0x[a-f0-9]+,%ecx
+[ ]*[a-f0-9]+: ff d1 call \*%ecx
+[ ]*[a-f0-9]+: 83 ec 0c sub \$0xc,%esp
+[ ]*[a-f0-9]+: 6a 00 push \$0x0
+[ ]*[a-f0-9]+: 6a 00 push \$0x0
+[ ]*[a-f0-9]+: [ a-f0-9]+ jmp [a-f0-9]+ <myexit>
+[ ]*[a-f0-9]+: 90 nop
+#pass
diff --git a/ld/testsuite/ld-i386/got1.out b/ld/testsuite/ld-i386/got1.out
new file mode 100644
index 0000000..99d4f7f
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1.out
@@ -0,0 +1,7 @@
+foo
+bar
+plt
+foo
+bar
+plt
+foo
diff --git a/ld/testsuite/ld-i386/got1a.S b/ld/testsuite/ld-i386/got1a.S
new file mode 100644
index 0000000..f3d5330
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1a.S
@@ -0,0 +1,21 @@
+ .text
+ .globl main
+ .type main, @function
+main:
+ subl $12, %esp
+ call *foo@GOT
+ call *bar@GOT
+ call *plt@GOT
+ movl foo@GOT, %eax
+ call *%eax
+ movl bar@GOT, %eax
+ call *%eax
+ movl plt@GOT, %eax
+ call *%eax
+ movl foo@GOT(%ebx), %ecx
+ call *%ecx
+ subl $12, %esp
+ pushl $0
+ pushl $0 # Push a dummy return address onto stack.
+ jmp *myexit@GOT
+ .size main, .-main
diff --git a/ld/testsuite/ld-i386/got1b.c b/ld/testsuite/ld-i386/got1b.c
new file mode 100644
index 0000000..cf0c78e
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1b.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+foo (void)
+{
+ printf ("%s\n", __FUNCTION__);
+}
diff --git a/ld/testsuite/ld-i386/got1c.c b/ld/testsuite/ld-i386/got1c.c
new file mode 100644
index 0000000..05f5fc2
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1c.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+void
+myexit (int status)
+{
+ exit (status);
+}
diff --git a/ld/testsuite/ld-i386/got1d.S b/ld/testsuite/ld-i386/got1d.S
new file mode 100644
index 0000000..a6d51c6
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1d.S
@@ -0,0 +1,54 @@
+ .globl bar
+ .type bar, @function
+bar:
+ pushl %ebx
+ call __x86.get_pc_thunk.cx
+ addl $_GLOBAL_OFFSET_TABLE_, %ecx
+ subl $24, %esp
+ leal __FUNCTION__.1862@GOTOFF(%ecx), %eax
+ movl %eax, (%esp)
+ call *puts@GOT(%ecx)
+ addl $24, %esp
+ popl %ebx
+ ret
+ .size bar, .-bar
+
+ .globl plt
+ .type plt, @function
+plt:
+ pushl %esi
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+1:
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ subl $20, %esp
+ leal __FUNCTION__.1866@GOTOFF(%ebx), %esi
+ movl %esi, (%esp)
+ call *puts@GOT(%ebx)
+ addl $20, %esp
+ popl %ebx
+ popl %esi
+ ret
+ .section .rodata
+ .type __FUNCTION__.1866, @object
+ .size __FUNCTION__.1866, 4
+__FUNCTION__.1866:
+ .string "plt"
+ .type __FUNCTION__.1862, @object
+ .size __FUNCTION__.1862, 4
+__FUNCTION__.1862:
+ .string "bar"
+ .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+ .globl __x86.get_pc_thunk.bx
+ .hidden __x86.get_pc_thunk.bx
+ .type __x86.get_pc_thunk.bx, @function
+__x86.get_pc_thunk.bx:
+ movl (%esp), %ebx
+ ret
+ .section .text.__x86.get_pc_thunk.cx,"axG",@progbits,__x86.get_pc_thunk.cx,comdat
+ .globl __x86.get_pc_thunk.cx
+ .hidden __x86.get_pc_thunk.cx
+ .type __x86.get_pc_thunk.cx, @function
+__x86.get_pc_thunk.cx:
+ movl (%esp), %ecx
+ ret
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 8cddfce..3d28dcc 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -293,6 +293,19 @@ run_dump_test "lea1e"
run_dump_test "lea1f"
run_dump_test "mov1a"
run_dump_test "mov1b"
+run_dump_test "branch1"
+run_dump_test "call1"
+run_dump_test "call2"
+run_dump_test "jmp1"
+run_dump_test "jmp2"
+run_dump_test "load1"
+run_dump_test "load2"
+run_dump_test "load3"
+run_dump_test "load4a"
+run_dump_test "load4b"
+run_dump_test "load5a"
+run_dump_test "load5b"
+run_dump_test "load6"
if { !([istarget "i?86-*-linux*"]
|| [istarget "i?86-*-gnu*"]
@@ -498,6 +511,22 @@ if { [isnative]
"" \
"pr19031.so" \
] \
+ [list \
+ "Build got1d.so" \
+ "-shared" \
+ "" \
+ { got1d.S } \
+ "" \
+ "got1d.so" \
+ ] \
+ [list \
+ "Build gotpc1" \
+ "tmpdir/got1d.so" \
+ "" \
+ { got1a.S got1b.c got1c.c } \
+ {{objdump {-dw} got1.dd}} \
+ "got1" \
+ ] \
]
run_ld_link_exec_tests [] [list \
@@ -568,6 +597,14 @@ if { [isnative]
"pr19031" \
"pr19031.out" \
] \
+ [list \
+ "Run got1" \
+ "tmpdir/got1d.so" \
+ "" \
+ { got1a.S got1b.c got1c.c } \
+ "got1" \
+ "got1.out" \
+ ] \
]
}
diff --git a/ld/testsuite/ld-i386/jmp1.d b/ld/testsuite/ld-i386/jmp1.d
new file mode 100644
index 0000000..69383b2
--- /dev/null
+++ b/ld/testsuite/ld-i386/jmp1.d
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -shared -melf_i386
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/jmp1.s b/ld/testsuite/ld-i386/jmp1.s
new file mode 100644
index 0000000..8c80696
--- /dev/null
+++ b/ld/testsuite/ld-i386/jmp1.s
@@ -0,0 +1,9 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ ret
+ .globl _start
+ .type _start, @function
+_start:
+ jmp *foo@GOT
diff --git a/ld/testsuite/ld-i386/jmp2.d b/ld/testsuite/ld-i386/jmp2.d
new file mode 100644
index 0000000..69383b2
--- /dev/null
+++ b/ld/testsuite/ld-i386/jmp2.d
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -shared -melf_i386
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/jmp2.s b/ld/testsuite/ld-i386/jmp2.s
new file mode 100644
index 0000000..b4bc38d
--- /dev/null
+++ b/ld/testsuite/ld-i386/jmp2.s
@@ -0,0 +1,8 @@
+ .text
+ .type foo, @function
+foo:
+ ret
+ .globl _start
+ .type _start, @function
+_start:
+ jmp *foo@GOT
diff --git a/ld/testsuite/ld-i386/lea1c.d b/ld/testsuite/ld-i386/lea1c.d
index c84f413..54ec0de 100644
--- a/ld/testsuite/ld-i386/lea1c.d
+++ b/ld/testsuite/ld-i386/lea1c.d
@@ -9,6 +9,6 @@
Disassembly of section .text:
#...
-[ ]*[a-f0-9]+: 8d 81 ([0-9a-f]{2} ){4} * lea -0x[a-f0-9]+\(%ecx\),%eax
-[ ]*[a-f0-9]+: 8d 81 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%ecx\),%eax
+[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
+[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
#pass
diff --git a/ld/testsuite/ld-i386/load1.d b/ld/testsuite/ld-i386/load1.d
new file mode 100644
index 0000000..e93531e
--- /dev/null
+++ b/ld/testsuite/ld-i386/load1.d
@@ -0,0 +1,57 @@
+#as: --32
+#ld: -melf_i386
+#objdump: -dw --sym
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+8049170 l O .data 0+1 bar
+#...
+0+8049171 g O .data 0+1 foo
+#...
+
+Disassembly of section .text:
+
+0+8048074 <_start>:
+[ ]*[a-f0-9]+: 8d 05 70 91 04 08 lea 0x8049170,%eax
+[ ]*[a-f0-9]+: 81 d0 70 91 04 08 adc \$0x8049170,%eax
+[ ]*[a-f0-9]+: 81 c3 70 91 04 08 add \$0x8049170,%ebx
+[ ]*[a-f0-9]+: 81 e1 70 91 04 08 and \$0x8049170,%ecx
+[ ]*[a-f0-9]+: 81 fa 70 91 04 08 cmp \$0x8049170,%edx
+[ ]*[a-f0-9]+: 81 cf 70 91 04 08 or \$0x8049170,%edi
+[ ]*[a-f0-9]+: 81 de 70 91 04 08 sbb \$0x8049170,%esi
+[ ]*[a-f0-9]+: 81 ed 70 91 04 08 sub \$0x8049170,%ebp
+[ ]*[a-f0-9]+: 81 f4 70 91 04 08 xor \$0x8049170,%esp
+[ ]*[a-f0-9]+: f7 c1 70 91 04 08 test \$0x8049170,%ecx
+[ ]*[a-f0-9]+: 8d 05 70 91 04 08 lea 0x8049170,%eax
+[ ]*[a-f0-9]+: 81 d0 70 91 04 08 adc \$0x8049170,%eax
+[ ]*[a-f0-9]+: 81 c3 70 91 04 08 add \$0x8049170,%ebx
+[ ]*[a-f0-9]+: 81 e1 70 91 04 08 and \$0x8049170,%ecx
+[ ]*[a-f0-9]+: 81 fa 70 91 04 08 cmp \$0x8049170,%edx
+[ ]*[a-f0-9]+: 81 cf 70 91 04 08 or \$0x8049170,%edi
+[ ]*[a-f0-9]+: 81 de 70 91 04 08 sbb \$0x8049170,%esi
+[ ]*[a-f0-9]+: 81 ed 70 91 04 08 sub \$0x8049170,%ebp
+[ ]*[a-f0-9]+: 81 f4 70 91 04 08 xor \$0x8049170,%esp
+[ ]*[a-f0-9]+: f7 c1 70 91 04 08 test \$0x8049170,%ecx
+[ ]*[a-f0-9]+: 8d 05 71 91 04 08 lea 0x8049171,%eax
+[ ]*[a-f0-9]+: 81 d0 71 91 04 08 adc \$0x8049171,%eax
+[ ]*[a-f0-9]+: 81 c3 71 91 04 08 add \$0x8049171,%ebx
+[ ]*[a-f0-9]+: 81 e1 71 91 04 08 and \$0x8049171,%ecx
+[ ]*[a-f0-9]+: 81 fa 71 91 04 08 cmp \$0x8049171,%edx
+[ ]*[a-f0-9]+: 81 cf 71 91 04 08 or \$0x8049171,%edi
+[ ]*[a-f0-9]+: 81 de 71 91 04 08 sbb \$0x8049171,%esi
+[ ]*[a-f0-9]+: 81 ed 71 91 04 08 sub \$0x8049171,%ebp
+[ ]*[a-f0-9]+: 81 f4 71 91 04 08 xor \$0x8049171,%esp
+[ ]*[a-f0-9]+: f7 c1 71 91 04 08 test \$0x8049171,%ecx
+[ ]*[a-f0-9]+: 8d 05 71 91 04 08 lea 0x8049171,%eax
+[ ]*[a-f0-9]+: 81 d0 71 91 04 08 adc \$0x8049171,%eax
+[ ]*[a-f0-9]+: 81 c3 71 91 04 08 add \$0x8049171,%ebx
+[ ]*[a-f0-9]+: 81 e1 71 91 04 08 and \$0x8049171,%ecx
+[ ]*[a-f0-9]+: 81 fa 71 91 04 08 cmp \$0x8049171,%edx
+[ ]*[a-f0-9]+: 81 cf 71 91 04 08 or \$0x8049171,%edi
+[ ]*[a-f0-9]+: 81 de 71 91 04 08 sbb \$0x8049171,%esi
+[ ]*[a-f0-9]+: 81 ed 71 91 04 08 sub \$0x8049171,%ebp
+[ ]*[a-f0-9]+: 81 f4 71 91 04 08 xor \$0x8049171,%esp
+[ ]*[a-f0-9]+: f7 c1 71 91 04 08 test \$0x8049171,%ecx
+#pass
diff --git a/ld/testsuite/ld-i386/load1.s b/ld/testsuite/ld-i386/load1.s
new file mode 100644
index 0000000..a9f8460
--- /dev/null
+++ b/ld/testsuite/ld-i386/load1.s
@@ -0,0 +1,55 @@
+ .data
+ .type bar, @object
+bar:
+ .byte 1
+ .size bar, .-bar
+ .globl foo
+ .type foo, @object
+foo:
+ .byte 1
+ .size foo, .-foo
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ movl bar@GOT(%ecx), %eax
+ adcl bar@GOT(%ecx), %eax
+ addl bar@GOT(%ecx), %ebx
+ andl bar@GOT(%ecx), %ecx
+ cmpl bar@GOT(%ecx), %edx
+ orl bar@GOT(%ecx), %edi
+ sbbl bar@GOT(%ecx), %esi
+ subl bar@GOT(%ecx), %ebp
+ xorl bar@GOT(%ecx), %esp
+ testl %ecx, bar@GOT(%ecx)
+ movl bar@GOT, %eax
+ adcl bar@GOT, %eax
+ addl bar@GOT, %ebx
+ andl bar@GOT, %ecx
+ cmpl bar@GOT, %edx
+ orl bar@GOT, %edi
+ sbbl bar@GOT, %esi
+ subl bar@GOT, %ebp
+ xorl bar@GOT, %esp
+ testl %ecx, bar@GOT
+ movl foo@GOT(%ecx), %eax
+ adcl foo@GOT(%ecx), %eax
+ addl foo@GOT(%ecx), %ebx
+ andl foo@GOT(%ecx), %ecx
+ cmpl foo@GOT(%ecx), %edx
+ orl foo@GOT(%ecx), %edi
+ sbbl foo@GOT(%ecx), %esi
+ subl foo@GOT(%ecx), %ebp
+ xorl foo@GOT(%ecx), %esp
+ testl %ecx, foo@GOT(%ecx)
+ movl foo@GOT, %eax
+ adcl foo@GOT, %eax
+ addl foo@GOT, %ebx
+ andl foo@GOT, %ecx
+ cmpl foo@GOT, %edx
+ orl foo@GOT, %edi
+ sbbl foo@GOT, %esi
+ subl foo@GOT, %ebp
+ xorl foo@GOT, %esp
+ testl %ecx, foo@GOT
+ .size _start, .-_start
diff --git a/ld/testsuite/ld-i386/load2.d b/ld/testsuite/ld-i386/load2.d
new file mode 100644
index 0000000..87c2509
--- /dev/null
+++ b/ld/testsuite/ld-i386/load2.d
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -melf_i386 -shared
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/load2.s b/ld/testsuite/ld-i386/load2.s
new file mode 100644
index 0000000..7aad5d0
--- /dev/null
+++ b/ld/testsuite/ld-i386/load2.s
@@ -0,0 +1,8 @@
+ .data
+ .type foo, @object
+foo:
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ addl foo@GOT, %ebx
diff --git a/ld/testsuite/ld-i386/load3.d b/ld/testsuite/ld-i386/load3.d
new file mode 100644
index 0000000..87c2509
--- /dev/null
+++ b/ld/testsuite/ld-i386/load3.d
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -melf_i386 -shared
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/load3.s b/ld/testsuite/ld-i386/load3.s
new file mode 100644
index 0000000..d9b7083
--- /dev/null
+++ b/ld/testsuite/ld-i386/load3.s
@@ -0,0 +1,9 @@
+ .data
+ .globl foo
+ .type foo, @object
+foo:
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ addl foo@GOT, %ebx
diff --git a/ld/testsuite/ld-i386/load4.s b/ld/testsuite/ld-i386/load4.s
new file mode 100644
index 0000000..fe2c4cd
--- /dev/null
+++ b/ld/testsuite/ld-i386/load4.s
@@ -0,0 +1,9 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ ret
+ .globl _start
+ .type _start, @function
+_start:
+ movl foo@GOT, %eax
diff --git a/ld/testsuite/ld-i386/load4a.d b/ld/testsuite/ld-i386/load4a.d
new file mode 100644
index 0000000..3aa56bd
--- /dev/null
+++ b/ld/testsuite/ld-i386/load4a.d
@@ -0,0 +1,4 @@
+#source: load4.s
+#as: --32
+#ld: -Bsymbolic -shared -melf_i386
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/load4b.d b/ld/testsuite/ld-i386/load4b.d
new file mode 100644
index 0000000..0f6f4e2
--- /dev/null
+++ b/ld/testsuite/ld-i386/load4b.d
@@ -0,0 +1,13 @@
+#source: load4.s
+#as: --32
+#ld: -melf_i386
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+#...
+[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
+#pass
diff --git a/ld/testsuite/ld-i386/load5.s b/ld/testsuite/ld-i386/load5.s
new file mode 100644
index 0000000..1ecd50c
--- /dev/null
+++ b/ld/testsuite/ld-i386/load5.s
@@ -0,0 +1,8 @@
+ .text
+ .type foo, @function
+foo:
+ ret
+ .globl _start
+ .type _start, @function
+_start:
+ movl foo@GOT, %eax
diff --git a/ld/testsuite/ld-i386/load5a.d b/ld/testsuite/ld-i386/load5a.d
new file mode 100644
index 0000000..88c225a
--- /dev/null
+++ b/ld/testsuite/ld-i386/load5a.d
@@ -0,0 +1,4 @@
+#source: load5.s
+#as: --32
+#ld: -Bsymbolic -shared -melf_i386
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/load5b.d b/ld/testsuite/ld-i386/load5b.d
new file mode 100644
index 0000000..6db0b28
--- /dev/null
+++ b/ld/testsuite/ld-i386/load5b.d
@@ -0,0 +1,13 @@
+#source: load5.s
+#as: --32
+#ld: -melf_i386
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+#...
+[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
+#pass
diff --git a/ld/testsuite/ld-i386/load6.d b/ld/testsuite/ld-i386/load6.d
new file mode 100644
index 0000000..69319cf
--- /dev/null
+++ b/ld/testsuite/ld-i386/load6.d
@@ -0,0 +1,28 @@
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -dw
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[ ]*[a-f0-9]+: 13 81 f8 ff ff ff adc -0x8\(%ecx\),%eax
+[ ]*[a-f0-9]+: 03 99 f8 ff ff ff add -0x8\(%ecx\),%ebx
+[ ]*[a-f0-9]+: 23 89 f8 ff ff ff and -0x8\(%ecx\),%ecx
+[ ]*[a-f0-9]+: 3b 91 f8 ff ff ff cmp -0x8\(%ecx\),%edx
+[ ]*[a-f0-9]+: 0b b9 f8 ff ff ff or -0x8\(%ecx\),%edi
+[ ]*[a-f0-9]+: 1b b1 f8 ff ff ff sbb -0x8\(%ecx\),%esi
+[ ]*[a-f0-9]+: 2b a9 f8 ff ff ff sub -0x8\(%ecx\),%ebp
+[ ]*[a-f0-9]+: 33 a1 f8 ff ff ff xor -0x8\(%ecx\),%esp
+[ ]*[a-f0-9]+: 85 89 f8 ff ff ff test %ecx,-0x8\(%ecx\)
+[ ]*[a-f0-9]+: 13 81 fc ff ff ff adc -0x4\(%ecx\),%eax
+[ ]*[a-f0-9]+: 03 99 fc ff ff ff add -0x4\(%ecx\),%ebx
+[ ]*[a-f0-9]+: 23 89 fc ff ff ff and -0x4\(%ecx\),%ecx
+[ ]*[a-f0-9]+: 3b 91 fc ff ff ff cmp -0x4\(%ecx\),%edx
+[ ]*[a-f0-9]+: 0b b9 fc ff ff ff or -0x4\(%ecx\),%edi
+[ ]*[a-f0-9]+: 1b b1 fc ff ff ff sbb -0x4\(%ecx\),%esi
+[ ]*[a-f0-9]+: 2b a9 fc ff ff ff sub -0x4\(%ecx\),%ebp
+[ ]*[a-f0-9]+: 33 a1 fc ff ff ff xor -0x4\(%ecx\),%esp
+[ ]*[a-f0-9]+: 85 89 fc ff ff ff test %ecx,-0x4\(%ecx\)
+#pass
diff --git a/ld/testsuite/ld-i386/load6.s b/ld/testsuite/ld-i386/load6.s
new file mode 100644
index 0000000..eac3137
--- /dev/null
+++ b/ld/testsuite/ld-i386/load6.s
@@ -0,0 +1,33 @@
+ .data
+ .type bar, @object
+bar:
+ .byte 1
+ .size bar, .-bar
+ .globl foo
+ .type foo, @object
+foo:
+ .byte 1
+ .size foo, .-foo
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ adcl bar@GOT(%ecx), %eax
+ addl bar@GOT(%ecx), %ebx
+ andl bar@GOT(%ecx), %ecx
+ cmpl bar@GOT(%ecx), %edx
+ orl bar@GOT(%ecx), %edi
+ sbbl bar@GOT(%ecx), %esi
+ subl bar@GOT(%ecx), %ebp
+ xorl bar@GOT(%ecx), %esp
+ testl %ecx, bar@GOT(%ecx)
+ adcl foo@GOT(%ecx), %eax
+ addl foo@GOT(%ecx), %ebx
+ andl foo@GOT(%ecx), %ecx
+ cmpl foo@GOT(%ecx), %edx
+ orl foo@GOT(%ecx), %edi
+ sbbl foo@GOT(%ecx), %esi
+ subl foo@GOT(%ecx), %ebp
+ xorl foo@GOT(%ecx), %esp
+ testl %ecx, foo@GOT(%ecx)
+ .size _start, .-_start
diff --git a/ld/testsuite/ld-i386/plt-main1.rd b/ld/testsuite/ld-i386/plt-main1.rd
index d27589e..53c49d9 100644
--- a/ld/testsuite/ld-i386/plt-main1.rd
+++ b/ld/testsuite/ld-i386/plt-main1.rd
@@ -1,3 +1,3 @@
#...
-[0-9a-f ]+R_386_GOT32 +0+ +bar
+[0-9a-f ]+R_386_GOT32X +0+ +bar
#pass
diff --git a/ld/testsuite/ld-i386/plt-main3.rd b/ld/testsuite/ld-i386/plt-main3.rd
index 7b78818..417fb20 100644
--- a/ld/testsuite/ld-i386/plt-main3.rd
+++ b/ld/testsuite/ld-i386/plt-main3.rd
@@ -1,5 +1,5 @@
#...
-[0-9a-f ]+R_386_GOT32 +0+ +bar
+[0-9a-f ]+R_386_GOT32X +0+ +bar
#...
[0-9a-f ]+R_386_PLT32 +0+ +bar
#pass
diff --git a/ld/testsuite/ld-i386/plt-main4.rd b/ld/testsuite/ld-i386/plt-main4.rd
index 882a3ad..393fe29 100644
--- a/ld/testsuite/ld-i386/plt-main4.rd
+++ b/ld/testsuite/ld-i386/plt-main4.rd
@@ -1,5 +1,5 @@
#...
-[0-9a-f ]+R_386_GOT32 +0+ +foo
+[0-9a-f ]+R_386_GOT32X +0+ +foo
#...
[0-9a-f ]+R_386_PLT32 +0+ +foo
#pass