]> 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:15:42 +0000 (12:15 -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 dd1ffdd33f5a95623a7c443ab95aff4974dc3a58..7043b6c99526cd18ce25cdd00534cf93bf9f300f 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.
+
 2016-12-23  Maciej W. Rozycki  <macro@imgtec.com>
 
        * bfd/elfxx-mips.c (_bfd_mips_post_process_headers): Revert
index 417957214dbb6257e97fe1510ebd431807a1a256..d549ffee71629799390cede0f2c7ecd9019d0d70 100644 (file)
@@ -3993,7 +3993,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;
@@ -4263,13 +4265,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 6cc35c7e73b9869b25ba3d9aabb6a30124c1ee0a..e952351b0d2b0388ec198d4e03a602352e5b3aa8 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.
+
 2016-10-14  Alan Modra  <amodra@gmail.com>
 
        * scripttempl/DWARF.sc: Add .debug_addr.
index 9efe406b9b5d666b975a268c7cea40ddac27684f..6eb7299fa6bebbf5de1ae0bc7ee9a97c4c1f5c89 100644 (file)
@@ -831,6 +831,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 \
@@ -852,6 +866,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