GNU Binutils with patches for OS216
Revision | 91d9e98ebf64688a62467541ab22cf2a7b4170f1 (tree) |
---|---|
Time | 2015-10-22 08:45:47 |
Author | H.J. Lu <hjl.tools@gmai...> |
Commiter | H.J. Lu |
Add R_386_GOT32X support to gas and ld
This patch adds support for the R_386_GOT32X relocation proposed in
https://groups.google.com/forum/#!topic/ia32-abi/GbJJskkid4I
to gas and ld. It updates gas to generate R_386_GOT32X relocation for
memory operand, foo@GOT[(%reg)]. We must encode "mov foo@GOT, %eax"
with the 0x8b opcode, instead of the 0xb8 opcode, so that it can be
transformed to "lea foo, %eax". With the locally defined symbol, foo,
we convert
to
and convert
to
When PIC is false, convert
to
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.
@@ -3177,6 +3177,7 @@ instruction. */ | ||
3177 | 3177 | BFD_RELOC_386_TLS_DESC_CALL, |
3178 | 3178 | BFD_RELOC_386_TLS_DESC, |
3179 | 3179 | BFD_RELOC_386_IRELATIVE, |
3180 | + BFD_RELOC_386_GOT32X, | |
3180 | 3181 | |
3181 | 3182 | /* x86-64/elf relocations */ |
3182 | 3183 | BFD_RELOC_X86_64_GOT32, |
@@ -29,6 +29,7 @@ | ||
29 | 29 | #include "objalloc.h" |
30 | 30 | #include "hashtab.h" |
31 | 31 | #include "dwarf2.h" |
32 | +#include "opcode/i386.h" | |
32 | 33 | |
33 | 34 | /* 386 uses REL relocations instead of RELA. */ |
34 | 35 | #define USE_REL 1 |
@@ -146,9 +147,12 @@ static reloc_howto_type elf_howto_table[]= | ||
146 | 147 | HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, |
147 | 148 | bfd_elf_generic_reloc, "R_386_IRELATIVE", |
148 | 149 | TRUE, 0xffffffff, 0xffffffff, FALSE), |
150 | + HOWTO(R_386_GOT32X, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, | |
151 | + bfd_elf_generic_reloc, "R_386_GOT32X", | |
152 | + TRUE, 0xffffffff, 0xffffffff, FALSE), | |
149 | 153 | |
150 | 154 | /* Another gap. */ |
151 | -#define R_386_ext2 (R_386_IRELATIVE + 1 - R_386_tls_offset) | |
155 | +#define R_386_ext2 (R_386_GOT32X + 1 - R_386_tls_offset) | |
152 | 156 | #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_ext2) |
153 | 157 | |
154 | 158 | /* GNU extension to record C++ vtable hierarchy. */ |
@@ -332,6 +336,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, | ||
332 | 336 | TRACE ("BFD_RELOC_386_IRELATIVE"); |
333 | 337 | return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset]; |
334 | 338 | |
339 | + case BFD_RELOC_386_GOT32X: | |
340 | + TRACE ("BFD_RELOC_386_GOT32X"); | |
341 | + return &elf_howto_table[R_386_GOT32X - R_386_tls_offset]; | |
342 | + | |
335 | 343 | case BFD_RELOC_VTABLE_INHERIT: |
336 | 344 | TRACE ("BFD_RELOC_VTABLE_INHERIT"); |
337 | 345 | 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, | ||
1468 | 1476 | |
1469 | 1477 | /* Rename some of the generic section flags to better document how they |
1470 | 1478 | are used here. */ |
1471 | -#define need_convert_mov_to_lea sec_flg0 | |
1479 | +#define need_convert_load sec_flg0 | |
1472 | 1480 | |
1473 | 1481 | /* Look through the relocs for a section during the first phase, and |
1474 | 1482 | calculate needed space in the global offset table, procedure linkage |
@@ -1580,6 +1588,7 @@ elf_i386_check_relocs (bfd *abfd, | ||
1580 | 1588 | case R_386_PC32: |
1581 | 1589 | case R_386_PLT32: |
1582 | 1590 | case R_386_GOT32: |
1591 | + case R_386_GOT32X: | |
1583 | 1592 | if (htab->elf.dynobj == NULL) |
1584 | 1593 | htab->elf.dynobj = abfd; |
1585 | 1594 | if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) |
@@ -1637,6 +1646,7 @@ elf_i386_check_relocs (bfd *abfd, | ||
1637 | 1646 | /* Fall through */ |
1638 | 1647 | |
1639 | 1648 | case R_386_GOT32: |
1649 | + case R_386_GOT32X: | |
1640 | 1650 | case R_386_TLS_GD: |
1641 | 1651 | case R_386_TLS_GOTDESC: |
1642 | 1652 | case R_386_TLS_DESC_CALL: |
@@ -1647,7 +1657,10 @@ elf_i386_check_relocs (bfd *abfd, | ||
1647 | 1657 | switch (r_type) |
1648 | 1658 | { |
1649 | 1659 | default: |
1650 | - case R_386_GOT32: tls_type = GOT_NORMAL; break; | |
1660 | + case R_386_GOT32: | |
1661 | + case R_386_GOT32X: | |
1662 | + tls_type = GOT_NORMAL; | |
1663 | + break; | |
1651 | 1664 | case R_386_TLS_GD: tls_type = GOT_TLS_GD; break; |
1652 | 1665 | case R_386_TLS_GOTDESC: |
1653 | 1666 | case R_386_TLS_DESC_CALL: |
@@ -1948,9 +1961,9 @@ do_size: | ||
1948 | 1961 | return FALSE; |
1949 | 1962 | } |
1950 | 1963 | |
1951 | - if (r_type == R_386_GOT32 | |
1964 | + if ((r_type == R_386_GOT32 || r_type == R_386_GOT32X) | |
1952 | 1965 | && (h == NULL || h->type != STT_GNU_IFUNC)) |
1953 | - sec->need_convert_mov_to_lea = 1; | |
1966 | + sec->need_convert_load = 1; | |
1954 | 1967 | } |
1955 | 1968 | |
1956 | 1969 | return TRUE; |
@@ -2074,6 +2087,7 @@ elf_i386_gc_sweep_hook (bfd *abfd, | ||
2074 | 2087 | case R_386_TLS_IE: |
2075 | 2088 | case R_386_TLS_GOTIE: |
2076 | 2089 | case R_386_GOT32: |
2090 | + case R_386_GOT32X: | |
2077 | 2091 | if (h != NULL) |
2078 | 2092 | { |
2079 | 2093 | if (h->got.refcount > 0) |
@@ -2718,14 +2732,27 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) | ||
2718 | 2732 | return TRUE; |
2719 | 2733 | } |
2720 | 2734 | |
2721 | -/* Convert | |
2722 | - mov foo@GOT(%reg), %reg | |
2735 | +/* With the local symbol, foo, we convert | |
2736 | + mov foo@GOT[(%reg1)], %reg2 | |
2737 | + to | |
2738 | + lea foo[@GOTOFF(%reg1)], %reg2 | |
2739 | + and convert | |
2740 | + call/jmp *foo@GOT[(%reg)] | |
2723 | 2741 | to |
2724 | - lea foo@GOTOFF(%reg), %reg | |
2725 | - with the local symbol, foo. */ | |
2742 | + nop call foo/jmp foo nop | |
2743 | + When PIC is false, convert | |
2744 | + test %reg1, foo@GOT[(%reg2)] | |
2745 | + to | |
2746 | + test $foo, %reg1 | |
2747 | + and convert | |
2748 | + binop foo@GOT[(%reg1)], %reg2 | |
2749 | + to | |
2750 | + binop $foo, %reg2 | |
2751 | + where binop is one of adc, add, and, cmp, or, sbb, sub, xor | |
2752 | + instructions. */ | |
2726 | 2753 | |
2727 | 2754 | static bfd_boolean |
2728 | -elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, | |
2755 | +elf_i386_convert_load (bfd *abfd, asection *sec, | |
2729 | 2756 | struct bfd_link_info *link_info) |
2730 | 2757 | { |
2731 | 2758 | Elf_Internal_Shdr *symtab_hdr; |
@@ -2743,7 +2770,7 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, | ||
2743 | 2770 | |
2744 | 2771 | /* Nothing to do if there is no need or no output. */ |
2745 | 2772 | if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC) |
2746 | - || sec->need_convert_mov_to_lea == 0 | |
2773 | + || sec->need_convert_load == 0 | |
2747 | 2774 | || bfd_is_abs_section (sec->output_section)) |
2748 | 2775 | return TRUE; |
2749 | 2776 |
@@ -2777,32 +2804,92 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, | ||
2777 | 2804 | unsigned int r_symndx = ELF32_R_SYM (irel->r_info); |
2778 | 2805 | unsigned int indx; |
2779 | 2806 | struct elf_link_hash_entry *h; |
2807 | + unsigned int opcode; | |
2808 | + unsigned int modrm; | |
2809 | + bfd_vma roff; | |
2810 | + bfd_boolean baseless; | |
2811 | + Elf_Internal_Sym *isym; | |
2812 | + unsigned int addend; | |
2813 | + unsigned int nop; | |
2814 | + bfd_vma nop_offset; | |
2780 | 2815 | |
2781 | - if (r_type != R_386_GOT32) | |
2816 | + if (r_type != R_386_GOT32 && r_type != R_386_GOT32X) | |
2782 | 2817 | continue; |
2783 | 2818 | |
2784 | - /* Get the symbol referred to by the reloc. */ | |
2785 | - if (r_symndx < symtab_hdr->sh_info) | |
2819 | + roff = irel->r_offset; | |
2820 | + if (roff < 2) | |
2821 | + continue; | |
2822 | + | |
2823 | + modrm = bfd_get_8 (abfd, contents + roff - 1); | |
2824 | + baseless = (modrm & 0xc7) == 0x5; | |
2825 | + | |
2826 | + if (r_type == R_386_GOT32X | |
2827 | + && baseless | |
2828 | + && bfd_link_pic (link_info)) | |
2786 | 2829 | { |
2787 | - Elf_Internal_Sym *isym; | |
2830 | + /* For PIC, disallow R_386_GOT32X without a base register | |
2831 | + since we don't know what the GOT base is. Allow | |
2832 | + R_386_GOT32 for existing object files. */ | |
2833 | + const char *name; | |
2834 | + | |
2835 | + if (r_symndx < symtab_hdr->sh_info) | |
2836 | + { | |
2837 | + isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, | |
2838 | + r_symndx); | |
2839 | + name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); | |
2840 | + } | |
2841 | + else | |
2842 | + { | |
2843 | + indx = r_symndx - symtab_hdr->sh_info; | |
2844 | + h = elf_sym_hashes (abfd)[indx]; | |
2845 | + BFD_ASSERT (h != NULL); | |
2846 | + name = h->root.root.string; | |
2847 | + } | |
2848 | + | |
2849 | + (*_bfd_error_handler) | |
2850 | + (_("%B: direct GOT relocation R_386_GOT32X against `%s' without base register can not be used when making a shared object"), | |
2851 | + abfd, name); | |
2852 | + goto error_return; | |
2853 | + } | |
2854 | + | |
2855 | + opcode = bfd_get_8 (abfd, contents + roff - 2); | |
2856 | + | |
2857 | + /* It is OK to convert mov to lea. */ | |
2858 | + if (opcode != 0x8b) | |
2859 | + { | |
2860 | + /* Only convert R_386_GOT32X relocation for call, jmp or | |
2861 | + one of adc, add, and, cmp, or, sbb, sub, test, xor | |
2862 | + instructions. */ | |
2863 | + if (r_type != R_386_GOT32X) | |
2864 | + continue; | |
2865 | + | |
2866 | + /* It is OK to convert indirect branch to direct branch. It | |
2867 | + is OK to convert adc, add, and, cmp, or, sbb, sub, test, | |
2868 | + xor only when PIC is false. */ | |
2869 | + if (opcode != 0xff && bfd_link_pic (link_info)) | |
2870 | + continue; | |
2871 | + } | |
2788 | 2872 | |
2873 | + /* Try to convert R_386_GOT32 and R_386_GOT32X. Get the symbol | |
2874 | + referred to by the reloc. */ | |
2875 | + if (r_symndx < symtab_hdr->sh_info) | |
2876 | + { | |
2789 | 2877 | isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
2790 | 2878 | abfd, r_symndx); |
2791 | 2879 | |
2792 | - /* STT_GNU_IFUNC must keep R_386_GOT32 relocation. */ | |
2793 | - if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC | |
2794 | - && irel->r_offset >= 2 | |
2795 | - && bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b) | |
2796 | - { | |
2797 | - bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2); | |
2798 | - irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF); | |
2799 | - if (local_got_refcounts != NULL | |
2800 | - && local_got_refcounts[r_symndx] > 0) | |
2801 | - local_got_refcounts[r_symndx] -= 1; | |
2802 | - changed_contents = TRUE; | |
2803 | - changed_relocs = TRUE; | |
2804 | - } | |
2805 | - continue; | |
2880 | + /* STT_GNU_IFUNC must keep GOT32 relocations. */ | |
2881 | + if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) | |
2882 | + continue; | |
2883 | + | |
2884 | + h = NULL; | |
2885 | + if (opcode == 0x0ff) | |
2886 | + /* Convert "call/jmp *foo@GOT[(%reg)]". */ | |
2887 | + goto convert_branch; | |
2888 | + else | |
2889 | + /* Convert "mov foo@GOT[(%reg1)], %reg2", | |
2890 | + "test %reg1, foo@GOT(%reg2)" and | |
2891 | + "binop foo@GOT[(%reg1)], %reg2". */ | |
2892 | + goto convert_load; | |
2806 | 2893 | } |
2807 | 2894 | |
2808 | 2895 | indx = r_symndx - symtab_hdr->sh_info; |
@@ -2813,22 +2900,147 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, | ||
2813 | 2900 | || h->root.type == bfd_link_hash_warning) |
2814 | 2901 | h = (struct elf_link_hash_entry *) h->root.u.i.link; |
2815 | 2902 | |
2816 | - /* STT_GNU_IFUNC must keep R_386_GOT32 relocation. We also avoid | |
2817 | - optimizing _DYNAMIC since ld.so may use its link-time address. */ | |
2818 | - if ((h->root.type == bfd_link_hash_defined | |
2819 | - || h->root.type == bfd_link_hash_defweak) | |
2820 | - && h->type != STT_GNU_IFUNC | |
2821 | - && h != htab->elf.hdynamic | |
2822 | - && SYMBOL_REFERENCES_LOCAL (link_info, h) | |
2823 | - && irel->r_offset >= 2 | |
2824 | - && bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b) | |
2903 | + /* STT_GNU_IFUNC must keep GOT32 relocations. */ | |
2904 | + if (h->type == STT_GNU_IFUNC) | |
2905 | + continue; | |
2906 | + | |
2907 | + if (opcode == 0xff) | |
2908 | + { | |
2909 | + /* We have "call/jmp *foo@GOT[(%reg)]". */ | |
2910 | + if ((h->root.type == bfd_link_hash_defined | |
2911 | + || h->root.type == bfd_link_hash_defweak) | |
2912 | + && SYMBOL_REFERENCES_LOCAL (link_info, h)) | |
2913 | + { | |
2914 | + /* The function is locally defined. */ | |
2915 | +convert_branch: | |
2916 | + addend = bfd_get_32 (abfd, contents + roff); | |
2917 | + /* Addend for R_386_GOT32X relocation must be 0. */ | |
2918 | + if (addend != 0) | |
2919 | + continue; | |
2920 | + | |
2921 | + /* Convert R_386_GOT32X to R_386_PC32. */ | |
2922 | + if (modrm == 0x15 || (modrm & 0xf8) == 0x90) | |
2923 | + { | |
2924 | + /* Convert to "nop call foo". ADDR_PREFIX_OPCODE | |
2925 | + is a nop prefix. */ | |
2926 | + modrm = 0xe8; | |
2927 | + nop = ADDR_PREFIX_OPCODE; | |
2928 | + nop_offset = roff - 2; | |
2929 | + } | |
2930 | + else | |
2931 | + { | |
2932 | + /* Convert to "jmp foo nop". */ | |
2933 | + modrm = 0xe9; | |
2934 | + nop = NOP_OPCODE; | |
2935 | + nop_offset = roff + 3; | |
2936 | + irel->r_offset -= 1; | |
2937 | + } | |
2938 | + | |
2939 | + bfd_put_8 (abfd, nop, contents + nop_offset); | |
2940 | + bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1); | |
2941 | + /* When converting to PC-relative relocation, we | |
2942 | + need to adjust addend by -4. */ | |
2943 | + bfd_put_32 (abfd, -4, contents + irel->r_offset); | |
2944 | + irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32); | |
2945 | + | |
2946 | + if (h) | |
2947 | + { | |
2948 | + if (h->got.refcount > 0) | |
2949 | + h->got.refcount -= 1; | |
2950 | + } | |
2951 | + else | |
2952 | + { | |
2953 | + if (local_got_refcounts != NULL | |
2954 | + && local_got_refcounts[r_symndx] > 0) | |
2955 | + local_got_refcounts[r_symndx] -= 1; | |
2956 | + } | |
2957 | + | |
2958 | + changed_contents = TRUE; | |
2959 | + changed_relocs = TRUE; | |
2960 | + } | |
2961 | + } | |
2962 | + else | |
2825 | 2963 | { |
2826 | - bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2); | |
2827 | - irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF); | |
2828 | - if (h->got.refcount > 0) | |
2829 | - h->got.refcount -= 1; | |
2830 | - changed_contents = TRUE; | |
2831 | - changed_relocs = TRUE; | |
2964 | + /* We have "mov foo@GOT[(%re1g)], %reg2", | |
2965 | + "test %reg1, foo@GOT(%reg2)" and | |
2966 | + "binop foo@GOT[(%reg1)], %reg2". | |
2967 | + | |
2968 | + Avoid optimizing _DYNAMIC since ld.so may use its | |
2969 | + link-time address. */ | |
2970 | + if (h == htab->elf.hdynamic) | |
2971 | + continue; | |
2972 | + | |
2973 | + if ((h->root.type == bfd_link_hash_defined | |
2974 | + || h->root.type == bfd_link_hash_defweak) | |
2975 | + && SYMBOL_REFERENCES_LOCAL (link_info, h)) | |
2976 | + { | |
2977 | +convert_load: | |
2978 | + if (opcode == 0x8b) | |
2979 | + { | |
2980 | + /* Convert "mov foo@GOT(%reg1), %reg2" to | |
2981 | + "lea foo@GOTOFF(%reg1), %reg2". */ | |
2982 | + if (r_type == R_386_GOT32X | |
2983 | + && (baseless || !bfd_link_pic (link_info))) | |
2984 | + { | |
2985 | + r_type = R_386_32; | |
2986 | + /* For R_386_32, convert | |
2987 | + "lea foo@GOTOFF(%reg1), %reg2" to | |
2988 | + "lea foo@GOT, %reg2". */ | |
2989 | + if (!baseless) | |
2990 | + { | |
2991 | + modrm = 0x5 | (modrm & 0x38); | |
2992 | + bfd_put_8 (abfd, modrm, contents + roff - 1); | |
2993 | + } | |
2994 | + } | |
2995 | + else | |
2996 | + r_type = R_386_GOTOFF; | |
2997 | + opcode = 0x8d; | |
2998 | + } | |
2999 | + else | |
3000 | + { | |
3001 | + /* Addend for R_386_GOT32X relocation must be 0. */ | |
3002 | + addend = bfd_get_32 (abfd, contents + roff); | |
3003 | + if (addend != 0) | |
3004 | + continue; | |
3005 | + | |
3006 | + if (opcode == 0x85) | |
3007 | + { | |
3008 | + /* Convert "test %reg1, foo@GOT(%reg2)" to | |
3009 | + "test $foo, %reg1". */ | |
3010 | + modrm = 0xc0 | (modrm & 0x38) >> 3; | |
3011 | + opcode = 0xf7; | |
3012 | + } | |
3013 | + else | |
3014 | + { | |
3015 | + /* Convert "binop foo@GOT(%reg1), %reg2" to | |
3016 | + "binop $foo, %reg2". */ | |
3017 | + modrm = (0xc0 | |
3018 | + | (modrm & 0x38) >> 3 | |
3019 | + | (opcode & 0x3c)); | |
3020 | + opcode = 0x81; | |
3021 | + } | |
3022 | + bfd_put_8 (abfd, modrm, contents + roff - 1); | |
3023 | + r_type = R_386_32; | |
3024 | + } | |
3025 | + | |
3026 | + bfd_put_8 (abfd, opcode, contents + roff - 2); | |
3027 | + irel->r_info = ELF32_R_INFO (r_symndx, r_type); | |
3028 | + | |
3029 | + if (h) | |
3030 | + { | |
3031 | + if (h->got.refcount > 0) | |
3032 | + h->got.refcount -= 1; | |
3033 | + } | |
3034 | + else | |
3035 | + { | |
3036 | + if (local_got_refcounts != NULL | |
3037 | + && local_got_refcounts[r_symndx] > 0) | |
3038 | + local_got_refcounts[r_symndx] -= 1; | |
3039 | + } | |
3040 | + | |
3041 | + changed_contents = TRUE; | |
3042 | + changed_relocs = TRUE; | |
3043 | + } | |
2832 | 3044 | } |
2833 | 3045 | } |
2834 | 3046 |
@@ -2914,7 +3126,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) | ||
2914 | 3126 | { |
2915 | 3127 | struct elf_dyn_relocs *p; |
2916 | 3128 | |
2917 | - if (!elf_i386_convert_mov_to_lea (ibfd, s, info)) | |
3129 | + if (!elf_i386_convert_load (ibfd, s, info)) | |
2918 | 3130 | return FALSE; |
2919 | 3131 | |
2920 | 3132 | for (p = ((struct elf_dyn_relocs *) |
@@ -3664,6 +3876,7 @@ elf_i386_relocate_section (bfd *output_bfd, | ||
3664 | 3876 | goto do_relocation; |
3665 | 3877 | |
3666 | 3878 | case R_386_GOT32: |
3879 | + case R_386_GOT32X: | |
3667 | 3880 | base_got = htab->elf.sgot; |
3668 | 3881 | off = h->got.offset; |
3669 | 3882 |
@@ -3741,7 +3954,61 @@ elf_i386_relocate_section (bfd *output_bfd, | ||
3741 | 3954 | eh = (struct elf_i386_link_hash_entry *) h; |
3742 | 3955 | switch (r_type) |
3743 | 3956 | { |
3957 | + case R_386_GOT32X: | |
3958 | + /* Avoid optimizing _DYNAMIC since ld.so may use its | |
3959 | + link-time address. */ | |
3960 | + if (h == htab->elf.hdynamic) | |
3961 | + goto r_386_got32; | |
3962 | + | |
3963 | + if (bfd_link_pic (info)) | |
3964 | + { | |
3965 | + /* It is OK to convert mov to lea and convert indirect | |
3966 | + branch to direct branch. It is OK to convert adc, | |
3967 | + add, and, cmp, or, sbb, sub, test, xor only when PIC | |
3968 | + is false. */ | |
3969 | + unsigned int opcode; | |
3970 | + opcode = bfd_get_8 (abfd, contents + rel->r_offset - 2); | |
3971 | + if (opcode != 0x8b && opcode != 0xff) | |
3972 | + goto r_386_got32; | |
3973 | + } | |
3974 | + | |
3975 | + /* Resolve "mov GOT[(%reg)], %reg", | |
3976 | + "call/jmp *GOT[(%reg)]", "test %reg, foo@GOT[(%reg)]" | |
3977 | + and "binop foo@GOT[(%reg)], %reg". */ | |
3978 | + if (h == NULL | |
3979 | + || (h->plt.offset == (bfd_vma) -1 | |
3980 | + && h->got.offset == (bfd_vma) -1) | |
3981 | + || htab->elf.sgotplt == NULL) | |
3982 | + abort (); | |
3983 | + | |
3984 | + offplt = (htab->elf.sgotplt->output_section->vma | |
3985 | + + htab->elf.sgotplt->output_offset); | |
3986 | + | |
3987 | + /* It is relative to .got.plt section. */ | |
3988 | + if (h->got.offset != (bfd_vma) -1) | |
3989 | + /* Use GOT entry. */ | |
3990 | + relocation = (htab->elf.sgot->output_section->vma | |
3991 | + + htab->elf.sgot->output_offset | |
3992 | + + h->got.offset - offplt); | |
3993 | + else | |
3994 | + /* Use GOTPLT entry. */ | |
3995 | + relocation = (h->plt.offset / plt_entry_size - 1 + 3) * 4; | |
3996 | + | |
3997 | + if (!bfd_link_pic (info)) | |
3998 | + { | |
3999 | + /* If not PIC, add the .got.plt section address for | |
4000 | + baseless adressing. */ | |
4001 | + unsigned int modrm; | |
4002 | + modrm = bfd_get_8 (abfd, contents + rel->r_offset - 1); | |
4003 | + if ((modrm & 0xc7) == 0x5) | |
4004 | + relocation += offplt; | |
4005 | + } | |
4006 | + | |
4007 | + unresolved_reloc = FALSE; | |
4008 | + break; | |
4009 | + | |
3744 | 4010 | case R_386_GOT32: |
4011 | +r_386_got32: | |
3745 | 4012 | /* Relocation is to the entry for this symbol in the global |
3746 | 4013 | offset table. */ |
3747 | 4014 | if (htab->elf.sgot == NULL) |
@@ -1292,6 +1292,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", | ||
1292 | 1292 | "BFD_RELOC_386_TLS_DESC_CALL", |
1293 | 1293 | "BFD_RELOC_386_TLS_DESC", |
1294 | 1294 | "BFD_RELOC_386_IRELATIVE", |
1295 | + "BFD_RELOC_386_GOT32X", | |
1295 | 1296 | "BFD_RELOC_X86_64_GOT32", |
1296 | 1297 | "BFD_RELOC_X86_64_PLT32", |
1297 | 1298 | "BFD_RELOC_X86_64_COPY", |
@@ -2676,6 +2676,8 @@ ENUMX | ||
2676 | 2676 | BFD_RELOC_386_TLS_DESC |
2677 | 2677 | ENUMX |
2678 | 2678 | BFD_RELOC_386_IRELATIVE |
2679 | +ENUMX | |
2680 | + BFD_RELOC_386_GOT32X | |
2679 | 2681 | ENUMDOC |
2680 | 2682 | i386/elf relocations |
2681 | 2683 |
@@ -2928,6 +2928,7 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED) | ||
2928 | 2928 | || fixP->fx_r_type == BFD_RELOC_386_GOTOFF |
2929 | 2929 | || fixP->fx_r_type == BFD_RELOC_386_PLT32 |
2930 | 2930 | || fixP->fx_r_type == BFD_RELOC_386_GOT32 |
2931 | + || fixP->fx_r_type == BFD_RELOC_386_GOT32X | |
2931 | 2932 | || fixP->fx_r_type == BFD_RELOC_386_TLS_GD |
2932 | 2933 | || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM |
2933 | 2934 | || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32 |
@@ -4791,6 +4792,10 @@ match_template (void) | ||
4791 | 4792 | } |
4792 | 4793 | } |
4793 | 4794 | |
4795 | + /* Force 0x8b encoding for "mov foo@GOT, %eax". */ | |
4796 | + if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0) | |
4797 | + continue; | |
4798 | + | |
4794 | 4799 | /* We check register size if needed. */ |
4795 | 4800 | check_register = t->opcode_modifier.checkregsize; |
4796 | 4801 | overlap0 = operand_type_and (i.types[0], operand_types[0]); |
@@ -7157,6 +7162,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) | ||
7157 | 7162 | int size = disp_size (n); |
7158 | 7163 | int sign = i.types[n].bitfield.disp32s; |
7159 | 7164 | int pcrel = (i.flags[n] & Operand_PCrel) != 0; |
7165 | + fixS *fixP; | |
7160 | 7166 | |
7161 | 7167 | /* We can't have 8 bit displacement here. */ |
7162 | 7168 | gas_assert (!i.types[n].bitfield.disp8); |
@@ -7225,8 +7231,34 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) | ||
7225 | 7231 | insn, and that is taken care of in other code. */ |
7226 | 7232 | reloc_type = BFD_RELOC_X86_64_GOTPC32; |
7227 | 7233 | } |
7228 | - fix_new_exp (frag_now, p - frag_now->fr_literal, size, | |
7229 | - i.op[n].disps, pcrel, reloc_type); | |
7234 | + fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, | |
7235 | + size, i.op[n].disps, pcrel, | |
7236 | + reloc_type); | |
7237 | + /* Check for "call/jmp *mem", "mov mem, %reg", | |
7238 | + "test %reg, mem" and "binop mem, %reg" where binop | |
7239 | + is one of adc, add, and, cmp, or, sbb, sub, xor | |
7240 | + instructions. */ | |
7241 | + if ((i.rm.mode == 2 | |
7242 | + || (i.rm.mode == 0 && i.rm.regmem == 5)) | |
7243 | + && ((i.operands == 1 | |
7244 | + && i.tm.base_opcode == 0xff | |
7245 | + && (i.rm.reg == 2 || i.rm.reg == 4)) | |
7246 | + || (i.operands == 2 | |
7247 | + && (i.tm.base_opcode == 0x8b | |
7248 | + || i.tm.base_opcode == 0x85 | |
7249 | + || (i.tm.base_opcode & 0xc7) == 0x03)))) | |
7250 | + { | |
7251 | + if (object_64bit) | |
7252 | + { | |
7253 | + fixP->fx_tcbit = i.rex != 0; | |
7254 | + if (i.base_reg | |
7255 | + && (i.base_reg->reg_num == RegRip | |
7256 | + || i.base_reg->reg_num == RegEip)) | |
7257 | + fixP->fx_tcbit2 = 1; | |
7258 | + } | |
7259 | + else | |
7260 | + fixP->fx_tcbit2 = 1; | |
7261 | + } | |
7230 | 7262 | } |
7231 | 7263 | } |
7232 | 7264 | } |
@@ -10321,23 +10353,39 @@ s_bss (int ignore ATTRIBUTE_UNUSED) | ||
10321 | 10353 | void |
10322 | 10354 | i386_validate_fix (fixS *fixp) |
10323 | 10355 | { |
10324 | - if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol) | |
10356 | + if (fixp->fx_subsy) | |
10325 | 10357 | { |
10326 | - if (fixp->fx_r_type == BFD_RELOC_32_PCREL) | |
10327 | - { | |
10328 | - if (!object_64bit) | |
10329 | - abort (); | |
10330 | - fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; | |
10331 | - } | |
10332 | - else | |
10358 | + if (fixp->fx_subsy == GOT_symbol) | |
10333 | 10359 | { |
10334 | - if (!object_64bit) | |
10335 | - fixp->fx_r_type = BFD_RELOC_386_GOTOFF; | |
10360 | + if (fixp->fx_r_type == BFD_RELOC_32_PCREL) | |
10361 | + { | |
10362 | + if (!object_64bit) | |
10363 | + abort (); | |
10364 | +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) | |
10365 | + if (fixp->fx_tcbit2) | |
10366 | + fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; | |
10367 | + else | |
10368 | +#endif | |
10369 | + fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; | |
10370 | + } | |
10336 | 10371 | else |
10337 | - fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64; | |
10372 | + { | |
10373 | + if (!object_64bit) | |
10374 | + fixp->fx_r_type = BFD_RELOC_386_GOTOFF; | |
10375 | + else | |
10376 | + fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64; | |
10377 | + } | |
10378 | + fixp->fx_subsy = 0; | |
10338 | 10379 | } |
10339 | - fixp->fx_subsy = 0; | |
10340 | 10380 | } |
10381 | +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) | |
10382 | + else if (!object_64bit) | |
10383 | + { | |
10384 | + if (fixp->fx_r_type == BFD_RELOC_386_GOT32 | |
10385 | + && fixp->fx_tcbit2) | |
10386 | + fixp->fx_r_type = BFD_RELOC_386_GOT32X; | |
10387 | + } | |
10388 | +#endif | |
10341 | 10389 | } |
10342 | 10390 | |
10343 | 10391 | arelent * |
@@ -10373,6 +10421,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) | ||
10373 | 10421 | case BFD_RELOC_X86_64_GOTPCREL: |
10374 | 10422 | case BFD_RELOC_386_PLT32: |
10375 | 10423 | case BFD_RELOC_386_GOT32: |
10424 | + case BFD_RELOC_386_GOT32X: | |
10376 | 10425 | case BFD_RELOC_386_GOTOFF: |
10377 | 10426 | case BFD_RELOC_386_GOTPC: |
10378 | 10427 | case BFD_RELOC_386_TLS_GD: |
@@ -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_GOT32X foo | |
11 | +[ ]*[a-f0-9]+: 8b 80 00 00 00 00 mov 0x0\(%eax\),%eax d: R_386_GOT32X 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_GOT32X foo | |
14 | +[ ]*[a-f0-9]+: 03 80 00 00 00 00 add 0x0\(%eax\),%eax 1e: R_386_GOT32X foo | |
15 | +[ ]*[a-f0-9]+: ff 15 00 00 00 00 call \*0x0 24: R_386_GOT32X foo | |
16 | +[ ]*[a-f0-9]+: ff 90 00 00 00 00 call \*0x0\(%eax\) 2a: R_386_GOT32X foo | |
17 | +[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0 30: R_386_GOT32X foo | |
18 | +[ ]*[a-f0-9]+: ff a0 00 00 00 00 jmp \*0x0\(%eax\) 36: R_386_GOT32X 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_GOT32X foo | |
21 | +[ ]*[a-f0-9]+: 8b 80 00 00 00 00 mov 0x0\(%eax\),%eax 47: R_386_GOT32X 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_GOT32X foo | |
24 | +[ ]*[a-f0-9]+: 03 80 00 00 00 00 add 0x0\(%eax\),%eax 58: R_386_GOT32X foo | |
25 | +[ ]*[a-f0-9]+: ff 90 00 00 00 00 call \*0x0\(%eax\) 5e: R_386_GOT32X foo | |
26 | +[ ]*[a-f0-9]+: ff 15 00 00 00 00 call \*0x0 64: R_386_GOT32X foo | |
27 | +[ ]*[a-f0-9]+: ff a0 00 00 00 00 jmp \*0x0\(%eax\) 6a: R_386_GOT32X foo | |
28 | +[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0 70: R_386_GOT32X foo | |
29 | +#pass |
@@ -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] |
@@ -404,6 +404,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] | ||
404 | 404 | run_dump_test "relax-3" |
405 | 405 | run_dump_test "relax-4" |
406 | 406 | |
407 | + run_dump_test "got" | |
408 | + | |
407 | 409 | if {![istarget "*-*-nacl*"]} then { |
408 | 410 | run_dump_test "iamcu-1" |
409 | 411 | run_dump_test "iamcu-2" |
@@ -3,7 +3,7 @@ | ||
3 | 3 | |
4 | 4 | Relocation section '.rel.text' at offset 0x[0-9a-f]+ contains 1 entries: |
5 | 5 | 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_GOT32X +[0-9a-f]+ +foo | |
7 | 7 | #... |
8 | 8 | +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo |
9 | 9 | #pass |
@@ -6,9 +6,9 @@ | ||
6 | 6 | |
7 | 7 | RELOCATION RECORDS FOR \[.text\]: |
8 | 8 | OFFSET[ ]+TYPE[ ]+VALUE[ ]* |
9 | -[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]* | |
9 | +[0-9a-f]+[ ]+R_386_GOT32X[ ]+xtrn[ ]* | |
10 | 10 | [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]* |
11 | -[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]* | |
11 | +[0-9a-f]+[ ]+R_386_GOT32X[ ]+xtrn[ ]* | |
12 | 12 | [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]* |
13 | -[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]* | |
13 | +[0-9a-f]+[ ]+R_386_GOT32X[ ]+xtrn[ ]* | |
14 | 14 | [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]* |
@@ -18,7 +18,7 @@ Disassembly of section \.text: | ||
18 | 18 | .*[ ]+R_386_PC32[ ]+xtrn |
19 | 19 | .*[ ]+R_386_PC8[ ]+xtrn |
20 | 20 | .*[ ]+R_386_GOT32[ ]+xtrn |
21 | -.*[ ]+R_386_GOT32[ ]+xtrn | |
21 | +.*[ ]+R_386_GOT32X[ ]+xtrn | |
22 | 22 | .*[ ]+R_386_GOTOFF[ ]+xtrn |
23 | 23 | .*[ ]+R_386_GOTOFF[ ]+xtrn |
24 | 24 | .*[ ]+R_386_GOTPC[ ]+_GLOBAL_OFFSET_TABLE_ |
@@ -66,6 +66,8 @@ START_RELOC_NUMBERS (elf_i386_reloc_type) | ||
66 | 66 | RELOC_NUMBER (R_386_TLS_DESC_CALL,40) |
67 | 67 | RELOC_NUMBER (R_386_TLS_DESC, 41) |
68 | 68 | RELOC_NUMBER (R_386_IRELATIVE, 42) /* Adjust indirectly by program base */ |
69 | + /* Load from 32 bit GOT entry, relaxable. */ | |
70 | + RELOC_NUMBER (R_386_GOT32X, 43) | |
69 | 71 | |
70 | 72 | /* Used by Intel. */ |
71 | 73 | RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200) |
@@ -0,0 +1,17 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -melf_i386 | |
3 | +#objdump: -dw | |
4 | + | |
5 | +.*: +file format .* | |
6 | + | |
7 | + | |
8 | +Disassembly of section .text: | |
9 | + | |
10 | +#... | |
11 | +[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <foo> | |
12 | +[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <bar> | |
13 | +[ ]*[a-f0-9]+: e9 ([0-9a-f]{2} ){4} * jmp +[a-f0-9]+ <foo> | |
14 | +[ ]*[a-f0-9]+: 90 nop | |
15 | +[ ]*[a-f0-9]+: e9 ([0-9a-f]{2} ){4} * jmp +[a-f0-9]+ <bar> | |
16 | +[ ]*[a-f0-9]+: 90 nop | |
17 | +#pass |
@@ -0,0 +1,15 @@ | ||
1 | + .text | |
2 | + .type bar, @function | |
3 | +bar: | |
4 | + ret | |
5 | + .globl foo | |
6 | + .type foo, @function | |
7 | +foo: | |
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 |
@@ -0,0 +1,3 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -shared -melf_i386 | |
3 | +#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object |
@@ -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 | + call *foo@GOT |
@@ -0,0 +1,3 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -shared -melf_i386 | |
3 | +#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object |
@@ -0,0 +1,8 @@ | ||
1 | + .text | |
2 | + .type foo, @function | |
3 | +foo: | |
4 | + ret | |
5 | + .globl _start | |
6 | + .type _start, @function | |
7 | +_start: | |
8 | + call *foo@GOT |
@@ -0,0 +1,20 @@ | ||
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]+: 6a 00 push \$0x0 | |
18 | +[ ]*[a-f0-9]+: [ a-f0-9]+ jmp [a-f0-9]+ <myexit> | |
19 | +[ ]*[a-f0-9]+: 90 nop | |
20 | +#pass |
@@ -0,0 +1,7 @@ | ||
1 | +foo | |
2 | +bar | |
3 | +plt | |
4 | +foo | |
5 | +bar | |
6 | +plt | |
7 | +foo |
@@ -0,0 +1,21 @@ | ||
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 | + pushl $0 # Push a dummy return address onto stack. | |
20 | + jmp *myexit@GOT | |
21 | + .size main, .-main |
@@ -0,0 +1,7 @@ | ||
1 | +#include <stdio.h> | |
2 | + | |
3 | +void | |
4 | +foo (void) | |
5 | +{ | |
6 | + printf ("%s\n", __FUNCTION__); | |
7 | +} |
@@ -0,0 +1,7 @@ | ||
1 | +#include <stdlib.h> | |
2 | + | |
3 | +void | |
4 | +myexit (int status) | |
5 | +{ | |
6 | + exit (status); | |
7 | +} |
@@ -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 |
@@ -293,6 +293,19 @@ run_dump_test "lea1e" | ||
293 | 293 | run_dump_test "lea1f" |
294 | 294 | run_dump_test "mov1a" |
295 | 295 | run_dump_test "mov1b" |
296 | +run_dump_test "branch1" | |
297 | +run_dump_test "call1" | |
298 | +run_dump_test "call2" | |
299 | +run_dump_test "jmp1" | |
300 | +run_dump_test "jmp2" | |
301 | +run_dump_test "load1" | |
302 | +run_dump_test "load2" | |
303 | +run_dump_test "load3" | |
304 | +run_dump_test "load4a" | |
305 | +run_dump_test "load4b" | |
306 | +run_dump_test "load5a" | |
307 | +run_dump_test "load5b" | |
308 | +run_dump_test "load6" | |
296 | 309 | |
297 | 310 | if { !([istarget "i?86-*-linux*"] |
298 | 311 | || [istarget "i?86-*-gnu*"] |
@@ -498,6 +511,22 @@ if { [isnative] | ||
498 | 511 | "" \ |
499 | 512 | "pr19031.so" \ |
500 | 513 | ] \ |
514 | + [list \ | |
515 | + "Build got1d.so" \ | |
516 | + "-shared" \ | |
517 | + "" \ | |
518 | + { got1d.S } \ | |
519 | + "" \ | |
520 | + "got1d.so" \ | |
521 | + ] \ | |
522 | + [list \ | |
523 | + "Build gotpc1" \ | |
524 | + "tmpdir/got1d.so" \ | |
525 | + "" \ | |
526 | + { got1a.S got1b.c got1c.c } \ | |
527 | + {{objdump {-dw} got1.dd}} \ | |
528 | + "got1" \ | |
529 | + ] \ | |
501 | 530 | ] |
502 | 531 | |
503 | 532 | run_ld_link_exec_tests [] [list \ |
@@ -568,6 +597,14 @@ if { [isnative] | ||
568 | 597 | "pr19031" \ |
569 | 598 | "pr19031.out" \ |
570 | 599 | ] \ |
600 | + [list \ | |
601 | + "Run got1" \ | |
602 | + "tmpdir/got1d.so" \ | |
603 | + "" \ | |
604 | + { got1a.S got1b.c got1c.c } \ | |
605 | + "got1" \ | |
606 | + "got1.out" \ | |
607 | + ] \ | |
571 | 608 | ] |
572 | 609 | } |
573 | 610 |
@@ -0,0 +1,3 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -shared -melf_i386 | |
3 | +#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object |
@@ -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 | + jmp *foo@GOT |
@@ -0,0 +1,3 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -shared -melf_i386 | |
3 | +#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object |
@@ -0,0 +1,8 @@ | ||
1 | + .text | |
2 | + .type foo, @function | |
3 | +foo: | |
4 | + ret | |
5 | + .globl _start | |
6 | + .type _start, @function | |
7 | +_start: | |
8 | + jmp *foo@GOT |
@@ -9,6 +9,6 @@ | ||
9 | 9 | Disassembly of section .text: |
10 | 10 | |
11 | 11 | #... |
12 | -[ ]*[a-f0-9]+: 8d 81 ([0-9a-f]{2} ){4} * lea -0x[a-f0-9]+\(%ecx\),%eax | |
13 | -[ ]*[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 | |
13 | +[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax | |
14 | 14 | #pass |
@@ -0,0 +1,57 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -melf_i386 | |
3 | +#objdump: -dw --sym | |
4 | + | |
5 | +.*: +file format .* | |
6 | + | |
7 | +SYMBOL TABLE: | |
8 | +#... | |
9 | +0+8049170 l O .data 0+1 bar | |
10 | +#... | |
11 | +0+8049171 g O .data 0+1 foo | |
12 | +#... | |
13 | + | |
14 | +Disassembly of section .text: | |
15 | + | |
16 | +0+8048074 <_start>: | |
17 | +[ ]*[a-f0-9]+: 8d 05 70 91 04 08 lea 0x8049170,%eax | |
18 | +[ ]*[a-f0-9]+: 81 d0 70 91 04 08 adc \$0x8049170,%eax | |
19 | +[ ]*[a-f0-9]+: 81 c3 70 91 04 08 add \$0x8049170,%ebx | |
20 | +[ ]*[a-f0-9]+: 81 e1 70 91 04 08 and \$0x8049170,%ecx | |
21 | +[ ]*[a-f0-9]+: 81 fa 70 91 04 08 cmp \$0x8049170,%edx | |
22 | +[ ]*[a-f0-9]+: 81 cf 70 91 04 08 or \$0x8049170,%edi | |
23 | +[ ]*[a-f0-9]+: 81 de 70 91 04 08 sbb \$0x8049170,%esi | |
24 | +[ ]*[a-f0-9]+: 81 ed 70 91 04 08 sub \$0x8049170,%ebp | |
25 | +[ ]*[a-f0-9]+: 81 f4 70 91 04 08 xor \$0x8049170,%esp | |
26 | +[ ]*[a-f0-9]+: f7 c1 70 91 04 08 test \$0x8049170,%ecx | |
27 | +[ ]*[a-f0-9]+: 8d 05 70 91 04 08 lea 0x8049170,%eax | |
28 | +[ ]*[a-f0-9]+: 81 d0 70 91 04 08 adc \$0x8049170,%eax | |
29 | +[ ]*[a-f0-9]+: 81 c3 70 91 04 08 add \$0x8049170,%ebx | |
30 | +[ ]*[a-f0-9]+: 81 e1 70 91 04 08 and \$0x8049170,%ecx | |
31 | +[ ]*[a-f0-9]+: 81 fa 70 91 04 08 cmp \$0x8049170,%edx | |
32 | +[ ]*[a-f0-9]+: 81 cf 70 91 04 08 or \$0x8049170,%edi | |
33 | +[ ]*[a-f0-9]+: 81 de 70 91 04 08 sbb \$0x8049170,%esi | |
34 | +[ ]*[a-f0-9]+: 81 ed 70 91 04 08 sub \$0x8049170,%ebp | |
35 | +[ ]*[a-f0-9]+: 81 f4 70 91 04 08 xor \$0x8049170,%esp | |
36 | +[ ]*[a-f0-9]+: f7 c1 70 91 04 08 test \$0x8049170,%ecx | |
37 | +[ ]*[a-f0-9]+: 8d 05 71 91 04 08 lea 0x8049171,%eax | |
38 | +[ ]*[a-f0-9]+: 81 d0 71 91 04 08 adc \$0x8049171,%eax | |
39 | +[ ]*[a-f0-9]+: 81 c3 71 91 04 08 add \$0x8049171,%ebx | |
40 | +[ ]*[a-f0-9]+: 81 e1 71 91 04 08 and \$0x8049171,%ecx | |
41 | +[ ]*[a-f0-9]+: 81 fa 71 91 04 08 cmp \$0x8049171,%edx | |
42 | +[ ]*[a-f0-9]+: 81 cf 71 91 04 08 or \$0x8049171,%edi | |
43 | +[ ]*[a-f0-9]+: 81 de 71 91 04 08 sbb \$0x8049171,%esi | |
44 | +[ ]*[a-f0-9]+: 81 ed 71 91 04 08 sub \$0x8049171,%ebp | |
45 | +[ ]*[a-f0-9]+: 81 f4 71 91 04 08 xor \$0x8049171,%esp | |
46 | +[ ]*[a-f0-9]+: f7 c1 71 91 04 08 test \$0x8049171,%ecx | |
47 | +[ ]*[a-f0-9]+: 8d 05 71 91 04 08 lea 0x8049171,%eax | |
48 | +[ ]*[a-f0-9]+: 81 d0 71 91 04 08 adc \$0x8049171,%eax | |
49 | +[ ]*[a-f0-9]+: 81 c3 71 91 04 08 add \$0x8049171,%ebx | |
50 | +[ ]*[a-f0-9]+: 81 e1 71 91 04 08 and \$0x8049171,%ecx | |
51 | +[ ]*[a-f0-9]+: 81 fa 71 91 04 08 cmp \$0x8049171,%edx | |
52 | +[ ]*[a-f0-9]+: 81 cf 71 91 04 08 or \$0x8049171,%edi | |
53 | +[ ]*[a-f0-9]+: 81 de 71 91 04 08 sbb \$0x8049171,%esi | |
54 | +[ ]*[a-f0-9]+: 81 ed 71 91 04 08 sub \$0x8049171,%ebp | |
55 | +[ ]*[a-f0-9]+: 81 f4 71 91 04 08 xor \$0x8049171,%esp | |
56 | +[ ]*[a-f0-9]+: f7 c1 71 91 04 08 test \$0x8049171,%ecx | |
57 | +#pass |
@@ -0,0 +1,55 @@ | ||
1 | + .data | |
2 | + .type bar, @object | |
3 | +bar: | |
4 | + .byte 1 | |
5 | + .size bar, .-bar | |
6 | + .globl foo | |
7 | + .type foo, @object | |
8 | +foo: | |
9 | + .byte 1 | |
10 | + .size foo, .-foo | |
11 | + .text | |
12 | + .globl _start | |
13 | + .type _start, @function | |
14 | +_start: | |
15 | + movl bar@GOT(%ecx), %eax | |
16 | + adcl bar@GOT(%ecx), %eax | |
17 | + addl bar@GOT(%ecx), %ebx | |
18 | + andl bar@GOT(%ecx), %ecx | |
19 | + cmpl bar@GOT(%ecx), %edx | |
20 | + orl bar@GOT(%ecx), %edi | |
21 | + sbbl bar@GOT(%ecx), %esi | |
22 | + subl bar@GOT(%ecx), %ebp | |
23 | + xorl bar@GOT(%ecx), %esp | |
24 | + testl %ecx, bar@GOT(%ecx) | |
25 | + movl bar@GOT, %eax | |
26 | + adcl bar@GOT, %eax | |
27 | + addl bar@GOT, %ebx | |
28 | + andl bar@GOT, %ecx | |
29 | + cmpl bar@GOT, %edx | |
30 | + orl bar@GOT, %edi | |
31 | + sbbl bar@GOT, %esi | |
32 | + subl bar@GOT, %ebp | |
33 | + xorl bar@GOT, %esp | |
34 | + testl %ecx, bar@GOT | |
35 | + movl foo@GOT(%ecx), %eax | |
36 | + adcl foo@GOT(%ecx), %eax | |
37 | + addl foo@GOT(%ecx), %ebx | |
38 | + andl foo@GOT(%ecx), %ecx | |
39 | + cmpl foo@GOT(%ecx), %edx | |
40 | + orl foo@GOT(%ecx), %edi | |
41 | + sbbl foo@GOT(%ecx), %esi | |
42 | + subl foo@GOT(%ecx), %ebp | |
43 | + xorl foo@GOT(%ecx), %esp | |
44 | + testl %ecx, foo@GOT(%ecx) | |
45 | + movl foo@GOT, %eax | |
46 | + adcl foo@GOT, %eax | |
47 | + addl foo@GOT, %ebx | |
48 | + andl foo@GOT, %ecx | |
49 | + cmpl foo@GOT, %edx | |
50 | + orl foo@GOT, %edi | |
51 | + sbbl foo@GOT, %esi | |
52 | + subl foo@GOT, %ebp | |
53 | + xorl foo@GOT, %esp | |
54 | + testl %ecx, foo@GOT | |
55 | + .size _start, .-_start |
@@ -0,0 +1,3 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -melf_i386 -shared | |
3 | +#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object |
@@ -0,0 +1,8 @@ | ||
1 | + .data | |
2 | + .type foo, @object | |
3 | +foo: | |
4 | + .text | |
5 | + .globl _start | |
6 | + .type _start, @function | |
7 | +_start: | |
8 | + addl foo@GOT, %ebx |
@@ -0,0 +1,3 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -melf_i386 -shared | |
3 | +#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object |
@@ -0,0 +1,9 @@ | ||
1 | + .data | |
2 | + .globl foo | |
3 | + .type foo, @object | |
4 | +foo: | |
5 | + .text | |
6 | + .globl _start | |
7 | + .type _start, @function | |
8 | +_start: | |
9 | + addl foo@GOT, %ebx |
@@ -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 |
@@ -0,0 +1,4 @@ | ||
1 | +#source: load4.s | |
2 | +#as: --32 | |
3 | +#ld: -Bsymbolic -shared -melf_i386 | |
4 | +#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object |
@@ -0,0 +1,13 @@ | ||
1 | +#source: load4.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 |
@@ -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 |
@@ -0,0 +1,4 @@ | ||
1 | +#source: load5.s | |
2 | +#as: --32 | |
3 | +#ld: -Bsymbolic -shared -melf_i386 | |
4 | +#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object |
@@ -0,0 +1,13 @@ | ||
1 | +#source: load5.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 |
@@ -0,0 +1,28 @@ | ||
1 | +#as: --32 | |
2 | +#ld: -shared -melf_i386 | |
3 | +#objdump: -dw | |
4 | + | |
5 | +.*: +file format .* | |
6 | + | |
7 | +Disassembly of section .text: | |
8 | + | |
9 | +[a-f0-9]+ <_start>: | |
10 | +[ ]*[a-f0-9]+: 13 81 f8 ff ff ff adc -0x8\(%ecx\),%eax | |
11 | +[ ]*[a-f0-9]+: 03 99 f8 ff ff ff add -0x8\(%ecx\),%ebx | |
12 | +[ ]*[a-f0-9]+: 23 89 f8 ff ff ff and -0x8\(%ecx\),%ecx | |
13 | +[ ]*[a-f0-9]+: 3b 91 f8 ff ff ff cmp -0x8\(%ecx\),%edx | |
14 | +[ ]*[a-f0-9]+: 0b b9 f8 ff ff ff or -0x8\(%ecx\),%edi | |
15 | +[ ]*[a-f0-9]+: 1b b1 f8 ff ff ff sbb -0x8\(%ecx\),%esi | |
16 | +[ ]*[a-f0-9]+: 2b a9 f8 ff ff ff sub -0x8\(%ecx\),%ebp | |
17 | +[ ]*[a-f0-9]+: 33 a1 f8 ff ff ff xor -0x8\(%ecx\),%esp | |
18 | +[ ]*[a-f0-9]+: 85 89 f8 ff ff ff test %ecx,-0x8\(%ecx\) | |
19 | +[ ]*[a-f0-9]+: 13 81 fc ff ff ff adc -0x4\(%ecx\),%eax | |
20 | +[ ]*[a-f0-9]+: 03 99 fc ff ff ff add -0x4\(%ecx\),%ebx | |
21 | +[ ]*[a-f0-9]+: 23 89 fc ff ff ff and -0x4\(%ecx\),%ecx | |
22 | +[ ]*[a-f0-9]+: 3b 91 fc ff ff ff cmp -0x4\(%ecx\),%edx | |
23 | +[ ]*[a-f0-9]+: 0b b9 fc ff ff ff or -0x4\(%ecx\),%edi | |
24 | +[ ]*[a-f0-9]+: 1b b1 fc ff ff ff sbb -0x4\(%ecx\),%esi | |
25 | +[ ]*[a-f0-9]+: 2b a9 fc ff ff ff sub -0x4\(%ecx\),%ebp | |
26 | +[ ]*[a-f0-9]+: 33 a1 fc ff ff ff xor -0x4\(%ecx\),%esp | |
27 | +[ ]*[a-f0-9]+: 85 89 fc ff ff ff test %ecx,-0x4\(%ecx\) | |
28 | +#pass |
@@ -0,0 +1,33 @@ | ||
1 | + .data | |
2 | + .type bar, @object | |
3 | +bar: | |
4 | + .byte 1 | |
5 | + .size bar, .-bar | |
6 | + .globl foo | |
7 | + .type foo, @object | |
8 | +foo: | |
9 | + .byte 1 | |
10 | + .size foo, .-foo | |
11 | + .text | |
12 | + .globl _start | |
13 | + .type _start, @function | |
14 | +_start: | |
15 | + adcl bar@GOT(%ecx), %eax | |
16 | + addl bar@GOT(%ecx), %ebx | |
17 | + andl bar@GOT(%ecx), %ecx | |
18 | + cmpl bar@GOT(%ecx), %edx | |
19 | + orl bar@GOT(%ecx), %edi | |
20 | + sbbl bar@GOT(%ecx), %esi | |
21 | + subl bar@GOT(%ecx), %ebp | |
22 | + xorl bar@GOT(%ecx), %esp | |
23 | + testl %ecx, bar@GOT(%ecx) | |
24 | + adcl foo@GOT(%ecx), %eax | |
25 | + addl foo@GOT(%ecx), %ebx | |
26 | + andl foo@GOT(%ecx), %ecx | |
27 | + cmpl foo@GOT(%ecx), %edx | |
28 | + orl foo@GOT(%ecx), %edi | |
29 | + sbbl foo@GOT(%ecx), %esi | |
30 | + subl foo@GOT(%ecx), %ebp | |
31 | + xorl foo@GOT(%ecx), %esp | |
32 | + testl %ecx, foo@GOT(%ecx) | |
33 | + .size _start, .-_start |
@@ -1,3 +1,3 @@ | ||
1 | 1 | #... |
2 | -[0-9a-f ]+R_386_GOT32 +0+ +bar | |
2 | +[0-9a-f ]+R_386_GOT32X +0+ +bar | |
3 | 3 | #pass |
@@ -1,5 +1,5 @@ | ||
1 | 1 | #... |
2 | -[0-9a-f ]+R_386_GOT32 +0+ +bar | |
2 | +[0-9a-f ]+R_386_GOT32X +0+ +bar | |
3 | 3 | #... |
4 | 4 | [0-9a-f ]+R_386_PLT32 +0+ +bar |
5 | 5 | #pass |
@@ -1,5 +1,5 @@ | ||
1 | 1 | #... |
2 | -[0-9a-f ]+R_386_GOT32 +0+ +foo | |
2 | +[0-9a-f ]+R_386_GOT32X +0+ +foo | |
3 | 3 | #... |
4 | 4 | [0-9a-f ]+R_386_PLT32 +0+ +foo |
5 | 5 | #pass |