GNU Binutils with patches for OS216
Revision | f4fbcd1272c868121b7b3b272d6df955572a08ac (tree) |
---|---|
Zeit | 2015-09-02 21:16:01 |
Autor | H.J. Lu <hjl.tools@gmai...> |
Commiter | H.J. Lu |
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.
@@ -3175,6 +3175,7 @@ instruction. */ | ||
3175 | 3175 | BFD_RELOC_386_TLS_DESC_CALL, |
3176 | 3176 | BFD_RELOC_386_TLS_DESC, |
3177 | 3177 | BFD_RELOC_386_IRELATIVE, |
3178 | + BFD_RELOC_386_LOAD_GOT32, | |
3178 | 3179 | |
3179 | 3180 | /* x86-64/elf relocations */ |
3180 | 3181 | 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_LOAD_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, | |
151 | + bfd_elf_generic_reloc, "R_386_LOAD_GOT32", | |
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_LOAD_GOT32 + 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_LOAD_GOT32: | |
340 | + TRACE ("BFD_RELOC_386_LOAD_GOT32"); | |
341 | + return &elf_howto_table[R_386_LOAD_GOT32 - 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_mov_and_branch 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_LOAD_GOT32: | |
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_LOAD_GOT32: | |
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_LOAD_GOT32: | |
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: |
@@ -1940,9 +1953,9 @@ do_size: | ||
1940 | 1953 | return FALSE; |
1941 | 1954 | } |
1942 | 1955 | |
1943 | - if (r_type == R_386_GOT32 | |
1956 | + if ((r_type == R_386_GOT32 || r_type == R_386_LOAD_GOT32) | |
1944 | 1957 | && (h == NULL || h->type != STT_GNU_IFUNC)) |
1945 | - sec->need_convert_mov_to_lea = 1; | |
1958 | + sec->need_convert_mov_and_branch = 1; | |
1946 | 1959 | } |
1947 | 1960 | |
1948 | 1961 | return TRUE; |
@@ -2066,6 +2079,7 @@ elf_i386_gc_sweep_hook (bfd *abfd, | ||
2066 | 2079 | case R_386_TLS_IE: |
2067 | 2080 | case R_386_TLS_GOTIE: |
2068 | 2081 | case R_386_GOT32: |
2082 | + case R_386_LOAD_GOT32: | |
2069 | 2083 | if (h != NULL) |
2070 | 2084 | { |
2071 | 2085 | if (h->got.refcount > 0) |
@@ -2711,14 +2725,18 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) | ||
2711 | 2725 | } |
2712 | 2726 | |
2713 | 2727 | /* Convert |
2714 | - mov foo@GOT(%reg), %reg | |
2728 | + mov foo@GOT[(%reg)], %reg | |
2715 | 2729 | 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. */ | |
2718 | 2736 | |
2719 | 2737 | 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) | |
2722 | 2740 | { |
2723 | 2741 | Elf_Internal_Shdr *symtab_hdr; |
2724 | 2742 | Elf_Internal_Rela *internal_relocs; |
@@ -2735,7 +2753,7 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, | ||
2735 | 2753 | |
2736 | 2754 | /* Nothing to do if there is no need or no output. */ |
2737 | 2755 | 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 | |
2739 | 2757 | || bfd_is_abs_section (sec->output_section)) |
2740 | 2758 | return TRUE; |
2741 | 2759 |
@@ -2769,34 +2787,57 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, | ||
2769 | 2787 | unsigned int r_symndx = ELF32_R_SYM (irel->r_info); |
2770 | 2788 | unsigned int indx; |
2771 | 2789 | 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; | |
2772 | 2800 | |
2773 | - if (r_type != R_386_GOT32) | |
2801 | + if (r_type != R_386_GOT32 && r_type != R_386_LOAD_GOT32) | |
2774 | 2802 | continue; |
2775 | 2803 | |
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. */ | |
2777 | 2818 | if (r_symndx < symtab_hdr->sh_info) |
2778 | 2819 | { |
2779 | - Elf_Internal_Sym *isym; | |
2780 | - | |
2781 | 2820 | isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
2782 | 2821 | abfd, r_symndx); |
2783 | 2822 | |
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) | |
2788 | 2825 | { |
2789 | - bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2); | |
2790 | - irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF); | |
2791 | 2826 | if (local_got_refcounts != NULL |
2792 | 2827 | && local_got_refcounts[r_symndx] > 0) |
2793 | 2828 | 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; | |
2796 | 2836 | } |
2797 | 2837 | continue; |
2798 | 2838 | } |
2799 | 2839 | |
2840 | + isym = NULL; | |
2800 | 2841 | indx = r_symndx - symtab_hdr->sh_info; |
2801 | 2842 | h = elf_sym_hashes (abfd)[indx]; |
2802 | 2843 | BFD_ASSERT (h != NULL); |
@@ -2805,21 +2846,176 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, | ||
2805 | 2846 | || h->root.type == bfd_link_hash_warning) |
2806 | 2847 | h = (struct elf_link_hash_entry *) h->root.u.i.link; |
2807 | 2848 | |
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 | |
2816 | 2947 | { |
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 | + } | |
2823 | 3019 | } |
2824 | 3020 | } |
2825 | 3021 |
@@ -2905,7 +3101,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) | ||
2905 | 3101 | { |
2906 | 3102 | struct elf_dyn_relocs *p; |
2907 | 3103 | |
2908 | - if (!elf_i386_convert_mov_to_lea (ibfd, s, info)) | |
3104 | + if (!elf_i386_convert_mov_and_branch (ibfd, s, info)) | |
2909 | 3105 | return FALSE; |
2910 | 3106 | |
2911 | 3107 | for (p = ((struct elf_dyn_relocs *) |
@@ -3655,6 +3851,7 @@ elf_i386_relocate_section (bfd *output_bfd, | ||
3655 | 3851 | goto do_relocation; |
3656 | 3852 | |
3657 | 3853 | case R_386_GOT32: |
3854 | + case R_386_LOAD_GOT32: | |
3658 | 3855 | base_got = htab->elf.sgot; |
3659 | 3856 | off = h->got.offset; |
3660 | 3857 |
@@ -3732,6 +3929,34 @@ elf_i386_relocate_section (bfd *output_bfd, | ||
3732 | 3929 | eh = (struct elf_i386_link_hash_entry *) h; |
3733 | 3930 | switch (r_type) |
3734 | 3931 | { |
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 | + | |
3735 | 3960 | case R_386_GOT32: |
3736 | 3961 | /* Relocation is to the entry for this symbol in the global |
3737 | 3962 | offset table. */ |
@@ -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_LOAD_GOT32", | |
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_LOAD_GOT32 | |
2679 | 2681 | ENUMDOC |
2680 | 2682 | i386/elf relocations |
2681 | 2683 |
@@ -2934,6 +2934,7 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED) | ||
2934 | 2934 | || fixP->fx_r_type == BFD_RELOC_386_GOTOFF |
2935 | 2935 | || fixP->fx_r_type == BFD_RELOC_386_PLT32 |
2936 | 2936 | || fixP->fx_r_type == BFD_RELOC_386_GOT32 |
2937 | + || fixP->fx_r_type == BFD_RELOC_386_LOAD_GOT32 | |
2937 | 2938 | || fixP->fx_r_type == BFD_RELOC_386_TLS_GD |
2938 | 2939 | || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM |
2939 | 2940 | || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32 |
@@ -3713,6 +3714,20 @@ md_assemble (char *line) | ||
3713 | 3714 | } |
3714 | 3715 | } |
3715 | 3716 | |
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 | + | |
3716 | 3731 | if (i.rex != 0) |
3717 | 3732 | add_prefix (REX_OPCODE | i.rex); |
3718 | 3733 |
@@ -4798,6 +4813,10 @@ match_template (void) | ||
4798 | 4813 | } |
4799 | 4814 | } |
4800 | 4815 | |
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 | + | |
4801 | 4820 | /* We check register size if needed. */ |
4802 | 4821 | check_register = t->opcode_modifier.checkregsize; |
4803 | 4822 | overlap0 = operand_type_and (i.types[0], operand_types[0]); |
@@ -10396,6 +10415,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) | ||
10396 | 10415 | case BFD_RELOC_X86_64_INDBR_GOTPCREL: |
10397 | 10416 | case BFD_RELOC_386_PLT32: |
10398 | 10417 | case BFD_RELOC_386_GOT32: |
10418 | + case BFD_RELOC_386_LOAD_GOT32: | |
10399 | 10419 | case BFD_RELOC_386_GOTOFF: |
10400 | 10420 | case BFD_RELOC_386_GOTPC: |
10401 | 10421 | 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_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 |
@@ -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_LOAD_GOT32 +[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_LOAD_GOT32[ ]+xtrn[ ]* | |
10 | 10 | [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]* |
11 | -[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]* | |
11 | +[0-9a-f]+[ ]+R_386_LOAD_GOT32[ ]+xtrn[ ]* | |
12 | 12 | [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]* |
13 | -[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]* | |
13 | +[0-9a-f]+[ ]+R_386_LOAD_GOT32[ ]+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_LOAD_GOT32[ ]+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 via 32 bit GOT entry */ | |
70 | + RELOC_NUMBER (R_386_LOAD_GOT32, 43) | |
69 | 71 | |
70 | 72 | /* Used by Intel. */ |
71 | 73 | RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200) |
@@ -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 |
@@ -0,0 +1,7 @@ | ||
1 | +foo | |
2 | +bar | |
3 | +plt | |
4 | +foo | |
5 | +bar | |
6 | +plt | |
7 | +foo |
@@ -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 |
@@ -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 |
@@ -291,6 +291,12 @@ run_dump_test "lea1c" | ||
291 | 291 | run_dump_test "lea1d" |
292 | 292 | run_dump_test "lea1e" |
293 | 293 | 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" | |
294 | 300 | run_dump_test "mov1a" |
295 | 301 | run_dump_test "mov1b" |
296 | 302 |
@@ -490,6 +496,22 @@ if { [isnative] | ||
490 | 496 | {{readelf {-Wrd} pr18900b.rd}} \ |
491 | 497 | "pr18900b" \ |
492 | 498 | ] \ |
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 | + ] \ | |
493 | 515 | ] |
494 | 516 | |
495 | 517 | run_ld_link_exec_tests [] [list \ |
@@ -552,6 +574,14 @@ if { [isnative] | ||
552 | 574 | "pr18900" \ |
553 | 575 | "pr18900.out" \ |
554 | 576 | ] \ |
577 | + [list \ | |
578 | + "Run got1" \ | |
579 | + "tmpdir/got1d.so" \ | |
580 | + "" \ | |
581 | + { got1a.S got1b.c got1c.c } \ | |
582 | + "got1" \ | |
583 | + "got1.out" \ | |
584 | + ] \ | |
555 | 585 | ] |
556 | 586 | } |
557 | 587 |
@@ -9,5 +9,5 @@ | ||
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 | |
12 | +[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax | |
13 | 13 | #pass |
@@ -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: 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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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: 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 |
@@ -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 |
@@ -1,3 +1,3 @@ | ||
1 | 1 | #... |
2 | -[0-9a-f ]+R_386_GOT32 +0+ +bar | |
2 | +[0-9a-f ]+R_386_LOAD_GOT32 +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_(LOAD_|)GOT32 +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_LOAD_GOT32 +0+ +foo | |
3 | 3 | #... |
4 | 4 | [0-9a-f ]+R_386_PLT32 +0+ +foo |
5 | 5 | #pass |