• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

Revisionf4fbcd1272c868121b7b3b272d6df955572a08ac (tree)
Zeit2015-09-02 21:16:01
AutorH.J. Lu <hjl.tools@gmai...>
CommiterH.J. Lu

Log Message

Add R_386_LOAD_GOT32

Change relocation in "call/jmp *puts@GOT[(%reg])" and
"mov *foo@GOT[(%reg)], %reg" from R_386_GOT32 to R_386_LOAD_GOT32.

Ändern Zusammenfassung

Diff

--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3175,6 +3175,7 @@ instruction. */
31753175 BFD_RELOC_386_TLS_DESC_CALL,
31763176 BFD_RELOC_386_TLS_DESC,
31773177 BFD_RELOC_386_IRELATIVE,
3178+ BFD_RELOC_386_LOAD_GOT32,
31783179
31793180 /* x86-64/elf relocations */
31803181 BFD_RELOC_X86_64_GOT32,
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -29,6 +29,7 @@
2929 #include "objalloc.h"
3030 #include "hashtab.h"
3131 #include "dwarf2.h"
32+#include "opcode/i386.h"
3233
3334 /* 386 uses REL relocations instead of RELA. */
3435 #define USE_REL 1
@@ -146,9 +147,12 @@ static reloc_howto_type elf_howto_table[]=
146147 HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
147148 bfd_elf_generic_reloc, "R_386_IRELATIVE",
148149 TRUE, 0xffffffff, 0xffffffff, FALSE),
150+ HOWTO(R_386_LOAD_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
151+ bfd_elf_generic_reloc, "R_386_LOAD_GOT32",
152+ TRUE, 0xffffffff, 0xffffffff, FALSE),
149153
150154 /* Another gap. */
151-#define R_386_ext2 (R_386_IRELATIVE + 1 - R_386_tls_offset)
155+#define R_386_ext2 (R_386_LOAD_GOT32 + 1 - R_386_tls_offset)
152156 #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_ext2)
153157
154158 /* GNU extension to record C++ vtable hierarchy. */
@@ -332,6 +336,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
332336 TRACE ("BFD_RELOC_386_IRELATIVE");
333337 return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset];
334338
339+ case BFD_RELOC_386_LOAD_GOT32:
340+ TRACE ("BFD_RELOC_386_LOAD_GOT32");
341+ return &elf_howto_table[R_386_LOAD_GOT32 - R_386_tls_offset];
342+
335343 case BFD_RELOC_VTABLE_INHERIT:
336344 TRACE ("BFD_RELOC_VTABLE_INHERIT");
337345 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,
14681476
14691477 /* Rename some of the generic section flags to better document how they
14701478 are used here. */
1471-#define need_convert_mov_to_lea sec_flg0
1479+#define need_convert_mov_and_branch sec_flg0
14721480
14731481 /* Look through the relocs for a section during the first phase, and
14741482 calculate needed space in the global offset table, procedure linkage
@@ -1580,6 +1588,7 @@ elf_i386_check_relocs (bfd *abfd,
15801588 case R_386_PC32:
15811589 case R_386_PLT32:
15821590 case R_386_GOT32:
1591+ case R_386_LOAD_GOT32:
15831592 if (htab->elf.dynobj == NULL)
15841593 htab->elf.dynobj = abfd;
15851594 if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
@@ -1637,6 +1646,7 @@ elf_i386_check_relocs (bfd *abfd,
16371646 /* Fall through */
16381647
16391648 case R_386_GOT32:
1649+ case R_386_LOAD_GOT32:
16401650 case R_386_TLS_GD:
16411651 case R_386_TLS_GOTDESC:
16421652 case R_386_TLS_DESC_CALL:
@@ -1647,7 +1657,10 @@ elf_i386_check_relocs (bfd *abfd,
16471657 switch (r_type)
16481658 {
16491659 default:
1650- case R_386_GOT32: tls_type = GOT_NORMAL; break;
1660+ case R_386_GOT32:
1661+ case R_386_LOAD_GOT32:
1662+ tls_type = GOT_NORMAL;
1663+ break;
16511664 case R_386_TLS_GD: tls_type = GOT_TLS_GD; break;
16521665 case R_386_TLS_GOTDESC:
16531666 case R_386_TLS_DESC_CALL:
@@ -1940,9 +1953,9 @@ do_size:
19401953 return FALSE;
19411954 }
19421955
1943- if (r_type == R_386_GOT32
1956+ if ((r_type == R_386_GOT32 || r_type == R_386_LOAD_GOT32)
19441957 && (h == NULL || h->type != STT_GNU_IFUNC))
1945- sec->need_convert_mov_to_lea = 1;
1958+ sec->need_convert_mov_and_branch = 1;
19461959 }
19471960
19481961 return TRUE;
@@ -2066,6 +2079,7 @@ elf_i386_gc_sweep_hook (bfd *abfd,
20662079 case R_386_TLS_IE:
20672080 case R_386_TLS_GOTIE:
20682081 case R_386_GOT32:
2082+ case R_386_LOAD_GOT32:
20692083 if (h != NULL)
20702084 {
20712085 if (h->got.refcount > 0)
@@ -2711,14 +2725,18 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
27112725 }
27122726
27132727 /* Convert
2714- mov foo@GOT(%reg), %reg
2728+ mov foo@GOT[(%reg)], %reg
27152729 to
2716- lea foo@GOTOFF(%reg), %reg
2717- with the local symbol, foo. */
2730+ lea foo[@GOTOFF(%reg)], %reg
2731+ with the local symbol, foo, and convert
2732+ call/jmp *foo@GOT[(%reg)]
2733+ to
2734+ nop call foo/jmp foo nop
2735+ with the locally defined function, foo. */
27182736
27192737 static bfd_boolean
2720-elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
2721- struct bfd_link_info *link_info)
2738+elf_i386_convert_mov_and_branch (bfd *abfd, asection *sec,
2739+ struct bfd_link_info *link_info)
27222740 {
27232741 Elf_Internal_Shdr *symtab_hdr;
27242742 Elf_Internal_Rela *internal_relocs;
@@ -2735,7 +2753,7 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
27352753
27362754 /* Nothing to do if there is no need or no output. */
27372755 if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
2738- || sec->need_convert_mov_to_lea == 0
2756+ || sec->need_convert_mov_and_branch == 0
27392757 || bfd_is_abs_section (sec->output_section))
27402758 return TRUE;
27412759
@@ -2769,34 +2787,57 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
27692787 unsigned int r_symndx = ELF32_R_SYM (irel->r_info);
27702788 unsigned int indx;
27712789 struct elf_link_hash_entry *h;
2790+ bfd_vma roff;
2791+ unsigned int opcode;
2792+ unsigned int modrm;
2793+ bfd_boolean baseless;
2794+ unsigned int new_r_type;
2795+ const char *name;
2796+ Elf_Internal_Sym *isym;
2797+ unsigned int disp;
2798+ unsigned int nop;
2799+ bfd_vma nop_offset;
27722800
2773- if (r_type != R_386_GOT32)
2801+ if (r_type != R_386_GOT32 && r_type != R_386_LOAD_GOT32)
27742802 continue;
27752803
2776- /* Get the symbol referred to by the reloc. */
2804+ roff = irel->r_offset;
2805+
2806+ if (roff < 2)
2807+ continue;
2808+
2809+ opcode = bfd_get_8 (abfd, contents + roff - 2);
2810+
2811+ if (!(opcode == 0x8b
2812+ && (r_type == R_386_GOT32 || r_type == R_386_LOAD_GOT32))
2813+ && !(opcode == 0xff && r_type == R_386_LOAD_GOT32))
2814+ continue;
2815+
2816+ /* Try to convert R_386_GOT32 and R_386_LOAD_GOT32. Get the
2817+ symbol referred to by the reloc. */
27772818 if (r_symndx < symtab_hdr->sh_info)
27782819 {
2779- Elf_Internal_Sym *isym;
2780-
27812820 isym = bfd_sym_from_r_symndx (&htab->sym_cache,
27822821 abfd, r_symndx);
27832822
2784- /* STT_GNU_IFUNC must keep R_386_GOT32 relocation. */
2785- if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC
2786- && irel->r_offset >= 2
2787- && bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b)
2823+ /* STT_GNU_IFUNC must keep GOT32 relocation. */
2824+ if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC)
27882825 {
2789- bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2);
2790- irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF);
27912826 if (local_got_refcounts != NULL
27922827 && local_got_refcounts[r_symndx] > 0)
27932828 local_got_refcounts[r_symndx] -= 1;
2794- changed_contents = TRUE;
2795- changed_relocs = TRUE;
2829+ h = NULL;
2830+ if (opcode == 0x8b)
2831+ /* Convert "mov *foo@GOT[(%reg)], %reg". */
2832+ goto convert_mov_to_gotoff;
2833+ else
2834+ /* Convert "call/jmp *foo@GOT[(%reg)]". */
2835+ goto convert_branch_to_gotoff;
27962836 }
27972837 continue;
27982838 }
27992839
2840+ isym = NULL;
28002841 indx = r_symndx - symtab_hdr->sh_info;
28012842 h = elf_sym_hashes (abfd)[indx];
28022843 BFD_ASSERT (h != NULL);
@@ -2805,21 +2846,176 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
28052846 || h->root.type == bfd_link_hash_warning)
28062847 h = (struct elf_link_hash_entry *) h->root.u.i.link;
28072848
2808- /* STT_GNU_IFUNC must keep R_386_GOT32 relocation. We also avoid
2809- optimizing _DYNAMIC since ld.so may use its link-time address. */
2810- if (h->def_regular
2811- && h->type != STT_GNU_IFUNC
2812- && h != htab->elf.hdynamic
2813- && SYMBOL_REFERENCES_LOCAL (link_info, h)
2814- && irel->r_offset >= 2
2815- && bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b)
2849+ if (opcode == 0xff && r_type == R_386_LOAD_GOT32)
2850+ {
2851+ /* We have "call/jmp *foo@GOT[(%reg)]". */
2852+ if (h->def_regular
2853+ && SYMBOL_REFERENCES_LOCAL (link_info, h))
2854+ {
2855+ /* The function is defined. But STT_GNU_IFUNC must keep
2856+ R_386_LOAD_GOT32 relocation. */
2857+ if (h->type != STT_GNU_IFUNC)
2858+ {
2859+convert_branch_to_gotoff:
2860+ modrm = bfd_get_8 (abfd, contents + irel->r_offset - 1);
2861+ /* Convert R_386_LOAD_GOT32 to R_386_PC32. */
2862+ if (modrm == 0x15
2863+ || (modrm >= 0x90 && modrm <= 0x97))
2864+ modrm = 0xe8;
2865+ else if (modrm == 0x25
2866+ || (modrm >= 0xa0 && modrm <= 0xa7))
2867+ modrm = 0xe9;
2868+ else
2869+ /* Skip "lcall/ljmp *foo@GOT[(%reg)]". */
2870+ continue;
2871+ /* When converting to PC-relative relocation, we
2872+ need to adjust addend by 4. */
2873+ disp = bfd_get_32 (abfd, contents + irel->r_offset);
2874+ disp -= 4;
2875+ if (modrm == 0xe9)
2876+ {
2877+ /* Convert to "jmp foo nop". */
2878+ nop = NOP_OPCODE;
2879+ nop_offset = irel->r_offset + 3;
2880+ irel->r_offset -= 1;
2881+ }
2882+ else
2883+ {
2884+ /* Convert to "nop call foo". ADDR_PREFIX_OPCODE
2885+ is a nop prefix. */
2886+ nop = ADDR_PREFIX_OPCODE;
2887+ nop_offset = irel->r_offset - 2;
2888+ }
2889+ bfd_put_8 (abfd, nop, contents + nop_offset);
2890+ bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
2891+ bfd_put_32 (abfd, disp, contents + irel->r_offset);
2892+ irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32);
2893+ if (h)
2894+ {
2895+ if (h->got.refcount > 0)
2896+ h->got.refcount -= 1;
2897+ }
2898+ changed_contents = TRUE;
2899+ changed_relocs = TRUE;
2900+ }
2901+ }
2902+ else
2903+ {
2904+ /* The function is undefined. */
2905+ modrm = bfd_get_8 (abfd, contents + irel->r_offset - 1);
2906+ baseless = (modrm & 0xc7) == 0x5;
2907+ if (bfd_link_pic (link_info))
2908+ {
2909+ /* For PIC, we leave "call/jmp *foo@GOT(%reg)" alone
2910+ and disallow "call/jmp *foo@GOT" since we don't
2911+ know what the GOT base is. */
2912+ if (baseless)
2913+ {
2914+baseless_error:
2915+ if (h)
2916+ name = h->root.root.string;
2917+ else
2918+ name = bfd_elf_sym_name (abfd, symtab_hdr,
2919+ isym, NULL);
2920+ (*_bfd_error_handler)
2921+ (_("%B: direct GOT relocation R_386_LOAD_GOT32 against `%s' without base register can not be used when making a shared object"),
2922+ abfd, name);
2923+ goto error_return;
2924+ }
2925+ }
2926+ else if (!baseless)
2927+ {
2928+ /* For non-PIC, convert "call/jmp *foo@GOT(%reg)"
2929+ to "call/jmp *foo@GOT" since we don't know if
2930+ REG is the GOT base. No need to convert
2931+ "call/jmp *foo@GOT". */
2932+ if (modrm >= 0x90 && modrm <= 0x97)
2933+ /* Convert to "call *foo@GOT". */
2934+ modrm = 0x15;
2935+ else if (modrm >= 0xa0 && modrm <= 0xa7)
2936+ /* Convert to "jmp *foo@GOT". */
2937+ modrm = 0x25;
2938+ else
2939+ /* Skip "lcall/ljmp *foo@GOT(%reg)". */
2940+ continue;
2941+ bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
2942+ changed_contents = TRUE;
2943+ }
2944+ }
2945+ }
2946+ else
28162947 {
2817- bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2);
2818- irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF);
2819- if (h->got.refcount > 0)
2820- h->got.refcount -= 1;
2821- changed_contents = TRUE;
2822- changed_relocs = TRUE;
2948+ /* STT_GNU_IFUNC must keep GOT32 relocation. */
2949+ if (h->def_regular
2950+ && h->type != STT_GNU_IFUNC
2951+ && SYMBOL_REFERENCES_LOCAL (link_info, h))
2952+ {
2953+ /* Avoid optimizing _DYNAMIC since ld.so may use its
2954+ link-time address. Convert R_386_LOAD_GOT32 in
2955+ "mov _DYNAMIC@GOT(%reg), %reg" to R_386_GOT32 to
2956+ avoid adding the GOT base in non-PIC mode in
2957+ elf_i386_relocate_section. */
2958+ if (h == htab->elf.hdynamic)
2959+ {
2960+ if (r_type == R_386_LOAD_GOT32)
2961+ {
2962+ irel->r_info = ELF32_R_INFO (r_symndx,
2963+ R_386_GOT32);
2964+ changed_relocs = TRUE;
2965+ }
2966+ continue;
2967+ }
2968+
2969+ if (h->got.refcount > 0)
2970+ h->got.refcount -= 1;
2971+
2972+convert_mov_to_gotoff:
2973+ bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2);
2974+ modrm = bfd_get_8 (abfd, contents + irel->r_offset - 1);
2975+ baseless = (modrm & 0xc7) == 0x5;
2976+ /* For PIC, disallow "mov foo@GOT, %reg" since we don't
2977+ know what the GOT base is. */
2978+ if (baseless && bfd_link_pic (link_info))
2979+ goto baseless_error;
2980+ if (r_type == R_386_LOAD_GOT32
2981+ && (baseless || !bfd_link_pic (link_info)))
2982+ new_r_type = R_386_32;
2983+ else
2984+ new_r_type = R_386_GOTOFF;
2985+ irel->r_info = ELF32_R_INFO (r_symndx, new_r_type);
2986+ changed_contents = TRUE;
2987+ changed_relocs = TRUE;
2988+ /* For non-PIC, convert "lea foo@GOTOFF(%reg1), %reg2"
2989+ to "lea foo, %reg2". */
2990+ if (!baseless && new_r_type == R_386_32)
2991+ goto convert_to_baseless;
2992+ }
2993+ else if (r_type == R_386_LOAD_GOT32)
2994+ {
2995+ /* Function is undefined. */
2996+ modrm = bfd_get_8 (abfd, contents + irel->r_offset - 1);
2997+ baseless = (modrm & 0xc5) == 0x5;
2998+
2999+ if (bfd_link_pic (link_info))
3000+ {
3001+ /* For PIC, we leave "mov *foo@GOT(%reg), %reg" alone
3002+ and disallow "mov foo@GOT, %reg" since we don't
3003+ know what the GOT base is. */
3004+ if (baseless)
3005+ goto baseless_error;
3006+ }
3007+ else if (!baseless)
3008+ {
3009+ /* For non-PIC, convert "mov foo@GOT(%reg1), %reg2"
3010+ to "mov foo@GOT, %reg2" since the GOT base will be
3011+ added in elf_i386_relocate_section. No need to
3012+ convert "mov foo@GOT, %reg". */
3013+convert_to_baseless:
3014+ modrm = 0x5 | (modrm & 0x38);
3015+ bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
3016+ changed_contents = TRUE;
3017+ }
3018+ }
28233019 }
28243020 }
28253021
@@ -2905,7 +3101,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
29053101 {
29063102 struct elf_dyn_relocs *p;
29073103
2908- if (!elf_i386_convert_mov_to_lea (ibfd, s, info))
3104+ if (!elf_i386_convert_mov_and_branch (ibfd, s, info))
29093105 return FALSE;
29103106
29113107 for (p = ((struct elf_dyn_relocs *)
@@ -3655,6 +3851,7 @@ elf_i386_relocate_section (bfd *output_bfd,
36553851 goto do_relocation;
36563852
36573853 case R_386_GOT32:
3854+ case R_386_LOAD_GOT32:
36583855 base_got = htab->elf.sgot;
36593856 off = h->got.offset;
36603857
@@ -3732,6 +3929,34 @@ elf_i386_relocate_section (bfd *output_bfd,
37323929 eh = (struct elf_i386_link_hash_entry *) h;
37333930 switch (r_type)
37343931 {
3932+ case R_386_LOAD_GOT32:
3933+ /* Resolve "call/jmp *GOT[(%reg)]"/"mov GOT[(%reg)], %reg". */
3934+ if (h == NULL
3935+ || (h->plt.offset == (bfd_vma) -1
3936+ && h->got.offset == (bfd_vma) -1)
3937+ || htab->elf.sgotplt == NULL)
3938+ abort ();
3939+
3940+ offplt = (htab->elf.sgotplt->output_section->vma
3941+ + htab->elf.sgotplt->output_offset);
3942+
3943+ /* It is relative to .got.plt section. */
3944+ if (h->got.offset != (bfd_vma) -1)
3945+ /* Use GOT entry. */
3946+ relocation = (htab->elf.sgot->output_section->vma
3947+ + htab->elf.sgot->output_offset
3948+ + h->got.offset - offplt);
3949+ else
3950+ /* Use GOTPLT entry. */
3951+ relocation = (h->plt.offset / plt_entry_size - 1 + 3) * 4;
3952+
3953+ /* If not PIC, add the .got.plt section address. */
3954+ if (!bfd_link_pic (info))
3955+ relocation += offplt;
3956+
3957+ unresolved_reloc = FALSE;
3958+ break;
3959+
37353960 case R_386_GOT32:
37363961 /* Relocation is to the entry for this symbol in the global
37373962 offset table. */
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1292,6 +1292,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
12921292 "BFD_RELOC_386_TLS_DESC_CALL",
12931293 "BFD_RELOC_386_TLS_DESC",
12941294 "BFD_RELOC_386_IRELATIVE",
1295+ "BFD_RELOC_386_LOAD_GOT32",
12951296 "BFD_RELOC_X86_64_GOT32",
12961297 "BFD_RELOC_X86_64_PLT32",
12971298 "BFD_RELOC_X86_64_COPY",
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2676,6 +2676,8 @@ ENUMX
26762676 BFD_RELOC_386_TLS_DESC
26772677 ENUMX
26782678 BFD_RELOC_386_IRELATIVE
2679+ENUMX
2680+ BFD_RELOC_386_LOAD_GOT32
26792681 ENUMDOC
26802682 i386/elf relocations
26812683
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -2934,6 +2934,7 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
29342934 || fixP->fx_r_type == BFD_RELOC_386_GOTOFF
29352935 || fixP->fx_r_type == BFD_RELOC_386_PLT32
29362936 || fixP->fx_r_type == BFD_RELOC_386_GOT32
2937+ || fixP->fx_r_type == BFD_RELOC_386_LOAD_GOT32
29372938 || fixP->fx_r_type == BFD_RELOC_386_TLS_GD
29382939 || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM
29392940 || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32
@@ -3713,6 +3714,20 @@ md_assemble (char *line)
37133714 }
37143715 }
37153716
3717+ /* We don't check BFD_RELOC_X86_64_GOTPCREL here since it is set
3718+ by i386_validate_fix from BFD_RELOC_32_PCREL. */
3719+ if (i.reloc[0] == BFD_RELOC_386_GOT32)
3720+ {
3721+ if (i.operands == 1
3722+ && t->base_opcode == 0xff
3723+ && (t->extension_opcode == 2 || t->extension_opcode == 4))
3724+ /* call/jmp *foo@GOT[(%reg]) */
3725+ i.reloc[0] = BFD_RELOC_386_LOAD_GOT32;
3726+ else if (i.operands == 2 && i.tm.base_opcode == 0x8b)
3727+ /* mov foo@GOT[(%reg]), %reg */
3728+ i.reloc[0] = BFD_RELOC_386_LOAD_GOT32;
3729+ }
3730+
37163731 if (i.rex != 0)
37173732 add_prefix (REX_OPCODE | i.rex);
37183733
@@ -4798,6 +4813,10 @@ match_template (void)
47984813 }
47994814 }
48004815
4816+ /* Force 0x8b encoding for "mov foo@GOT, %eax". */
4817+ if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0)
4818+ continue;
4819+
48014820 /* We check register size if needed. */
48024821 check_register = t->opcode_modifier.checkregsize;
48034822 overlap0 = operand_type_and (i.types[0], operand_types[0]);
@@ -10396,6 +10415,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
1039610415 case BFD_RELOC_X86_64_INDBR_GOTPCREL:
1039710416 case BFD_RELOC_386_PLT32:
1039810417 case BFD_RELOC_386_GOT32:
10418+ case BFD_RELOC_386_LOAD_GOT32:
1039910419 case BFD_RELOC_386_GOTOFF:
1040010420 case BFD_RELOC_386_GOTPC:
1040110421 case BFD_RELOC_386_TLS_GD:
--- /dev/null
+++ b/gas/testsuite/gas/i386/got.d
@@ -0,0 +1,29 @@
1+#objdump: -dwr
2+
3+.*: +file format .*
4+
5+
6+Disassembly of section .text:
7+
8+0+ <_start>:
9+[ ]*[a-f0-9]+: b8 00 00 00 00 mov \$0x0,%eax 1: R_386_GOT32 foo
10+[ ]*[a-f0-9]+: 8b 05 00 00 00 00 mov 0x0,%eax 7: R_386_LOAD_GOT32 foo
11+[ ]*[a-f0-9]+: 8b 80 00 00 00 00 mov 0x0\(%eax\),%eax d: R_386_LOAD_GOT32 foo
12+[ ]*[a-f0-9]+: 05 00 00 00 00 add \$0x0,%eax 12: R_386_GOT32 foo
13+[ ]*[a-f0-9]+: 03 05 00 00 00 00 add 0x0,%eax 18: R_386_GOT32 foo
14+[ ]*[a-f0-9]+: 03 80 00 00 00 00 add 0x0\(%eax\),%eax 1e: R_386_GOT32 foo
15+[ ]*[a-f0-9]+: ff 15 00 00 00 00 call \*0x0 24: R_386_LOAD_GOT32 foo
16+[ ]*[a-f0-9]+: ff 90 00 00 00 00 call \*0x0\(%eax\) 2a: R_386_LOAD_GOT32 foo
17+[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0 30: R_386_LOAD_GOT32 foo
18+[ ]*[a-f0-9]+: ff a0 00 00 00 00 jmp \*0x0\(%eax\) 36: R_386_LOAD_GOT32 foo
19+[ ]*[a-f0-9]+: b8 00 00 00 00 mov \$0x0,%eax 3b: R_386_GOT32 foo
20+[ ]*[a-f0-9]+: 8b 05 00 00 00 00 mov 0x0,%eax 41: R_386_LOAD_GOT32 foo
21+[ ]*[a-f0-9]+: 8b 80 00 00 00 00 mov 0x0\(%eax\),%eax 47: R_386_LOAD_GOT32 foo
22+[ ]*[a-f0-9]+: 05 00 00 00 00 add \$0x0,%eax 4c: R_386_GOT32 foo
23+[ ]*[a-f0-9]+: 03 05 00 00 00 00 add 0x0,%eax 52: R_386_GOT32 foo
24+[ ]*[a-f0-9]+: 03 80 00 00 00 00 add 0x0\(%eax\),%eax 58: R_386_GOT32 foo
25+[ ]*[a-f0-9]+: ff 90 00 00 00 00 call \*0x0\(%eax\) 5e: R_386_LOAD_GOT32 foo
26+[ ]*[a-f0-9]+: ff 15 00 00 00 00 call \*0x0 64: R_386_LOAD_GOT32 foo
27+[ ]*[a-f0-9]+: ff a0 00 00 00 00 jmp \*0x0\(%eax\) 6a: R_386_LOAD_GOT32 foo
28+[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0 70: R_386_LOAD_GOT32 foo
29+#pass
--- /dev/null
+++ b/gas/testsuite/gas/i386/got.s
@@ -0,0 +1,29 @@
1+ .text
2+_start:
3+ movl $foo@GOT, %eax
4+ movl foo@GOT, %eax
5+ movl foo@GOT(%eax), %eax
6+
7+ addl $foo@GOT, %eax
8+ addl foo@GOT, %eax
9+ addl foo@GOT(%eax), %eax
10+
11+ call *foo@GOT
12+ call *foo@GOT(%eax)
13+ jmp *foo@GOT
14+ jmp *foo@GOT(%eax)
15+
16+ .intel_syntax noprefix
17+
18+ mov eax, offset foo@got
19+ mov eax, DWORD PTR [foo@GOT]
20+ mov eax, DWORD PTR [eax + foo@GOT]
21+
22+ add eax, offset foo@got
23+ add eax, DWORD PTR [foo@GOT]
24+ add eax, DWORD PTR [eax + foo@GOT]
25+
26+ call DWORD PTR [eax + foo@GOT]
27+ call DWORD PTR [foo@GOT]
28+ jmp DWORD PTR [eax + foo@GOT]
29+ jmp DWORD PTR [foo@GOT]
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -404,6 +404,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]]
404404 run_dump_test "relax-3"
405405 run_dump_test "relax-4"
406406
407+ run_dump_test "got"
408+
407409 if {![istarget "*-*-nacl*"]} then {
408410 run_dump_test "iamcu-1"
409411 run_dump_test "iamcu-2"
--- a/gas/testsuite/gas/i386/localpic.d
+++ b/gas/testsuite/gas/i386/localpic.d
@@ -3,7 +3,7 @@
33
44 Relocation section '.rel.text' at offset 0x[0-9a-f]+ contains 1 entries:
55 Offset Info Type Sym.Value Sym. Name
6-[0-9a-f]+ +[0-9a-f]+ R_386_GOT32 +[0-9a-f]+ +foo
6+[0-9a-f]+ +[0-9a-f]+ R_386_LOAD_GOT32 +[0-9a-f]+ +foo
77 #...
88 +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
99 #pass
--- a/gas/testsuite/gas/i386/mixed-mode-reloc32.d
+++ b/gas/testsuite/gas/i386/mixed-mode-reloc32.d
@@ -6,9 +6,9 @@
66
77 RELOCATION RECORDS FOR \[.text\]:
88 OFFSET[ ]+TYPE[ ]+VALUE[ ]*
9-[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]*
9+[0-9a-f]+[ ]+R_386_LOAD_GOT32[ ]+xtrn[ ]*
1010 [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]*
11-[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]*
11+[0-9a-f]+[ ]+R_386_LOAD_GOT32[ ]+xtrn[ ]*
1212 [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]*
13-[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]*
13+[0-9a-f]+[ ]+R_386_LOAD_GOT32[ ]+xtrn[ ]*
1414 [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]*
--- a/gas/testsuite/gas/i386/reloc32.d
+++ b/gas/testsuite/gas/i386/reloc32.d
@@ -18,7 +18,7 @@ Disassembly of section \.text:
1818 .*[ ]+R_386_PC32[ ]+xtrn
1919 .*[ ]+R_386_PC8[ ]+xtrn
2020 .*[ ]+R_386_GOT32[ ]+xtrn
21-.*[ ]+R_386_GOT32[ ]+xtrn
21+.*[ ]+R_386_LOAD_GOT32[ ]+xtrn
2222 .*[ ]+R_386_GOTOFF[ ]+xtrn
2323 .*[ ]+R_386_GOTOFF[ ]+xtrn
2424 .*[ ]+R_386_GOTPC[ ]+_GLOBAL_OFFSET_TABLE_
--- a/include/elf/i386.h
+++ b/include/elf/i386.h
@@ -66,6 +66,8 @@ START_RELOC_NUMBERS (elf_i386_reloc_type)
6666 RELOC_NUMBER (R_386_TLS_DESC_CALL,40)
6767 RELOC_NUMBER (R_386_TLS_DESC, 41)
6868 RELOC_NUMBER (R_386_IRELATIVE, 42) /* Adjust indirectly by program base */
69+ /* Load via 32 bit GOT entry */
70+ RELOC_NUMBER (R_386_LOAD_GOT32, 43)
6971
7072 /* Used by Intel. */
7173 RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200)
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1.dd
@@ -0,0 +1,19 @@
1+#...
2+[a-f0-9]+ <main>:
3+[ ]*[a-f0-9]+: 83 ec 0c sub \$0xc,%esp
4+[ ]*[a-f0-9]+: [ a-f0-9]+ addr16 call [a-f0-9]+ <foo>
5+[ ]*[a-f0-9]+: [ a-f0-9]+ call \*0x[a-f0-9]+
6+[ ]*[a-f0-9]+: [ a-f0-9]+ call \*0x[a-f0-9]+
7+[ ]*[a-f0-9]+: [ a-f0-9]+ lea *0x[a-f0-9]+,%eax
8+[ ]*[a-f0-9]+: ff d0 call \*%eax
9+[ ]*[a-f0-9]+: [ a-f0-9]+ mov *0x[a-f0-9]+,%eax
10+[ ]*[a-f0-9]+: ff d0 call \*%eax
11+[ ]*[a-f0-9]+: [ a-f0-9]+ mov *0x[a-f0-9]+,%eax
12+[ ]*[a-f0-9]+: ff d0 call \*%eax
13+[ ]*[a-f0-9]+: [ a-f0-9]+ lea *0x[a-f0-9]+,%ecx
14+[ ]*[a-f0-9]+: ff d1 call \*%ecx
15+[ ]*[a-f0-9]+: 83 ec 0c sub \$0xc,%esp
16+[ ]*[a-f0-9]+: 6a 00 push \$0x0
17+[ ]*[a-f0-9]+: [ a-f0-9]+ jmp [a-f0-9]+ <myexit>
18+[ ]*[a-f0-9]+: 90 nop
19+#pass
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1.out
@@ -0,0 +1,7 @@
1+foo
2+bar
3+plt
4+foo
5+bar
6+plt
7+foo
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1a.S
@@ -0,0 +1,20 @@
1+ .text
2+ .globl main
3+ .type main, @function
4+main:
5+ subl $12, %esp
6+ call *foo@GOT
7+ call *bar@GOT
8+ call *plt@GOT
9+ movl foo@GOT, %eax
10+ call *%eax
11+ movl bar@GOT, %eax
12+ call *%eax
13+ movl plt@GOT, %eax
14+ call *%eax
15+ movl foo@GOT(%ebx), %ecx
16+ call *%ecx
17+ subl $12, %esp
18+ pushl $0
19+ jmp *myexit@GOT
20+ .size main, .-main
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1b.c
@@ -0,0 +1,7 @@
1+#include <stdio.h>
2+
3+void
4+foo (void)
5+{
6+ printf ("%s\n", __FUNCTION__);
7+}
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1c.c
@@ -0,0 +1,7 @@
1+#include <stdlib.h>
2+
3+void
4+myexit (int status)
5+{
6+ exit (status);
7+}
--- /dev/null
+++ b/ld/testsuite/ld-i386/got1d.S
@@ -0,0 +1,54 @@
1+ .globl bar
2+ .type bar, @function
3+bar:
4+ pushl %ebx
5+ call __x86.get_pc_thunk.cx
6+ addl $_GLOBAL_OFFSET_TABLE_, %ecx
7+ subl $24, %esp
8+ leal __FUNCTION__.1862@GOTOFF(%ecx), %eax
9+ movl %eax, (%esp)
10+ call *puts@GOT(%ecx)
11+ addl $24, %esp
12+ popl %ebx
13+ ret
14+ .size bar, .-bar
15+
16+ .globl plt
17+ .type plt, @function
18+plt:
19+ pushl %esi
20+ pushl %ebx
21+ call __x86.get_pc_thunk.bx
22+1:
23+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
24+ subl $20, %esp
25+ leal __FUNCTION__.1866@GOTOFF(%ebx), %esi
26+ movl %esi, (%esp)
27+ call *puts@GOT(%ebx)
28+ addl $20, %esp
29+ popl %ebx
30+ popl %esi
31+ ret
32+ .section .rodata
33+ .type __FUNCTION__.1866, @object
34+ .size __FUNCTION__.1866, 4
35+__FUNCTION__.1866:
36+ .string "plt"
37+ .type __FUNCTION__.1862, @object
38+ .size __FUNCTION__.1862, 4
39+__FUNCTION__.1862:
40+ .string "bar"
41+ .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
42+ .globl __x86.get_pc_thunk.bx
43+ .hidden __x86.get_pc_thunk.bx
44+ .type __x86.get_pc_thunk.bx, @function
45+__x86.get_pc_thunk.bx:
46+ movl (%esp), %ebx
47+ ret
48+ .section .text.__x86.get_pc_thunk.cx,"axG",@progbits,__x86.get_pc_thunk.cx,comdat
49+ .globl __x86.get_pc_thunk.cx
50+ .hidden __x86.get_pc_thunk.cx
51+ .type __x86.get_pc_thunk.cx, @function
52+__x86.get_pc_thunk.cx:
53+ movl (%esp), %ecx
54+ ret
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -291,6 +291,12 @@ run_dump_test "lea1c"
291291 run_dump_test "lea1d"
292292 run_dump_test "lea1e"
293293 run_dump_test "lea1f"
294+run_dump_test "lea2a"
295+run_dump_test "lea2b"
296+run_dump_test "lea3a"
297+run_dump_test "lea3b"
298+run_dump_test "lea4a"
299+run_dump_test "lea4b"
294300 run_dump_test "mov1a"
295301 run_dump_test "mov1b"
296302
@@ -490,6 +496,22 @@ if { [isnative]
490496 {{readelf {-Wrd} pr18900b.rd}} \
491497 "pr18900b" \
492498 ] \
499+ [list \
500+ "Build got1d.so" \
501+ "-shared" \
502+ "" \
503+ { got1d.S } \
504+ "" \
505+ "got1d.so" \
506+ ] \
507+ [list \
508+ "Build gotpc1" \
509+ "tmpdir/got1d.so" \
510+ "" \
511+ { got1a.S got1b.c got1c.c } \
512+ {{objdump {-dw} got1.dd}} \
513+ "got1" \
514+ ] \
493515 ]
494516
495517 run_ld_link_exec_tests [] [list \
@@ -552,6 +574,14 @@ if { [isnative]
552574 "pr18900" \
553575 "pr18900.out" \
554576 ] \
577+ [list \
578+ "Run got1" \
579+ "tmpdir/got1d.so" \
580+ "" \
581+ { got1a.S got1b.c got1c.c } \
582+ "got1" \
583+ "got1.out" \
584+ ] \
555585 ]
556586 }
557587
--- a/ld/testsuite/ld-i386/lea1c.d
+++ b/ld/testsuite/ld-i386/lea1c.d
@@ -9,5 +9,5 @@
99 Disassembly of section .text:
1010
1111 #...
12-[ ]*[a-f0-9]+: 8d 81 ([0-9a-f]{2} ){4} * lea -0x[a-f0-9]+\(%ecx\),%eax
12+[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
1313 #pass
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea2.s
@@ -0,0 +1,9 @@
1+ .text
2+ .globl foo
3+ .type foo, @function
4+foo:
5+ ret
6+ .globl _start
7+ .type _start, @function
8+_start:
9+ movl foo@GOT, %eax
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea2a.d
@@ -0,0 +1,4 @@
1+#source: lea2.s
2+#as: --32
3+#ld: -Bsymbolic -shared -melf_i386
4+#error: direct GOT relocation R_386_LOAD_GOT32 against `foo' without base register can not be used when making a shared object
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea2b.d
@@ -0,0 +1,13 @@
1+#source: lea2.s
2+#as: --32
3+#ld: -melf_i386
4+#objdump: -dw
5+
6+.*: +file format .*
7+
8+
9+Disassembly of section .text:
10+
11+#...
12+[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
13+#pass
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea3.s
@@ -0,0 +1,15 @@
1+ .text
2+ .globl foo
3+ .type foo, @function
4+foo:
5+ ret
6+ .type bar, @function
7+bar:
8+ ret
9+ .globl _start
10+ .type _start, @function
11+_start:
12+ call *foo@GOT
13+ call *bar@GOT
14+ jmp *foo@GOT
15+ jmp *bar@GOT
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea3a.d
@@ -0,0 +1,18 @@
1+#source: lea3.s
2+#as: --32
3+#ld: -Bsymbolic -shared -melf_i386
4+#objdump: -dw
5+
6+.*: +file format .*
7+
8+
9+Disassembly of section .text:
10+
11+#...
12+[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4}[ ]*addr16 call [a-f0-9]+ <foo>
13+[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4}[ ]*addr16 call [a-f0-9]+ <bar>
14+[ ]*[a-f0-9]+: [ a-f0-9]+ jmp [a-f0-9]+ <foo>
15+[ ]*[a-f0-9]+: 90 nop
16+[ ]*[a-f0-9]+: [ a-f0-9]+ jmp [a-f0-9]+ <bar>
17+[ ]*[a-f0-9]+: 90 nop
18+#pass
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea3b.d
@@ -0,0 +1,18 @@
1+#source: lea3.s
2+#as: --32
3+#ld: -melf_i386
4+#objdump: -dw
5+
6+.*: +file format .*
7+
8+
9+Disassembly of section .text:
10+
11+#...
12+[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4}[ ]*addr16 call [a-f0-9]+ <foo>
13+[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4}[ ]*addr16 call [a-f0-9]+ <bar>
14+[ ]*[a-f0-9]+: [ a-f0-9]+ jmp [a-f0-9]+ <foo>
15+[ ]*[a-f0-9]+: 90 nop
16+[ ]*[a-f0-9]+: [ a-f0-9]+ jmp [a-f0-9]+ <bar>
17+[ ]*[a-f0-9]+: 90 nop
18+#pass
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea4.s
@@ -0,0 +1,8 @@
1+ .text
2+ .type foo, @function
3+foo:
4+ ret
5+ .globl _start
6+ .type _start, @function
7+_start:
8+ movl foo@GOT, %eax
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea4a.d
@@ -0,0 +1,4 @@
1+#source: lea4.s
2+#as: --32
3+#ld: -Bsymbolic -shared -melf_i386
4+#error: direct GOT relocation R_386_LOAD_GOT32 against `foo' without base register can not be used when making a shared object
--- /dev/null
+++ b/ld/testsuite/ld-i386/lea4b.d
@@ -0,0 +1,13 @@
1+#source: lea4.s
2+#as: --32
3+#ld: -melf_i386
4+#objdump: -dw
5+
6+.*: +file format .*
7+
8+
9+Disassembly of section .text:
10+
11+#...
12+[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
13+#pass
--- a/ld/testsuite/ld-i386/plt-main1.rd
+++ b/ld/testsuite/ld-i386/plt-main1.rd
@@ -1,3 +1,3 @@
11 #...
2-[0-9a-f ]+R_386_GOT32 +0+ +bar
2+[0-9a-f ]+R_386_LOAD_GOT32 +0+ +bar
33 #pass
--- a/ld/testsuite/ld-i386/plt-main3.rd
+++ b/ld/testsuite/ld-i386/plt-main3.rd
@@ -1,5 +1,5 @@
11 #...
2-[0-9a-f ]+R_386_GOT32 +0+ +bar
2+[0-9a-f ]+R_386_(LOAD_|)GOT32 +0+ +bar
33 #...
44 [0-9a-f ]+R_386_PLT32 +0+ +bar
55 #pass
--- a/ld/testsuite/ld-i386/plt-main4.rd
+++ b/ld/testsuite/ld-i386/plt-main4.rd
@@ -1,5 +1,5 @@
11 #...
2-[0-9a-f ]+R_386_GOT32 +0+ +foo
2+[0-9a-f ]+R_386_LOAD_GOT32 +0+ +foo
33 #...
44 [0-9a-f ]+R_386_PLT32 +0+ +foo
55 #pass