]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
i386: Allow "lea foo@GOT, %reg" in PIC
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 15 Feb 2017 19:39:30 +0000 (11:39 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 15 Feb 2017 20:07:33 +0000 (12:07 -0800)
"lea foo@GOT, %reg" is OK in PIC since it only loads the GOT offset
into register, which can be used later with a GOT base register to
get the value in the GOT entry.

(cherry picked from commit 2a5684011edabf5804abb9e11253a9747587b284)

bfd/

PR ld/21168
* elf32-i386.c (elf_i386_relocate_section): Allow
"lea foo@GOT, %reg" in PIC.

ld/

PR ld/21168
* testsuite/ld-i386/i386.exp: Run pr21168.
* testsuite/ld-i386/pr21168a.c: New file.
* testsuite/ld-i386/pr21168b.S: Likewise.

bfd/ChangeLog
bfd/elf32-i386.c
ld/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pr21168a.c [new file with mode: 0644]
ld/testsuite/ld-i386/pr21168b.S [new file with mode: 0644]

index b406691ce4bde40304c1a594de21aa38fc4faced..30161c8ce5a7b3a0066be3f9392620d201e60c3d 100644 (file)
@@ -1,3 +1,9 @@
+2017-02-15  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/21168
+       * elf32-i386.c (elf_i386_relocate_section): Allow
+       "lea foo@GOT, %reg" in PIC.
+
 2017-02-14  Alan Modra  <amodra@gmail.com>
 
        * elf64-ppc.c (ppc64_elf_gc_mark_dynamic_ref): Support
index 0860ada37ef205336133c123e566f49004850b2b..b564d672d0862bc36428cc48c42afcc916ceb7ed 100644 (file)
@@ -4074,7 +4074,9 @@ elf_i386_relocate_section (bfd *output_bfd,
                              - gotplt->output_section->vma
                              - gotplt->output_offset);
 
-             if ((*(contents + rel->r_offset - 1) & 0xc7) == 0x5)
+             if (rel->r_offset > 1
+                 && (*(contents + rel->r_offset - 1) & 0xc7) == 0x5
+                 && *(contents + rel->r_offset - 2) != 0x8d)
                {
                  if (bfd_link_pic (info))
                    goto disallow_got32;
@@ -4345,13 +4347,15 @@ r_386_got32:
 
          relocation = (htab->elf.sgot->output_section->vma
                        + htab->elf.sgot->output_offset + off);
-         if ((*(contents + rel->r_offset - 1) & 0xc7) == 0x5)
+         if (rel->r_offset > 1
+             && (*(contents + rel->r_offset - 1) & 0xc7) == 0x5
+             && *(contents + rel->r_offset - 2) != 0x8d)
            {
              if (bfd_link_pic (info))
                {
                  /* For PIC, disallow R_386_GOT32 without a base
-                    register since we don't know what the GOT base
-                    is.  */
+                    register, except for "lea foo@GOT, %reg", since
+                    we don't know what the GOT base is.  */
                  const char *name;
 
 disallow_got32:
index c9aef537dd164c72e548deabb94d2425a85e0c67..ccf5bef8d87359b62747bd5d2bbfb74b7ed173b0 100644 (file)
@@ -1,3 +1,10 @@
+2017-02-15  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/21168
+       * testsuite/ld-i386/i386.exp: Run pr21168.
+       * testsuite/ld-i386/pr21168a.c: New file.
+       * testsuite/ld-i386/pr21168b.S: Likewise.
+
 2017-02-13  Palmer Dabbelt  <palmer@dabbelt.com>
 
        * emulparams/elf32lriscv-defs.sh (SDATA_START_SYMBOLS): Change
index f439411956dc91cd3023050ce460341bb4f70c64..e29f3f257846d4458efd6677edb9977a37c385d6 100644 (file)
@@ -832,6 +832,20 @@ if { [isnative]
            "-fPIC -O2 -g" \
            { ifunc-1a.c ifunc-1b.S ifunc-1c.S ifunc-1d.S } \
        ] \
+       [list \
+           "Build pr21168a.o" \
+           "" \
+           "" \
+           { pr21168a.c } \
+       ] \
+       [list \
+           "Build pr21168.so" \
+           "-shared" \
+           "" \
+           { pr21168b.S } \
+           "" \
+           "pr21168.so" \
+       ] \
     ]
 
     run_ld_link_exec_tests [list \
@@ -853,6 +867,14 @@ if { [isnative]
            "ifunc-1b" \
            "pass.out" \
        ] \
+       [list \
+           "Run pr21168" \
+           "tmpdir/pr21168a.o tmpdir/pr21168.so" \
+           "" \
+           { dummy.c } \
+           "pr21168" \
+           "pass.out" \
+       ] \
     ]
 }
 
diff --git a/ld/testsuite/ld-i386/pr21168a.c b/ld/testsuite/ld-i386/pr21168a.c
new file mode 100644 (file)
index 0000000..a6c0da1
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+int foo = 1;
+
+extern int *bar (void);
+extern int bar_ifunc (void);
+
+int
+main (void)
+{
+  if (bar () == &foo && bar_ifunc () == 0xbadbeef)
+    printf ("PASS\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-i386/pr21168b.S b/ld/testsuite/ld-i386/pr21168b.S
new file mode 100644 (file)
index 0000000..a4ea5c9
--- /dev/null
@@ -0,0 +1,29 @@
+       .text
+       .globl  bar
+       .type   bar, @function
+bar:
+       call    __x86.get_pc_thunk.ax
+       addl    $_GLOBAL_OFFSET_TABLE_, %eax
+       lea     foo@GOT, %ecx
+       mov     (%eax,%ecx,1), %eax
+       ret
+       .globl  bar_ifunc
+       .type   bar_ifunc, @function
+bar_ifunc:
+       call    __x86.get_pc_thunk.ax
+       addl    $_GLOBAL_OFFSET_TABLE_, %eax
+       lea     ifunc@GOT, %ecx
+       mov     (%eax,%ecx,1), %eax
+       ret
+       .type ifunc, @gnu_indirect_function
+ifunc:
+       mov     $0xbadbeef, %eax
+       ret
+       .section        .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
+       .globl  __x86.get_pc_thunk.ax
+       .hidden __x86.get_pc_thunk.ax
+       .type   __x86.get_pc_thunk.ax, @function
+__x86.get_pc_thunk.ax:
+       movl    (%esp), %eax
+       ret
+       .section        .note.GNU-stack,"",@progbits