]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add R_386_GOT32X support to gas and ld
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 22 Oct 2015 11:46:51 +0000 (04:46 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 22 Oct 2015 11:47:07 +0000 (04:47 -0700)
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.

52 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf32-i386.c
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/config/tc-i386.c
gas/testsuite/ChangeLog
gas/testsuite/gas/i386/got.d [new file with mode: 0644]
gas/testsuite/gas/i386/got.s [new file with mode: 0644]
gas/testsuite/gas/i386/i386.exp
gas/testsuite/gas/i386/localpic.d
gas/testsuite/gas/i386/mixed-mode-reloc32.d
gas/testsuite/gas/i386/reloc32.d
include/elf/ChangeLog
include/elf/i386.h
ld/testsuite/ChangeLog
ld/testsuite/ld-i386/branch1.d [new file with mode: 0644]
ld/testsuite/ld-i386/branch1.s [new file with mode: 0644]
ld/testsuite/ld-i386/call1.d [new file with mode: 0644]
ld/testsuite/ld-i386/call1.s [new file with mode: 0644]
ld/testsuite/ld-i386/call2.d [new file with mode: 0644]
ld/testsuite/ld-i386/call2.s [new file with mode: 0644]
ld/testsuite/ld-i386/got1.dd [new file with mode: 0644]
ld/testsuite/ld-i386/got1.out [new file with mode: 0644]
ld/testsuite/ld-i386/got1a.S [new file with mode: 0644]
ld/testsuite/ld-i386/got1b.c [new file with mode: 0644]
ld/testsuite/ld-i386/got1c.c [new file with mode: 0644]
ld/testsuite/ld-i386/got1d.S [new file with mode: 0644]
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/jmp1.d [new file with mode: 0644]
ld/testsuite/ld-i386/jmp1.s [new file with mode: 0644]
ld/testsuite/ld-i386/jmp2.d [new file with mode: 0644]
ld/testsuite/ld-i386/jmp2.s [new file with mode: 0644]
ld/testsuite/ld-i386/lea1c.d
ld/testsuite/ld-i386/load1.d [new file with mode: 0644]
ld/testsuite/ld-i386/load1.s [new file with mode: 0644]
ld/testsuite/ld-i386/load2.d [new file with mode: 0644]
ld/testsuite/ld-i386/load2.s [new file with mode: 0644]
ld/testsuite/ld-i386/load3.d [new file with mode: 0644]
ld/testsuite/ld-i386/load3.s [new file with mode: 0644]
ld/testsuite/ld-i386/load4.s [new file with mode: 0644]
ld/testsuite/ld-i386/load4a.d [new file with mode: 0644]
ld/testsuite/ld-i386/load4b.d [new file with mode: 0644]
ld/testsuite/ld-i386/load5.s [new file with mode: 0644]
ld/testsuite/ld-i386/load5a.d [new file with mode: 0644]
ld/testsuite/ld-i386/load5b.d [new file with mode: 0644]
ld/testsuite/ld-i386/load6.d [new file with mode: 0644]
ld/testsuite/ld-i386/load6.s [new file with mode: 0644]
ld/testsuite/ld-i386/plt-main1.rd
ld/testsuite/ld-i386/plt-main3.rd
ld/testsuite/ld-i386/plt-main4.rd

index 3956966a664c3e8c3cb160f0f01aac210c274552..a2e3034d31805a0caabff490d46530d9974e0785 100644 (file)
@@ -1,3 +1,23 @@
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * 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.
+
 2015-10-22  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * elf32-s390.c (elf_s390_check_relocs): Set the non_got_ref marker
index 60d7e4512d9eccdb0bed9127d21f3bcc591181ed..ad246c81c46d929f04562e9518a2f20d95ba9587 100644 (file)
@@ -3177,6 +3177,7 @@ instruction.  */
   BFD_RELOC_386_TLS_DESC_CALL,
   BFD_RELOC_386_TLS_DESC,
   BFD_RELOC_386_IRELATIVE,
+  BFD_RELOC_386_GOT32X,
 
 /* x86-64/elf relocations  */
   BFD_RELOC_X86_64_GOT32,
index 8c1dadb4cf3a1dd1711a3ea53da3f140f418704a..f56b39e838640ab6ca5d369cb062893f46623318 100644 (file)
@@ -29,6 +29,7 @@
 #include "objalloc.h"
 #include "hashtab.h"
 #include "dwarf2.h"
+#include "opcode/i386.h"
 
 /* 386 uses REL relocations instead of RELA.  */
 #define USE_REL        1
@@ -146,9 +147,12 @@ static reloc_howto_type elf_howto_table[]=
   HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_386_IRELATIVE",
        TRUE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(R_386_GOT32X, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_386_GOT32X",
+       TRUE, 0xffffffff, 0xffffffff, FALSE),
 
   /* Another gap.  */
-#define R_386_ext2 (R_386_IRELATIVE + 1 - R_386_tls_offset)
+#define R_386_ext2 (R_386_GOT32X + 1 - R_386_tls_offset)
 #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_ext2)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -332,6 +336,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       TRACE ("BFD_RELOC_386_IRELATIVE");
       return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset];
 
+    case BFD_RELOC_386_GOT32X:
+      TRACE ("BFD_RELOC_386_GOT32X");
+      return &elf_howto_table[R_386_GOT32X - R_386_tls_offset];
+
     case BFD_RELOC_VTABLE_INHERIT:
       TRACE ("BFD_RELOC_VTABLE_INHERIT");
       return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
@@ -1468,7 +1476,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
 /* Rename some of the generic section flags to better document how they
    are used here.  */
-#define need_convert_mov_to_lea sec_flg0
+#define need_convert_load sec_flg0
 
 /* Look through the relocs for a section during the first phase, and
    calculate needed space in the global offset table, procedure linkage
@@ -1580,6 +1588,7 @@ elf_i386_check_relocs (bfd *abfd,
            case R_386_PC32:
            case R_386_PLT32:
            case R_386_GOT32:
+           case R_386_GOT32X:
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
              if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
@@ -1637,6 +1646,7 @@ elf_i386_check_relocs (bfd *abfd,
          /* Fall through */
 
        case R_386_GOT32:
+       case R_386_GOT32X:
        case R_386_TLS_GD:
        case R_386_TLS_GOTDESC:
        case R_386_TLS_DESC_CALL:
@@ -1647,7 +1657,10 @@ elf_i386_check_relocs (bfd *abfd,
            switch (r_type)
              {
              default:
-             case R_386_GOT32: tls_type = GOT_NORMAL; break;
+             case R_386_GOT32:
+             case R_386_GOT32X:
+               tls_type = GOT_NORMAL;
+               break;
              case R_386_TLS_GD: tls_type = GOT_TLS_GD; break;
              case R_386_TLS_GOTDESC:
              case R_386_TLS_DESC_CALL:
@@ -1948,9 +1961,9 @@ do_size:
            return FALSE;
        }
 
-      if (r_type == R_386_GOT32
+      if ((r_type == R_386_GOT32 || r_type == R_386_GOT32X)
          && (h == NULL || h->type != STT_GNU_IFUNC))
-       sec->need_convert_mov_to_lea = 1;
+       sec->need_convert_load = 1;
     }
 
   return TRUE;
@@ -2074,6 +2087,7 @@ elf_i386_gc_sweep_hook (bfd *abfd,
        case R_386_TLS_IE:
        case R_386_TLS_GOTIE:
        case R_386_GOT32:
+       case R_386_GOT32X:
          if (h != NULL)
            {
              if (h->got.refcount > 0)
@@ -2718,14 +2732,27 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   return TRUE;
 }
 
-/* Convert
-   mov foo@GOT(%reg), %reg
+/* With the local symbol, foo, we convert
+   mov foo@GOT[(%reg1)], %reg2
+   to
+   lea foo[@GOTOFF(%reg1)], %reg2
+   and convert
+   call/jmp *foo@GOT[(%reg)]
    to
-   lea foo@GOTOFF(%reg), %reg
-   with the local symbol, foo.  */
+   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.  */
 
 static bfd_boolean
-elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
+elf_i386_convert_load (bfd *abfd, asection *sec,
                             struct bfd_link_info *link_info)
 {
   Elf_Internal_Shdr *symtab_hdr;
@@ -2743,7 +2770,7 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
 
   /* Nothing to do if there is no need or no output.  */
   if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
-      || sec->need_convert_mov_to_lea == 0
+      || sec->need_convert_load == 0
       || bfd_is_abs_section (sec->output_section))
     return TRUE;
 
@@ -2777,32 +2804,92 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
       unsigned int r_symndx = ELF32_R_SYM (irel->r_info);
       unsigned int indx;
       struct elf_link_hash_entry *h;
+      unsigned int opcode;
+      unsigned int modrm;
+      bfd_vma roff;
+      bfd_boolean baseless;
+      Elf_Internal_Sym *isym;
+      unsigned int addend;
+      unsigned int nop;
+      bfd_vma nop_offset;
 
-      if (r_type != R_386_GOT32)
+      if (r_type != R_386_GOT32 && r_type != R_386_GOT32X)
        continue;
 
-      /* Get the symbol referred to by the reloc.  */
-      if (r_symndx < symtab_hdr->sh_info)
+      roff = irel->r_offset;
+      if (roff < 2)
+       continue;
+
+      modrm = bfd_get_8 (abfd, contents + roff - 1);
+      baseless = (modrm & 0xc7) == 0x5;
+
+      if (r_type == R_386_GOT32X
+         && baseless
+         && bfd_link_pic (link_info))
        {
-         Elf_Internal_Sym *isym;
+         /* For PIC, disallow R_386_GOT32X without a base register
+            since we don't know what the GOT base is.   Allow
+            R_386_GOT32 for existing object files.  */
+         const char *name;
+
+         if (r_symndx < symtab_hdr->sh_info)
+           {
+             isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
+                                           r_symndx);
+             name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
+           }
+         else
+           {
+             indx = r_symndx - symtab_hdr->sh_info;
+             h = elf_sym_hashes (abfd)[indx];
+             BFD_ASSERT (h != NULL);
+             name = h->root.root.string;
+           }
+
+         (*_bfd_error_handler)
+           (_("%B: direct GOT relocation R_386_GOT32X against `%s' without base register can not be used when making a shared object"),
+            abfd, name);
+         goto error_return;
+       }
+
+      opcode = bfd_get_8 (abfd, contents + roff - 2);
+
+      /* It is OK to convert mov to lea.  */
+      if (opcode != 0x8b)
+       {
+         /* Only convert R_386_GOT32X relocation for call, jmp or
+            one of adc, add, and, cmp, or, sbb, sub, test, xor
+            instructions.  */
+         if (r_type != R_386_GOT32X)
+           continue;
+
+         /* It is OK to convert indirect branch to direct branch.  It
+            is OK to convert adc, add, and, cmp, or, sbb, sub, test,
+            xor only when PIC is false.   */
+         if (opcode != 0xff && bfd_link_pic (link_info))
+           continue;
+       }
 
+      /* Try to convert R_386_GOT32 and R_386_GOT32X.  Get the symbol
+        referred to by the reloc.  */
+      if (r_symndx < symtab_hdr->sh_info)
+       {
          isym = bfd_sym_from_r_symndx (&htab->sym_cache,
                                        abfd, r_symndx);
 
-         /* STT_GNU_IFUNC must keep R_386_GOT32 relocation.  */
-         if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC
-             && irel->r_offset >= 2
-             && bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b)
-           {
-             bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2);
-             irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF);
-             if (local_got_refcounts != NULL
-                 && local_got_refcounts[r_symndx] > 0)
-               local_got_refcounts[r_symndx] -= 1;
-             changed_contents = TRUE;
-             changed_relocs = TRUE;
-           }
-         continue;
+         /* STT_GNU_IFUNC must keep GOT32 relocations.  */
+         if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+           continue;
+
+         h = NULL;
+         if (opcode == 0x0ff)
+           /* Convert "call/jmp *foo@GOT[(%reg)]".  */
+           goto convert_branch;
+         else
+           /* Convert "mov foo@GOT[(%reg1)], %reg2",
+              "test %reg1, foo@GOT(%reg2)" and
+              "binop foo@GOT[(%reg1)], %reg2". */
+           goto convert_load;
        }
 
       indx = r_symndx - symtab_hdr->sh_info;
@@ -2813,22 +2900,147 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
             || h->root.type == bfd_link_hash_warning)
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-      /* STT_GNU_IFUNC must keep R_386_GOT32 relocation.  We also avoid
-        optimizing _DYNAMIC since ld.so may use its link-time address.  */
-      if ((h->root.type == bfd_link_hash_defined
-          || h->root.type == bfd_link_hash_defweak)
-         && h->type != STT_GNU_IFUNC
-         && h != htab->elf.hdynamic
-         && SYMBOL_REFERENCES_LOCAL (link_info, h)
-         && irel->r_offset >= 2
-         && bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b)
+      /* STT_GNU_IFUNC must keep GOT32 relocations.  */
+      if (h->type == STT_GNU_IFUNC)
+       continue;
+
+      if (opcode == 0xff)
+       {
+         /* We have "call/jmp *foo@GOT[(%reg)]".  */
+         if ((h->root.type == bfd_link_hash_defined
+              || h->root.type == bfd_link_hash_defweak)
+             && SYMBOL_REFERENCES_LOCAL (link_info, h))
+           {
+             /* The function is locally defined.   */
+convert_branch:
+             addend = bfd_get_32 (abfd, contents + roff);
+             /* Addend for R_386_GOT32X relocation must be 0.  */
+             if (addend != 0)
+               continue;
+
+             /* Convert R_386_GOT32X to R_386_PC32.  */
+             if (modrm == 0x15 || (modrm & 0xf8) == 0x90)
+               {
+                 /* Convert to "nop call foo".  ADDR_PREFIX_OPCODE
+                    is a nop prefix.  */
+                 modrm = 0xe8;
+                 nop = ADDR_PREFIX_OPCODE;
+                 nop_offset = roff - 2;
+               }
+             else
+               {
+                 /* Convert to "jmp foo nop".  */
+                 modrm = 0xe9;
+                 nop = NOP_OPCODE;
+                 nop_offset = roff + 3;
+                 irel->r_offset -= 1;
+               }
+
+             bfd_put_8 (abfd, nop, contents + nop_offset);
+             bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
+             /* When converting to PC-relative relocation, we
+                need to adjust addend by -4.  */
+             bfd_put_32 (abfd, -4, contents + irel->r_offset);
+             irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32);
+
+             if (h)
+               {
+                 if (h->got.refcount > 0)
+                   h->got.refcount -= 1;
+               }
+             else
+               {
+                 if (local_got_refcounts != NULL
+                     && local_got_refcounts[r_symndx] > 0)
+                   local_got_refcounts[r_symndx] -= 1;
+               }
+
+             changed_contents = TRUE;
+             changed_relocs = TRUE;
+           }
+       }
+      else
        {
-         bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2);
-         irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF);
-         if (h->got.refcount > 0)
-           h->got.refcount -= 1;
-         changed_contents = TRUE;
-         changed_relocs = TRUE;
+         /* We have "mov foo@GOT[(%re1g)], %reg2",
+            "test %reg1, foo@GOT(%reg2)" and
+            "binop foo@GOT[(%reg1)], %reg2".
+
+            Avoid optimizing _DYNAMIC since ld.so may use its
+            link-time address.  */
+         if (h == htab->elf.hdynamic)
+           continue;
+
+         if ((h->root.type == bfd_link_hash_defined
+              || h->root.type == bfd_link_hash_defweak)
+             && SYMBOL_REFERENCES_LOCAL (link_info, h))
+           {
+convert_load:
+             if (opcode == 0x8b)
+               {
+                 /* Convert "mov foo@GOT(%reg1), %reg2" to
+                    "lea foo@GOTOFF(%reg1), %reg2".  */
+                 if (r_type == R_386_GOT32X
+                     && (baseless || !bfd_link_pic (link_info)))
+                   {
+                     r_type = R_386_32;
+                     /* For R_386_32, convert
+                        "lea foo@GOTOFF(%reg1), %reg2" to
+                        "lea foo@GOT, %reg2".  */
+                     if (!baseless)
+                       {
+                         modrm = 0x5 | (modrm & 0x38);
+                         bfd_put_8 (abfd, modrm, contents + roff - 1);
+                       }
+                   }
+                 else
+                   r_type = R_386_GOTOFF;
+                 opcode = 0x8d;
+               }
+             else
+               {
+                 /* Addend for R_386_GOT32X relocation must be 0.  */
+                 addend = bfd_get_32 (abfd, contents + roff);
+                 if (addend != 0)
+                   continue;
+
+                 if (opcode == 0x85)
+                   {
+                     /* Convert "test %reg1, foo@GOT(%reg2)" to
+                        "test $foo, %reg1".  */
+                     modrm = 0xc0 | (modrm & 0x38) >> 3;
+                     opcode = 0xf7;
+                   }
+                 else
+                   {
+                     /* Convert "binop foo@GOT(%reg1), %reg2" to
+                        "binop $foo, %reg2".  */
+                     modrm = (0xc0
+                              | (modrm & 0x38) >> 3
+                              | (opcode & 0x3c));
+                     opcode = 0x81;
+                   }
+                 bfd_put_8 (abfd, modrm, contents + roff - 1);
+                 r_type = R_386_32;
+               }
+
+             bfd_put_8 (abfd, opcode, contents + roff - 2);
+             irel->r_info = ELF32_R_INFO (r_symndx, r_type);
+
+             if (h)
+               {
+                 if (h->got.refcount > 0)
+                   h->got.refcount -= 1;
+               }
+             else
+               {
+                 if (local_got_refcounts != NULL
+                     && local_got_refcounts[r_symndx] > 0)
+                   local_got_refcounts[r_symndx] -= 1;
+               }
+
+             changed_contents = TRUE;
+             changed_relocs = TRUE;
+           }
        }
     }
 
@@ -2914,7 +3126,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
        {
          struct elf_dyn_relocs *p;
 
-         if (!elf_i386_convert_mov_to_lea (ibfd, s, info))
+         if (!elf_i386_convert_load (ibfd, s, info))
            return FALSE;
 
          for (p = ((struct elf_dyn_relocs *)
@@ -3664,6 +3876,7 @@ elf_i386_relocate_section (bfd *output_bfd,
              goto do_relocation;
 
            case R_386_GOT32:
+           case R_386_GOT32X:
              base_got = htab->elf.sgot;
              off = h->got.offset;
 
@@ -3741,7 +3954,61 @@ elf_i386_relocate_section (bfd *output_bfd,
       eh = (struct elf_i386_link_hash_entry *) h;
       switch (r_type)
        {
+       case R_386_GOT32X:
+         /* Avoid optimizing _DYNAMIC since ld.so may use its
+            link-time address.  */
+         if (h == htab->elf.hdynamic)
+           goto r_386_got32;
+
+         if (bfd_link_pic (info))
+           {
+             /* It is OK to convert mov to lea and convert indirect
+                branch to direct branch.  It is OK to convert adc,
+                add, and, cmp, or, sbb, sub, test, xor only when PIC
+                is false.   */
+             unsigned int opcode;
+             opcode = bfd_get_8 (abfd, contents + rel->r_offset - 2);
+             if (opcode != 0x8b && opcode != 0xff)
+               goto r_386_got32;
+           }
+
+         /* Resolve "mov GOT[(%reg)], %reg",
+            "call/jmp *GOT[(%reg)]", "test %reg, foo@GOT[(%reg)]"
+            and "binop foo@GOT[(%reg)], %reg".  */
+         if (h == NULL
+             || (h->plt.offset == (bfd_vma) -1
+                 && h->got.offset == (bfd_vma) -1)
+             || htab->elf.sgotplt == NULL)
+           abort ();
+
+         offplt = (htab->elf.sgotplt->output_section->vma
+                   + htab->elf.sgotplt->output_offset);
+
+         /* It is relative to .got.plt section.  */
+         if (h->got.offset != (bfd_vma) -1)
+           /* Use GOT entry.  */
+           relocation = (htab->elf.sgot->output_section->vma
+                         + htab->elf.sgot->output_offset
+                         + h->got.offset - offplt);
+         else
+           /* Use GOTPLT entry.  */
+           relocation = (h->plt.offset / plt_entry_size - 1 + 3) * 4;
+
+         if (!bfd_link_pic (info))
+           {
+             /* If not PIC, add the .got.plt section address for
+                baseless adressing.  */
+             unsigned int modrm;
+             modrm = bfd_get_8 (abfd, contents + rel->r_offset - 1);
+             if ((modrm & 0xc7) == 0x5)
+               relocation += offplt;
+           }
+
+         unresolved_reloc = FALSE;
+         break;
+
        case R_386_GOT32:
+r_386_got32:
          /* Relocation is to the entry for this symbol in the global
             offset table.  */
          if (htab->elf.sgot == NULL)
index 9ae9ba26c3b074ec90ed2c8011f3c81d833adc30..3bf14002bebdab21221be05510b9ad0f8252bb25 100644 (file)
@@ -1292,6 +1292,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_386_TLS_DESC_CALL",
   "BFD_RELOC_386_TLS_DESC",
   "BFD_RELOC_386_IRELATIVE",
+  "BFD_RELOC_386_GOT32X",
   "BFD_RELOC_X86_64_GOT32",
   "BFD_RELOC_X86_64_PLT32",
   "BFD_RELOC_X86_64_COPY",
index 886c63eb13f72980cffd1ce1cbe10af71c5a62b2..c6e2807f9a009dcfb917ee860909009c9cad7ec8 100644 (file)
@@ -2676,6 +2676,8 @@ ENUMX
   BFD_RELOC_386_TLS_DESC
 ENUMX
   BFD_RELOC_386_IRELATIVE
+ENUMX
+  BFD_RELOC_386_GOT32X
 ENUMDOC
   i386/elf relocations
 
index 4c8af4c25dcfb7c3c9539bb187f0250e7402ba92..d2d0da41d10a4a56995669069491f34b882af4e1 100644 (file)
@@ -1,3 +1,17 @@
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * 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.
+
 2015-10-21  Nick Clifton  <nickc@redhat.com>
 
        PR gas/19109
index b5c27ee859cf37861538e72af2dcad95f5f66b76..dd1a41b87a07f3738f4f0660c4f1f0b65f820e12 100644 (file)
@@ -2928,6 +2928,7 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
       || fixP->fx_r_type == BFD_RELOC_386_GOTOFF
       || fixP->fx_r_type == BFD_RELOC_386_PLT32
       || fixP->fx_r_type == BFD_RELOC_386_GOT32
+      || fixP->fx_r_type == BFD_RELOC_386_GOT32X
       || fixP->fx_r_type == BFD_RELOC_386_TLS_GD
       || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM
       || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32
@@ -4791,6 +4792,10 @@ match_template (void)
            }
          }
 
+      /* Force 0x8b encoding for "mov foo@GOT, %eax".  */
+      if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0)
+       continue;
+
       /* We check register size if needed.  */
       check_register = t->opcode_modifier.checkregsize;
       overlap0 = operand_type_and (i.types[0], operand_types[0]);
@@ -7157,6 +7162,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
              int size = disp_size (n);
              int sign = i.types[n].bitfield.disp32s;
              int pcrel = (i.flags[n] & Operand_PCrel) != 0;
+             fixS *fixP;
 
              /* We can't have 8 bit displacement here.  */
              gas_assert (!i.types[n].bitfield.disp8);
@@ -7225,8 +7231,34 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
                       insn, and that is taken care of in other code.  */
                    reloc_type = BFD_RELOC_X86_64_GOTPC32;
                }
-             fix_new_exp (frag_now, p - frag_now->fr_literal, size,
-                          i.op[n].disps, pcrel, reloc_type);
+             fixP = fix_new_exp (frag_now, p - frag_now->fr_literal,
+                                 size, i.op[n].disps, pcrel,
+                                 reloc_type);
+             /* 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.  */
+             if ((i.rm.mode == 2
+                  || (i.rm.mode == 0 && i.rm.regmem == 5))
+                 && ((i.operands == 1
+                      && i.tm.base_opcode == 0xff
+                      && (i.rm.reg == 2 || i.rm.reg == 4))
+                     || (i.operands == 2
+                         && (i.tm.base_opcode == 0x8b
+                             || i.tm.base_opcode == 0x85
+                             || (i.tm.base_opcode & 0xc7) == 0x03))))
+               {
+                 if (object_64bit)
+                   {
+                     fixP->fx_tcbit = i.rex != 0;
+                     if (i.base_reg
+                         && (i.base_reg->reg_num == RegRip
+                             || i.base_reg->reg_num == RegEip))
+                     fixP->fx_tcbit2 = 1;
+                   }
+                 else
+                   fixP->fx_tcbit2 = 1;
+               }
            }
        }
     }
@@ -10321,23 +10353,39 @@ s_bss (int ignore ATTRIBUTE_UNUSED)
 void
 i386_validate_fix (fixS *fixp)
 {
-  if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol)
+  if (fixp->fx_subsy)
     {
-      if (fixp->fx_r_type == BFD_RELOC_32_PCREL)
-       {
-         if (!object_64bit)
-           abort ();
-         fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
-       }
-      else
+      if (fixp->fx_subsy == GOT_symbol)
        {
-         if (!object_64bit)
-           fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
+         if (fixp->fx_r_type == BFD_RELOC_32_PCREL)
+           {
+             if (!object_64bit)
+               abort ();
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+             if (fixp->fx_tcbit2)
+               fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
+             else
+#endif
+               fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
+           }
          else
-           fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
+           {
+             if (!object_64bit)
+               fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
+             else
+               fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
+           }
+         fixp->fx_subsy = 0;
        }
-      fixp->fx_subsy = 0;
     }
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+  else if (!object_64bit)
+    {
+      if (fixp->fx_r_type == BFD_RELOC_386_GOT32
+         && fixp->fx_tcbit2)
+       fixp->fx_r_type = BFD_RELOC_386_GOT32X;
+    }
+#endif
 }
 
 arelent *
@@ -10373,6 +10421,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
     case BFD_RELOC_X86_64_GOTPCREL:
     case BFD_RELOC_386_PLT32:
     case BFD_RELOC_386_GOT32:
+    case BFD_RELOC_386_GOT32X:
     case BFD_RELOC_386_GOTOFF:
     case BFD_RELOC_386_GOTPC:
     case BFD_RELOC_386_TLS_GD:
index fd3d479ebed66ce3cb5e725f41235aae033bb409..d149faa732153c63f507dde2ada44fbd4fdf544e 100644 (file)
@@ -1,3 +1,12 @@
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * 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.
+
 2015-10-22  Alan Modra  <amodra@gmail.com>
 
        PR gas/18500
diff --git a/gas/testsuite/gas/i386/got.d b/gas/testsuite/gas/i386/got.d
new file mode 100644 (file)
index 0000000..f76ca47
--- /dev/null
@@ -0,0 +1,29 @@
+#objdump: -dwr
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[      ]*[a-f0-9]+:    b8 00 00 00 00          mov    \$0x0,%eax       1: R_386_GOT32  foo
+[      ]*[a-f0-9]+:    8b 05 00 00 00 00       mov    0x0,%eax 7: R_386_GOT32X foo
+[      ]*[a-f0-9]+:    8b 80 00 00 00 00       mov    0x0\(%eax\),%eax d: R_386_GOT32X foo
+[      ]*[a-f0-9]+:    05 00 00 00 00          add    \$0x0,%eax       12: R_386_GOT32 foo
+[      ]*[a-f0-9]+:    03 05 00 00 00 00       add    0x0,%eax 18: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    03 80 00 00 00 00       add    0x0\(%eax\),%eax 1e: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    ff 15 00 00 00 00       call   \*0x0    24: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    ff 90 00 00 00 00       call   \*0x0\(%eax\)    2a: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    ff 25 00 00 00 00       jmp    \*0x0    30: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    ff a0 00 00 00 00       jmp    \*0x0\(%eax\)    36: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    b8 00 00 00 00          mov    \$0x0,%eax       3b: R_386_GOT32 foo
+[      ]*[a-f0-9]+:    8b 05 00 00 00 00       mov    0x0,%eax 41: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    8b 80 00 00 00 00       mov    0x0\(%eax\),%eax 47: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    05 00 00 00 00          add    \$0x0,%eax       4c: R_386_GOT32 foo
+[      ]*[a-f0-9]+:    03 05 00 00 00 00       add    0x0,%eax 52: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    03 80 00 00 00 00       add    0x0\(%eax\),%eax 58: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    ff 90 00 00 00 00       call   \*0x0\(%eax\)    5e: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    ff 15 00 00 00 00       call   \*0x0    64: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    ff a0 00 00 00 00       jmp    \*0x0\(%eax\)    6a: R_386_GOT32X        foo
+[      ]*[a-f0-9]+:    ff 25 00 00 00 00       jmp    \*0x0    70: R_386_GOT32X        foo
+#pass
diff --git a/gas/testsuite/gas/i386/got.s b/gas/testsuite/gas/i386/got.s
new file mode 100644 (file)
index 0000000..10fa881
--- /dev/null
@@ -0,0 +1,29 @@
+       .text
+_start:
+       movl    $foo@GOT, %eax
+       movl    foo@GOT, %eax
+       movl    foo@GOT(%eax), %eax
+
+       addl    $foo@GOT, %eax
+       addl    foo@GOT, %eax
+       addl    foo@GOT(%eax), %eax
+
+       call    *foo@GOT
+       call    *foo@GOT(%eax)
+       jmp     *foo@GOT
+       jmp     *foo@GOT(%eax)
+
+       .intel_syntax noprefix
+
+       mov     eax, offset foo@got
+       mov     eax, DWORD PTR [foo@GOT]
+       mov     eax, DWORD PTR [eax + foo@GOT]
+
+       add     eax, offset foo@got
+       add     eax, DWORD PTR [foo@GOT]
+       add     eax, DWORD PTR [eax + foo@GOT]
+
+       call    DWORD PTR [eax + foo@GOT]
+       call    DWORD PTR [foo@GOT]
+       jmp     DWORD PTR [eax + foo@GOT]
+       jmp     DWORD PTR [foo@GOT]
index f59b598ffcc6cc9b35858f670afc43b74e5c451a..8c374f2080f2fbb2b92af39c9f43d4df3686ea7f 100644 (file)
@@ -404,6 +404,8 @@ if [expr ([istarget "i*86-*-*"] ||  [istarget "x86_64-*-*"]) && [gas_32_check]]
        run_dump_test "relax-3"
        run_dump_test "relax-4"
 
+       run_dump_test "got"
+
        if {![istarget "*-*-nacl*"]} then {
            run_dump_test "iamcu-1"
            run_dump_test "iamcu-2"
index 93ac871d570af1cf2a7326e4114abc683be36f4b..04fb5ce0daf1ce2bf33860fc4bf7b6ebc793e64f 100644 (file)
@@ -3,7 +3,7 @@
 
 Relocation section '.rel.text' at offset 0x[0-9a-f]+ contains 1 entries:
  Offset     Info    Type            Sym.Value  Sym. Name
-[0-9a-f]+ +[0-9a-f]+ R_386_GOT32 +[0-9a-f]+ +foo
+[0-9a-f]+ +[0-9a-f]+ R_386_GOT32X +[0-9a-f]+ +foo
 #...
  +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
 #pass
index 6bc52f7959aef324640e4d9c8812d0a61621c0f0..9affc367bba96707e2cde989224a42ffee8e4f2b 100644 (file)
@@ -6,9 +6,9 @@
 
 RELOCATION RECORDS FOR \[.text\]:
 OFFSET[        ]+TYPE[         ]+VALUE[        ]*
-[0-9a-f]+[     ]+R_386_GOT32[  ]+xtrn[         ]*
+[0-9a-f]+[     ]+R_386_GOT32X[         ]+xtrn[         ]*
 [0-9a-f]+[     ]+R_386_PLT32[  ]+xtrn[         ]*
-[0-9a-f]+[     ]+R_386_GOT32[  ]+xtrn[         ]*
+[0-9a-f]+[     ]+R_386_GOT32X[         ]+xtrn[         ]*
 [0-9a-f]+[     ]+R_386_PLT32[  ]+xtrn[         ]*
-[0-9a-f]+[     ]+R_386_GOT32[  ]+xtrn[         ]*
+[0-9a-f]+[     ]+R_386_GOT32X[         ]+xtrn[         ]*
 [0-9a-f]+[     ]+R_386_PLT32[  ]+xtrn[         ]*
index cbd71d6d81f9cd522bf2073ea504711d9f3c30e1..45c9cd2334f2d0eaa5df625f04b5ec7d91d344aa 100644 (file)
@@ -18,7 +18,7 @@ Disassembly of section \.text:
 .*[    ]+R_386_PC32[   ]+xtrn
 .*[    ]+R_386_PC8[    ]+xtrn
 .*[    ]+R_386_GOT32[  ]+xtrn
-.*[    ]+R_386_GOT32[  ]+xtrn
+.*[    ]+R_386_GOT32X[         ]+xtrn
 .*[    ]+R_386_GOTOFF[         ]+xtrn
 .*[    ]+R_386_GOTOFF[         ]+xtrn
 .*[    ]+R_386_GOTPC[  ]+_GLOBAL_OFFSET_TABLE_
index 5e4605d4a4355715cba79b3335169ef98644c12c..8dc601ce405bd1c5751c73963a3f6703ade07100 100644 (file)
@@ -1,3 +1,7 @@
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * i386.h (R_386_GOT32X): New relocation.
+
 2015-10-07  Cupertino Miranda  <cmiranda@synopsys.com>
 
        * arc-reloc.def: Macro file with definition of all relocation
index 08c94556a300d9fe7fe29260e916b5dab4dc15e9..dea65f4a423a2cda4b08f21f3c380d6b05cfcb20 100644 (file)
@@ -66,6 +66,8 @@ START_RELOC_NUMBERS (elf_i386_reloc_type)
      RELOC_NUMBER (R_386_TLS_DESC_CALL,40)
      RELOC_NUMBER (R_386_TLS_DESC,     41)
      RELOC_NUMBER (R_386_IRELATIVE,    42) /* Adjust indirectly by program base */
+     /* Load from 32 bit GOT entry, relaxable.  */
+     RELOC_NUMBER (R_386_GOT32X,       43)
 
      /* Used by Intel.  */
      RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200)
index 46587a7caba5260849100bf7a44e63a95423d296..becfd53fe4bfcb9c5d33a4a384ea02f2e25f6523 100644 (file)
@@ -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 (file)
index 0000000..a078f1d
--- /dev/null
@@ -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 (file)
index 0000000..0ccf5cf
--- /dev/null
@@ -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 (file)
index 0000000..69383b2
--- /dev/null
@@ -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 (file)
index 0000000..ce003c8
--- /dev/null
@@ -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 (file)
index 0000000..69383b2
--- /dev/null
@@ -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 (file)
index 0000000..57cd88f
--- /dev/null
@@ -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 (file)
index 0000000..e46153d
--- /dev/null
@@ -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 (file)
index 0000000..99d4f7f
--- /dev/null
@@ -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 (file)
index 0000000..f3d5330
--- /dev/null
@@ -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 (file)
index 0000000..cf0c78e
--- /dev/null
@@ -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 (file)
index 0000000..05f5fc2
--- /dev/null
@@ -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 (file)
index 0000000..a6d51c6
--- /dev/null
@@ -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
index 8cddfce9e48bb7f625a5a4a6d01400804eee5499..3d28dcc08fa92617fd537511c72d6fd715929d73 100644 (file)
@@ -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 (file)
index 0000000..69383b2
--- /dev/null
@@ -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 (file)
index 0000000..8c80696
--- /dev/null
@@ -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 (file)
index 0000000..69383b2
--- /dev/null
@@ -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 (file)
index 0000000..b4bc38d
--- /dev/null
@@ -0,0 +1,8 @@
+       .text
+       .type   foo, @function
+foo:
+       ret
+       .globl  _start
+       .type   _start, @function
+_start:
+       jmp     *foo@GOT
index c84f4137d3d28b1cd74f98da397942d13cd031cc..54ec0deb18ebfa391ec51e8cc1dc296f63253d7b 100644 (file)
@@ -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 (file)
index 0000000..e93531e
--- /dev/null
@@ -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 (file)
index 0000000..a9f8460
--- /dev/null
@@ -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 (file)
index 0000000..87c2509
--- /dev/null
@@ -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 (file)
index 0000000..7aad5d0
--- /dev/null
@@ -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 (file)
index 0000000..87c2509
--- /dev/null
@@ -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 (file)
index 0000000..d9b7083
--- /dev/null
@@ -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 (file)
index 0000000..fe2c4cd
--- /dev/null
@@ -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 (file)
index 0000000..3aa56bd
--- /dev/null
@@ -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 (file)
index 0000000..0f6f4e2
--- /dev/null
@@ -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 (file)
index 0000000..1ecd50c
--- /dev/null
@@ -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 (file)
index 0000000..88c225a
--- /dev/null
@@ -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 (file)
index 0000000..6db0b28
--- /dev/null
@@ -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 (file)
index 0000000..69319cf
--- /dev/null
@@ -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 (file)
index 0000000..eac3137
--- /dev/null
@@ -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
index d27589e163200ae651b3ef94113ed8fe14773365..53c49d9b52c9a227a5fe7b7345e19fc92104c82b 100644 (file)
@@ -1,3 +1,3 @@
 #...
-[0-9a-f ]+R_386_GOT32 +0+ +bar
+[0-9a-f ]+R_386_GOT32X +0+ +bar
 #pass
index 7b78818d0be44b7d60fa2146eb4579553fe37735..417fb2002829c2f78d2c57a801cc12c7c7f89913 100644 (file)
@@ -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
index 882a3ad565cce31319367af5c23a38bb077d9bd6..393fe29717650c7005373316fc6b8dd86a7b790a 100644 (file)
@@ -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